2025-01-26 15:07:58 +08:00
|
|
|
#meta
|
|
|
|
|
|
|
|
Editor support for Lua, implemented in Lua. Of course.
|
|
|
|
|
|
|
|
# Code complete support
|
|
|
|
```space-lua
|
|
|
|
local LUA_KEYWORDS = {"do", "if", "then", "for", "else", "end", "function", "local", "return"}
|
|
|
|
|
|
|
|
-- Are we in a comment?
|
2025-02-06 17:04:45 +08:00
|
|
|
local function inComment(line)
|
2025-01-26 15:07:58 +08:00
|
|
|
return string.find(line, "--")
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Are we in a string?
|
2025-02-06 17:04:45 +08:00
|
|
|
local function inString(line)
|
|
|
|
local singleQuotes = 0
|
|
|
|
local doubleQuotes = 0
|
2025-01-26 15:07:58 +08:00
|
|
|
local brackets = 0
|
|
|
|
for i = 1, string.len(line) do
|
|
|
|
local c = line[i]
|
|
|
|
if c == "'" then
|
2025-02-06 17:04:45 +08:00
|
|
|
singleQuotes = singleQuotes + 1
|
2025-01-26 15:07:58 +08:00
|
|
|
elseif c == '"' then
|
2025-02-06 17:04:45 +08:00
|
|
|
doubleQuotes = doubleQuotes + 1
|
2025-01-26 15:07:58 +08:00
|
|
|
elseif c == "[" and line[i+1] == "[" then
|
|
|
|
brackets = brackets + 1
|
|
|
|
elseif c == "]" and line[i-1] == "]" then
|
|
|
|
brackets = brackets - 1
|
|
|
|
end
|
|
|
|
end
|
2025-02-06 17:04:45 +08:00
|
|
|
return singleQuotes % 2 == 1 or doubleQuotes % 2 == 1 or brackets > 0
|
2025-01-26 15:07:58 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
-- API code completion for Lua
|
|
|
|
-- Completes something.somethingelse APIs
|
|
|
|
event.listen {
|
|
|
|
name = "editor:complete",
|
|
|
|
run = function(e)
|
|
|
|
local parents = e.data.parentNodes
|
2025-02-06 17:04:45 +08:00
|
|
|
local foundSpaceLua = false
|
2025-01-26 15:07:58 +08:00
|
|
|
for _, parent in ipairs(parents) do
|
2025-02-10 01:37:21 +08:00
|
|
|
if string.startsWith(parent, "FencedCode:space-lua") or parent == "LuaDirective" then
|
2025-02-06 17:04:45 +08:00
|
|
|
foundSpaceLua = true
|
2025-01-26 15:07:58 +08:00
|
|
|
end
|
|
|
|
end
|
2025-02-06 17:04:45 +08:00
|
|
|
if not foundSpaceLua then
|
2025-01-26 15:07:58 +08:00
|
|
|
return
|
|
|
|
end
|
2025-02-06 17:04:45 +08:00
|
|
|
local linePrefix = e.data.linePrefix
|
|
|
|
if inComment(linePrefix) or inString(linePrefix) then
|
2025-01-26 15:07:58 +08:00
|
|
|
return
|
|
|
|
end
|
|
|
|
local pos = e.data.pos
|
2025-02-06 17:04:45 +08:00
|
|
|
local propaccessPrefix = string.matchRegex(linePrefix, "([a-zA-Z_0-9]+\\.)*([a-zA-Z_0-9]*)$")
|
|
|
|
if not propaccessPrefix or not propaccessPrefix[1] then
|
2025-01-26 15:07:58 +08:00
|
|
|
-- No propaccess prefix, so we can't complete
|
|
|
|
return
|
|
|
|
end
|
|
|
|
-- Split propaccess and traverse
|
2025-02-06 17:04:45 +08:00
|
|
|
local propParts = string.split(propaccessPrefix[1], ".")
|
|
|
|
local currentValue = _CTX._GLOBAL
|
2025-01-26 15:07:58 +08:00
|
|
|
local failed = false
|
2025-02-06 17:04:45 +08:00
|
|
|
for i = 1, #propParts-1 do
|
|
|
|
local prop = propParts[i]
|
|
|
|
if currentValue then
|
|
|
|
currentValue = currentValue[prop]
|
2025-01-26 15:07:58 +08:00
|
|
|
else
|
|
|
|
failed = true
|
|
|
|
end
|
|
|
|
end
|
2025-01-26 16:00:10 +08:00
|
|
|
if failed then
|
|
|
|
return
|
|
|
|
end
|
2025-02-06 17:04:45 +08:00
|
|
|
local lastProp = propParts[#propParts]
|
|
|
|
if table.includes(LUA_KEYWORDS, lastProp) then
|
2025-01-26 15:07:58 +08:00
|
|
|
return
|
|
|
|
end
|
2025-01-26 16:00:10 +08:00
|
|
|
local options = {}
|
2025-02-07 03:51:17 +08:00
|
|
|
if not currentValue then
|
|
|
|
return
|
|
|
|
end
|
2025-02-06 17:04:45 +08:00
|
|
|
for key, val in pairs(currentValue) do
|
2025-02-10 01:37:21 +08:00
|
|
|
if string.startsWith(key, lastProp) and val then
|
2025-01-26 16:00:10 +08:00
|
|
|
if val.call then
|
|
|
|
-- We got a function
|
|
|
|
if val.body then
|
|
|
|
-- Function defined in Lua
|
|
|
|
table.insert(options, {
|
|
|
|
label = key .. "(" .. table.concat(val.body.parameters, ", ") ..")",
|
2025-01-30 21:43:30 +08:00
|
|
|
apply = key,
|
2025-01-26 16:00:10 +08:00
|
|
|
detail = "Lua function"
|
|
|
|
})
|
2025-01-26 15:07:58 +08:00
|
|
|
else
|
2025-01-26 16:00:10 +08:00
|
|
|
-- Builtin
|
2025-01-26 15:07:58 +08:00
|
|
|
table.insert(options, {
|
2025-01-26 16:00:10 +08:00
|
|
|
label = key .. "()",
|
2025-01-30 21:43:30 +08:00
|
|
|
apply = key,
|
2025-01-26 16:00:10 +08:00
|
|
|
detail = "Lua built-in"
|
2025-01-26 15:07:58 +08:00
|
|
|
})
|
|
|
|
end
|
2025-01-26 16:00:10 +08:00
|
|
|
else
|
|
|
|
-- Table
|
|
|
|
table.insert(options, {
|
|
|
|
label = key,
|
|
|
|
detail = "Lua table"
|
|
|
|
})
|
2025-01-26 15:07:58 +08:00
|
|
|
end
|
|
|
|
end
|
2025-01-26 16:00:10 +08:00
|
|
|
end
|
|
|
|
if #options > 0 then
|
|
|
|
return {
|
2025-02-06 17:04:45 +08:00
|
|
|
from = pos - string.len(lastProp),
|
2025-01-26 16:00:10 +08:00
|
|
|
options = options
|
|
|
|
}
|
2025-01-26 15:07:58 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
# Slash templates
|
|
|
|
Various useful slash templates.
|
|
|
|
|
|
|
|
```space-lua
|
2025-02-06 17:04:45 +08:00
|
|
|
template.defineSlashCommand {
|
2025-01-26 15:07:58 +08:00
|
|
|
name = "function",
|
|
|
|
description = "Lua function",
|
2025-02-06 17:04:45 +08:00
|
|
|
onlyContexts = {"FencedCode:space-lua"},
|
2025-01-26 15:07:58 +08:00
|
|
|
template = template.new [==[function |^|()
|
|
|
|
end]==]
|
|
|
|
}
|
|
|
|
|
2025-02-06 17:04:45 +08:00
|
|
|
template.defineSlashCommand {
|
2025-01-26 15:07:58 +08:00
|
|
|
name = "tpl",
|
|
|
|
description = "Lua template",
|
2025-02-06 17:04:45 +08:00
|
|
|
onlyContexts = {"FencedCode:space-lua"},
|
2025-01-26 15:07:58 +08:00
|
|
|
template = template.new "template.new[==[|^|]==]"
|
|
|
|
}
|
|
|
|
|
2025-02-06 17:04:45 +08:00
|
|
|
template.defineSlashCommand {
|
2025-01-26 15:07:58 +08:00
|
|
|
name = "lua-query",
|
|
|
|
description = "Lua query",
|
2025-02-06 17:04:45 +08:00
|
|
|
onlyContexts = {"FencedCode:space-lua", "LuaDirective"},
|
2025-01-26 15:07:58 +08:00
|
|
|
template = template.new 'query[[from index.tag "|^|"]]'
|
|
|
|
}
|
|
|
|
|
2025-01-26 16:00:10 +08:00
|
|
|
|
2025-01-26 15:07:58 +08:00
|
|
|
-- A query embedded in ${}
|
2025-02-06 17:04:45 +08:00
|
|
|
template.defineSlashCommand {
|
2025-01-26 15:07:58 +08:00
|
|
|
name = "query",
|
|
|
|
description = "Lua query",
|
2025-02-06 17:04:45 +08:00
|
|
|
exceptContexts = {"FencedCode:space-lua", "LuaDirective"},
|
2025-01-26 15:07:58 +08:00
|
|
|
template = function() return '${query[[from index.tag "|^|"]]}' end
|
|
|
|
}
|