diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-03 16:28:12 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-09-03 16:28:12 -0300 |
| commit | 8f34d29cb7b480545d25c68a8a6146deefdf0523 (patch) | |
| tree | 89f6ae799dd43cff78fe58194583b700c313b95c /src/normal_input.zig | |
| parent | 0d0691b7bad87763d2e0ad1a0ae90f5e3591c663 (diff) | |
| download | pardes-8f34d29cb7b480545d25c68a8a6146deefdf0523.tar.gz pardes-8f34d29cb7b480545d25c68a8a6146deefdf0523.zip | |
pipe: helix's other three shell commands, and its newline rule
`|` was the only one of helix's five. The other four differ in exactly two
things — whether the selection is stdin, and where the output lands — so they
are one action carrying a `PipeBehavior` rather than four code paths:
| stdin is the selection, output REPLACES it (had this)
A-| stdin is the selection, output discarded shell_pipe_to
! no stdin, output inserted BEFORE each selection shell_insert_output
A-! no stdin, output appended AFTER each selection shell_append_output
Each arms the same visible tag-tail prompt with its own marker (`|`, `|-`, `!`,
`!+`) so the prompt says which one you are in — they take the same command line
and do very different things to the buffer.
Two helix rules came with them. A behaviour that sends no stdin runs the
command ONCE and every cursor gets that one answer (helix's `shell_output`
cache): ten cursors and `date` give ten identical stamps rather than ten forks
racing to produce one. And a command that put a trailing newline on a selection
which did not have one has it taken back off — that is what keeps a one-line
`| tr a-z A-Z` from becoming two lines. The existing multi-range test moved
with that rule and now pins it deliberately.
In all three writing behaviours the OUTPUT is what ends up selected, keeping
the original range's direction, so an operator can follow straight on from what
the command just produced.
`$` (`shell_keep_pipe` — drop the selections whose command exited nonzero) is
still missing: it needs a per-selection verdict and the runner's answer is
atomic. Noted in docs/helix-keys.md beside the `$` divergence already there.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_016Q4RATpafkwahrovHQLKRf
Diffstat (limited to 'src/normal_input.zig')
| -rw-r--r-- | src/normal_input.zig | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/src/normal_input.zig b/src/normal_input.zig index 4b047a7f..5fa29bea 100644 --- a/src/normal_input.zig +++ b/src/normal_input.zig @@ -125,6 +125,9 @@ pub const Role = enum { leader, command_line, pipe_selection, + pipe_selection_to, + insert_output, + append_output, search, search_next, search_prev, @@ -180,6 +183,27 @@ pub const State = struct { } }; +/// WHERE a filter's output goes, and whether the selection is its stdin. +/// helix's `|`, `A-|`, `!` and `A-!` in one word each (commands.rs +/// `ShellBehavior`); its `$` (keep selections by exit status) is not here yet +/// because it needs a per-selection verdict rather than one atomic answer. +pub const PipeBehavior = enum { + /// `|` — stdin is the selection, and the output REPLACES it. + replace, + /// `A-|` — stdin is the selection, and the output is discarded. The text + /// is not touched at all; the point is the command's side effect. + ignore, + /// `!` — no stdin, and the output is inserted BEFORE each selection. + insert, + /// `A-!` — no stdin, and the output is appended AFTER each selection. + append, + + /// Do the selections become stdin? helix's `pipe` flag. + pub fn pipes(b: PipeBehavior) bool { + return b == .replace or b == .ignore; + } +}; + pub const Scope = enum { once, per_selection }; pub const Direction = enum { backward, forward }; pub const Motion = enum { @@ -286,7 +310,10 @@ pub const Action = union(enum) { adjust_number: i64, leader, command_line, - pipe_selection, + /// helix's five shell commands are one action with a behaviour, because + /// they differ only in where the output lands and whether the selection is + /// stdin. See `PipeBehavior`. + pipe_selection: PipeBehavior, search, search_step: Direction, @@ -548,7 +575,10 @@ pub fn parse(state: *State, key: Input) Result { if (key.has(.leader)) return resultAction(.leader); if (key.has(.command_line)) return resultAction(.command_line); - if (key.has(.pipe_selection)) return resultAction(.pipe_selection); + if (key.has(.pipe_selection)) return resultAction(.{ .pipe_selection = .replace }); + if (key.has(.pipe_selection_to)) return resultAction(.{ .pipe_selection = .ignore }); + if (key.has(.insert_output)) return resultAction(.{ .pipe_selection = .insert }); + if (key.has(.append_output)) return resultAction(.{ .pipe_selection = .append }); if (key.has(.search)) return resultAction(.search); if (key.has(.search_next)) return resultAction(.{ .search_step = .forward }); if (key.has(.search_prev)) return resultAction(.{ .search_step = .backward }); |
