## treegrep
treegrep is a regex pattern matcher that displays results in a tree structure with an interface to jump to matched text.
[](https://github.com/4imothy/treegrep/actions)
[](https://github.com/4imothy/treegrep/actions)
[introduction video](https://youtu.be/lRMwCE6Zwuw?si=m9SRypN6_NxgW6K4)
[examples](#examples), [editor integrations](#editor-integrations), and [help](#--help).
### links
[crates.io](https://crates.io/crates/treegrep) | [GitHub](https://github.com/4imothy/treegrep) | [AUR](https://aur.archlinux.org/packages/treegrep-bin) | [NetBSD](https://pkgsrc.se/sysutils/treegrep)
### installation
- **cargo:** ```cargo install treegrep```
- **releases:** Download from [releases](https://github.com/4imothy/treegrep/releases/)
- **manual:**
```
git clone https://github.com/4imothy/treegrep
cd treegrep
cargo build --release
```
### editor integrations
neovim
- sample installation using [lazy.nvim](https://github.com/folke/lazy.nvim)
```lua
return {
'4imothy/treegrep',
build = function()
require('treegrep').build_tgrep()
end,
config = function()
require('treegrep').setup({
selection_file = '/tmp/tgrep-select',
repeat_file = '/tmp/tgrep-repeat',
})
vim.keymap.set('n', 'tt', function() require('treegrep').tgrep_with('--menu') end)
vim.keymap.set('n', 'tr', function() require('treegrep').tgrep_with('--repeat') end)
vim.keymap.set('n', 'tf', function() require('treegrep').tgrep_with('--files --select') end)
end,
}
```
helix
- sample keybind to run treegrep and open selection
```toml
C-t = [
':sh rm -f /tmp/tgrep-select',
':insert-output tgrep --menu --selection-file=/tmp/tgrep-select --repeat-file=/tmp/tgrep-repeat > /dev/tty',
':open %sh{ f=$(sed -n 1p /tmp/tgrep-select); l=$(sed -n 2p /tmp/tgrep-select); [ -n "$l" ] && echo "$f:$l" || echo "$f"; }',
':redraw',
':set mouse false',
':set mouse true',
]
```
vim
- sample installation using [vim-plug](https://github.com/junegunn/vim-plug)
```vim
Plug '4imothy/treegrep', {'do': {-> TgrepBuild()}}
let g:tgrep_selection_file = '/tmp/tgrep-select'
let g:tgrep_repeat_file = '/tmp/tgrep-repeat'
nnoremap tt :call TgrepWith('--menu')
nnoremap tr :call TgrepWith('--repeat')
nnoremap tf :call TgrepWith('--files --select')
```
### examples
tgrep --regexp \bstruct\s+\w+ --regexp \bimpl\s+\w+ --path src --line-number --count
```
src: 10
├──term.rs: 1
│ └──15: pub struct Term<'a> {
├──matcher.rs: 3
│ ├──18: struct Matcher {
│ ├──23: impl Matcher {
│ └──42: struct MatchSink<'a> {
├──match_system.rs: 8
│ ├──23: pub struct Directory {
│ ├──30: impl Directory {
│ ├──41: pub struct File {
│ ├──47: impl File {
│ ├──73: pub struct Match {
│ ├──79: impl Match {
│ ├──104: pub struct Line {
│ └──110: impl Line {
├──style.rs: 2
│ ├──22: pub struct Chars {
│ └──99: pub struct DisplayRepeater(T, usize);
├──config.rs: 5
│ ├──15: pub struct Characters {
│ ├──29: pub struct Colors {
│ ├──40: impl args::Color {
│ ├──58: pub struct Config {
│ └──169: impl Config {
├──errors.rs: 4
│ ├──14: pub struct Message {
│ ├──17: impl Error for Message {}
│ ├──34: impl fmt::Debug for Message {
│ └──40: impl fmt::Display for Message {
├──select_menu.rs: 5
│ ├──33: impl OpenStrategy {
│ ├──45: pub struct SelectMenu<'a, 'b> {
│ ├──60: struct Window {
│ ├──65: impl Window {
│ └──86: impl JumpLocation {
├──args_menu.rs: 1
│ └──21: pub struct ArgsMenu<'a, 'b> {
├──args.rs: 6
│ ├──18: pub struct ArgInfo {
│ ├──24: impl ArgInfo {
│ ├──39: impl ValueEnum for OpenStrategy {
│ ├──88: impl ValueEnum for CharacterStyle {
│ ├──120: struct ColorParser;
│ └──122: impl clap::builder::TypedValueParser for ColorParser {
└──writer.rs: 9
├──26: pub struct OpenInfo<'a> {
├──37: struct PathDisplay<'a> {
├──150: struct LineDisplay<'a> {
├──262: struct LongBranchDisplay<'a> {
├──303: struct OverviewDisplay {
├──311: impl Entry for OverviewDisplay {
├──323: impl Display for OverviewDisplay {
├──371: impl Directory {
└──456: impl File {
```
tgrep Print src/select_menu.rs --trim --line-number --char-style=ascii
```
select_menu.rs
+--8: style::{Print, SetBackgroundColor},
+--344: queue!(self.term, cursor::MoveTo(START_X, cursor), Print(line))?;
+--365: queue!(self.term, scroll, cursor::MoveTo(START_X, y), Print(line))?;
+--590: Print(style::style_with(config().chars.selected_indicator, c)),
+--594: queue!(self.term, Print(config().chars.selected_indicator),)?;
+--599: Print(&self.lines[self.selected_id])
+--607: Print(style::SELECTED_INDICATOR_CLEAR),
+--609: Print(&self.lines[self.selected_id])
+--623: Print(format!(
+--635: Print(format!(
+--648: Print(format!(
```
tgrep --files --hidden --glob=!.git
```
treegrep
├──doc
│ ├──treegrep.nvim.txt
│ └──treegrep.vim9.txt
├──src
│ ├──match_system.rs
│ ├──style.rs
│ ├──matcher.rs
│ ├──config.rs
│ ├──writer.rs
│ ├──main.rs
│ ├──term.rs
│ ├──select_menu.rs
│ ├──args_menu.rs
│ ├──args.rs
│ ├──log.rs
│ └──errors.rs
├──.github
│ └──workflows
│ ├──update_readme.yml
│ ├──update_readme
│ ├──cr.yml
│ └──test.yml
├──plugin
│ └──treegrep.vim
├──benchmarks
│ ├──runner
│ └──times
├──lua
│ └──treegrep.lua
├──tests
│ ├──pool
│ │ └──alice_adventures_in_wonderland_by_lewis_carroll.txt
│ ├──targets
│ │ ├──wide_1
│ │ ├──links_3
│ │ ├──files_long_branch_2
│ │ ├──glob_exclusion
│ │ ├──wide_2
│ │ ├──colon
│ │ ├──overlapping
│ │ ├──files_long_branch_expr_count_2
│ │ ├──max_depth
│ │ ├──files_1
│ │ ├──files_long_branch_expr_2
│ │ ├──files_long_branch_1
│ │ ├──glob_inclusion
│ │ ├──files_with_expr
│ │ ├──deep
│ │ ├──files_long_branch_expr_count_1
│ │ ├──links_4
│ │ ├──count
│ │ ├──links_2
│ │ ├──links_1
│ │ ├──files_2
│ │ ├──no_matches
│ │ ├──file
│ │ ├──line_number
│ │ └──files_long_branch_expr_1
│ ├──utils.rs
│ ├──tests.rs
│ └──file_system.rs
├──Cargo.toml
├──README.md
├──.gitignore
├──Cargo.lock
├──rustfmt.toml
├──todos.md
└──LICENSE
```
tgrep --files --long-branch --hidden --glob=!.git
```
treegrep
├──src
│ ├──match_system.rs, style.rs, matcher.rs, config.rs, writer.rs
│ ├──main.rs, term.rs, select_menu.rs, args_menu.rs, args.rs
│ └──log.rs, errors.rs
├──plugin
│ └──treegrep.vim
├──tests
│ ├──pool
│ │ └──alice_adventures_in_wonderland_by_lewis_carroll.txt
│ ├──targets
│ │ ├──links_3, files_long_branch_2, glob_exclusion, wide_2, colon
│ │ ├──overlapping, files_long_branch_expr_count_2, max_depth, files_1, files_long_branch_expr_2
│ │ ├──files_long_branch_1, glob_inclusion, files_with_expr, deep, files_long_branch_expr_count_1
│ │ ├──links_4, count, links_2, links_1, files_2
│ │ └──no_matches, file, line_number, files_long_branch_expr_1, wide_1
│ └──file_system.rs, utils.rs, tests.rs
├──lua
│ └──treegrep.lua
├──.github
│ └──workflows
│ └──update_readme.yml, update_readme, cr.yml, test.yml
├──benchmarks
│ └──runner, times
├──doc
│ └──treegrep.nvim.txt, treegrep.vim9.txt
├──Cargo.toml, rustfmt.toml, todos.md, README.md, .gitignore
└──Cargo.lock, LICENSE
```
### *--help*
```
treegrep 1.3.0
by Timothy Cronin
home page: https://github.com/4imothy/treegrep
regex pattern matcher that displays results in a tree structure with an interface to jump to matched text
tgrep [OPTIONS] [positional regexp] [positional target]
Arguments:
[positional regexp] a regex expression to search for
[positional target] the path to search, if not provided, search the current directory
Options:
-e, --regexp <> a regex expression to search for
-p, --path <> the path to search, if not provided, search the current directory
--menu provide arguments and select results through an interface
-s, --select results are shown in a selection interface for opening
--glob <> rules match .gitignore globs, but ! has inverted meaning, overrides other ignore logic
-f, --files if an expression is given, hide matched content, otherwise, show the files that would be searched
-., --hidden search hidden files
-n, --line-number show line number of match
--links search linked paths
--no-ignore don't use ignore files
-c, --count display number of files matched in directory and number of lines matched in a file
--no-color don't use colors
--no-bold don't bold anything
--overview conclude results with an overview
--max-depth <> the max depth to search
--prefix-len <> number of characters to show before a match [default: 3]
--max-length <> set the max length for a matched line
--trim trim whitespace at the beginning of lines
--threads <> set the appropriate number of threads to use
--long-branch multiple files from the same directory are shown on the same branch
--long-branch-each <> number of files to print on each branch [default: 5]
--editor <> command used to open selections
--open-like <> command line syntax for opening a file at a line [possible values: vi, hx, code, jed, default]
--char-style <> style of characters to use [possible values: single, rounded, heavy, double, ascii, none]
--file-color <> black, white, red, green, yellow, blue, magenta, cyan, grey, rgb(_._._), ansi(_)
--dir-color <> black, white, red, green, yellow, blue, magenta, cyan, grey, rgb(_._._), ansi(_)
--text-color <> black, white, red, green, yellow, blue, magenta, cyan, grey, rgb(_._._), ansi(_)
--line-number-color <> black, white, red, green, yellow, blue, magenta, cyan, grey, rgb(_._._), ansi(_)
--branch-color <> black, white, red, green, yellow, blue, magenta, cyan, grey, rgb(_._._), ansi(_)
--match-colors <> black, white, red, green, yellow, blue, magenta, cyan, grey, rgb(_._._), ansi(_)
--selected-indicator-color <> black, white, red, green, yellow, blue, magenta, cyan, grey, rgb(_._._), ansi(_)
--selected-bg-color <> black, white, red, green, yellow, blue, magenta, cyan, grey, rgb(_._._), ansi(_)
--completions <> generate completions for given shell [possible values: bash, elvish, fish, powershell, zsh]
--selection-file <> file to write selection to (first line: file path, second line: line number if applicable)
--repeat-file <> file where arguments are saved
--repeat repeats the last saved search
-h, --help print help
-V, --version print version
arguments are prefixed with the contents of the TREEGREP_DEFAULT_OPTS environment variable
```