diff options
Diffstat (limited to 'src/pardes.zig')
| -rw-r--r-- | src/pardes.zig | 51 |
1 files changed, 39 insertions, 12 deletions
diff --git a/src/pardes.zig b/src/pardes.zig index b8b2de33..61950562 100644 --- a/src/pardes.zig +++ b/src/pardes.zig @@ -8818,7 +8818,17 @@ pub const Pardes = struct { // a topbar word runs on the PRESS — there is no // drag to chord into, so the argument is simply // whatever is selected right now: select a word, - if (word.len > 0) _ = p.execute(p.active, p.withArg(word, p.heldSelection(p.active))); + // ...but only for a builtin that HAS somewhere to + // put one (see takesArg): a word left selected in + // some pane an hour ago is not an argument to + // Kill, and splicing it made a name that matches + // no builtin and therefore went to a shell. + const named = std.meta.stringToEnum(Builtin, word); + const held = if (named) |b| + (if (takesArg(b)) p.heldSelection(p.active) else null) + else + p.heldSelection(p.active); // not a builtin: an ordinary acme 2-1 + if (word.len > 0) _ = p.execute(p.active, p.withArg(word, held)); } return; } @@ -10998,17 +11008,7 @@ pub const Pardes = struct { const sp = std.mem.indexOfAny(u8, cmd, " \t"); const bi: ?Builtin = std.meta.stringToEnum(Builtin, cmd) orelse blk: { const head = std.meta.stringToEnum(Builtin, cmd[0 .. sp orelse break :blk null]) orelse break :blk null; - break :blk switch (head) { - .Restore, .Find, .Grep, .Rename, .WsSymbols, .Theme, .Look, .Exec => head, - // Font is a BRANCH and not another name in that prong for the - // reason output_pane.traits has the same shape: it is not in - // the enum at all off the gui, and a comptime-false `if` is - // the one form that is not analysed there. - else => { - if (platform == .gui) if (head == .Font) break :blk head; - break :blk null; - }, - }; + break :blk if (takesArg(head)) head else null; }; const b = bi orelse return false; p.exec_depth += 1; @@ -11018,6 +11018,33 @@ pub const Pardes = struct { return true; } + /// Which builtins match their name with a TAIL — `Restore <path>`, + /// `Grep <pat>`, `Theme <name>`, and the two verbs, `Look <word>` / + /// `Exec <cmd>`, which is what makes `` @`Look .` `` nest. Every other + /// name must match WHOLE, so `Kill foo` is a shell command and not Kill. + /// + /// Asked in two places and so written in one. The second asker is the + /// topbar's execute, and it is why this is a function: a topbar click runs + /// the word under it WITH whatever happens to be selected (select a word, + /// click Grep, it greps that word), and a builtin that takes no argument + /// was getting one anyway — `Kill` with a stale sweep somewhere became + /// `Kill <word>`, which is not Kill, so it fell through to the shell and + /// ran as a command nobody typed. A selection is only an argument to + /// something that has somewhere to put it. + fn takesArg(b: Builtin) bool { + switch (b) { + .Restore, .Find, .Grep, .Rename, .WsSymbols, .Theme, .Look, .Exec => return true, + // Font is a BRANCH and not another name in that prong for the + // reason output_pane.traits has the same shape: it is not in the + // enum at all off the gui, and a comptime-false `if` is the one + // form that is not analysed there. + else => { + if (platform == .gui) if (b == .Font) return true; + return false; + }, + } + } + fn applyStartupConfig(p: *Pardes) void { var lines = std.mem.splitScalar(u8, p.opts.startup_config orelse return, '\n'); while (lines.next()) |line| _ = p.executeBuiltinLine(p.active, line); |
