diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/src/async/async.lua | 6 | ||||
-rw-r--r-- | server/src/async/scanfiles.lua | 106 | ||||
-rw-r--r-- | server/src/core/library.lua | 20 | ||||
-rw-r--r-- | server/src/log.lua | 2 | ||||
-rw-r--r-- | server/src/path_filter.lua | 68 | ||||
-rw-r--r-- | server/src/utility.lua | 42 | ||||
-rw-r--r-- | server/src/workspace.lua | 32 |
7 files changed, 141 insertions, 135 deletions
diff --git a/server/src/async/async.lua b/server/src/async/async.lua index 953cf5cf..b385aac8 100644 --- a/server/src/async/async.lua +++ b/server/src/async/async.lua @@ -72,12 +72,12 @@ end local function callback(id, running) if running.callback then while true do - local ok, result = running.task.response:pop() - if not ok then + local results = table.pack(running.task.response:pop()) + if not results[1] then break end -- TODO 封装成对象 - local suc, destroy = xpcall(running.callback, log.error, result) + local suc, destroy = xpcall(running.callback, log.error, table.unpack(results, 2)) if not suc or destroy then RunningList[id] = nil IdlePool[#IdlePool+1] = running.task diff --git a/server/src/async/scanfiles.lua b/server/src/async/scanfiles.lua index c242dcfe..a9c266b3 100644 --- a/server/src/async/scanfiles.lua +++ b/server/src/async/scanfiles.lua @@ -2,92 +2,46 @@ local args = ... require 'utility' local fs = require 'bee.filesystem' -local root = fs.absolute(fs.path(args.root)) - -local function glob_compile(pattern) - return ("^%s$"):format(pattern:gsub("[%^%$%(%)%%%.%[%]%+%-%?]", "%%%0"):gsub("%*", ".*")) -end -local function glob_match(pattern, target) - return target:match(pattern) ~= nil -end - -local function accept_path(t, path) - if t[path:string()] then - return - end - t[#t+1] = path:string() - t[path:string()] = #t -end -local function expand_dir(t, pattern, dir) - if not fs.exists(dir) then - return - end - for file in dir:list_directory() do - if fs.is_directory(file) then - expand_dir(t, pattern, file) - else - if glob_match(pattern, file:filename():string():lower()) then - accept_path(t, file) - end +local path_filter = require 'path_filter' + +local function scan(root, filter) + local len = #root + local result = {fs.path(root)} + local i = 0 + return function () + i = i + 1 + local current = result[i] + if not current then + return nil end - end -end -local function expand_path(t, root, source) - if source:sub(1, 1) == '/' then - source = source:sub(2) - end - local path = root / source - if source:find("*", 1, true) == nil then - accept_path(t, path) - return - end - local filename = path:filename():string():lower() - local pattern = glob_compile(filename) - expand_dir(t, pattern, path:parent_path()) -end -local function get_sources(root, sources) - local result = {} - local ignore = {} - for _, source in ipairs(sources) do - if source:sub(1,1) ~= "!" then - expand_path(result, root, source) - else - expand_path(ignore, root, source:sub(2)) - end - end - for _, path in ipairs(ignore) do - local pos = result[path] - if pos then - result[pos] = result[#result] - result[result[pos]] = pos - result[path] = nil - result[#result] = nil + if fs.is_directory(current) then + local name = current:string():sub(len+2):gsub('/', '\\') + if filter(name) then + OUT:push('log', '过滤目录:', current:string()) + else + for path in current:list_directory() do + local name = path:string():sub(len+2):gsub('/', '\\') + if filter(name) then + OUT:push('log', '过滤文件:', path:string()) + else + result[#result+1] = path + end + end + end end + return current end - return result end -local function computePath() - local ignore = { '.git' } - - - for name in pairs(args.ignore) do - ignore[#ignore+1] = name:lower() - end - - return get_sources(root, ignore) -end - -local ignored = computePath() - -for path in io.scan(root, ignored) do +local filter = path_filter(args.ignored) +for path in scan(args.root, filter) do if path:extension():string() == '.lua' then local buf = io.load(path) if buf then - OUT:push { + OUT:push('file', { path = fs.absolute(path):string(), buf = buf, - } + }) end end end diff --git a/server/src/core/library.lua b/server/src/core/library.lua index b268b368..6bceadc4 100644 --- a/server/src/core/library.lua +++ b/server/src/core/library.lua @@ -144,6 +144,24 @@ local function fix(libs) end end +local function scan(path) + local result = {path} + local i = 0 + return function () + i = i + 1 + local current = result[i] + if not current then + return nil + end + if fs.is_directory(current) then + for path in current:list_directory() do + result[#result+1] = path + end + end + return current + end +end + local function init() local lang = require 'language' local id = lang.id @@ -152,7 +170,7 @@ local function init() library = table.container(), object = table.container(), } - for path in io.scan(ROOT / 'libs') do + for path in scan(ROOT / 'libs') do local libs local buf = io.load(path) if buf then diff --git a/server/src/log.lua b/server/src/log.lua index eb34505a..c4fa9461 100644 --- a/server/src/log.lua +++ b/server/src/log.lua @@ -24,7 +24,7 @@ local function push_log(level, ...) for i = 1, t.n do t[i] = tostring(t[i]) end - local str = table.concat(t, '\t') + local str = table.concat(t, '\t', 1, t.n) if level == 'error' then str = str .. '\n' .. debug.traceback(nil, 3) end diff --git a/server/src/path_filter.lua b/server/src/path_filter.lua new file mode 100644 index 00000000..2a362677 --- /dev/null +++ b/server/src/path_filter.lua @@ -0,0 +1,68 @@ +local m = require 'lpeglabel' + +local m_cut = m.S'/\\' +local m_path = (1-m_cut)^1 + +local function match_any(p, pass) + return m.P{p + pass * m.V(1)} +end + +local function compile_format(fmt) + local function next(cur) + local pos, fn = fmt:find('%*+', cur) + if not pos then + return m.P(fmt:sub(cur)) * -1 + end + local word = m.P(fmt:sub(cur, pos-1)) + return word * match_any(next(fn+1), 1) + end + return next(1) +end + +local function compile_exp(exp) + if exp:sub(1, 1) == '/' then + exp = exp:sub(2) + else + exp = '**/' .. exp + end + local function next(cur) + local pos, fn = exp:find('[/\\]+', cur) + if not pos then + return compile_format(exp:sub(cur)) + end + local fmt = exp:sub(cur, pos-1) + if fmt == '**' then + return match_any(next(fn+1), m_path * m_cut) + elseif fmt == '' then + return m_cut + else + if fn < #exp then + return m.P(fmt) * m_cut * next(fn+1) + else + return m.P(fmt) * m_cut + end + end + end + return next(1) +end + +local function compile_exps(exp) + local matcher + for _, exp in ipairs(exp) do + exp = exp:lower() + if matcher then + matcher = matcher + compile_exp(exp) + else + matcher = compile_exp(exp) + end + end + return matcher +end + +return function (exp) + local matcher = compile_exps(exp) + return function (path) + local filename = path:lower() + return not not matcher:match(filename) + end +end diff --git a/server/src/utility.lua b/server/src/utility.lua index ee15bf38..b0d44a60 100644 --- a/server/src/utility.lua +++ b/server/src/utility.lua @@ -142,45 +142,3 @@ function io.save(file_path, content) return false, e end end - -function io.scan(path, ignore) - local result = {path} - local i = 0 - local absolute - if ignore then - absolute = {} - for _, name in ipairs(ignore) do - local absoluteName = fs.path(name):string():lower() - absolute[#absolute+1] = absoluteName - end - end - - local function isIgnored(path) - if not absolute then - return false - end - local target = path:string():lower() - for _, name in ipairs(absolute) do - if target == name then - return true - end - end - return false - end - - return function () - i = i + 1 - local current = result[i] - if not current then - return nil - end - if fs.is_directory(current) then - if not isIgnored(current) then - for path in current:list_directory() do - result[#result+1] = path - end - end - end - return current - end -end diff --git a/server/src/workspace.lua b/server/src/workspace.lua index 348208ca..034a057c 100644 --- a/server/src/workspace.lua +++ b/server/src/workspace.lua @@ -78,16 +78,18 @@ function mt:init(rootUri) log.info('Log path: ', logPath) log.init(ROOT, logPath) - local ignored = {} + local ignored = { + ['.git'] = true, + } for path in pairs(config.config.workspace.ignoreDir) do - ignored[path] = true + ignored[#ignored+1] = path end if config.config.workspace.ignoreSubmodules then local buf = io.load(self.root / '.gitmodules') if buf then for path in buf:gmatch('path = ([^\r\n]+)') do log.debug('忽略子模块:', path) - ignored[path] = true + ignored[#ignored+1] = path end end end @@ -95,25 +97,31 @@ function mt:init(rootUri) local buf = io.load(self.root / '.gitignore') if buf then for line in buf:gmatch '[^\r\n]+' do - ignored[line] = true + ignored[#ignored+1] = line end end end + log.debug('忽略文件:\r\n' .. table.concat(ignored, '\r\n')) + async.run('scanfiles', { root = self.root:string(), - ignore = ignored, - }, function (file) - if file == 'ok' then + ignored = ignored, + }, function (mode, ...) + if mode == 'ok' then self:reset() self._complete = true return true + elseif mode == 'log' then + log.debug(...) + elseif mode == 'file' then + local file = ... + local path = fs.path(file.path) + local name = path:string():lower() + local uri = self:uriEncode(path) + self.files[name] = uri + self.lsp:readText(uri, path, file.buf) end - local path = fs.path(file.path) - local name = path:string():lower() - local uri = self:uriEncode(path) - self.files[name] = uri - self.lsp:readText(uri, path, file.buf) end) end |