summaryrefslogtreecommitdiff
path: root/script-beta
diff options
context:
space:
mode:
Diffstat (limited to 'script-beta')
-rw-r--r--script-beta/core/completion.lua51
-rw-r--r--script-beta/core/matchkey.lua30
-rw-r--r--script-beta/parser/guide.lua33
3 files changed, 114 insertions, 0 deletions
diff --git a/script-beta/core/completion.lua b/script-beta/core/completion.lua
index e69de29b..d3a7a022 100644
--- a/script-beta/core/completion.lua
+++ b/script-beta/core/completion.lua
@@ -0,0 +1,51 @@
+local ckind = require 'define.CompletionItemKind'
+local files = require 'files'
+local guide = require 'parser.guide'
+local matchKey = require 'core.matchKey'
+
+local function findWord(text, offset)
+ for i = offset, 1, -1 do
+ if not text:sub(i, i):match '[%w_]' then
+ if i == offset then
+ return nil
+ end
+ return text:sub(i+1, offset)
+ end
+ end
+ return nil
+end
+
+local function checkLocal(ast, word, offset, results)
+ guide.getVisibleLocalNames(ast.ast, offset, function (name)
+ if matchKey(word, name) then
+ results[#results+1] = {
+ label = name,
+ kind = ckind.Variable,
+ }
+ end
+ end)
+end
+
+local function tryWord(ast, text, offset, results)
+ local word = findWord(text, offset)
+ if not word then
+ return nil
+ end
+ checkLocal(ast, word, offset, results)
+end
+
+return function (uri, offset)
+ local ast = files.getAst(uri)
+ if not ast then
+ return nil
+ end
+ local text = files.getText(uri)
+ local results = {}
+
+ tryWord(ast, text, offset, results)
+
+ if #results == 0 then
+ return nil
+ end
+ return results
+end
diff --git a/script-beta/core/matchkey.lua b/script-beta/core/matchkey.lua
new file mode 100644
index 00000000..b46250cb
--- /dev/null
+++ b/script-beta/core/matchkey.lua
@@ -0,0 +1,30 @@
+return function (me, other)
+ if me == other then
+ return true
+ end
+ if me == '' then
+ return true
+ end
+ if #me > #other then
+ return false
+ end
+ local lMe = me:lower()
+ local lOther = other:lower()
+ if lMe == lOther:sub(1, #lMe) then
+ return true
+ end
+ local chars = {}
+ for i = 1, #lOther do
+ local c = lOther:sub(i, i)
+ chars[c] = (chars[c] or 0) + 1
+ end
+ for i = 1, #lMe do
+ local c = lMe:sub(i, i)
+ if chars[c] and chars[c] > 0 then
+ chars[c] = chars[c] - 1
+ else
+ return false
+ end
+ end
+ return true
+end
diff --git a/script-beta/parser/guide.lua b/script-beta/parser/guide.lua
index 2e26a3da..4ccfd23d 100644
--- a/script-beta/parser/guide.lua
+++ b/script-beta/parser/guide.lua
@@ -235,6 +235,39 @@ function m.getLocal(block, name, pos)
error('guide.getLocal overstack')
end
+--- 获取指定区块中所有的可见局部变量名称
+function m.getVisibleLocalNames(block, pos, callback)
+ block = m.getBlock(block)
+ local used = {}
+ for _ = 1, 1000 do
+ if not block then
+ return nil
+ end
+ local locals = block.locals
+ local res
+ if not locals then
+ goto CONTINUE
+ end
+ for i = 1, #locals do
+ local loc = locals[i]
+ if loc.effect > pos then
+ break
+ end
+ local name = loc[1]
+ if not used[name] then
+ used[name] = true
+ callback(name)
+ end
+ end
+ if res then
+ return res, res
+ end
+ ::CONTINUE::
+ block = m.getParentBlock(block)
+ end
+ error('guide.getLocal overstack')
+end
+
--- 获取指定区块中可见的标签
---@param block table
---@param name string {comment = '标签名'}