diff options
Diffstat (limited to 'src/builtins.zig')
| -rw-r--r-- | src/builtins.zig | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/src/builtins.zig b/src/builtins.zig index 4d257a9e..edeb7ac8 100644 --- a/src/builtins.zig +++ b/src/builtins.zig @@ -38,6 +38,29 @@ pub const capabilities: config.Runtime.Capabilities = .{ /// ctl; pardes's root `ctl` takes the session builtins and a pane's `ctl` /// the pane ones. A builtin says `pub const scope: Scope = .session;`, /// and every setting is one; the rest act on their pane. +/// The kinds of pane a builtin may be for alone (registry.needs). +pub const PaneKind = enum { + terminal, + pdf, + image, + + pub fn has(kind: PaneKind, pane: *const panes.Pane) bool { + return switch (kind) { + .terminal => pane.isTerminal(), + .pdf => pane.hasPdf(), + .image => pane.image != null, + }; + } + + pub fn noun(kind: PaneKind) []const u8 { + return switch (kind) { + .terminal => "a terminal", + .pdf => "a PDF", + .image => "an image", + }; + } +}; + pub const Scope = enum { pane, session }; pub const Ctx = struct { @@ -181,6 +204,15 @@ pub const registry = struct { /// `Msg`, a setting's value), or would ask for it at a prompt (`Find`): /// a ctl refuses it bare before any line of the write runs. A builtin /// says `pub const requires_arg = true;` beside `takes_arg`. + /// The one kind of pane a builtin means something on, or null for any: + /// it says `pub const needs: PaneKind = .terminal;`, and on any other + /// pane it is refused (exec.runBuiltinFrom), as Repl and Edit are. + pub fn needs(b: Builtin()) ?PaneKind { + inline for (manualBuiltinList(), 0..) |T, i| + if (@intFromEnum(b) == i) return if (@hasDecl(T, "needs")) T.needs else null; + return null; + } + pub fn requiresArg(b: Builtin()) bool { inline for (manualBuiltinList(), 0..) |T, i| if (@intFromEnum(b) == i) return @hasDecl(T, "requires_arg") and T.requires_arg; @@ -869,7 +901,7 @@ pub const TreeContext = struct { pub fn run(c: Ctx) void { if (comptime !enabled) unreachable; - if (!panes.File.supportsContext(c.pane)) return; + if (!panes.File.supportsContext(c.pane)) return c.p.reportFailure(c.id, "TreeContext: only a source file the parser knows has context"); const file = &c.pane.file.?; const arg = std.mem.trim(u8, c.arg orelse "", " \t\r\n"); const on = if (arg.len == 0) !file.tree_context else if (std.mem.eql(u8, arg, "on")) true else if (std.mem.eql(u8, arg, "off")) false else { @@ -889,6 +921,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 needs: PaneKind = .pdf; pub const enabled = pardes.pdf_enabled; pub fn run(c: Ctx) void { if (comptime enabled) apply(c) else unreachable; @@ -900,6 +933,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 needs: PaneKind = .pdf; pub const enabled = pardes.pdf_enabled; pub fn run(c: Ctx) void { if (comptime enabled) apply(c) else unreachable; @@ -911,6 +945,7 @@ pub const PdfTint = struct { /// List the PDF's sections in a pane, each a place to go. pub const PdfSections = struct { + pub const needs: PaneKind = .pdf; pub const output: OutputTraits = .{ .name = config.pdf_sections_buffer, .steps = true, .locations = true }; pub const enabled = pardes.pdf_enabled; pub fn run(c: Ctx) void { @@ -923,6 +958,7 @@ pub const PdfSections = struct { /// glyph art over the host's pixels pub const Petscii = struct { + pub const needs: PaneKind = .image; pub fn run(c: Ctx) void { if (c.pane.image) |*state| panes.Image.toggleGlyphArt(state); } @@ -930,6 +966,7 @@ pub const Petscii = struct { /// the C64 palette or the terminal's own 16 pub const Palette = struct { + pub const needs: PaneKind = .image; pub fn run(c: Ctx) void { if (c.pane.image) |*state| panes.Image.togglePalette(state); } @@ -937,6 +974,7 @@ pub const Palette = struct { /// add the printable ASCII bitmaps to the matcher's glyph set pub const Ascii = struct { + pub const needs: PaneKind = .image; pub fn run(c: Ctx) void { if (c.pane.image) |*state| panes.Image.toggleAscii(state); } @@ -1057,8 +1095,8 @@ 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 const needs: PaneKind = .terminal; pub fn run(c: Ctx) void { - if (!c.pane.isTerminal()) return; c.pane.tty_filter = !c.pane.tty_filter; } }; @@ -1066,12 +1104,14 @@ pub const Filter = struct { /// Cycle the pane's input modes: terminals add raw tty mode to normal/insert. pub const Mode = struct { pub fn run(c: Ctx) void { + if (c.pane.file == null and !c.pane.isTerminal()) return c.p.reportFailure(c.id, "Mode: only a text or terminal pane has modes"); c.p.cycleMode(c.id); } }; /// Switch this terminal between raw program input and normal editor mode. pub const Togglettymode = struct { + pub const needs: PaneKind = .terminal; pub fn run(c: Ctx) void { c.p.toggleTty(c.id); } |
