summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-29 06:22:15 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:16 -0300
commit7dfd8def3f3c24e288b4d0b18f9f0281637c12ba (patch)
treebabcbdf6effaf2b0fc1644d32ab4da9e591456e8
parent95631fe885388275e3d8d6d6619cfbcfd78ab6a5 (diff)
downloadpardes-7dfd8def3f3c24e288b4d0b18f9f0281637c12ba.tar.gz
pardes-7dfd8def3f3c24e288b4d0b18f9f0281637c12ba.zip
Every builtin says what it does in /commands, and a test holds each to it
87 of the listed words had no description: settings have no doc comment to read, so each now carries a one-sentence doc, and the builtins without one got theirs. Exit's no longer names an internal function, and Repl's first sentence is short enough to be read whole. Co-Authored-By: Claude Opus 5.5 <[email protected]>
-rw-r--r--src/builtins.zig69
-rw-r--r--src/config.zig86
-rw-r--r--src/ninep/ctl.zig29
3 files changed, 133 insertions, 51 deletions
diff --git a/src/builtins.zig b/src/builtins.zig
index 5818ff51..13f04859 100644
--- a/src/builtins.zig
+++ b/src/builtins.zig
@@ -431,6 +431,7 @@ comptime {
// ---- the two acme verbs ----
+/// Look at its argument: open the file or address it names, else find the word, as a right click does.
pub const Look = struct {
pub const takes_arg = true;
pub const requires_arg = true;
@@ -442,6 +443,7 @@ pub const Look = struct {
}
};
+/// Execute its argument as a middle click on it would, a builtin or a shell command.
pub const Exec = struct {
pub const takes_arg = true;
pub const requires_arg = true;
@@ -517,8 +519,9 @@ fn warnModifiedIn(c: Ctx, asking: Pane.Discarding, which: Asked) bool {
return modified;
}
-/// acme's Exit (editors/acme/exec.c:892): quit, once warnModified has
-/// nothing to say.
+/// Quit the editor, refusing once while a pane holds unsaved text: an Exit
+/// with nothing edited since discards it (acme's Exit, editors/acme/exec.c:892,
+/// asking warnModified first).
pub const Exit = struct {
pub const scope: Scope = .session;
pub fn run(c: Ctx) void {
@@ -580,6 +583,7 @@ pub const Kill = struct {
}
};
+/// Write the session's panes and layout to a dump file, for Restore.
pub const Dump = struct {
pub const scope: Scope = .session;
pub fn run(c: Ctx) void {
@@ -587,6 +591,7 @@ pub const Dump = struct {
}
};
+/// Replace every pane with those of a dump file, the last one Dump wrote when bare.
pub const Restore = struct {
pub const scope: Scope = .session;
pub const takes_arg = true;
@@ -622,6 +627,7 @@ pub const Restore = struct {
}
};
+/// Attach this terminal to a detached pardes session by name.
pub const Attach = struct {
pub const scope: Scope = .session;
pub const takes_arg = true;
@@ -637,6 +643,7 @@ pub const Attach = struct {
}
};
+/// Detach this pardes from its terminal, leaving the session running.
pub const Detach = struct {
pub const scope: Scope = .session;
pub const enabled = pardes.can_attach;
@@ -648,6 +655,7 @@ pub const Detach = struct {
}
};
+/// Mount another pardes's 9P tree under /n/<name>, given its dial address.
pub const Mount = struct {
pub const scope: Scope = .session;
pub const takes_arg = true;
@@ -663,6 +671,7 @@ pub const Mount = struct {
}
};
+/// Unmount the 9P tree mounted under /n/<name>.
pub const Unmount = struct {
pub const scope: Scope = .session;
pub const takes_arg = true;
@@ -679,6 +688,7 @@ pub const Unmount = struct {
// ---- the message row ----
+/// Show its argument on this pane's message row.
pub const Msg = struct {
pub const takes_arg = true;
pub const requires_arg = true;
@@ -691,6 +701,7 @@ pub const Msg = struct {
}
};
+/// Switch to the next bundled theme.
pub const NextColor = struct {
pub const scope: Scope = .session;
pub fn run(c: Ctx) void {
@@ -698,6 +709,7 @@ pub const NextColor = struct {
}
};
+/// List the themes in a pane, each a word to click.
pub const ThemeSel = struct {
pub const scope: Scope = .session;
pub const output: OutputTraits = .{ .name = config.themes_buffer, .steps = true, .commands = true };
@@ -706,6 +718,7 @@ pub const ThemeSel = struct {
}
};
+/// Load a theme from a file.
pub const ThemeFile = struct {
pub const scope: Scope = .session;
pub const takes_arg = true;
@@ -719,6 +732,7 @@ pub const ThemeFile = struct {
}
};
+/// Write the bundled themes into the config directory's themes, to edit.
pub const DumpThemes = struct {
pub const scope: Scope = .session;
pub const enabled = pardes.hosted;
@@ -733,6 +747,7 @@ pub const DumpThemes = struct {
}
};
+/// List the fonts in a pane, each a word to click.
pub const FontSel = struct {
pub const scope: Scope = .session;
pub const output: OutputTraits = .{ .name = config.fonts_buffer, .steps = true, .commands = true };
@@ -745,6 +760,7 @@ pub const FontSel = struct {
}
};
+/// Show the declarations enclosing the top row at the pane's head, on or off.
pub const TreeContext = struct {
pub const enabled = pardes.syntax.enabled;
pub const takes_arg = true;
@@ -769,6 +785,7 @@ pub const TreeContext = struct {
}
};
+/// Fit the PDF page to the pane by width or by height, flipping between them.
pub const PdfFit = struct {
pub const enabled = pardes.pdf_enabled;
pub fn run(c: Ctx) void {
@@ -779,6 +796,7 @@ pub const PdfFit = struct {
}
};
+/// Tint the PDF page to the theme, or show it as printed, flipping between them.
pub const PdfTint = struct {
pub const enabled = pardes.pdf_enabled;
pub fn run(c: Ctx) void {
@@ -789,6 +807,7 @@ pub const PdfTint = struct {
}
};
+/// List the PDF's sections in a pane, each a place to go.
pub const PdfSections = struct {
pub const output: OutputTraits = .{ .name = config.pdf_sections_buffer, .steps = true, .locations = true };
pub const enabled = pardes.pdf_enabled;
@@ -823,6 +842,7 @@ pub const Ascii = struct {
// ---- the system clipboard ----
+/// Copy the selection to the system clipboard.
pub const ClipYank = struct {
pub fn run(c: Ctx) void {
edit.clipYank(c.p, c.pane, false);
@@ -837,18 +857,21 @@ pub const ClipYankMain = struct {
}
};
+/// Paste the system clipboard after the selection.
pub const ClipPaste = struct {
pub fn run(c: Ctx) void {
edit.clipRequest(c.p, c.id, .after);
}
};
+/// Paste the system clipboard before the selection.
pub const ClipPasteBefore = struct {
pub fn run(c: Ctx) void {
edit.clipRequest(c.p, c.id, .before);
}
};
+/// Replace the selection with the system clipboard.
pub const ClipReplace = struct {
pub fn run(c: Ctx) void {
edit.clipRequest(c.p, c.id, .replace);
@@ -857,6 +880,7 @@ pub const ClipReplace = struct {
// ---- panes and columns ----
+/// Write the pane's text to its file, or to the file its argument names.
pub const Save = struct {
pub const takes_arg = true;
pub fn run(c: Ctx) void {
@@ -867,6 +891,7 @@ pub const Save = struct {
}
};
+/// Open an empty scratch pane, <dir>/+New, in this pane's directory.
pub const New = struct {
pub const output: OutputTraits = .{ .name = config.scratch_buffer, .doc = true, .saves = true };
pub fn run(c: Ctx) void {
@@ -923,6 +948,7 @@ pub const Del = struct {
}
};
+/// Recolour a terminal's program colours to the theme, or show them as sent, flipping between them.
pub const Filter = struct {
pub fn run(c: Ctx) void {
if (!c.pane.isTerminal()) return;
@@ -987,6 +1013,7 @@ pub const Undo = struct {
}
};
+/// Redo the last undone edit.
pub const Redo = struct {
pub fn run(c: Ctx) void {
if (c.pane.file) |f| if (f.history.redo_len == 0) return c.p.setMessage(c.id, "Redo: nothing to redo");
@@ -1001,6 +1028,7 @@ pub const Collapse = struct {
}
};
+/// Close this column and its panes, refusing once over unsaved text.
pub const Delcol = struct {
pub fn run(c: Ctx) void {
// The column of the tag it came from, else the pane's: a pane ctl's
@@ -1013,12 +1041,14 @@ pub const Delcol = struct {
}
};
+/// Close the pane, giving its rows to the pane above it.
pub const DelAbove = struct {
pub fn run(c: Ctx) void {
Del.run(.{ .p = c.p, .pane = c.pane, .id = c.id, .txt = c.txt, .arg = "k" });
}
};
+/// Close the pane, giving its rows to the pane below it.
pub const DelBelow = struct {
pub fn run(c: Ctx) void {
Del.run(.{ .p = c.p, .pane = c.pane, .id = c.id, .txt = c.txt, .arg = "j" });
@@ -1056,7 +1086,8 @@ pub const Tty9p = struct {
}
};
-/// Binds this terminal as a language's REPL, by the language's name as the
+/// Binds this terminal as a language's REPL, so an exec on that language's
+/// files is typed into it instead of run. The language is named as the
/// syntax table has it: an exec made on the body of a file in that
/// language -- a middle click, the execute key, a single word like `ls`
/// as much as a selection -- and one made on this terminal's own body, is
@@ -1142,6 +1173,7 @@ pub const Joincol = struct {
}
};
+/// Open the tutor, a document to work through.
pub const Tutor = struct {
pub const scope: Scope = .session;
pub fn run(c: Ctx) void {
@@ -1151,6 +1183,7 @@ pub const Tutor = struct {
}
};
+/// Open the help: every key and every builtin.
pub const Help = struct {
pub const scope: Scope = .session;
pub const output: OutputTraits = .{ .name = config.help_buffer };
@@ -1159,6 +1192,7 @@ pub const Help = struct {
}
};
+/// Open the settings in effect, each a word to click.
pub const Config = struct {
pub const scope: Scope = .session;
pub const output: OutputTraits = .{ .name = config.config_buffer };
@@ -1167,6 +1201,7 @@ pub const Config = struct {
}
};
+/// Set how location rows are drawn, or show how they are when bare.
pub const LocationsConfig = struct {
pub const scope: Scope = .session;
pub const takes_arg = true;
@@ -1197,6 +1232,7 @@ pub const LocationsConfig = struct {
}
};
+/// Open the messages shown so far.
pub const Messages = struct {
pub const scope: Scope = .session;
pub const output: OutputTraits = .{ .name = config.messages_buffer };
@@ -1215,6 +1251,7 @@ pub const Changelog = struct {
}
};
+/// Open the source of a panel transition or post shader, by name.
pub const EffectCode = struct {
pub const scope: Scope = .session;
pub const takes_arg = true;
@@ -1242,6 +1279,7 @@ pub const Pet = struct {
}
};
+/// Open a minimap of the file in braille dots.
pub const Mini = struct {
pub const takes_arg = true;
pub const output: OutputTraits = .{ .name = "Mini", .doc = true };
@@ -1254,6 +1292,7 @@ pub const Mini = struct {
// ---- search ----
+/// List every place a pattern matches in the pane, in a +Search.
pub const Find = struct {
pub const takes_arg = true;
pub const requires_arg = true;
@@ -1290,6 +1329,7 @@ pub const Grep = struct {
// nothing above it reaches its column's tag, then the workspace's, and Down
// comes back the same way. Left and Right walk the column tags.
+/// Move the keyboard to the pane, or column tag, to the left.
pub const Left = struct {
pub fn run(c: Ctx) void {
if (c.p.header_focus) {
@@ -1300,6 +1340,7 @@ pub const Left = struct {
}
};
+/// Move the keyboard to the pane below, off a tag onto the pane under it.
pub const Down = struct {
pub fn run(c: Ctx) void {
if (c.p.header_focus) {
@@ -1318,6 +1359,7 @@ pub const Down = struct {
}
};
+/// Move the keyboard to the pane above, and from a column's top pane to its tag.
pub const Up = struct {
pub fn run(c: Ctx) void {
if (c.p.header_focus) {
@@ -1331,6 +1373,7 @@ pub const Up = struct {
}
};
+/// Move the keyboard to the pane, or column tag, to the right.
pub const Right = struct {
pub fn run(c: Ctx) void {
if (c.p.header_focus) {
@@ -1359,6 +1402,7 @@ pub const Forward = struct {
}
};
+/// Go back to the last place jumped from in another pane.
pub const Last = struct {
pub fn run(c: Ctx) void {
var i = c.p.njumps;
@@ -1374,6 +1418,7 @@ pub const Last = struct {
}
};
+/// List the places jumped from, each a place to go.
pub const Jumplist = struct {
pub const scope: Scope = .session;
pub const output: OutputTraits = .{ .name = config.jumps_buffer, .steps = true, .locations = true };
@@ -1384,66 +1429,77 @@ pub const Jumplist = struct {
// ---- the language group ----
+/// Ask the language server about the symbol under the cursor.
pub const Hover = struct {
pub fn run(c: Ctx) void {
c.p.lspRequest(c.id, .hover, "");
}
};
+/// List the language server's code actions for the cursor.
pub const CodeAction = struct {
pub fn run(c: Ctx) void {
c.p.lspRequest(c.id, .code_action, "");
}
};
+/// Select every reference to the symbol under the cursor.
pub const SelectRefs = struct {
pub fn run(c: Ctx) void {
c.p.lspRequest(c.id, .select_refs, "");
}
};
+/// List the file's symbols from the language server.
pub const Symbols = struct {
pub fn run(c: Ctx) void {
c.p.lspRequest(c.id, .document_symbols, "");
}
};
+/// List the file's diagnostics from the language server.
pub const Diagnostics = struct {
pub fn run(c: Ctx) void {
c.p.lspRequest(c.id, .diagnostics, "");
}
};
+/// List the workspace's diagnostics from the language server.
pub const WsDiagnostics = struct {
pub fn run(c: Ctx) void {
c.p.lspRequest(c.id, .workspace_diagnostics, "");
}
};
+/// List the callers of the function under the cursor.
pub const Callers = struct {
pub fn run(c: Ctx) void {
c.p.lspRequest(c.id, .incoming_calls, "");
}
};
+/// List the functions the function under the cursor calls.
pub const Callees = struct {
pub fn run(c: Ctx) void {
c.p.lspRequest(c.id, .outgoing_calls, "");
}
};
+/// List the supertypes of the type under the cursor.
pub const Supertypes = struct {
pub fn run(c: Ctx) void {
c.p.lspRequest(c.id, .supertypes, "");
}
};
+/// List the subtypes of the type under the cursor.
pub const Subtypes = struct {
pub fn run(c: Ctx) void {
c.p.lspRequest(c.id, .subtypes, "");
}
};
+/// Rename the symbol under the cursor everywhere, to its argument.
pub const Rename = struct {
pub const takes_arg = true;
pub const requires_arg = true;
@@ -1454,6 +1510,7 @@ pub const Rename = struct {
}
};
+/// Search the workspace's symbols for its argument.
pub const WsSymbols = struct {
pub const takes_arg = true;
pub const requires_arg = true;
@@ -1464,18 +1521,21 @@ pub const WsSymbols = struct {
}
};
+/// Show which language servers serve this file and their state.
pub const Lspinfo = struct {
pub fn run(c: Ctx) void {
c.p.lspRequest(c.id, .status, "");
}
};
+/// Explain how the last language server request was answered, step by step.
pub const Lspwhy = struct {
pub fn run(c: Ctx) void {
c.p.lspRequest(c.id, .explain, "");
}
};
+/// Read the board memory at an address, into a pane.
pub const Peek = struct {
pub const scope: Scope = .session;
pub const takes_arg = true;
@@ -1490,6 +1550,7 @@ pub const Peek = struct {
}
};
+/// Write a value to the board memory at an address.
pub const Poke = struct {
pub const scope: Scope = .session;
pub const takes_arg = true;
@@ -1503,6 +1564,7 @@ pub const Poke = struct {
}
};
+/// Dump a range of the board memory in hex, into a pane.
pub const Hexdump = struct {
pub const scope: Scope = .session;
pub const takes_arg = true;
@@ -1517,6 +1579,7 @@ pub const Hexdump = struct {
}
};
+/// Read or set the board GPIO pins, into a pane.
pub const Gpio = struct {
pub const scope: Scope = .session;
pub const takes_arg = true;
diff --git a/src/config.zig b/src/config.zig
index b7662f1a..2fa6f89d 100644
--- a/src/config.zig
+++ b/src/config.zig
@@ -917,6 +917,8 @@ pub const Runtime = struct {
pub const Setting = struct {
word: []const u8,
action: Action,
+ /// What it does, one sentence: /commands lists it after the word.
+ doc: []const u8,
availability: ?Capability = null,
pub fn enabled(setting: Setting, capabilities: Capabilities) bool {
@@ -929,48 +931,48 @@ pub const Runtime = struct {
// The builtin registry and Config report share this command table.
pub const settings = [_]Setting{
- .{ .word = "Colors", .action = .{ .toggle = .colors } },
- .{ .word = "Wrap", .action = .{ .toggle = .wrap } },
- .{ .word = "TreeContextTagStyle", .action = .{ .toggle = .tree_context_tag_style } },
- .{ .word = "Tagbottom", .action = .{ .toggle = .tag_bottom } },
- .{ .word = "Debug", .action = .{ .toggle = .debug } },
- .{ .word = "FocusTint", .action = .{ .toggle = .focus_tint } },
- .{ .word = "SyntaxBold", .action = .{ .toggle = .syntax_bold } },
- .{ .word = "Verbose", .action = .{ .toggle = .verbose } },
- .{ .word = "MessageAnimation", .action = .{ .toggle = .message_animation } },
- .{ .word = "Ligatures", .action = .{ .toggle = .ligatures }, .availability = .ligatures },
- .{ .word = "CursorBlink", .action = .{ .toggle = .cursor_blink }, .availability = .lift },
- .{ .word = "Lift", .action = .lift, .availability = .lift },
- .{ .word = "Motion", .action = .motion },
- .{ .word = "InactiveDim", .action = .inactive_dim },
- .{ .word = "GripWidth", .action = .grip_width, .availability = .lift },
- .{ .word = "MessageLinger", .action = .{ .message_ms = .linger } },
- .{ .word = "MessageFall", .action = .{ .message_ms = .fall } },
- .{ .word = "MessageDissolve", .action = .{ .message_ms = .dissolve } },
- .{ .word = "DumpDir", .action = .dump_dir },
- .{ .word = "Theme", .action = .theme },
- .{ .word = "Shell", .action = .shell },
- .{ .word = "Font", .action = .font, .availability = .font_picker },
- .{ .word = "TaglineSize", .action = .tagline_size, .availability = .font_picker },
- .{ .word = "WindowOpacity", .action = .window_opacity, .availability = .window_opacity },
- .{ .word = "WindowBlur", .action = .window_blur, .availability = .window_blur },
- .{ .word = "PanelSlide", .action = .{ .transition = .slide }, .availability = .panel_transitions },
- .{ .word = "PanelZoom", .action = .{ .transition = .zoom }, .availability = .panel_transitions },
- .{ .word = "PanelDissolve", .action = .{ .transition = .dissolve }, .availability = .panel_transitions },
- .{ .word = "PanelAscii", .action = .{ .transition = .ascii }, .availability = .panel_transitions },
- .{ .word = "PanelVertical", .action = .{ .transition = .vertical }, .availability = .panel_transitions },
- .{ .word = "PanelEdges", .action = .{ .transition = .edges }, .availability = .panel_transitions },
- .{ .word = "PanelFall", .action = .{ .transition = .fall }, .availability = .panel_transitions },
- .{ .word = "PanelWave", .action = .{ .transition = .wave }, .availability = .panel_transitions },
- .{ .word = "PanelCurtain", .action = .{ .transition = .curtain }, .availability = .panel_transitions },
- .{ .word = "PanelScramble", .action = .{ .transition = .scramble }, .availability = .panel_transitions },
- .{ .word = "PanelType", .action = .{ .transition = .typewriter }, .availability = .panel_transitions },
- .{ .word = "Crt", .action = .{ .scene = .crt }, .availability = .scene_shaders },
- .{ .word = "Shader", .action = .shader, .availability = .scene_shaders },
- .{ .word = "ShaderAnimation", .action = .shader_animation, .availability = .scene_shaders },
- .{ .word = "Placement", .action = .{ .choice = .placement } },
- .{ .word = "BootShell", .action = .{ .choice = .boot_shell } },
- .{ .word = "LookWord", .action = .{ .choice = .look_word } },
+ .{ .word = "Colors", .action = .{ .toggle = .colors }, .doc = "Syntax colours in text panes, on or off." },
+ .{ .word = "Wrap", .action = .{ .toggle = .wrap }, .doc = "Long lines wrap onto the next row, on or off." },
+ .{ .word = "TreeContextTagStyle", .action = .{ .toggle = .tree_context_tag_style }, .doc = "A pane's TreeContext rows draw in the tag's style, on or off." },
+ .{ .word = "Tagbottom", .action = .{ .toggle = .tag_bottom }, .doc = "Each pane's tag goes at its foot rather than its head, on or off." },
+ .{ .word = "Debug", .action = .{ .toggle = .debug }, .doc = "A small box of frame statistics at the top right, on or off." },
+ .{ .word = "FocusTint", .action = .{ .toggle = .focus_tint }, .doc = "The focused pane's and column's tags are tinted, on or off." },
+ .{ .word = "SyntaxBold", .action = .{ .toggle = .syntax_bold }, .doc = "Keywords and the like are drawn bold, on or off." },
+ .{ .word = "Verbose", .action = .{ .toggle = .verbose }, .doc = "A builtin says its own name on the message row as it runs, on or off." },
+ .{ .word = "MessageAnimation", .action = .{ .toggle = .message_animation }, .doc = "A message falls into its row and dissolves out of it, on or off." },
+ .{ .word = "Ligatures", .action = .{ .toggle = .ligatures }, .availability = .ligatures, .doc = "A font's programming ligatures draw across their cells, on or off." },
+ .{ .word = "CursorBlink", .action = .{ .toggle = .cursor_blink }, .availability = .lift, .doc = "The cursor blinks, solid while typing, on or off." },
+ .{ .word = "Lift", .action = .lift, .availability = .lift, .doc = "How the focused pane stands off the page: off, shadow, rim or auto." },
+ .{ .word = "Motion", .action = .motion, .doc = "How animations move: off, crisp, smooth, bouncy or playful." },
+ .{ .word = "InactiveDim", .action = .inactive_dim, .doc = "Fade the unfocused panes' text by a percentage, 0 through 100, 0 off." },
+ .{ .word = "GripWidth", .action = .grip_width, .availability = .lift, .doc = "The grip and scrollbar width, as a percent of the theme's rail." },
+ .{ .word = "MessageLinger", .action = .{ .message_ms = .linger }, .doc = "How long, in milliseconds, a message stays after what dismisses it." },
+ .{ .word = "MessageFall", .action = .{ .message_ms = .fall }, .doc = "How long, in milliseconds, a message takes to fall into its row." },
+ .{ .word = "MessageDissolve", .action = .{ .message_ms = .dissolve }, .doc = "How long, in milliseconds, a message takes to dissolve." },
+ .{ .word = "DumpDir", .action = .dump_dir, .doc = "The directory Dump writes to and a relative Restore reads from; bare, the default." },
+ .{ .word = "Theme", .action = .theme, .doc = "Switch to the named theme." },
+ .{ .word = "Shell", .action = .shell, .doc = "The shell new terminals run; bare, the login shell." },
+ .{ .word = "Font", .action = .font, .availability = .font_picker, .doc = "The body font, by name or path, and its size." },
+ .{ .word = "TaglineSize", .action = .tagline_size, .availability = .font_picker, .doc = "Scale the tag font, a percentage." },
+ .{ .word = "WindowOpacity", .action = .window_opacity, .availability = .window_opacity, .doc = "The window's opacity, a percentage." },
+ .{ .word = "WindowBlur", .action = .window_blur, .availability = .window_blur, .doc = "The blur behind a translucent window, a radius." },
+ .{ .word = "PanelSlide", .action = .{ .transition = .slide }, .availability = .panel_transitions, .doc = "Panes slide in and out as they open and close, on or off." },
+ .{ .word = "PanelZoom", .action = .{ .transition = .zoom }, .availability = .panel_transitions, .doc = "Panes zoom in and out as they open and close, on or off." },
+ .{ .word = "PanelDissolve", .action = .{ .transition = .dissolve }, .availability = .panel_transitions, .doc = "Panes dissolve in and out as they open and close, on or off." },
+ .{ .word = "PanelAscii", .action = .{ .transition = .ascii }, .availability = .panel_transitions, .doc = "Panes open and close through a scatter of ASCII, on or off." },
+ .{ .word = "PanelVertical", .action = .{ .transition = .vertical }, .availability = .panel_transitions, .doc = "Panes open and close with a vertical wipe, on or off." },
+ .{ .word = "PanelEdges", .action = .{ .transition = .edges }, .availability = .panel_transitions, .doc = "Panes open and close from their edges, on or off." },
+ .{ .word = "PanelFall", .action = .{ .transition = .fall }, .availability = .panel_transitions, .doc = "Panes fall into place as they open, on or off." },
+ .{ .word = "PanelWave", .action = .{ .transition = .wave }, .availability = .panel_transitions, .doc = "Panes open and close in a wave, on or off." },
+ .{ .word = "PanelCurtain", .action = .{ .transition = .curtain }, .availability = .panel_transitions, .doc = "Panes open and close like a curtain, on or off." },
+ .{ .word = "PanelScramble", .action = .{ .transition = .scramble }, .availability = .panel_transitions, .doc = "Panes open and close through scrambled text, on or off." },
+ .{ .word = "PanelType", .action = .{ .transition = .typewriter }, .availability = .panel_transitions, .doc = "Panes type themselves in as they open, on or off." },
+ .{ .word = "Crt", .action = .{ .scene = .crt }, .availability = .scene_shaders, .doc = "The bundled CRT post pass over the window, on or off." },
+ .{ .word = "Shader", .action = .shader, .availability = .scene_shaders, .doc = "A Shadertoy file into the post chain, or out of it; off empties the chain." },
+ .{ .word = "ShaderAnimation", .action = .shader_animation, .availability = .scene_shaders, .doc = "When the post chain animates on its own: off, on (while focused) or always." },
+ .{ .word = "Placement", .action = .{ .choice = .placement }, .doc = "Where a new pane goes: acme, as makenewwindow does, or pardes, the older rules." },
+ .{ .word = "BootShell", .action = .{ .choice = .boot_shell }, .doc = "A document dropped where a lone untouched shell stands: keep the shell, or replace it." },
+ .{ .word = "LookWord", .action = .{ .choice = .look_word }, .doc = "A plain word looked at: search selects its next place in the pane, list lists every place in a +Search." },
};
pub fn find(name: []const u8) ?Setting {
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index bed53473..de63c6aa 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -636,9 +636,9 @@ fn writeCommands(w: *std.Io.Writer) !void {
var first = true;
while (parts.next()) |v| : (first = false) try w.print("{s}{s}", .{ if (first) "" else ",", v });
};
- // Then ` -- ` and what it does, when its source says.
+ // Then ` -- ` and what it does: a setting's doc, else its source's.
var summary_buf: [2048]u8 = undefined;
- const summary = summaryOf(@tagName(b), &summary_buf);
+ const summary = if (config.Runtime.find(@tagName(b))) |setting| setting.doc else summaryOf(@tagName(b), &summary_buf);
if (summary.len > 0) {
// The sentence whole unless it is long, then cut between words.
const kept = @import("../Messages.zig").clip(summary, 240);
@@ -1760,14 +1760,20 @@ test "a looked word is found in its own pane, next place after the dot, wrapping
try testing.expect(listed);
}
-test "each word's /commands description is its own doc comment's first sentence, no citation" {
+test "every word's /commands description is its own doc comment's first sentence, no citation" {
const p = try withFile(testing.allocator, "x\n");
defer p.deinit();
const listed = rd(p, @intFromEnum(tree.TopFile.commands), 0, 1 << 16).bytes;
for ([_][]const u8{
- "\nRepl arg pane -- Binds this terminal as a language's REPL",
+ "\nRepl arg pane -- Binds this terminal as a language's REPL, so an exec on that language's files is typed into it instead of run.\n",
"\nJoincol root -- Fold the active pane's column into the one on its right, keeping its panes.\n",
- "\nExit root -- acme's Exit: quit, once warnModified has nothing to say.\n",
+ "\nExit root -- Quit the editor, refusing once while a pane holds unsaved text: an Exit with nothing edited since discards it.\n",
+ "\nColors arg root on,off -- Syntax colours in text panes, on or off.\n",
+ // fs.md's examples, as they read.
+ "\nNewcol root -- An empty column right of the keyboard's, its tag taking the keyboard.\n",
+ "\nSave arg pane -- Write the pane's text to its file, or to the file its argument names.\n",
+ "\nVerbose arg root on,off -- A builtin says its own name on the message row as it runs, on or off.\n",
+ "\nPlacement arg root acme,pardes -- Where a new pane goes: acme, as makenewwindow does, or pardes, the older rules.\n",
"\nKill arg root -- acme's Kill: stop the commands pardes started",
}) |row| try testing.expect(std.mem.indexOf(u8, listed, row) != null);
try testing.expect(std.mem.indexOf(u8, listed, ".c:") == null);
@@ -1775,9 +1781,19 @@ test "each word's /commands description is its own doc comment's first sentence,
// above its word's declaration in builtins.zig.
const source = @embedFile("../builtins.zig");
var it = std.mem.tokenizeScalar(u8, listed, '\n');
+ var undescribed: usize = 0;
while (it.next()) |line| {
- const dashes = std.mem.indexOf(u8, line, " -- ") orelse continue;
+ // Every builtin has one: a word nobody can look up is no use.
+ const dashes = std.mem.indexOf(u8, line, " -- ") orelse {
+ std.debug.print("no doc comment: {s}\n", .{line});
+ undescribed += 1;
+ continue;
+ };
const word = line[0 .. std.mem.indexOfScalar(u8, line, ' ').?];
+ if (config.Runtime.find(word)) |setting| {
+ try testing.expect(std.mem.endsWith(u8, line, setting.doc));
+ continue;
+ }
var needle: [64]u8 = undefined;
const at = std.mem.indexOf(u8, source, try std.fmt.bufPrint(&needle, "\npub const {s} = struct", .{word})).?;
const said = std.mem.trimEnd(u8, line[dashes + 4 ..], "…");
@@ -1786,6 +1802,7 @@ test "each word's /commands description is its own doc comment's first sentence,
const block_start = std.mem.lastIndexOf(u8, source[0..at], "\n\n") orelse 0;
try testing.expect(std.mem.indexOf(u8, source[block_start..at], head) != null);
}
+ try testing.expectEqual(0, undescribed);
}
test "Newcol at the column cap fails the write and says the cap" {