silverbullet/plugs/core/Library/Std/Lua.md

151 lines
3.8 KiB
Markdown
Raw Normal View History

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?
local function inComment(line)
2025-01-26 15:07:58 +08:00
return string.find(line, "--")
end
-- Are we in a string?
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
singleQuotes = singleQuotes + 1
2025-01-26 15:07:58 +08:00
elseif c == '"' then
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
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
local foundSpaceLua = false
2025-01-26 15:07:58 +08:00
for _, parent in ipairs(parents) do
if string.startswith(parent, "FencedCode:space-lua") then
foundSpaceLua = true
2025-01-26 15:07:58 +08:00
end
end
if not foundSpaceLua then
2025-01-26 15:07:58 +08:00
return
end
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
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
local propParts = string.split(propaccessPrefix[1], ".")
local currentValue = _CTX._GLOBAL
2025-01-26 15:07:58 +08:00
local failed = false
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
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 = {}
for key, val in pairs(currentValue) do
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 {
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
template.defineSlashCommand {
2025-01-26 15:07:58 +08:00
name = "function",
description = "Lua function",
onlyContexts = {"FencedCode:space-lua"},
2025-01-26 15:07:58 +08:00
template = template.new [==[function |^|()
end]==]
}
template.defineSlashCommand {
2025-01-26 15:07:58 +08:00
name = "tpl",
description = "Lua template",
onlyContexts = {"FencedCode:space-lua"},
2025-01-26 15:07:58 +08:00
template = template.new "template.new[==[|^|]==]"
}
template.defineSlashCommand {
2025-01-26 15:07:58 +08:00
name = "lua-query",
description = "Lua query",
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 ${}
template.defineSlashCommand {
2025-01-26 15:07:58 +08:00
name = "query",
description = "Lua query",
exceptContexts = {"FencedCode:space-lua", "LuaDirective"},
2025-01-26 15:07:58 +08:00
template = function() return '${query[[from index.tag "|^|"]]}' end
}