diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2021-07-09 16:54:10 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2021-07-09 16:54:10 +0800 |
commit | 2e76da9f371bccd35e3da80b3a2af60a703f627c (patch) | |
tree | e7240d9da3ae60af576c51c68a978c54516024a2 /script | |
parent | e32f17eb3cb4b98960f1f048bae654e43cf95984 (diff) | |
download | lua-language-server-2e76da9f371bccd35e3da80b3a2af60a703f627c.zip |
improve `auto require`
Diffstat (limited to 'script')
-rw-r--r-- | script/client.lua | 20 | ||||
-rw-r--r-- | script/core/command/autoRequire.lua | 125 | ||||
-rw-r--r-- | script/core/completion.lua | 14 | ||||
-rw-r--r-- | script/provider/capability.lua | 1 | ||||
-rw-r--r-- | script/provider/provider.lua | 3 |
5 files changed, 162 insertions, 1 deletions
diff --git a/script/client.lua b/script/client.lua index 1928910f..64a5cbef 100644 --- a/script/client.lua +++ b/script/client.lua @@ -149,6 +149,26 @@ function m.setConfig(changes, onlyMemory) end end +---@alias textEdit {start: integer, finish: integer, text: string} + +---@param uri uri +---@param edits textEdit[] +function m.editText(uri, edits) + local files = require 'files' + local textEdits = {} + uri = files.getOriginUri(uri) + for i, edit in ipairs(edits) do + textEdits[i] = define.textEdit(files.range(uri, edit.start, edit.finish), edit.text) + end + proto.request('workspace/applyEdit', { + edit = { + changes = { + [uri] = textEdits, + } + } + }) +end + function m.init(t) log.debug('Client init', util.dump(t)) m.info = t diff --git a/script/core/command/autoRequire.lua b/script/core/command/autoRequire.lua new file mode 100644 index 00000000..947e78aa --- /dev/null +++ b/script/core/command/autoRequire.lua @@ -0,0 +1,125 @@ +local files = require 'files' +local furi = require 'file-uri' +local config = require 'config' +local rpath = require 'workspace.require-path' +local client = require 'client' +local lang = require 'language' + +local function findInsertOffset(uri) + local lines = files.getLines(uri) + local text = files.getText(uri) + local fmt = { + pair = false, + quot = '"', + col = nil, + } + for i = 1, #lines do + local ln = lines[i] + local lnText = text:sub(ln.start, ln.finish) + if not lnText:find('require', 1, true) then + return ln.start, fmt + else + local lpPos = lnText:find '%(' + if lpPos then + fmt.pair = true + else + fmt.pair = false + end + local quot = lnText:match [=[(['"])]=] + fmt.quot = quot or fmt.quot + local eqPos = lnText:find '=' + if eqPos then + fmt.col = eqPos + end + end + end + return 1, fmt +end + +local function askAutoRequire(visiblePaths) + -- TODO: translate + local selects = {} + local nameMap = {} + for _, visible in ipairs(visiblePaths) do + local expect = visible.expect + local select = lang.script(expect) + nameMap[select] = expect + selects[#selects+1] = select + end + local disable = lang.script('禁用自动require') + selects[#selects+1] = disable + + local result = client.awaitRequestMessage('Info' + , lang.script('在文件顶部添加代码 require 此文件?') + , selects + ) + if not result then + return + end + if result == disable then + client.setConfig { + { + key = 'Lua.completion.autoRequire', + action = 'set', + value = false, + } + } + return + end + return nameMap[result] +end + +local function applyAutoRequire(uri, offset, name, result, fmt) + local quotedResult = ('%q'):format(result) + if fmt.quot == "'" then + quotedResult = ([['%s']]):format(quotedResult:sub(2, -2) + :gsub([[']], [[\']]) + :gsub([[\"]], [["]]) + ) + end + if fmt.pair then + quotedResult = ('(%s)'):format(quotedResult) + else + quotedResult = (' %s'):format(quotedResult) + end + local sp = ' ' + local text = ('local %s'):format(name) + if fmt.col and fmt.col > #text then + sp = (' '):rep(fmt.col - #text - 1) + end + text = ('local %s%s= require%s\n'):format(name, sp, quotedResult) + client.editText(uri, { + { + start = offset, + finish = offset - 1, + text = text, + } + }) +end + +return function (data) + local uri = data.uri + local target = data.target + local name = data.name + local state = files.getState(uri) + if not state then + return + end + + local offset, fmt = findInsertOffset(uri) + local path = furi.decode(target) + local visiblePaths = rpath.getVisiblePath(path, config.get 'Lua.runtime.path') + if not visiblePaths or #visiblePaths == 0 then + return + end + table.sort(visiblePaths, function (a, b) + return #a.expect < #b.expect + end) + + local result = askAutoRequire(visiblePaths) + if not result then + return + end + + applyAutoRequire(uri, offset, name, result, fmt) +end diff --git a/script/core/completion.lua b/script/core/completion.lua index 17c4611f..8f8dda1c 100644 --- a/script/core/completion.lua +++ b/script/core/completion.lua @@ -1,3 +1,4 @@ +local sp = require 'bee.subprocess' local define = require 'proto.define' local files = require 'files' local searcher = require 'core.searcher' @@ -353,6 +354,17 @@ local function checkModule(ast, word, offset, results) label = stemName, kind = define.CompletionItemKind.Variable, commitCharacters = {'.'}, + command = { + title = 'autoRequire', + command = 'lua.autoRequire:' .. sp:get_id(), + arguments = { + { + uri = guide.getUri(ast.ast), + target = originUri, + name = stemName, + }, + }, + }, id = stack(function () return { detail = buildDetail(targetSource), @@ -361,7 +373,7 @@ local function checkModule(ast, word, offset, results) originUri )) .. '\n' .. buildDesc(targetSource), - additionalTextEdits = buildInsertRequire(ast, originUri, stemName), + --additionalTextEdits = buildInsertRequire(ast, originUri, stemName), } end) } diff --git a/script/provider/capability.lua b/script/provider/capability.lua index 9bb4ed1e..76cadc0d 100644 --- a/script/provider/capability.lua +++ b/script/provider/capability.lua @@ -84,6 +84,7 @@ function m.getIniter() 'lua.solve:' .. sp:get_id(), 'lua.jsonToLua:' .. sp:get_id(), 'lua.setConfig:' .. sp:get_id(), + 'lua.autoRequire:' .. sp:get_id(), }, }, foldingRangeProvider = true, diff --git a/script/provider/provider.lua b/script/provider/provider.lua index 208ff2c7..ad00a5b5 100644 --- a/script/provider/provider.lua +++ b/script/provider/provider.lua @@ -689,6 +689,9 @@ proto.on('workspace/executeCommand', function (params) elseif command == 'lua.setConfig' then local core = require 'core.command.setConfig' return core(params.arguments[1]) + elseif command == 'lua.autoRequire' then + local core = require 'core.command.autoRequire' + return core(params.arguments[1]) end end) |