Luau API
What plugins and your config get from require("@greed"): the module first, then the types it hands out. Positions are 0-based byte offsets and lines are 0-based, as language servers count them.
Greed
command
command: (spec: CommandSpec) -> ()
cli
cli: (spec: CliSpec) -> ()
Adds a command line command, greed NAME ARGS; see CliSpec.
run
run: (name: string, opts: { args: { string }?, force: boolean?, count: number?, wait: boolean? }?) -> ()
Runs a command by name, optionally with arguments, force and a count.
It returns once the command waits for something (a key, a prompt, a
reply); with wait, a command or handler instead waits until it has
finished, without blocking the editor. The command can do only what
this plugin may too, unless it has “commands”.
eval
eval: (source: string, opts: { sandbox: boolean? }?) -> (boolean, string)
Runs Luau code in a scratch environment whose globals persist, like a
REPL. Returns true and the values as text (tab-separated), or false
and the error. The code has every capability; calling it needs eval
from every plugin involved. With sandbox, it runs in a fresh environment that can
read the editor and edit buffers and nothing else: what it would do
beyond that (run programs or commands, change keys, reach files) fails
with an error starting “needs approval:”.
on
on: ((event: "mode.changed", handler: (event: ModeChanged) -> ()) -> ())
& ((event: "buffer.changed", handler: (event: BufferChanged) -> ()) -> ())
& ((event: "keys.pending", handler: (event: KeysPending) -> ()) -> ())
& ((event: "command.run", handler: (event: CommandRun) -> ()) -> ())
& ((event: "lsp.diagnostics", handler: (event: DiagnosticsChanged) -> ()) -> ())
& ((event: "control.request", handler: (event: ControlRequest) -> ()) -> ())
& ((event: "control.closed", handler: (event: ControlClosed) -> ()) -> ())
& ((event: "client.attached", handler: (event: ClientAttached) -> ()) -> ())
& ((event: "client.detached", handler: (event: ClientDetached) -> ()) -> ())
& ((event: "client.paste", handler: (event: ClientPaste) -> ()) -> ())
& ((event: "buffer.opened", handler: (event: BufferChanged) -> ()) -> ())
& ((event: "buffer.saved", handler: (event: BufferChanged) -> ()) -> ())
& ((event: "buffer.closed", handler: (event: BufferClosed) -> ()) -> ())
& ((event: "view.closed", handler: (event: ViewClosed) -> ()) -> ())
& ((event: "view.resized", handler: (event: ViewResized) -> ()) -> ())
& ((event: "pane.opened", handler: (event: PaneOpened) -> ()) -> ())
& ((event: "view.scrolled", handler: (event: ViewScrolled) -> ()) -> ())
& ((event: "selection.changed", handler: (event: SelectionChanged) -> ()) -> ())
& ((event: "view.focused", handler: (event: ViewFocused) -> ()) -> ())
& ((event: "mouse", handler: (event: MouseEvent) -> ()) -> ())
& ((event: "option.changed", handler: (event: OptionChanged) -> ()) -> ())
& ((event: "plugin.loaded", handler: (event: PluginLoaded) -> ()) -> ())
& ((event: "file.changed", handler: (event: FileChanged) -> ()) -> ())
& ((event: "plugin.unloaded", handler: (event: PluginUnloaded) -> ()) -> ())
& ((event: "editor.started", handler: (event: {}) -> ()) -> ())
& ((event: "editor.quitting", handler: (event: {}) -> ()) -> ())
& ((event: "terminal.output", handler: (event: TerminalOutput) -> ()) -> ())
& ((event: "terminal.exited", handler: (event: TerminalExited) -> ()) -> ())
Calls handler every time event happens, until greed.off removes
it or the plugin unloads.
off
off: (event: EventName, handler: (event: any) -> ()) -> ()
Removes handler, added by this plugin with greed.on(event, handler).
Does nothing if it’s not there.
echo
echo: (...any) -> ()
Shows a message to the user.
messages
messages: () -> { string }
The last messages shown, oldest first and whole (the status line shows a message’s first line).
view
view: () -> View
The focused view.
quit
quit: () -> ()
Asks the editor to exit.
line_numbers
line_numbers: (style: "absolute" | "relative" | "hybrid") -> ()
How line numbers count, where buffers show them: each line’s own number, “relative” to the cursor’s line (0 on it), or “hybrid”, relative with the cursor’s line showing its own.
reveal
reveal: (how: "line" | "cursor" | "never") -> ()
When text hidden by marks whose reveal is “auto” shows: “line” (on a cursor’s line, the default), “cursor” or “never”, as for a mark’s own reveal. Core sets it as the mode changes (see core.reveal).
detach
detach: () -> ()
Lets the attached terminal go and keeps the editor running in the
background, for greed attach to come back to.
sleep
sleep: (ms: number) -> ()
Waits ms milliseconds without blocking the editor. Works in commands
and event handlers.
spawn
spawn: (f: (...any) -> ...any, ...any) -> ()
Runs f on its own, the way a command runs, and returns at once: it can wait (greed.sleep, greed.process.run, …) while the editor and the code that started it go on. For work in the background, like a status line piece refreshing.
stalls
stalls: () -> { { ms: number, plugin: string?, what: string, time: number } }
Runs of plugin code that held the editor up (50 ms or more), newest first, for tracing a freeze to its plugin and what it was doing: a command’s name, “the status line”, “loading”. ms is how long it took; time is when, in seconds since 1970 (as os.time() counts, with a fraction).
errors
errors: () -> { { plugin: string?, what: string, message: string, traceback: string, time: number } }
Errors from plugin code that nothing caught (a command, an event handler or a task failing), newest first, up to 100: the plugin, what it ran (“on buffer.opened”, a command’s name), the message, where in its Luau it failed, and when, in seconds since 1970.
profile
profile: { start: () -> (), stop: () -> { ProfileRow }, running: () -> boolean }
Counting where the editor’s time goes: every run of plugin code (each command, event handler, status line) and the editor’s own work (handling a key, parsing, drawing), by plugin and what it did. start begins, stop ends and returns the rows, the most time first; running says whether one is being taken.
now
now: () -> number
Milliseconds on the editor’s clock, for timing animations. While a timer wakes code, it reads the time the timer was due.
hostname
hostname: () -> string?
This machine’s name, or nil if the system doesn’t say.
animate
animate: (ms: number, step: (t: number) -> ()) -> ()
Calls step(t) about once a frame for ms milliseconds, with t
going from 0 to 1, e.g. to fade a theme color or move a decoration.
Works in commands and event handlers.
next_key
next_key: () -> string
Waits for the next key press and returns its name, e.g. “g” or “ctrl-s”. The key doesn’t run anything. Works in commands and event handlers.
keys
keys: Keys
See Keys.
process
process: Process
See Process.
http
http: Http
See Http.
secrets
secrets: Secrets
See Secrets.
terminal
terminal: Terminals
See Terminals.
image
image: Images
See Images.
pdf
pdf: Pdfs
See Pdfs.
signal
signal: () -> Signal
A one-shot value that one piece of code waits for and another sends,
e.g. a tool waiting for the user’s review. wait works in commands and
event handlers; a value sent before anyone waits is kept for them.
vouch
vouch: <A..., R...>(f: (A...) -> R..., A...) -> R...
Runs f with ... as your plugin’s own action: only your capabilities count for what it does, not those of the plugins whose code called you or started what runs. For services that check what they do themselves, like the models plugin sending a key only to its provider. Anything you vouch for, any plugin can make you do: vouch only for narrow, checked operations. It can wait.
statusline
statusline: (build: (ctx: StatusContext) -> StatusParts) -> ()
Sets the function that builds the status line. It runs for every frame.
set_menus
set_menus: (menus: { { title: string, items: { { label: string, command: string } } } }) -> ()
Sets the menus a window shows as its menu bar (on macOS, the system’s), replacing those before; each item runs its command. The core plugin keeps them, so add to require("@core").menus rather than calling this.
create_buffer
create_buffer: (kind: string, text: string?, opts: { readonly: boolean?, language: string? }?) -> Buffer
A new buffer that isn’t shown anywhere yet. It goes away when the last view showing it closes.
language_of
language_of: (path: string) -> string?
The language of the file at path, by its name or extension.
filetype
filetype: (language: string, spec: { extensions: { string }?, names: { string }? }) -> ()
Makes files with these extensions (without the dot) or exact names, like
“Makefile”, be in language, replacing whatever it had before.
grammars
grammars: () -> { string }
The languages Greed has a grammar for, built in or loaded, sorted.
which
which: (program: string) -> string?
Where program is on PATH, or nil if it isn’t installed.
float
float: (buffer: Buffer, spec: FloatSpec?) -> View
Shows buffer in a view floating over the main one, and focuses it.
floats
floats: (opts: { hidden: boolean? }?) -> { View }
The floating views shown, the one in front last; with hidden = true, the hidden ones too.
panel
panel: (buffer: Buffer, spec: { side: ("left" | "right")?, width: (number | string)?, title: string?, focus: boolean? }?) -> View
Shows buffer in a panel beside the main view, which gives up the
room. Defaults: the left side, 30 cells wide, focused. Close it with
view:close().
buffers
buffers: () -> { Buffer }
Every open buffer.
open
open: (path: string) -> ()
Opens a file in the main view.
load
load: (path: string) -> Buffer
The buffer for the file at path, opening it without showing it.
buffer_for
buffer_for: (path: string) -> Buffer?
The open buffer for the file at path, or nil when it isn’t open; it
doesn’t open it. ~, . and .. are worked out and a relative path
is from the folder Greed started in, so every spelling of a file
finds its buffer.
diff
diff: (old: string, new: string) -> { { from: number, to: number, text: string } }
The changes that turn old into new, whole lines at a time: each
replaces from..to (byte offsets into old) with text. Sorted.
commands
commands: () -> { CommandInfo }
Every command, sorted by name.
handlers
handlers: () -> { HandlerInfo }
Every event handler, by event and then the order they were added.
fuzzy
fuzzy: (query: string, items: { string }, opts: { case: ("smart" | "ignore" | "match")? }?) -> { number }
The 1-based indices of items that match query, best first. case says how it minds case: “smart” (the default: only when query has a capital letter), “ignore” or “match”; core.search.case() gives what the user chose.
fuzzy_positions
fuzzy_positions: (query: string, text: string, opts: { case: ("smart" | "ignore" | "match")? }?) -> { number }
The byte offsets of the characters in text that query matches,
for highlighting them; empty if it doesn’t match. case as for fuzzy.
files
files: (dir: string?) -> { string }
Files under dir (default: the current directory), skipping hidden
and ignored files.
keymap
keymap: Keymap
See Keymap.
mode
mode: Mode
See Mode.
option
option: Options
See Options.
history
history: History
See History.
clipboard
clipboard: Clipboard
See Clipboard.
base64
base64: { encode: (bytes: string) -> string, decode: (text: string) -> string? }
Base64, as data goes in JSON, like an image for a model: encode takes bytes, decode gives them back, or nil for text that isn’t base64.
client
client: Client
See Client.
lsp
lsp: Lsp
See Lsp.
fs
fs: Fs
See Fs.
hash
hash: Hash
See Hash.
control
control: Control
See Control.
json
json: Json
See Json.
project
project: Projects
See Projects.
tab
tab: Tabs
See Tabs.
session
session: Sessions
See Sessions.
plugin
plugin: Plugins
See Plugins.
syntax
syntax: Syntax
See Syntax.
theme
theme: Theme
See Theme.
Range
A range of text. anchor is where it started and head is where the
cursor is; a cursor is a range where the two are equal.
anchor
anchor: number
head
head: number
Selection
One or more ranges, sorted and never overlapping. primary is the
1-based index of the main range.
ranges
ranges: { Range }
primary
primary: number
Edits
Collects the edits made inside Buffer:edit. They are applied together,
as one undoable change, when the callback returns.
insert
insert: (self: Edits, pos: number, text: string) -> ()
delete
delete: (self: Edits, from: number, to: number) -> ()
replace
replace: (self: Edits, from: number, to: number, text: string) -> ()
select
select: (self: Edits, selection: Selection) -> ()
Sets the selection after the edit (of every view showing the buffer, when the buffer didn’t come from a view). Without this, the current selection is moved along with the text: a cursor ends up after text inserted where it is, and after the new text of a replace or delete that covers it; a range doesn’t grow to take in text inserted at its edges.
Buffer
Open text, backed by a file or not. Two handles to the same buffer are
equal (==).
id
id: (self: Buffer) -> number
Its id, even after it was closed.
valid
valid: (self: Buffer) -> boolean
Whether it is still open. Other methods fail once it was closed.
len
len: (self: Buffer) -> number
Length in bytes.
text
text: (self: Buffer) -> string
slice
slice: (self: Buffer, from: number, to: number) -> string
line_count
line_count: (self: Buffer) -> number
line_of
line_of: (self: Buffer, pos: number) -> number
The line pos is on.
line_start
line_start: (self: Buffer, line: number) -> number
line_end
line_end: (self: Buffer, line: number) -> number
The end of line, before its line break.
line_text
line_text: (self: Buffer, line: number) -> string
The text of line, without its line break.
display_column
display_column: (self: Buffer, pos: number, tab_width: number?) -> number
The screen column pos is drawn at in its line: wide characters take two columns and tabs reach the next tab stop, every tab_width columns (4 if not given).
at_display_column
at_display_column: (self: Buffer, line: number, col: number, tab_width: number?) -> number
The position in line drawn at screen column col: the start of the character covering it, or the line’s end if the line is shorter.
char_at
char_at: (self: Buffer, pos: number) -> string?
The character at pos, or nil at the end of the buffer.
next_char
next_char: (self: Buffer, pos: number) -> number
prev_char
prev_char: (self: Buffer, pos: number) -> number
sentence
sentence: (self: Buffer, pos: number) -> (number, number)
The start and end of the sentence around pos, without the spaces
after it. Sentences end at blank lines.
kind
kind: (self: Buffer) -> string
What the buffer is: “file”, “terminal”, …
path
path: (self: Buffer) -> string?
project
project: (self: Buffer) -> number?
The id of the project it was opened in.
readonly
readonly: (self: Buffer) -> boolean
True if only plugins can change the text: edits from keys and undo are refused.
set_readonly
set_readonly: (self: Buffer, readonly: boolean) -> ()
name
name: (self: Buffer) -> string?
The name it was given, for a buffer without a file, like a terminal’s “nu ~/src”.
set_name
set_name: (self: Buffer, name: string?) -> ()
Names it where it shows (the tab line, float titles, the status line); nil or “” leaves it unnamed.
title
title: (self: Buffer) -> string
What it’s called where it shows: its file’s name, the name it was given, “untitled” for a file not saved yet, or its kind.
line_numbers
line_numbers: (self: Buffer) -> boolean
Whether the main view shows line numbers beside it (the default).
set_line_numbers
set_line_numbers: (self: Buffer, on: boolean) -> ()
views
views: (self: Buffer) -> { View }
The views showing it.
kept
kept: (self: Buffer) -> boolean
Whether it stays open while nothing shows it, though it has no file.
set_kept
set_kept: (self: Buffer, kept: boolean) -> ()
Keeps it open while nothing shows it, like a terminal to come back to; with false it goes once nothing shows it (right away if nothing does now).
set_screen_size
set_screen_size: (self: Buffer, size: { rows: number, cols: number, note: string?, cursor_row: number? }?) -> ()
Lays the text out at rows by cols in every view, whatever room a view has, like a terminal whose program has one screen size for one client: the screen is the buffer’s last rows lines. A client whose view is another size crops it (a terminal), keeping row cursor_row (0-based, where the program’s cursor is) in sight, or scales it (a window), and shows note (default “COLSxROWS”) in the room left over. nil lays it out at each view’s own size again.
screen_size
screen_size: (self: Buffer) -> { rows: number, cols: number, note: string?, cursor_row: number? }?
The size set_screen_size set, if any.
set_keys
set_keys: (self: Buffer, keys: { [string]: string }?) -> ()
Binds single keys for this buffer alone, e.g. { y = "answer-yes" }, in every mode and ahead of every other binding, while it has focus. Replaces what was bound for it before; nil drops them.
forget_history
forget_history: (self: Buffer) -> ()
Stops keeping undo history, for buffers whose edits nobody undoes, like a terminal’s: what’s kept goes, and later edits aren’t kept.
clear_history
clear_history: (self: Buffer) -> ()
Lets go of the undo history so far and keeps later edits: undo can’t go back past now, as at a shell’s prompt after a command runs.
language
language: (self: Buffer) -> string?
The language the text is highlighted as, e.g. “rust”.
set_language
set_language: (self: Buffer, language: string?) -> ()
Sets the language, or with nil goes back to the one the file’s extension implies.
tree
tree: (self: Buffer) -> Node?
The root of the syntax tree, or nil if the language has no grammar or the buffer is too big to parse. Just after an edit, when parsing again would hold the editor up, it’s the tree before with the edit applied (nodes moved with the text) until the new one is in.
node_at
node_at: (self: Buffer, from: number, to: number?) -> Node?
The smallest named node covering from..to (default: just from).
query
query: (self: Buffer, source: string, range: { from: number?, to: number? }?) -> { { [string]: Node } }
Runs a tree-sitter query over the buffer, or only for matches
overlapping from..to, e.g.
"(function_item name: (identifier) @name) @fn". One table per
match, from capture name to node. Errors on a query the language’s
grammar can’t compile; a buffer without a grammar has no matches, so
any query gives an empty list there.
edit
edit: (self: Buffer, f: (e: Edits) -> (), opts: { undo: boolean? }?) -> ()
Edits the buffer: f records edits on e, and they are applied
together, as one undoable change, when it returns. With undo = false
the change isn’t kept to undo, like output streaming in above where
someone types: undo skips it and still takes back only what the
steps before it did (redo branches are dropped).
save
save: (self: Buffer, path: string?) -> ()
Writes the buffer to its file, or to path, which becomes its file.
modified
modified: (self: Buffer) -> boolean
True if the text changed since it was opened or last saved.
version
version: (self: Buffer) -> number
A number that grows with every edit, for caches that follow the text.
reload
reload: (self: Buffer) -> boolean
Reads its file again, as an edit by “external” that undo can take back, and counts it as saved. Returns whether the text changed.
close
close: (self: Buffer) -> ()
Closes the buffer, unsaved changes and all. Errors while a view shows it: show something else there first. Plugins hear “buffer.closed”.
decorate
decorate: (self: Buffer, ns: string, marks: { Mark }, within: { from: number, to: number? }?) -> ()
Replaces the marks in namespace ns (pick one per plugin feature,
e.g. “search”). Marks move with edits; {} clears them. With
within, only those starting from from up to (not at) to (default:
the end) are replaced, e.g. on the lines an edit changed.
decorations
decorations: (self: Buffer, ns: string) -> { Mark }
The marks in namespace ns, where they are now.
marks_at
marks_at: (self: Buffer, pos: number) -> { Mark & { ns: string } }
The marks over pos in every namespace, each with its ns: those
whose range holds it, and empty ones that start there.
track
track: (self: Buffer, pos: number, opts: { gravity: ("left" | "right")? }?) -> Anchor
Follows pos through edits. Text inserted exactly there goes before it with gravity = "right" (the default) and after it with “left”. Deleting text around it moves it to where the deletion was.
track_range
track_range: (self: Buffer, from: number, to: number, opts: { from: ("left" | "right")?, to: ("left" | "right")? }?) -> Tracked
Follows from..to through edits. from and to in opts are each end’s gravity, as for track; by default text inserted at either end stays outside. It’s deleted once all of its text is.
find
find: (self: Buffer, pattern: string, from: number?, opts: { backward: boolean?, wrap: boolean? }?) -> (number?, number?, string?)
The first match of the regex pattern starting at or after from
(default 0), or with backward the last one starting before it; wrap
goes round the other end. Returns its start and end, nil when nothing
matches, or nil, nil and the error for a bad pattern.
find_all
find_all: (self: Buffer, pattern: string, from: number?, to: number?) -> ({ { from: number, to: number } }?, string?)
Every match of the regex pattern between from and to (default:
the whole buffer), or nil and the error for a bad pattern.
find_groups
find_groups: (self: Buffer, pattern: string, from: number?, to: number?) -> ({ { { from: number, to: number } | false } }?, string?)
Like find_all, but each match is the whole match’s range followed by
each group’s, false for a group that took no part.
history
history: (self: Buffer, filter: HistoryFilter?) -> { HistoryEntry }
The transactions applied to it, newest first: by author (“user”, “plugin”,
“agent” or “external”), plugin, cause (the command that made them, “undo”,
…), group, made at or after since (seconds, like time), at most limit.
text_before
text_before: (self: Buffer, id: number) -> string?
The text as it was before transaction id, or nil if the buffer has none by
that id.
undo_tree
undo_tree: (self: Buffer) -> { nodes: { UndoNode }, current: number }
The undo tree: every state the text has been in, from node 0 (as it was loaded) on, each with the step before it as parent; undo goes to the parent and redo to the last child. current is the node the text is at.
Node
A node in a buffer’s syntax tree, from buffer:tree(), buffer:node_at() or
buffer:query(). It describes the buffer as it was when found; after an edit,
find it again. tostring(node) shows its subtree, handy for writing queries.
kind
kind: string
The grammar’s name for it, e.g. “function_item” or “(”.
from
from: number
to
to: number
named
named: boolean
False for punctuation and keywords the grammar doesn’t name.
error
error: boolean
True for text the grammar couldn’t parse, or a missing piece it assumed.
field
field: string?
Its field name in its parent, e.g. “name” or “body”, if it has one.
parent
parent: (self: Node) -> Node?
children
children: (self: Node) -> { Node }
named_children
named_children: (self: Node) -> { Node }
Its children without the unnamed ones (punctuation, keywords).
child
child: (self: Node, field: string) -> Node?
The child in field field, e.g. fn:child("body").
next
next: (self: Node) -> Node?
The next named sibling.
prev
prev: (self: Node) -> Node?
The previous named sibling.
text
text: (self: Node) -> string
Its text. Errors if the buffer changed since the node was found.
Anchor
A position that moves with edits, from buffer:track. It goes when forgotten, when its buffer closes, or when the plugin that made it is unloaded.
pos
pos: (self: Anchor) -> number?
Where it is now, or nil once it’s gone.
forget
forget: (self: Anchor) -> ()
Stops following it.
Tracked
A range that moves with edits, from buffer:track_range. It goes as an Anchor does.
range
range: (self: Tracked) -> (number?, number?)
Where it is now, or nil once its text was deleted or it’s gone.
deleted
deleted: (self: Tracked) -> boolean
Whether all of its text was deleted, or it’s gone. Undo bringing the text back doesn’t change that.
forget
forget: (self: Tracked) -> ()
Stops following it.
MarkLine
A line a mark shows under its range: text, or pieces with styles of their own. On a float’s border (label, footer), a piece’s action is a command that a click on it runs, with any arguments after its name (“float-go 3”).
MarkLine = string | { { text: string, style: string?, action: string? } }
Mark
Text drawn with a style name, e.g. { from = 6, to = 11, style = "match" }.
Text typed at either edge stays outside it.
from
from: number
to
to: number
style
style: string
line
line: boolean?
Style every whole line the mark touches, not just its text.
text
text: string?
Text to show that isn’t in the buffer, like an inlay hint, before the
character at from. The cursor skips over it.
eol
eol: boolean?
Show text after the end of the line instead, cut off at the edge.
sign
sign: string?
A symbol for the sign column next to the line numbers, e.g. “E”.
gutter
gutter: string?
A style for the line number of each line the mark touches, e.g. “ui.gutter.diagnostic.error”.
above
above: boolean?
Draw over selections and cursors rather than under them.
overlay
overlay: boolean?
Draw text over the characters from from instead of inserting it,
like a jump label. The text doesn’t move.
conceal
conceal: boolean?
Hide the text, showing text (if any) in its place, e.g. the
brackets of a [[link]], except where reveal says.
reveal
reveal: ("line" | "cursor" | "never" | "auto")?
When concealed text shows: “line” (the default) when a cursor is on its line, “cursor” when a cursor is inside it past its start (a click leaves it hidden), “never”, or “auto” as greed.reveal last said, so the marks needn’t be drawn again when that changes.
fold
fold: boolean?
Hide the lines after the first one, up to the last, unless a cursor is in them, like a section folded under its heading.
plain
plain: boolean?
Draw the text without syntax highlighting, like a tool’s output in a Markdown buffer.
lines
lines: { MarkLine }?
Lines shown under the last line that aren’t in the buffer, like
backlinks. The cursor never goes on them. Each is a string, or pieces
with styles of their own on top of the mark’s, e.g.
{ { text = "x = " }, { text = "2", style = "diff.plus.change" } }.
image
image: { id: number, cols: number, rows: number, col: number?, row: number? }?
An image (from greed.image) drawn over cols by rows cells right
of and below from, whatever text is there. col and row say
which of its cells is at from, for an image cut off at the top or
left. Shown in terminals that can show images.
action
action: string?
A command that clicking text runs, with the cursor put at from
first, so the text works as a button, e.g. “proposal-accept”.
scale
scale: number?
How many times bigger the range’s text (and text) is, 1 to 4, e.g. 2 for a heading: each character takes that many cells across, and its row that many rows down. The window draws it big, and so does kitty (its text sizing); other terminals show it at the normal size.
data
data: any?
Anything to keep with the mark, given back where it is read: plain data (tables, strings, numbers, booleans), never drawn.
View
A buffer shown on screen, with its own selection. Two handles to the
same view are equal (==).
id
id: (self: View) -> number
Its id, even after it was closed.
valid
valid: (self: View) -> boolean
Whether it is still open. Other methods fail once it was closed.
selection
selection: (self: View) -> Selection
set_selection
set_selection: (self: View, selection: Selection) -> ()
cursor
cursor: (self: View) -> number
The head of the primary selection.
set_cursor
set_cursor: (self: View, pos: number) -> ()
Makes the selection a single cursor at pos.
visible
visible: (self: View) -> (number, number)
The start and end of the text on screen when the view was last drawn, or of the whole buffer before that.
size
size: (self: View) -> (number?, number?)
The rows and columns of text it had room for when last drawn; nil before it’s drawn. “view.resized” says when they change.
area
area: (self: View) -> { x: number, y: number, width: number, height: number }?
Where it was last drawn on the screen, in cells, its gutter included; nil before it’s drawn.
hidden_lines
hidden_lines: (self: View) -> { { from: number, to: number } }
The lines folds hide, 0-based and inclusive.
scroll
scroll: (self: View) -> number
The 0-based line at the top of the view.
set_scroll
set_scroll: (self: View, line: number) -> ()
Scrolls so line is at the top. Drawing scrolls again if the primary
cursor would be off screen, so move it first.
buffer
buffer: (self: View) -> Buffer
show
show: (self: View, buffer: Buffer) -> ()
Shows another buffer in this view.
focus
focus: (self: View) -> ()
Focuses this view, so keys go to it, showing its tab and project if it’s a pane or panel.
close
close: (self: View) -> boolean
Closes the view. Closing a tab’s last pane closes the tab; the project’s last pane can’t be closed, and returns false.
configure
configure: (self: View, spec: FloatSpec) -> boolean
Changes how a floating view is shown; fields left out stay as they are. False, changing nothing, if it isn’t floating; fails if it was closed.
raise
raise: (self: View) -> boolean
Brings a floating view in front of the other floats; false if it isn’t floating.
float_spec
float_spec: (self: View) -> FloatSpec?
How a floating view is shown, as greed.float takes it; nil if it isn’t floating.
is_pane
is_pane: (self: View) -> boolean
Whether it’s a pane of a tab, rather than a panel or a floating view.
split
split: (self: View, dir: "left" | "right" | "up" | "down", buffer: Buffer?) -> View
Opens a pane beside this one on its dir side, showing buffer, or
this view’s buffer as it shows it, and focuses it. Fails if this
view isn’t a pane.
neighbor
neighbor: (self: View, dir: "left" | "right" | "up" | "down") -> View?
The pane next to this one on its dir side, as last drawn: of
several, the one active most recently.
resize
resize: (self: View, dir: "left" | "right" | "up" | "down", cells: number) -> boolean
Moves this pane’s edge on its dir side by cells (negative to
shrink). False when no pane is on that side. A panel moves the edge by the main view, and only that.
undo
undo: (self: View) -> boolean
Undoes the last change. Returns false if there was nothing to undo.
undo_to
undo_to: (self: View, id: number) -> boolean
Takes the buffer to node id of its undo tree, undoing and redoing on the way, as one move; redo follows that branch from then on. False if there’s no such node or the text is there already.
redo
redo: (self: View) -> boolean
Context
What a command gets when it runs.
view
view: View
See View.
buffer
buffer: Buffer
See Buffer.
keys
keys: string?
The keys that ran the command, e.g. “g g”.
char
char: string?
The character typed, when a single printable key ran the command.
args
args: { string }
Arguments, e.g. from the command line; empty when a key ran it.
force
force: boolean
Go ahead even if the command would normally refuse, like :q!
quitting with unsaved changes.
count
count: number?
The number typed before the keys, in modes with counts on.
client
client: number
The id of the client it runs for, whose view and selections these are.
ArgSpec
An argument a command takes, for completion and help.
name
name: string
doc
doc: string?
complete
complete: string?
What completes it, e.g. “file”, “command”, “option” or “buffer”.
CommandSpec
name
name: string
Plain words with dashes, e.g. “select-line”.
doc
doc: string?
args
args: { ArgSpec }?
run
run: (ctx: Context) -> ()
CliSpec
A command for the command line, run as greed NAME ARGS in an editor
with no screen. run can wait like a command; what it echoes and
returns is printed, and an error makes greed fail.
name
name: string
Plain words with dashes, e.g. “bring”.
doc
doc: string?
usage
usage: string?
What follows the name, e.g. “HOST [PLUGIN]”.
run
run: (args: { string }) -> string?
Layer
A keymap layer. Leave mode or kind out to match any. In place of a
mode: layer names a layer that isn’t a mode, like the “leader”, which
every editing style enters its own way (space, or ctrl-space
without modes); role is an editing role (“command”, “typing”,
“selecting”) in every style, and with style in that style only.
mode
mode: string?
layer
layer: string?
role
role: string?
style
style: string?
kind
kind: string?
Keymap
bind
bind: (layer: string | Layer, bindings: { [string]: string }) -> ()
Binds key sequences to command names, e.g. { ["g g"] = "goto-start" }.
layer is a mode name or a Layer.
unbind
unbind: (layer: string | Layer, keys: { string }) -> ()
Hides what each key sequence runs in layer, e.g. { "w", "g g" }.
Removing (or reloading) the plugin that unbound them brings them back.
clear
clear: (layer: string | Layer) -> ()
Hides everything bound in layer so far, to start it over. Bindings
made afterwards, by any plugin, apply as usual.
counts
counts: (mode: string) -> ()
Makes digits typed before a key sequence in mode a count, which the
command gets as ctx.count. A leading 0 stays a key.
isolate
isolate: (mode: string) -> ()
Makes mode use only keys bound in it (and its fallback), skipping
inherited ones and those bound for every mode or for a buffer kind,
e.g. for a terminal that takes every key.
inherit
inherit: (mode: string, parent: string | Layer, prefixes: { string }?) -> ()
Makes mode fall back to parent’s keys for sequences starting with
one of prefixes (e.g. { "space", ":" }), or for every key without
them. Keys bound in mode itself come first; what parent inherits
applies in turn. parent can be a layer like { role = "typing" }.
inherit_first
inherit_first: (mode: string, parent: string | Layer) -> ()
Makes mode use parent’s keys ahead of its own, e.g. { style = "vim", role = "command" } for the Vim style’s command mode. core.style.define does this for each style’s roles.
enter
enter: (mode: string, keys: string, layer: string) -> ()
Makes keys typed in mode lead into layer, so what’s bound there works after them, e.g. enter("helix", "space", "leader"). It comes ahead of the mode’s own keys. core.style.define does this for each style’s leader.
fallback
fallback: (mode: string, command: string) -> ()
The command that handles a single unbound key in mode. A mode without one uses that of a mode it inherits every key from.
next
next: (keys: string?) -> { { key: string, command: string? } }
The keys that can follow keys (e.g. “space”) in the current mode, and
the command each runs. Keys without a command start longer sequences.
find
find: (command: string?) -> { { layer: string, keys: string, command: string } }
Every key sequence that runs command (every binding, without one),
the layer it’s bound in (a mode name, a named layer like “leader”,
“role:typing” or “vim:command”, or “global”) and its command.
active
active: () -> { { keys: string, command: string } }
Every key sequence that runs a command in the current mode and buffer, through the layers it enters and inherits (the leader’s as “space f”), less those a more specific layer hides.
overlay
overlay: (bindings: { [string]: string }?) -> ()
Binds single keys for the next key press only, over every layer, e.g. { ["1"] = "hint-1" }; any other key drops them and does what it always does. Nil drops them now.
resolve
resolve: (keys: string) -> (string?, boolean)
What keys runs in the current mode: the command, or nil and whether
more keys could still finish a sequence.
Mode
get
get: () -> string
set
set: (name: string) -> ()
Switches mode, emitting “mode.changed” if it changed.
set_cursor
set_cursor: (mode: string, shape: "block" | "bar" | "underline") -> ()
Sets how the cursor looks in mode; modes without a shape get a block.
cursor_of
cursor_of: (mode: string?) -> "block" | "bar" | "underline"
The cursor shape of mode, or of the current mode. A block or underline sits on a character, the last of a selection going forward; a bar sits between characters.
cursor
cursor: (mode: string, shape: "block" | "bar" | "underline") -> ()
The older name of set_cursor.
shape
shape: (mode: string?) -> "block" | "bar" | "underline"
The older name of cursor_of.
OptionValue
OptionValue = boolean | number | string
Options
define
define: (spec: { name: string, doc: string?, default: OptionValue, choices: { OptionValue }?, needs: string? }) -> ()
Defines an option. With choices, it takes only those values (the default among them), and :set completes them. With needs, a capability like “proc”, only code that has it, or you yourself (:set, your config), may set it: for an option whose value is run, like a command line. A plugin can’t define an option another plugin defined.
get
get: (name: string) -> OptionValue?
The option’s value for the acting client: its own, if it has one, else everyone’s.
set
set: (name: string, value: OptionValue?, opts: { client: boolean? }?) -> ()
Sets an option for every client; fails on an unknown name, the wrong type or a value that isn’t one of its choices. With client, sets a value of the acting client’s own instead, like a window’s font size, which nil takes away again; setting it for every client takes away each client’s own.
list
list: () -> { OptionInfo }
Every option, sorted by name.
OptionInfo
name
name: string
doc
doc: string
value
value: OptionValue
See OptionValue.
default
default: OptionValue
See OptionValue.
choices
choices: { OptionValue }
The values it can take; empty when any value of its type will do.
owner
owner: string
The plugin that defined it.
set_by
set_by: string?
The plugin that last set it (your config is a plugin too), if anything has.
source
source: string?
Where it was defined, e.g. “core/edit.luau:12”, and the file and line when that file is on disk.
path
path: string?
line
line: number?
HandlerInfo
An event handler, as greed.handlers() lists it.
event
event: string
owner
owner: string
The plugin that added it.
source
source: string?
path
path: string?
line
line: number?
Keys
Recording what’s typed and feeding keys back, for macros and repeating changes. Recordings have names (macros use the default, “”), so several can run at once.
record
record: (name: string?, opts: { fed: boolean? }?) -> ()
Starts keeping every key typed in the recording name, until stop; with fed, keys feed presses too.
stop
stop: (name: string?) -> { string }?
Stops the recording name and returns the keys typed, e.g. { "i", "x", "esc" }, or nil if it wasn’t recording.
recording
recording: (name: string?) -> boolean
feed
feed: (keys: string) -> ()
Presses the keys of a space-separated sequence as if they were
typed. Only recordings started with fed keep them. What they run
can do only what this plugin may (unless it has “commands”), and they
don’t answer a command waiting for you to press a key. A command
that works long enough to give the editor a turn finishes before
the next key; one waiting on a timer or a job doesn’t hold them up.
HttpRequest
A request for greed.http. method defaults to POST with a body and GET
without; timeout is in milliseconds, for the whole request. With save,
request writes a successful (2xx) response’s body to that file as it
arrives, creating its folders, and returns an empty body; the file appears
only once it’s whole. Other responses come back as usual and nothing is
written. Saving needs “fs.write”.
url
url: string
method
method: string?
headers
headers: { [string]: string }?
body
body: string?
timeout
timeout: number?
save
save: string?
HttpResponse
A whole response. Header names are lowercase.
status
status: number
headers
headers: { [string]: string }
body
body: string
HttpStream
A response whose body arrives in pieces. read waits for the next piece
and returns it, nil at the end, or nil and why it failed; close stops
reading.
status
status: number
headers
headers: { [string]: string }
read
read: (self: HttpStream) -> (string?, string?)
close
close: (self: HttpStream) -> ()
Http
Requests over the network, each on a thread of its own so the editor never waits. Both wait like greed.sleep, so they work in commands and event handlers. A plugin needs the “net” capability, or “net:HOST” for one host.
request
request: (request: HttpRequest) -> (HttpResponse?, string?)
Sends a request and returns the whole response, or nil and why.
stream
stream: (request: HttpRequest) -> (HttpStream?, string?)
Sends a request and returns once the status and headers are in; read the body as it arrives, e.g. tokens from a model.
Secrets
Secrets like API keys, kept out of config and plugin source: from the environment (GREED_SECRET_NAME, or the usual variable, e.g. ANTHROPIC_API_KEY), the system keyring, or Greed’s own secrets file. Both wait like greed.sleep. A plugin needs “secrets:NAME” for each secret it reads, or “secrets” for all.
get
get: (name: string) -> (string?, string?)
The secret name, or nil if it isn’t set anywhere.
set
set: (name: string, value: string) -> (string?, string?)
Keeps value as the secret name: in the keyring if there is one, otherwise in Greed’s secrets file. Returns where it went, or nil and why not.
variable
variable: (name: string) -> string
The environment variable that sets the secret name, to tell someone: the usual one, like ANTHROPIC_API_KEY, or GREED_SECRET_NAME. Reads nothing, so it needs no capability.
Process
Running other programs.
run
run: (
command: { string },
opts: { stdin: string?, cwd: string? }?
) -> ({ code: number?, stdout: string, stderr: string }?, string?)
Runs command (the program, then its arguments), with stdin as its
input and cwd as its folder, and returns how it exited and what it
printed; nil and the error if it couldn’t start. It runs in the
background and waits like greed.sleep, so only in commands, event
handlers and greed.spawn.
spawn
spawn: (command: { string }, opts: { cwd: string?, env: { [string]: string | false }?, stderr: ("keep" | "stream")?, group: boolean? }?) -> (Child?, string?)
Starts command to talk to over its input and output, like an agent speaking JSON-RPC, and returns at once; nil and the error if it couldn’t start. It runs until it exits, is killed, or the plugin that started it unloads. In env, false leaves a variable out of what it inherits. With stderr = "stream", what it prints as errors arrives from read too, in the order it comes; by default it’s only kept for child:stderr(). With group, it starts a process group of its own, which kill and signal reach, so the programs it starts end with it.
Child
A program started with greed.process.spawn.
pid
pid: number
write
write: (self: Child, text: string) -> boolean
Sends text to its input; false once that’s closed.
read
read: (self: Child) -> (string?, ("stdout" | "stderr")?)
Waits for the next piece of what it prints, and returns it with the output it came from, “stdout” or “stderr” (only with stderr = "stream"); nil once it exited and everything was read. Only in commands, event handlers and greed.spawn.
close
close: (self: Child) -> ()
Closes its input, which tells most programs to finish.
kill
kill: (self: Child) -> ()
Ends it (and with group, its process group) with KILL.
signal
signal: (self: Child, name: string) -> boolean
Sends it a signal by name, like “INT”, “TERM”, “HUP” or “QUIT”; with group, to its process group, even after it exited, as a shell signals a job. Returns whether it went.
wait
wait: (self: Child) -> (number?, string?)
Waits for it to exit and returns its exit code, or nil and the name of the signal that ended it, like “INT”.
stderr
stderr: (self: Child) -> string
The end of what it printed as errors so far.
TerminalRow
A line of a terminal: its text, and the parts with a style of their own
(byte offsets, 0-based, to exclusive), styled with inline names like
“=fg:red bold”.
text
text: string
spans
spans: { { from: number, to: number, style: string } }
images
images: { { from: number, id: number, col: number, row: number, cols: number, rows: number } }
Images on the row, as runs of cells from byte from: from the image’s
cell (col, row) on, of an image cols by rows cells. id is a
greed.image id, for a mark’s image.
links
links: { TerminalLink }
Links the program printed (OSC 8), as byte ranges and where they go.
wrapped
wrapped: boolean
Whether the line carries on on the next row: the program printed past the last column and the terminal wrapped it.
TerminalModes
The modes a terminal’s program set, from terminal:modes().
alternate
alternate: boolean
A full screen program, like an editor or a pager, is showing.
canonical
canonical: boolean
Input goes to the program a line at a time; off in raw mode, which editors and prompts set.
echo
echo: boolean
Typed text is echoed; off while a program reads a password.
mouse
mouse: boolean
The program asked for mouse events.
app_cursor
app_cursor: boolean
Arrow keys are sent in application mode.
bracketed_paste
bracketed_paste: boolean
Pastes are marked as pastes.
TerminalLink
TerminalLink = { from: number, to: number, uri: string }
TerminalScreen
What a terminal shows.
rows
rows: { TerminalRow }
cursor
cursor: { row: number, col: number }?
The cursor’s row (0-based) and byte offset in it, unless the program hid it.
alternate
alternate: boolean
Whether a full screen program, like an editor or a pager, is showing.
Terminal
A program running in a terminal. Two handles to the same terminal are
equal (==).
id
id: (self: Terminal) -> number
Its id, even after it was closed.
valid
valid: (self: Terminal) -> boolean
Whether it is still open. Other methods fail once it was closed.
screen
screen: (self: Terminal) -> TerminalScreen
scrollback
scrollback: (self: Terminal, from: number?) -> { first: number, rows: { TerminalRow } }
The lines that scrolled off the top, from line from (counting from
the terminal’s first line) on, or from the oldest one kept. first is
the number of the first line returned.
marks
marks: (self: Terminal, from: number?) -> { TerminalMark }
The places the shell marked (OSC 133) on line from (counting as
scrollback does) and after, oldest first: where a prompt starts,
where the typed command starts, where its output starts, and where it
was done, with its exit code if the shell said. col is a byte in the
line’s text.
marks_made
marks_made: (self: Terminal) -> number
How many marks the shell has made so far, to tell when there are new ones without asking for them all.
cwd
cwd: (self: Terminal) -> string?
The folder the shell last said it’s in (OSC 7), or the one it started in.
write
write: (self: Terminal, text: string) -> ()
Sends text to the program as if typed. This and the other methods that send input need “proc”: the plugin that started the terminal has it through the handle it got; others with one from an event need their own.
key
key: (self: Terminal, name: string) -> ()
Sends a key, e.g. “ctrl-c” or “up”, as a terminal encodes it.
paste
paste: (self: Terminal, text: string) -> ()
Sends pasted text, marked as a paste if the program asked for that.
resize
resize: (self: Terminal, rows: number, cols: number) -> ()
Changes its size, kept to between 1 by 1 and 1024 rows by 2048 columns.
wants_mouse
wants_mouse: (self: Terminal) -> boolean
Whether the program asked for mouse events, as editors and htop do.
modes
modes: (self: Terminal) -> TerminalModes
The modes the program set: the alternate screen, line input and echo (from the terminal’s settings), mouse, application cursor keys and bracketed paste.
mouse
mouse: (self: Terminal, kind: string, col: number, row: number, which: string?, mods: { ctrl: boolean?, alt: boolean?, shift: boolean? }?) -> boolean
Sends a mouse event at the program’s screen cell (col, row),
0-based, if it asked for that kind: kind as in a MouseEvent, with
a button or a scroll direction. Returns whether it was sent.
title
title: (self: Terminal) -> string?
What the program called its window, if it did.
program
program: (self: Terminal) -> string
The name of the program it started, like “nu” or “cargo”: its file name, or the shell’s for a terminal started without a command.
exit_code
exit_code: (self: Terminal) -> number?
The program’s exit code, once it has ended.
busy
busy: (self: Terminal) -> boolean
Whether a program other than the one it started is in the foreground, like a command its shell runs. False once it has ended.
kill
kill: (self: Terminal) -> ()
Asks the program to end.
close
close: (self: Terminal) -> ()
Ends the program and lets the terminal go; its handle stops working.
Terminals
Programs in terminals. A terminal belongs to the plugin that started it.
spawn
spawn: (spec: { command: { string }?, cwd: string?, env: { [string]: string | false }?, rows: number, cols: number, scrollback: number? }) -> Terminal
Starts command (the program, then its arguments; the user’s shell
without) in a terminal of rows by cols. Its output arrives as
“terminal.output” events and its end as “terminal.exited”.
scrollback lines are kept above the screen (default 10000). The
size is kept to between 1 by 1 and 1024 rows by 2048 columns. In
env, false leaves a variable out of what the program inherits.
TerminalMark
A place a shell marked in a terminal, from terminal:marks().
line
line: number
col
col: number
kind
kind: "prompt" | "command" | "output" | "done"
code
code: number?
The exit code, for “done”, if the shell said.
TerminalOutput
A terminal printed something; read it with terminal:screen().
terminal
terminal: Terminal
See Terminal.
TerminalExited
The program in a terminal ended.
terminal
terminal: Terminal
See Terminal.
code
code: number
UndoNode
A state of a buffer’s text in its undo tree, from buffer:undo_tree().
id
id: number
0 is the text as loaded; later states have higher ids.
parent
parent: number?
children
children: { number }
Oldest first; redo follows the last.
time
time: number?
When the step was last added to, in seconds like os.time(); nil for node 0.
HistoryEntry
A transaction applied to a buffer, from buffer:history().
id
id: number
author
author: "user" | "plugin" | "agent" | "external"
plugin
plugin: string?
The plugin, for edits a plugin made.
cause
cause: string?
Why: the command it was made for, “undo”, “redo”, …
group
group: number?
The undo group it was made in.
time
time: number
When, in seconds since 1970.
changes
changes: { { from: number, to: number, text: string } }
What it replaced, in the text before it, in order.
HistoryFilter
author
author: string?
plugin
plugin: string?
cause
cause: string?
group
group: number?
since
since: number?
limit
limit: number?
History
start_group
start_group: () -> ()
Edits until end_group become one undo step.
end_group
end_group: () -> ()
new_group
new_group: () -> number
A group id nothing has used yet, for set_group.
group
group: () -> number?
The group edits go into now, if any.
set_group
set_group: (group: number?) -> ()
Puts the edits that follow, in every buffer, into group (one used before
carries on), or with nil into none. Edits in a group undo as one step.
cause
cause: () -> string?
Why edits are being made: by default the command running.
set_cause
set_cause: (cause: string?) -> ()
Sets why the edits that follow are made, for the rest of this command.
undo_group
undo_group: (group: number) -> (number?, string?)
Undoes group in every buffer it changed, as one step. Returns how many
buffers changed (0 if it was undone already), or nil and why not, when
something was done on top of it since.
FloatSpec
How a floating view looks. Sizes are cells, or a share of the screen as a string like “60%” or “37.5%”, which keeps the float in proportion on clients with screens of other sizes; both default to “60%”.
title
title: string?
width
width: (number | string)?
height
height: (number | string)?
anchor
anchor: ("center" | "top" | "bottom" | "left" | "right" | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "cursor" | "above-cursor")?
Where it goes when x or y is left out: in the middle, at an edge
or in a corner. “cursor” opens it just below the cursor (or above,
near the bottom), like a completion menu; “above-cursor” prefers
above, like signature help.
focus
focus: boolean?
Whether the view takes focus. Defaults to true.
x
x: (number | string)?
Where the outside of the border goes, from the screen’s left and top
edges, in cells or like “37.5%”. Left out, the float goes where
anchor says on that axis. It’s always kept on screen.
y
y: (number | string)?
tab
tab: boolean?
Whether it belongs to the tab it opens in: shown only with that tab, and closed with it, like a floating terminal. Otherwise it floats over every tab, like a picker. Defaults to false.
shared
shared: boolean?
Whether every client is shown it, like a review meant for everyone. Otherwise only the client it opened for is (the one acting then), as with a picker or a prompt, unless it belongs to a tab, which every client showing the tab sees. Defaults to false.
label
label: MarkLine?
Text at the right end of the top border, e.g. “‹ 2/5 ›”, or pieces with styles of their own. “” takes it off.
See MarkLine.
footer
footer: MarkLine?
Text in the middle of the bottom border, as label takes it.
See MarkLine.
border
border: boolean?
Whether it has a border; defaults to true. Without one its text fills its whole box, like a one-line strip.
hidden
hidden: boolean?
Hides it: its view and buffer stay (a terminal keeps running), but
it isn’t drawn, greed.floats() leaves it out and focus moves on.
Focusing it shows it again.
CommandInfo
name
name: string
doc
doc: string
args
args: { ArgSpec }
owner
owner: string
The plugin that defined it.
source
source: string?
Where it was defined, e.g. “core/motions.luau:120”.
path
path: string?
The file and line it was defined on, when that file is on disk.
line
line: number?
BufferClosed
A buffer was closed. Only its id is left.
id
id: number
BufferChanged
buffer
buffer: Buffer
See Buffer.
from_line
from_line: number?
On “buffer.changed”: the first and last line (0-based, as the text is now) of what changed since the last “buffer.changed” for the buffer.
to_line
to_line: number?
ControlRequest
A request from the session socket, e.g. from greed ctl or an agent.
Answer it with greed.control.reply.
id
id: number
client
client: string
“socket” for the session socket (greed ctl, greed mcp), “ide” for Claude Code’s IDE connection.
connection
connection: number?
The session socket connection it came on, for greed.control.send;
nil for Claude Code’s IDE connection.
method
method: string
params
params: any
ControlClosed
A session socket connection closed, after its last request came.
connection
connection: number
The connection, as ControlRequest.connection gave it.
Signal
wait
wait: (self: Signal) -> any
Waits until a value is sent, and returns it.
send
send: (self: Signal, value: any) -> ()
Sends value to whoever waits. Only the first send counts.
ProjectInfo
A project: a folder with its own main view and panels.
id
id: number
root
root: string
current
current: boolean
Whether it’s the one shown.
Projects
list
list: () -> { ProjectInfo }
Every open project, in the order they were opened.
current
current: () -> ProjectInfo
open
open: (root: string) -> number
Opens a project rooted at root, with an empty main view, and shows
it. Returns its id.
switch
switch: (id: number) -> boolean
Shows project id. False if there is none.
close
close: (id: number) -> boolean
Closes project id with its views and the buffers opened in it. The
last project can’t be closed; false then.
Images
Images for marks to show. Each is kept until forgotten.
load
load: (path: string) -> (number?, string?)
Reads a PNG, JPEG or GIF file. Returns the image’s id, or nil and why not.
decode
decode: (bytes: string) -> (number?, string?)
The same, from the file’s bytes.
size
size: (id: number) -> (number?, number?)
Its width and height in pixels.
cells
cells: (id: number) -> (number?, number?)
How many cells it covers at its own size on the attached screen.
cell_size
cell_size: () -> (number, number)
A cell’s width and height in pixels on the attached screen.
forget
forget: (id: number) -> ()
Pdfs
PDF documents.
open
open: (path: string) -> (PdfDocument?, string?)
Reads the PDF at path. Returns the document, or nil and why not. It waits like greed.sleep, so only in commands, event handlers and greed.spawn.
PdfDocument
A PDF read with greed.pdf.open. Pages count from 1.
pages
pages: number
size
size: (self: PdfDocument, page: number) -> (number?, number?)
A page’s width and height in points (1/72 inch).
render
render: (self: PdfDocument, page: number, scale: number?) -> (number?, string?)
Draws a page at scale pixels per point (1 if not given) and returns it as a greed.image id, or nil and why not. Forget the image when done with it. Waits like greed.sleep.
text
text: (self: PdfDocument, page: number) -> (string?, string?)
The text on a page, line by line from the top, or nil and why not. Waits like greed.sleep.
TabInfo
A tab of the shown project: panes laid out side by side and one above another.
id
id: number
name
name: string?
The name it was given, if any.
current
current: boolean
Whether it’s the one shown.
zoomed
zoomed: boolean
Whether only its active pane is shown.
panes
panes: { View }
Its panes, left to right and top to bottom.
active
active: View
The pane keys go to while it’s shown.
See View.
Tabs
list
list: () -> { TabInfo }
The shown project’s tabs, in order.
current
current: () -> TabInfo
new
new: (buffer: Buffer?) -> number
Opens a tab after the shown one, with a pane showing buffer (or an
empty buffer), and shows it. Returns its id.
switch
switch: (id: number) -> boolean
Shows tab id, of whichever project, and its project. False if there’s no such tab.
close
close: (id: number) -> boolean
Closes tab id and its panes. The last tab can’t be closed; false
then.
rename
rename: (id: number, name: string?) -> boolean
Names tab id; nil or “” names it after what it shows again.
set_zoomed
set_zoomed: (zoomed: boolean) -> ()
Shows only the active pane of the shown tab, or all of them again.
layout
layout: (id: number?) -> any
How tab id (the shown one by default) lays out its panes, as a
PaneLayout, with sizes adding up to 1 in each split.
set_layout
set_layout: (layout: any, id: number?) -> ()
Lays tab id’s panes out as layout (a PaneLayout) instead. It
arranges the panes the tab has, so it has to hold each of them once;
opening and closing panes is view:split and view:close. A split
of one pane is that pane; splits nest at most 64 deep.
PaneLayout
A tab’s panes: a pane is its view, a split lays out its children side by
side (“row”) or one above another (“column”), sharing the room by
sizes, which are relative to each other (equal when left out).
PaneLayout = View | { split: "row" | "column", children: { PaneLayout }, sizes: { number }? }
PaneOpened
A pane was opened, beside from.
view
view: View
See View.
from
from: View
See View.
SessionInfo
A session running on this machine: an editor process of its own.
name
name: string
root
root: string?
The project it was started for.
current
current: boolean
Whether it’s this session.
Sessions
list
list: () -> { SessionInfo }
The sessions running on this machine, by name.
current
current: () -> string?
This session’s name, when the editor runs as one.
remote
remote: () -> boolean
Whether the attached client (or the last one) came over greed ssh; before any attached, whether greed ssh started the session.
attached
attached: () -> boolean
Whether a terminal or window is attached to the session.
program
program: () -> string?
Where the greed program running this editor is, to start greed mcp or greed ctl for this session.
switch
switch: (to: { name: string?, path: string?, new: boolean?, host: string? }) -> ()
Sends the attached client to the session name, or to the session for
the project path is in (opening it there), starting it if it isn’t
running. This session goes on without the client. With new, a new
session for path’s project, even when one is running for it. With
host, the session is on that machine, reached as greed ssh does.
Json
JSON. Tables with keys 1..n become arrays, other tables objects; an
empty table is an object unless it came from array.
encode
encode: (value: any) -> string
value as JSON. Text that isn’t UTF-8, like a program’s binary
output, has its broken bytes written as U+FFFD.
decode
decode: (text: string) -> (any, string?)
The value, or nil and why the text isn’t JSON. null becomes nil.
array
array: <T>(items: { T }?) -> { T }
Marks items (or a new table) to encode as an array even when empty.
Control
Needs the “control” capability (and serve_ide “net” too).
reply
reply: (id: number, result: any, message: string?) -> ()
Answers request id with result, or with an error message. Every
request needs exactly one answer.
send
send: (connection: number?, method: string, params: any) -> boolean
Sends a notification of method with params to the session socket
connection a request came on (its connection), e.g. MCP’s
“notifications/tools/list_changed”. False if that connection has closed.
serve_ide
serve_ide: (folders: { string }, lock_dir: string?) -> number
Lets Claude Code find this editor with /ide: listens on a localhost
WebSocket and writes a lock file naming folders as open, in lock_dir
(default ~/.claude/ide). Its requests come with client “ide”. Returns
the port; calling it again replaces the connection.
notify
notify: (method: string, params: any) -> ()
Sends a notification, e.g. “selection_changed”, to Claude Code.
ProfileRow
One row of greed.profile.stop(): what a plugin (nil for the editor itself) spent doing one thing, in all and at most once, in milliseconds.
ProfileRow = { plugin: string?, what: string, ms: number, longest: number, runs: number }
ClientAttached
A client attached, e.g. greed FILE in a session that was running. Handlers run as that client.
client
client: number
The client’s id.
path
path: string?
The file or folder it asked to open, if any.
terminal
terminal: boolean
Whether it asked for a terminal, e.g. greed ssh HOST --terminal.
remote
remote: boolean
Whether it came over greed ssh.
ClientDetached
A client went; the session goes on. Handlers run as that client, just before it’s gone.
client
client: number
ClientPaste
Text pasted into the client from the system clipboard: a terminal’s paste, or a window’s paste keys (ctrl-shift-v, shift-insert, cmd-v). The core plugin puts it at the cursors.
client
client: number
The client it was pasted into, which handlers run as.
text
text: string
ViewClosed
A view was closed. Its handle no longer works, but its id can be
compared with view:id().
view
view: number
MouseEvent
What the mouse did, and what was under it.
client
client: number
The client whose mouse it was, which handlers run as.
kind
kind: "press" | "release" | "drag" | "move" | "scroll"
button
button: ("left" | "middle" | "right")?
For a press, release or drag.
dir
dir: ("up" | "down" | "left" | "right")?
For a scroll.
col
col: number
The screen cell, from the top left.
row
row: number
ctrl
ctrl: boolean
alt
alt: boolean
shift
shift: boolean
view
view: View?
The view under it, if any.
See View.
pos
pos: number?
The place in the view’s buffer under it: the character there, or the end of the line past it. Over a mark’s text, where the mark starts.
action
action: string?
The action of the mark whose text it’s over, or of the status line segment (with no view), if that has one.
x
x: number?
The cell in the view’s text, from its top left, right of the gutter.
y
y: number?
tab
tab: number?
The tab whose name it’s over, in the tab line.
border
border: ("top" | "bottom" | "left" | "right" | "top-left" | "top-right" | "bottom-left" | "bottom-right")?
On a floating view’s border (with view set), which part: “top” (the title’s), “bottom”, “left”, “right”, or a corner like “bottom-right”.
edge
edge: ("left" | "right" | "down")?
On the line between a pane or panel (view) and its neighbor, the side of view it’s on: “right” or “down” for panes, the side by the main view for panels. Dragging it resizes view with resize.
ViewResized
A view was drawn for a client with room for a different number of rows or columns of text than before. Handlers run as that client.
client
client: number
view
view: View
See View.
rows
rows: number
cols
cols: number
ViewScrolled
A view was drawn for a client starting at a different line than before. What a handler changes shows in the same frame, so a view can scroll another along with it. Handlers run as that client.
client
client: number
view
view: View
See View.
line
line: number
The 0-based line now at the top.
SelectionChanged
A view’s selection changed for a client, or it shows another buffer, since the last frame: told once a frame however many changes there were, whatever made them (keys, the mouse, undo, a plugin or an agent). Handlers run as that client.
client
client: number
view
view: View
See View.
ViewFocused
Another view has a client’s focus. from had it before; nil when it was
closed. Handlers run as that client.
client
client: number
view
view: View
See View.
from
from: View?
See View.
moved
moved: boolean
The focus was moved under the client rather than by it: what it had focused went out of sight by another client’s doing (another tab or project shown, a pane closed), or it followed the others again. Its half-typed keys were dropped.
OptionChanged
An option was set, with greed.option.set or :set.
name
name: string
value
value: OptionValue
Its value now, as the client it was set for has it.
See OptionValue.
client
client: number?
The client it was set for, when one got a value of its own.
FileChanged
A file watched with greed.fs.watch was written, created or removed.
path
path: string
PluginLoaded
A plugin was loaded (or reloaded) and its entry file ran.
name
name: string
dir
dir: string?
Its folder, for plugins loaded from one.
PluginUnloaded
A plugin was unloaded, and everything it registered removed.
name
name: string
CommandRun
client
client: number
The client it runs for, which handlers run as.
name
name: string
The command about to run.
keys
keys: string?
The keys that ran it, when keys did, e.g. “g g”.
count
count: number?
The number typed before the keys.
KeysPending
client
client: number
The client typing them, which handlers run as.
keys
keys: string
The unfinished key sequence, e.g. “space”; “” once it’s finished.
StatusSegment
A piece of the status line: plain text, or text with a style.
text
text: string
style
style: string?
A style name, e.g. “ui.statusline.mode”, drawn over “ui.statusline”.
action
action: string?
A command a click on it runs.
StatusContext
What a status line function gets, for the main view.
view
view: View
See View.
buffer
buffer: Buffer
See Buffer.
mode
mode: string
message
message: string?
The latest message or error, if there is one to show.
width
width: number
The width of the screen in cells.
StatusParts
Segments for each side. The space between is padded; if the line is too long, the last segment on the left keeps only its end.
left
left: { StatusSegment }?
right
right: { StatusSegment }?
Clipboard
Copied text. Each copy holds one piece per selection it came from, so pasting into the same number of selections puts each piece back.
set
set: (pieces: string | { string }) -> ()
get
get: () -> { string }?
The latest copy.
history
history: () -> { { string } }
Recent copies, newest first.
image
image: () -> string?
The image on the system clipboard of the client acting now, as PNG bytes, read on that client’s own machine (so with greed ssh, your laptop’s); nil when there’s none or the client can’t read it. Waits like greed.sleep.
ClientInfo
A client attached to the editor: a terminal or window, on this machine or over greed ssh.
id
id: number
name
name: string
Its kind and machine, like “tui@laptop”; a client coming back with the same name gets its cursors, focus and mode back.
kind
kind: string
“tui”, “gui”, “headless” (the editor’s own, with nothing attached) or “test”.
remote
remote: boolean
Whether it came over greed ssh.
size
size: { width: number, height: number }?
Its screen in cells, once it has said.
layout
layout: "follow" | "independent"
“follow”: it shows the project, tab and panes the other followers do, with its own focus and zoom. “independent”: a layout of its own.
color
color: number
Which of the peer colors (1 to 6) its cursors show in for the other clients, as ui.cursor.peer.N.
person
person: string
Who it belongs to: “owner”, the session’s owner, for now.
Client
The clients you see the editor through. Commands, keys and event handlers act for one client at a time: the one that typed, clicked or ran them, or the one an event is about.
current
current: () -> ClientInfo
The client the running code acts for.
id
id: () -> number
The id of the client the running code acts for: current().id, without building the rest. For keeping what each client has open apart, like a picker of its own.
list
list: () -> { ClientInfo }
Every client, in the order they attached.
notify
notify: (title: string, body: string?) -> ()
Sends a notification to your desktop through the acting client: a terminal shows it with its notification escape (OSC 9, or OSC 777 in foot and urxvt) and a bell, while it isn’t focused. Without a client attached it goes nowhere.
set_layout
set_layout: (layout: "follow" | "independent", client: number?) -> boolean
Lays a client (the acting one by default) out on its own, “independent”, starting from a copy of the tabs, panes and panels it had, with views of its own; or has it “follow” the others again, closing those views (their buffers stay). Returns whether it changed.
Diagnostic
A problem a language server found.
from
from: number
to
to: number
severity
severity: number
1 error, 2 warning, 3 information, 4 hint.
message
message: string
source
source: string?
LspError
The error a language server answered a request with.
code
code: number
message
message: string
data
data: any?
LspPosition
A position as language servers count it.
line
line: number
character
character: number
Lsp
Language servers. A server runs per language and project root, started the first time a file that needs it is open, and started again if it stops.
server
server: (spec: { language: string, command: { string }?, commands: { { string } }?, root_markers: { string }? }) -> ()
Sets the server for a language, e.g.
{ language = "rust", command = { "rust-analyzer" }, root_markers = { "Cargo.toml" } }.
With commands, the first one whose program is installed runs, when
a file of the language first opens; with none installed, nothing does.
A server runs in the topmost folder with one of root_markers inside
the file’s project, or the project’s root without one.
remove
remove: (language: string) -> ()
Stops starting a server for a language; one running keeps running.
restart
restart: (language: string?) -> number
Stops the servers running for language (every language without one) and starts them again, as after they got stuck. Returns how many were running. Needs “proc”.
servers
servers: () -> { [string]: { { string } } }
The commands set for each language’s server, by language.
running
running: () -> { LspServer }
The servers running now, by language and then root.
root
root: (buffer: Buffer) -> string?
The folder the buffer’s server runs in, or would: nil without a file or a server set for its language.
request
request: (buffer: Buffer, method: string, params: any) -> (any, LspError?)
Sends a request to the buffer’s server and waits for the answer. Returns the result, or nil and the error; a server that stops before answering gives the error “the language server stopped”. Works in commands and event handlers. “workspace/executeCommand” needs “proc”, since a server’s commands can do anything.
uri
uri: (buffer: Buffer) -> string
The buffer’s file as a URI, for request parameters.
path
path: (uri: string) -> string?
The file path in a file:// URI.
position
position: (buffer: Buffer, pos: number) -> LspPosition
Byte offset pos as the buffer’s server counts positions.
offset
offset: (buffer: Buffer, position: LspPosition) -> number
The byte offset of a server position.
diagnostics
diagnostics: (buffer: Buffer) -> { Diagnostic }
The buffer’s latest diagnostics, where they are now: they move with
edits. They are marks in the buffer’s “diagnostics” namespace, with
{ severity, message, source } as their data.
problems
problems: () -> { LspProblem }
Every file’s latest problems, including files that aren’t open, with ranges as the server counts positions. Those in open files are where they are now.
capabilities
capabilities: (buffer: Buffer) -> any
What the buffer’s server said it can do (its ServerCapabilities),
or nil without a running server.
on_request
on_request: (method: string, handler: (params: any) -> any) -> ()
Answers requests of method from servers, e.g. “workspace/applyEdit”,
with what handler returns. It can wait, e.g. to ask you; the server gets the answer when it returns.
on_notification
on_notification: (method: string, handler: (params: any, language: string, root: string) -> ()) -> ()
Hears notifications of method from servers that the editor doesn’t deal with itself, e.g. “$/progress”, with the language and root of the server that sent it.
LspServer
A language server that’s running.
language
language: string
root
root: string
The folder it runs in.
command
command: { string }
ready
ready: boolean
Whether it has answered initialize.
stderr
stderr: { string }
The last lines it wrote to stderr.
LspProblem
uri
uri: string
range
range: { start: LspPosition, ["end"]: LspPosition }
severity
severity: number
message
message: string
source
source: string?
DiagnosticsChanged
buffer
buffer: Buffer
See Buffer.
ModeChanged
A client’s mode changed. Handlers run as that client.
client
client: number
from
from: string
to
to: string
DirEntry
name
name: string
dir
dir: boolean
FileInfo
kind
kind: "file" | "dir" | "other"
size
size: number
Size in bytes; 0 for a directory.
mode
mode: number
Its permission bits, like 420 (644 in octal, as string.format("%o", mode) shows).
modified
modified: number?
When it last changed, in seconds since 1970, where the system says.
Hash
SHA-256 digests as lowercase hex, for checking a download or telling whether some text changed.
sha256
sha256: (data: string) -> string
The digest of data.
sha256_file
sha256_file: (path: string) -> (string?, string?)
The digest of the file at path, read in pieces, or nil and why. Needs “fs.read”.
Fs
Reading and writing the file system. Failures return nil and a message.
list
list: (dir: string, opts: { hidden: boolean?, ignored: boolean? }?) -> ({ DirEntry }?, string?)
The entries directly in dir, folders first, then by name. Hidden
entries and ones .gitignore excludes are left out unless asked for.
read
read: (path: string, limit: number?) -> (string?, string?)
The file’s text, or its first limit bytes.
read_bytes
read_bytes: (path: string) -> (string?, string?)
The file’s bytes as they are, for a file that isn’t text, like an image.
stat
stat: (path: string) -> (FileInfo?, string?)
What’s at path; nil if nothing is, and nil and why when it can’t tell, as when a folder above it can’t be read.
write
write: (path: string, text: string, opts: { private: boolean? }?) -> (boolean?, string?)
Replaces the file’s contents with text, creating it and its folders
if needed. It’s written whole or not at all. With private, only you
can read it (mode 0600), and folders made for it are only yours.
mkdir
mkdir: (path: string) -> (boolean?, string?)
Makes the folder at path and any missing folders above it. Needs “fs.write”.
remove
remove: (path: string, opts: { recursive: boolean? }?) -> (boolean?, string?)
Removes the file, link or empty folder at path; with recursive, a folder and everything in it. Nothing being there counts as removed. It refuses (an error) the root, your home folder, a path with .. and a folder holding Greed’s approvals or secrets. Needs “fs.write”.
rename
rename: (from: string, to: string) -> (boolean?, string?)
Moves or renames from to to, replacing a file there. It refuses what remove does. Needs “fs.write”.
copy
copy: (from: string, to: string) -> (boolean?, string?)
Copies the file from to to, creating its folders. Needs “fs.read” and “fs.write”.
watch
watch: (path: string) -> ()
Watches the file at path: whenever it changes, from inside the
editor or out, plugins hear “file.changed”. It needn’t exist yet.
cwd
cwd: () -> string
The directory Greed was started in.
dirs
dirs: () -> { home: string?, config: string?, cache: string?, data: string?, brought: string? }
Your home folder, Greed’s config folder (where init.luau and plugins/ were read from), its cache folder, its data folder (where plugins made in the editor go when the config can’t be written) and, on the far end of greed ssh, the copy of your config it brought.
grep
grep: (
pattern: string,
dir: string?,
opts: { hidden: boolean?, ignored: boolean?, limit: number? }?
) -> ({ GrepLine }?, string?)
The lines matching the regex pattern in the text files under dir
(default: the current directory), sorted by path and line. It searches
in the background and waits like greed.sleep (commands, handlers, greed.spawn).
Hidden and ignored files are skipped unless asked for; limit
(default 10000) caps the lines returned. A bad pattern gives nil and
why.
GrepLine
A line greed.fs.grep found.
path
path: string
Relative to the directory searched.
line
line: number
0-based.
text
text: string
The line, without its line break.
matches
matches: { { from: number, to: number } }
Byte offsets of the matches in text.
PluginCheck
What greed.plugin.check found. types.skipped says why types weren’t
checked; tests.error why the tests couldn’t run.
types
types: { ok: boolean?, output: string?, skipped: string? }
tests
tests: { passed: number?, failed: { { file: string, name: string, message: string } }?, error: string? }
warnings
warnings: { string }
What looks wrong once it’s loaded with the others: a command it replaces from another plugin, keys bound to commands that don’t exist.
Plugins
list
list: () -> { string }
The names of the loaded plugins, sorted.
unload
unload: (name: string) -> ()
Removes a plugin and everything it registered: commands, keys, options and event handlers. Fails while another loaded plugin requires it. To turn off a default plugin, call this from your config.
load
load: (dir: string, name: string?) -> string
Loads (or reloads) the plugin in dir and returns its name. With
name, a folder without a plugin.toml loads too, with init.luau as
its entry.
dirs
dirs: () -> { [string]: string }
The folder of each plugin loaded from one, by name.
check
check: (dir: string) -> PluginCheck
Checks the plugin in dir without loading it: strict types against
Greed’s API (if luau-analyze is installed), then its tests with the
loaded plugins. Waits, like greed.sleep, while it runs. A plugin that
needs approving is tested with only what you approved for it, so what
needs more fails with “needs approval”, through the plugins it
calls and the commands it runs too.
describe
describe: (dir: string) -> PluginInfo
What the plugin in dir is and asks for, from its plugin.toml.
pending
pending: () -> { PluginInfo }
The plugins waiting until what they use is approved.
approve
approve: (dir: string) -> string
Approves what the plugin in dir declares, loads it, and loads the plugins that waited for it. Returns its name. Fails when a plugin without “plugins” started what runs: approving is yours to do.
caller
caller: () -> string?
The plugin whose code called yours: the innermost other plugin on the stack, or the one whose command, handler or task is running; nil if none but yours.
started_within
started_within: (capability: string) -> boolean
Whether everything that started the code running now may use capability: you (keys, the command line, your config), or plugins that have it. A vouch doesn’t hide what started it. For actions only you should take, like accepting a review.
within
within: <A..., R...>(name: string?, f: (A...) -> R..., A...) -> R...
Runs f with ... within the limit of the plugin name too, as if it had started it: for running what a plugin registered (a formatter, a runner, a source) later, from your plugin, so it can do no more than its plugin may. Config and unknown names add nothing. It can wait.
tie
tie: (remove: () -> ()) -> string?
For registries: runs remove when the plugin whose code called yours (see caller) is unloaded or reloaded, so what it added goes with it. Returns that plugin’s name, or nil (and does nothing) if none but yours called.
PluginInfo
A plugin, as greed.plugin.describe tells it, for a review.
name
name: string
dir
dir: string
requires
requires: { string }
capabilities
capabilities: { { name: string, what: string } }
What it declares, each with what it lets the plugin do in words.
missing
missing: { string }
The capabilities not approved yet; empty when it may load.
Style
How text looks. Colors are “red”, “bright-blue” and the other 16 terminal colors, “default”, or “#rrggbb”. Fields left out leave whatever is underneath, so styles layer.
fg
fg: string?
bg
bg: string?
underline
underline: (boolean | string)?
true, or “line”, “curl”, “dotted”, “dashed” or “double”.
underline_color
underline_color: string?
bold
bold: boolean?
italic
italic: boolean?
dim
dim: boolean?
reverse
reverse: boolean?
strikethrough
strikethrough: boolean?
rounded
rounded: boolean?
For floats in the window (ui.float, in its gui part): rounded corners and an outline instead of box lines, and a soft shadow.
shadow
shadow: boolean?
badge
badge: boolean?
For text in the window: its background as a badge, a box with rounded corners a little inside its cells, as motion hints have.
checkbox
checkbox: ("empty" | "checked" | "choice" | "chosen")?
In the window, drawn as a control over the cells of its text: a checkbox (“empty” or “checked”, for todos) or a choice (“choice” or “chosen”). Terminals show the text.
font
font: ("mono" | "prose")?
The window’s font for the text: “mono”, the grid’s (gui-font), or “prose”, a proportional one (gui-font-prose) fitted into the same cells. Terminals have only the one.
ThemeEntry
A theme entry: a style for every client, with changes for the terminal
(tui) or a graphical client (gui).
tui
tui: Style?
See Style.
gui
gui: Style?
See Style.
Syntax
The tree-sitter queries each language uses: “highlights” for highlighting,
“injections” for languages inside others (code blocks in Markdown), and
others (“textobjects”, …) that plugins read. The languages plugin sets them
from the queries/<language>/<kind>.scm files in plugins and your config.
set_query
set_query: (language: string, kind: string, source: string?) -> ()
Sets the kind query for language, or with nil takes this plugin’s away.
Errors if the language’s grammar can’t compile it. The newest one set is
used, and unloading a plugin takes its queries away.
query
query: (language: string, kind: string) -> string?
The kind query in use for language: the one set, or for “highlights”
and “injections” the one that comes with the grammar.
load_grammar
load_grammar: (language: string, path: string, symbol: string?) -> ()
Loads the grammar for language from a WebAssembly file, like one built
with tree-sitter build --wasm, so buffers in it get a syntax tree. symbol
is the grammar’s own name when it differs, e.g. “c_sharp” for “c-sharp”;
by default the language with “-” as “_”. Queries come separately.
Needs “fs.read”.
tags
tags: (dir: string?, opts: { limit: number? }?) -> { FileTags }
What the source files under dir (default: the current directory) define and use, from their syntax trees: the functions and types their “textobjects” query finds and how often each name appears, sorted by path. Hidden and ignored files are skipped; limit (default 10000) caps the files. It parses in the background and waits like greed.sleep. Needs “fs.read”.
FileTags
What one file defines and uses, from greed.syntax.tags.
path
path: string
Relative to the directory searched.
language
language: string
definitions
definitions: { { name: string, kind: "function" | "type", line: number, signature: string } }
Each with its 0-based line and its first line as signature.
references
references: { [string]: number }
How often each name appears in the file.
Theme
What style names look like. Everything on screen has one: “ui.text”, “ui.selection”, “ui.statusline.mode”, “ui.float.border”, “keyword”, “diagnostic.error”, or a name a plugin made up. Names fall back to their parent, so “markup.heading.1” uses “markup.heading” if it has no entry.
set
set: (entries: { [string]: ThemeEntry }) -> ()
Sets entries by name. Each changes only the fields it gives of the theme’s entry underneath, and replaces what was set for that name before.
base
base: (entries: { [string]: ThemeEntry }) -> ()
Replaces the base theme, the entries under those set with set: a
theme plugin calls it to switch themes without touching what your
config or other plugins set.
get
get: (name: string) -> ThemeEntry?
The entry for exactly name, if there is one.
EventName
The events greed.on and greed.off take; any other name is an error.
EventName =