rtk ast-grep: a directory named after a subcommand disables filtering for the whole implicit-run invocation

Open Beginner friendly
#4,162 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
84/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
rust
Domain
cli

Research direction

Start in src/cmds/system/ast_grep_cmd.rs, at filters_this_invocation and OTHER_SUBCOMMANDS, and reproduce the behavior with the ast-grep command shown in the issue. Check how the first positional is identified and adjust the filtering decision to match the stated scope. Done means an implicit run with a directory named test, scan, or new remains filtered while the lsp correctness guarantee is preserved.

Written by the indexing model from the issue text.

Description

area:cli bug filter-quality good first issue priority:medium

Pre-existing on develop (verified at 727ee6e6 with the binary built from it, rtk 0.48.0). Arrived in 1bd299b5 (#4121, merged). Surfaced while reviewing #4150, which is unrelated to it.

Summary

In the implicit-run form, filters_this_invocation disqualifies the whole invocation when any pre--- positional matches a subcommand name:

let identified_as_run = positionals.first() == Some(&"run");
if !identified_as_run && positionals.iter().any(|n| OTHER_SUBCOMMANDS.contains(n)) {
    return false;
}

A path argument spelled like a subcommand — test/, scan/, new/ — therefore turns off filtering for a plain pattern search. rtk ast-grep -p '…' src test passes 60 raw lines through where rtk ast-grep run -p '…' src test returns 13.

The trade-off is deliberate and the doc comment states it: reading lsp as a run would hand an editor a closed stdin, which is a correctness failure, while losing compression on a path spelled like a subcommand is not. This issue is about recovering the compression, not about reverting that order.

Reproduction

Needs ast-grep on PATH (verified with 0.45.3).

R=$(mktemp -d); cd "$R"
mkdir -p src test
for d in src test; do
  for i in $(seq 1 30); do printf 'fn f%02d() { println!("%s %d"); }\n' "$i" "$d" "$i"; done > $d/a.rs
done

ast-grep     -p 'println!($$$)' src test | wc -l   # 60  native
rtk ast-grep run -p 'println!($$$)' src test | wc -l   # 13  filtered
rtk ast-grep     -p 'println!($$$)' src test | wc -l   # 60  unfiltered
rtk ast-grep     -p 'println!($$$)' src      | wc -l   #  7  filtered again

Observed

The explicit-run form compresses:

test/a.rs:1:fn f01() { println!("test 1"); }
...
  … 25 more match line(s) in test/a.rs
src/a.rs:1:fn f01() { println!("src 1"); }
...
  … 25 more match line(s) in src/a.rs
[full output: ~/.cache/rtk/tee/…_ast-grep.log]

The implicit form, same search, emits all 60 lines. Dropping the test argument restores filtering (7 lines), which isolates the directory name as the trigger.

Expected

An invocation that is unambiguously run — the first positional is not a subcommand name — stays filtered regardless of what the remaining positionals are called.

Suggested direction

ast-grep's dispatch only ever reads the first positional as a subcommand; everything after it is a pattern or a path. Once the flag grammar is known well enough to locate the first positional reliably, the check can look at positionals.first() alone instead of .any(), which keeps the lsp/scan correctness guarantee and stops a directory name from costing the whole filter.

Source: src/cmds/system/ast_grep_cmd.rsfilters_this_invocation, OTHER_SUBCOMMANDS.

Scope note

The current OTHER_SUBCOMMANDS is ["scan", "test", "new", "lsp", "completions", "docs"]. Against ast-grep 0.45.3 the real list is run, scan, test, new, lsp, outline, completions, help — so docs is not a subcommand, and outline and help are missing. #4150 re-derives the table from the binary and corrects that. This issue is only about the .any() scope, which #4150 leaves as is.

Dominant language
Rust
Stars
81.1k
Forks
5.1k
Avg merge
4d 11h
Merged PRs (30d)
42

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from rtk-ai/rtk

All issues in rtk-ai/rtk

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.