Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions docs/contributing/TECHNICAL.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,10 @@ rewrite_compound(cmd, excluded) [src/discover/registry.rs]
|
| Step 2 — Split on operators, rewrite each segment
| Operator (&&, ||, ;) → rewrite both sides
| Pipe (|) → keep producers/intermediate stages raw
| rewrite only a pipeline-safe final stage
| Pipe (|) → keep intermediate stages raw
| rewrite a pipeline-safe final stage, or the
| producer when its rule allows it and all
| consumers are display-only (#3171)
| Stderr pipe (|&) → keep the complete pipeline raw
| Shellism (&) → rewrite both sides (background)
|
Expand Down
2 changes: 1 addition & 1 deletion src/discover/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ When a hook sends `cargo fmt --all && cargo test 2>&1 | tail -20`:
→ [Arg("cargo"), Arg("test"), Redirect("2>&1"), Operator("&&"), Arg("git"), Arg("status")]
```

**Compound splitting** — The rewrite engine walks the tokens, splitting on `Operator` (`&&`, `||`, `;`) and typed `Pipe` tokens (`|`, `|&`). For normal pipelines, producers and intermediate stages stay raw, and only an argument-safe final stage marked `pipeline_final_safe` is rewritten. The initial safe set is ordinary `grep` and `rg` invocations; search pattern-file forms (`-f`/`--file`) defer because they can consume pipeline stdin as configuration. Stderr pipelines (`|&`) and pipelines containing opaque shell groups remain raw.
**Compound splitting** — The rewrite engine walks the tokens, splitting on `Operator` (`&&`, `||`, `;`) and typed `Pipe` tokens (`|`, `|&`). For normal pipelines, intermediate stages stay raw. A final stage whose rule's `pipeline_safety` allows it (ordinary `grep` and `rg` invocations) is rewritten; search pattern-file forms (`-f`/`--file`) defer because they can consume pipeline stdin as configuration. The producer stage is rewritten when its rule's `pipeline_safety` allows it and every downstream stage is a display-only consumer (`cat`, `head`, non-following `tail`) with no file-target redirect (#3171). Stderr pipelines (`|&`) and pipelines containing opaque shell groups remain raw.

**Per-segment rewriting** — Each segment goes through:

Expand Down
2 changes: 1 addition & 1 deletion src/discover/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ fn contains_substitution(cmd: &str) -> bool {

// `>&N`/`>&-` (and `N>&M`) is fd-dup/close; bare `>&` before a word is
// `>word 2>&1` — a file target.
fn redirect_has_file_target(tokens: &[ParsedToken], i: usize) -> bool {
pub(crate) fn redirect_has_file_target(tokens: &[ParsedToken], i: usize) -> bool {
let value = &tokens[i].value;
if let Some(pos) = value.find(">&") {
let tail = &value[pos + 2..];
Expand Down
Loading
Loading