Skip to content

Feature: use heading-style output for rtk grep #2175

@liulifox233

Description

@liulifox233

rg uses heading-style output by default when printing to a TTY:

$ rg -n "FilterLevel" src
src/core/filter.rs
8:pub enum FilterLevel {
14:impl FromStr for FilterLevel {
19:            "none" => Ok(FilterLevel::None),
20:            "minimal" => Ok(FilterLevel::Minimal),
21:            "aggressive" => Ok(FilterLevel::Aggressive),
27:impl std::fmt::Display for FilterLevel {
30:            FilterLevel::None => write!(f, "none"),
31:            FilterLevel::Minimal => write!(f, "minimal"),
32:            FilterLevel::Aggressive => write!(f, "aggressive"),
315:pub fn get_filter(level: FilterLevel) -> Box<dyn FilterStrategy> {
317:        FilterLevel::None => Box::new(NoFilter),
318:        FilterLevel::Minimal => Box::new(MinimalFilter),
319:        FilterLevel::Aggressive => Box::new(AggressiveFilter),
370:        assert_eq!(FilterLevel::from_str("none").unwrap(), FilterLevel::None);
372:            FilterLevel::from_str("minimal").unwrap(),
373:            FilterLevel::Minimal
376:            FilterLevel::from_str("aggressive").unwrap(),
377:            FilterLevel::Aggressive

src/main.rs
101:        level: core::filter::FilterLevel,

src/cmds/system/read.rs
3:use crate::core::filter::{self, FilterLevel, Language};
11:    level: FilterLevel,
84:    level: FilterLevel,
197:        run(file.path(), FilterLevel::Minimal, None, None, false, 0)?;

src/cmds/system/README.md
7:- `read.rs` uses `core/filter` for language-aware code stripping (FilterLevel: none/minimal/aggressive)

But in agent cli, commands are usually captured through non-TTY stdout. In that case, rg defaults to grep-like output instead:

$ rg -n "FilterLevel" src > output.txt
$ cat output.txt
src/main.rs:101:        level: core::filter::FilterLevel,
src/core/filter.rs:8:pub enum FilterLevel {
src/core/filter.rs:14:impl FromStr for FilterLevel {
src/core/filter.rs:19:            "none" => Ok(FilterLevel::None),
src/core/filter.rs:20:            "minimal" => Ok(FilterLevel::Minimal),
src/core/filter.rs:21:            "aggressive" => Ok(FilterLevel::Aggressive),
src/core/filter.rs:27:impl std::fmt::Display for FilterLevel {
src/core/filter.rs:30:            FilterLevel::None => write!(f, "none"),
src/core/filter.rs:31:            FilterLevel::Minimal => write!(f, "minimal"),
src/core/filter.rs:32:            FilterLevel::Aggressive => write!(f, "aggressive"),
src/core/filter.rs:315:pub fn get_filter(level: FilterLevel) -> Box<dyn FilterStrategy> {
src/core/filter.rs:317:        FilterLevel::None => Box::new(NoFilter),
src/core/filter.rs:318:        FilterLevel::Minimal => Box::new(MinimalFilter),
src/core/filter.rs:319:        FilterLevel::Aggressive => Box::new(AggressiveFilter),
src/core/filter.rs:370:        assert_eq!(FilterLevel::from_str("none").unwrap(), FilterLevel::None);
src/core/filter.rs:372:            FilterLevel::from_str("minimal").unwrap(),
src/core/filter.rs:373:            FilterLevel::Minimal
src/core/filter.rs:376:            FilterLevel::from_str("aggressive").unwrap(),
src/core/filter.rs:377:            FilterLevel::Aggressive
src/cmds/system/README.md:7:- `read.rs` uses `core/filter` for language-aware code stripping (FilterLevel: none/minimal/aggressive)
src/cmds/system/read.rs:3:use crate::core::filter::{self, FilterLevel, Language};
src/cmds/system/read.rs:11:    level: FilterLevel,
src/cmds/system/read.rs:84:    level: FilterLevel,
src/cmds/system/read.rs:197:        run(file.path(), FilterLevel::Minimal, None, None, false, 0)?;

Because of this, rtk grep ends up producing output similar to the non-TTY rg format:

$ rtk grep -n "FilterLevel" src
24 matches in 4 files:

src/cmds/system/README.md:7:...filter` for language-aware code stripping (FilterLevel: none/minimal/aggressive)
src/cmds/system/read.rs:3:use crate::core::filter::{self, FilterLevel, Language};
src/cmds/system/read.rs:11:level: FilterLevel,
src/cmds/system/read.rs:84:level: FilterLevel,
src/cmds/system/read.rs:197:run(file.path(), FilterLevel::Minimal, None, None, false, 0)?;
src/core/filter.rs:8:pub enum FilterLevel {
src/core/filter.rs:14:impl FromStr for FilterLevel {
src/core/filter.rs:19:"none" => Ok(FilterLevel::None),
src/core/filter.rs:20:"minimal" => Ok(FilterLevel::Minimal),
src/core/filter.rs:21:"aggressive" => Ok(FilterLevel::Aggressive),
src/core/filter.rs:27:impl std::fmt::Display for FilterLevel {
src/core/filter.rs:30:FilterLevel::None => write!(f, "none"),
src/core/filter.rs:31:FilterLevel::Minimal => write!(f, "minimal"),
src/core/filter.rs:32:FilterLevel::Aggressive => write!(f, "aggressive"),
src/core/filter.rs:315:pub fn get_filter(level: FilterLevel) -> Box<dyn FilterStrategy> {
src/core/filter.rs:317:FilterLevel::None => Box::new(NoFilter),
src/core/filter.rs:318:FilterLevel::Minimal => Box::new(MinimalFilter),
src/core/filter.rs:319:FilterLevel::Aggressive => Box::new(AggressiveFilter),
src/core/filter.rs:370:assert_eq!(FilterLevel::from_str("none").unwrap(), FilterLevel::None);
src/core/filter.rs:372:FilterLevel::from_str("minimal").unwrap(),
src/core/filter.rs:373:FilterLevel::Minimal
src/core/filter.rs:376:FilterLevel::from_str("aggressive").unwrap(),
src/core/filter.rs:377:FilterLevel::Aggressive
src/main.rs:101:level: core::filter::FilterLevel,

This repeats the file path for every match, even when many matches come from the same file. For agent output, this is
noticeably more verbose than rg's default TTY heading style.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions