summaryrefslogtreecommitdiff
path: root/script
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2021-07-09 16:54:10 +0800
committer最萌小汐 <sumneko@hotmail.com>2021-07-09 16:54:10 +0800
commit2e76da9f371bccd35e3da80b3a2af60a703f627c (patch)
treee7240d9da3ae60af576c51c68a978c54516024a2 /script
parente32f17eb3cb4b98960f1f048bae654e43cf95984 (diff)
downloadlua-language-server-2e76da9f371bccd35e3da80b3a2af60a703f627c.zip
improve `auto require`
Diffstat (limited to 'script')
-rw-r--r--script/client.lua20
-rw-r--r--script/core/command/autoRequire.lua125
-rw-r--r--script/core/completion.lua14
-rw-r--r--script/provider/capability.lua1
-rw-r--r--script/provider/provider.lua3
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)