Documentation
¶
Overview ¶
Package script runs editor commands written in Lua: each script registers verbs of a golib editor's command line (its ':' prompt and RunCommand), and edits through the editor's core functions. AutoDoc loads its own scripts and the user's with it; any program with a golib Editor can do the same.
eng := script.New(editor.Core(), script.WithGlobal("autodoc"), script.WithNotify(say))
defer eng.Close()
errs := eng.LoadDir(os.DirFS(configDir), "lua") // every lua/*.lua, in name order
A script registers a command through the global table (named by WithGlobal; "editor" by default). Its run function gets the editor, the command's words and the rest of its line:
editor.command{
name = "upper", aliases = {"up"}, args = "[line]", help = "upper-case a line",
run = function(ed, args, line)
local n = tonumber(args[1]) or ed:cursor()
ed:replace(n, 1, n, #ed:line(n) + 1, ed:line(n):upper())
end,
}
A command with the name of one already registered (the editor's own, an earlier script's) replaces it. A host with a command catalog of its own takes the commands instead (SetRegistrar): the table's id names one there (lua.<name> when it has none) and title is how its lists call it, and the host decides what the name replaces. Positions are 1-based, as Lua's and the command line's line numbers are: line 1 is the first, column 1 the first character (a grapheme cluster). A range runs from its start up to, not including, its end, as the editor's do. The editor object:
ed:value() the whole text
ed:set_value(text) replace the whole text, as one edit
ed:line_count() how many lines
ed:line(n) line n's text
ed:lines() every line, a table
ed:cursor() line, column
ed:set_cursor(line, col)
ed:insert(text) at the cursor; returns the line and column after it
ed:insert_at(line, col, text) the same, at a position
ed:replace(l1, c1, l2, c2, text)
ed:delete(l1, c1, l2, c2)
ed:text(l1, c1, l2, c2) a range's text
ed:selection() l1, c1, l2, c2, or nil with none
ed:select(l1, c1, l2, c2) select a range; ed:unselect() ends the selection
ed:find(term, opts) the next match from the cursor: l1, c1, l2, c2, or nil;
opts: { ignore_case, whole_word, backward, wrap, at_cursor }
ed:find_all(term, opts) every match, a list of {l1, c1, l2, c2}
ed:replace_all(term, text, opts) every match replaced, as one edit; how many
ed:mode() "normal", "insert", "replace", "visual", "visual_line", "visual_block"
ed:read_only(), ed:modified() whether edits are refused; whether the text is unsaved
ed:run(line) run a command line, as the prompt does
EditorDocs documents each, as a reference lists them. run gets a fourth argument, cmd: cmd.name is the verb as typed (an alias, say), and cmd.bang whether it ended in '!'. The global table's notify(message) says something where the host shows messages (WithNotify), and its text table counts a string in characters, as the editor's columns do (TextDocs): text.columns(s), text.sub(s, i, j), text.chars(s). A host adds functions of its own to the global table with SetFunction, and tables of them through Global.
A host function that must wait (a call to a server) never waits on the loop: it takes a Lua function, does its work elsewhere, and hands the answer back on the loop with Callback, which runs the function as a command runs (the deadline, the editor, one undo step). ToGo and ToLua carry the values across, shaped as msgpack carries them. To reload its scripts a host makes a new engine and closes the old one (never while Running); an answer coming back for a function of the old one is Callback's ErrStale, and dropped.
A command's edits are one undo step (the editor runs every command in one). A script runs on the UI loop, as everything that touches the editor does, with a deadline (WithTimeout); an error, a script's or the deadline's, is the command's, shown in the prompt and never a crash; it is said by the error's value (a table's message, or its fields), without Lua's stack trace. Scripts get Lua's base, table, string and math libraries: no os, io, files or modules.
Concurrency Model ¶
- Ownership: loop-goroutine-owned, as the editor core it registers into. Load, LoadDir, SetFunction and every command run on the program's UI loop.
Index ¶
- Constants
- Variables
- func ModeName(m widget.EditorMode) string
- func ToGo(v lua.LValue) (any, error)
- func ToLua(L *lua.LState, v any) (lua.LValue, error)
- type BufferInfo
- type BufferSource
- type CommandInfo
- type Doc
- type Engine
- func (e *Engine) Callback(name string, fn *lua.LFunction, args ...lua.LValue) error
- func (e *Engine) Caller() (script string, grants Grants, ok bool)
- func (e *Engine) Close()
- func (e *Engine) CloseShell(sh *Shell)
- func (e *Engine) Emit(event string, info map[string]any) []error
- func (e *Engine) Eval(sh *Shell, chunk string) ([]string, error)
- func (e *Engine) Global() *lua.LTable
- func (e *Engine) Handles(event string) bool
- func (e *Engine) Load(name string, src []byte) error
- func (e *Engine) LoadDir(fsys fs.FS, dir string) []error
- func (e *Engine) LoadGated(script, name string, src []byte, grants Grants) error
- func (e *Engine) LoadPackage(script string, fsys fs.FS, grants Grants) error
- func (e *Engine) NewShell(out func(string)) *Shell
- func (e *Engine) Running() bool
- func (e *Engine) SetCommandList(fn func() []CommandInfo)
- func (e *Engine) SetDomainGate(domain string, g Gate)
- func (e *Engine) SetFunction(name string, fn lua.LGFunction)
- func (e *Engine) SetGate(name string, g Gate)
- func (e *Engine) SetRegistrar(fn func(Registration) error)
- type Gate
- type Grants
- type Notice
- type Option
- type Registration
- type Shell
Constants ¶
const DefaultTimeout = 2 * time.Second
DefaultTimeout is how long one command's script, or one file's loading, may run.
const Unclassified = "\x00unclassified"
Unclassified is a Gate's answer for a call it cannot classify (a daemon verb whose effect the daemon does not say): refused whatever the script was granted, since no grant can be known to cover it.
Variables ¶
var ErrIncomplete = errors.New("script: the chunk is not finished")
ErrIncomplete is a chunk that stops before its end: the shell asks for more.
var ErrNotCarried = errors.New("script: a value that cannot cross between Lua and Go")
ErrNotCarried is a value that cannot cross between Lua and Go: a function, a coroutine, a host's userdata, a table nested past maxDepth, a Go channel.
var ErrStale = errors.New("script: a callback of a replaced engine")
ErrStale is Callback's answer for a function another engine made: an engine a reload replaced, whose host function's answer came after. The function is not run.
Functions ¶
func ModeName ¶ added in v0.1.49
func ModeName(m widget.EditorMode) string
ModeName is m as ed:mode() says it: "normal", "insert", "visual_line", ….
Types ¶
type BufferInfo ¶ added in v0.1.51
type BufferInfo struct {
N int
Path string // "" for the untitled draft
Workspace string // "" for a file outside every workspace, and for the draft
Kind string
Modified bool
Active bool
}
BufferInfo is one buffer as buffers() lists it.
type BufferSource ¶ added in v0.1.51
type BufferSource interface {
// Buffers are the open buffers, in opening order.
Buffers() []BufferInfo
// Editor is buffer n's editor: the shown one, or a headless one; ok is false with no buffer n.
Editor(n int) (*widget.EditorCore, bool)
// Edited tells the host buffer n's text changed through a handle: dirty, its change event.
Edited(n int)
}
BufferSource is what a host gives the engine for its buffers (WithBuffers).
type CommandInfo ¶ added in v0.1.49
type CommandInfo struct {
ID string // the host's id for it: "lua.upper", "file.save"
Name string // its ':' name; "" for one ':' does not reach
Aliases []string // its other ':' names
Args string // what Tab shows after the name
Help string // one line
Title string // what the host's lists call it
Source string // who declared it: "lua", "plugin", "editor", …
}
CommandInfo is one command as the global table's commands() lists it. ID, Title and Source are a host catalog's (SetCommandList); without one they are empty, and commands() lists the editor's registry.
type Doc ¶ added in v0.1.47
type Doc struct {
Call string // "ed:line(n)"
Returns string // "string"
Notes string // "Line n's text, …"
}
Doc is one function of the script API as its reference lists it: how it is called, what it returns, and what to know (Markdown, one row of a table). EditorDocs and TextDocs are the engine's own tables, so the reference made from them lists what the engine has.
func EditorDocs ¶ added in v0.1.47
func EditorDocs() []Doc
EditorDocs is the editor object's methods as the reference lists them, in its order.
func GlobalDocs ¶ added in v0.1.49
GlobalDocs is the global table's own functions as the reference lists them, beside command and notify, the table named global: now, date, commands and on.
type Engine ¶
Engine is one Lua state registering into one editor's commands.
func New ¶
func New(core *widget.EditorCore, opts ...Option) *Engine
New is an engine registering into core's commands.
func (*Engine) Callback ¶ added in v0.1.38
Callback calls fn with args later, on the UI loop: when the answer a host function went to fetch has come (the host's own call to a server, say). It runs as a command does: under the deadline, its error (the script's, or the deadline's) returned and never a crash, the editor object reaching the editor again and fn's edits one undo step. The editor may hold another document by then than the command that asked had; a callback reads where things are now. name names fn in the error ("search.query's callback").
func (*Engine) Caller ¶ added in v0.1.49
Caller is the gated script calling the host function running now, through its proxy: its name and grants, for a host function that keeps something of the script's (a key) and checks its grant later, when it runs. ok is false for an ungated caller. A host function gated with a Gate that answers "" is one that checks later: the call goes through, with Caller set.
func (*Engine) CloseShell ¶ added in v0.1.55
CloseShell forgets sh: a callback made in it is stale from now on.
func (*Engine) Emit ¶ added in v0.1.49
Emit runs event's handlers, each as fn(ed, info), info as Lua values (ToLua). It returns their errors, each naming the event; a handler that fails stays.
func (*Engine) Eval ¶ added in v0.1.55
Eval runs chunk in sh: as an expression first (return chunk), else as statements. Its values come back as text, one per value; an error is the engine's, or ErrIncomplete.
func (*Engine) Global ¶ added in v0.1.38
Global is the global table scripts register through: a host adds its own fields to it, tables of functions among them (AutoDoc's autodoc.search.query). Only the loop touches it.
func (*Engine) Handles ¶ added in v0.1.49
Handles reports whether a script listens for event: a host may skip the work of an emit nobody hears.
func (*Engine) LoadDir ¶
LoadDir runs every *.lua file in dir of fsys, in name order. A file that fails is one error and the others still load; a dir that does not exist is no scripts.
func (*Engine) LoadGated ¶ added in v0.1.49
LoadGated runs one gated script, src, as script (the name its grants are kept under); name is how its errors name it.
func (*Engine) LoadPackage ¶ added in v0.1.49
LoadPackage runs the package in fsys (its folder: init.lua at the top) as script, gated by grants.
func (*Engine) NewShell ¶ added in v0.1.55
NewShell is a Shell whose print writes to out and whose ed is the page.
func (*Engine) Running ¶ added in v0.1.49
Running reports whether a script is running now: a file loading, a command, a completion or a callback. A host does not close the engine (a reload) from inside one.
func (*Engine) SetCommandList ¶ added in v0.1.49
func (e *Engine) SetCommandList(fn func() []CommandInfo)
SetCommandList makes fn what commands() lists: a host's catalog of commands, in place of the editor's registry. nil puts the registry back.
func (*Engine) SetDomainGate ¶ added in v0.1.49
SetDomainGate gates every function of the global table's table domain: autodoc.clipboard, or a daemon domain, autodoc.search.
func (*Engine) SetFunction ¶
func (e *Engine) SetFunction(name string, fn lua.LGFunction)
SetFunction adds fn to the global table as name: a host's own function for its scripts (the workspace's files, say). It runs on the UI loop, like the commands that call it.
func (*Engine) SetGate ¶ added in v0.1.49
SetGate gates the global table's function name. Functions SetFunction adds are ungated until gated here.
func (*Engine) SetRegistrar ¶ added in v0.1.40
func (e *Engine) SetRegistrar(fn func(Registration) error)
SetRegistrar hands every command{…} to fn in place of the editor's registry: a host's own catalog of commands, which registers it into the editor as it sees fit. fn's error is raised in the script, as a refusal of the command. nil puts the editor's registry back.
type Gate ¶ added in v0.1.49
Gate names the capability a call of a gated function needs, "" for none, Unclassified for one it cannot say. name is the function's key in its table ("call", "read"); L holds the call's arguments, from 1, for a gate that depends on them (autodoc.call: its verb).
type Grants ¶ added in v0.1.49
type Grants interface {
// Granted reports whether script may use capability now.
Granted(script, capability string) bool
// Request is the script's requires{…}: the capabilities it declared, for the host to ask about.
Request(script string, capabilities []string)
}
Grants is the host's record of what the user let each gated script do.
type Notice ¶ added in v0.1.59
Notice is a notification with an id, as notify(message, {id = …, ongoing = …}) gives it: with Ongoing, a toast updated in place under ID; without, that toast ended.
type Option ¶
type Option func(*config)
Option configures an Engine under construction.
func WithBuffers ¶ added in v0.1.51
func WithBuffers(s BufferSource) Option
WithBuffers gives scripts the host's buffers: buffers() and buffer(n). Without it, neither exists.
func WithClock ¶ added in v0.1.49
WithClock is where now() and date() read the time, and the zone date() writes local time in (time.Now and time.Local by default): a test's fixed time, say.
func WithGlobal ¶
WithGlobal names the global table scripts register through ("editor" by default): AutoDoc's is "autodoc".
func WithNotices ¶ added in v0.1.59
WithNotices is where notify(message, opts) goes when opts is given. fn's error is raised in the script, as a bad argument is: the host checks the notice. Unset, the message goes to WithNotify's function and the options are ignored.
func WithNotify ¶
WithNotify is where the global table's notify(message) goes: a status line, a toast. Unset, notify does nothing.
func WithTimeout ¶
WithTimeout is how long one command's script may run before it is stopped (DefaultTimeout).
type Registration ¶ added in v0.1.40
type Registration struct {
ID string // the table's id; "lua.<name>" when it has none
Title string // the table's title; its help, or its name, when it has none
File string // the file whose loading declared it; "" for one declared later (a callback)
Command widget.Command
}
Registration is one command{…} as a host's registrar takes it: its id and title, the file that declared it, and the command. The command's Run takes the core it is given, or the engine's when it is nil: a host running it from elsewhere than the prompt (a key) passes its own.