summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-08-05 18:46:42 -0300
committerGabriel Schneider <[email protected]>2026-08-10 09:17:07 -0300
commit30a44a55232b829866bc3554647de21929276d1a (patch)
tree52d59a2e5ac6b4947a0e33845540aa494d7866a0 /src
parent4ecf494b3af0ec8d8212dd9614b7e7d329a2251f (diff)
downloadpardes-30a44a55232b829866bc3554647de21929276d1a.tar.gz
pardes-30a44a55232b829866bc3554647de21929276d1a.zip
topbar execute: a selection is only an argument to a builtin that takes one
Diffstat (limited to 'src')
-rw-r--r--src/pardes.zig51
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);