treegrep is a regex pattern matcher that displays results in a tree structure with an interface to jump to matched text.
examples, integrations, and help.
crates.io | GitHub | AUR | NetBSD
- cargo:
cargo install treegrep - releases: Download from releases
- manual:
git clone https://github.com/4imothy/treegrep cd treegrep cargo build --release
neovim
- setup using lazy.nvim
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', '<leader>tt', function() require('treegrep').tgrep_with('--menu --live') end)
vim.keymap.set('n', '<leader>tr', function() require('treegrep').tgrep_with('--repeat --select --live') end)
vim.keymap.set('n', '<leader>tf', function() require('treegrep').tgrep_with('--files --select --live') end)
end,
}helix
- keybind to run treegrep and open selection
space.t = [
':sh rm -f /tmp/tgrep-select',
':insert-output tgrep --no-alternate-screen --menu --live --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-option mouse false',
':set-option mouse true',
]vim
- setup using vim-plug
Plug '4imothy/treegrep', {'do': {-> TgrepBuild()}}
let g:tgrep_selection_file = '/tmp/tgrep-select'
let g:tgrep_repeat_file = '/tmp/tgrep-repeat'
nnoremap <leader>tt :call TgrepWith('--menu')<cr>
nnoremap <leader>tr :call TgrepWith('--repeat --select')<cr>
nnoremap <leader>tf :call TgrepWith('--files --select')<cr>emacs
- sample setup using use-package with the built-in
term
(use-package treegrep
:ensure nil
:load-path "path/to/treegrep/plugin"
:preface
(let ((src (expand-file-name "path/to/treegrep/plugin/treegrep.el")))
(when (file-newer-than-file-p src (concat src "c"))
(byte-compile-file src)))
:custom
(tgrep-selection-file "/tmp/tgrep-select")
(tgrep-repeat-file "/tmp/tgrep-repeat")
(tgrep-terminal
(lambda (cmd)
(when-let ((old (get-buffer "*tgrep*")))
(when-let ((p (get-buffer-process old)))
(set-process-query-on-exit-flag p nil)
(delete-process p))
(kill-buffer old))
(let ((buf (get-buffer-create "*tgrep*")))
(switch-to-buffer buf)
(term-mode)
(setq-local scroll-margin 0)
(setq-local scroll-conservatively 0)
(setq-local term-suppress-hard-newline t)
(setq-local show-trailing-whitespace nil)
(setq-local display-line-numbers nil)
(setq-local truncate-lines t)
(let ((term-exec-hook nil))
(term-exec buf "tgrep" shell-file-name nil (list shell-command-switch cmd)))
(term-char-mode)
(let ((proc (get-buffer-process buf)))
(set-process-query-on-exit-flag proc nil)
proc))))
:config
(require 'term)
(tgrep-build)
:bind
("C-c t t" . (lambda () (interactive) (delete-other-windows) (tgrep-with "--menu --path=/some/path")))
("C-c t r" . (lambda () (interactive) (delete-other-windows) (tgrep-with "--repeat --select")))
("C-c t f" . (lambda () (interactive) (delete-other-windows) (tgrep-with "--files --select --path=/some/path"))))tgrep --regexp \bstruct\s+\w+ --regexp \bimpl\s+\w+ --path src --line-number --context=1 --count
src: 9
├──term.rs: 1
│ ├──-1:
│ ├──15: pub struct Term<'a> {
│ ╰──+1: pub height: u16,
├──style.rs: 1
│ ├──-1:
│ ├──23: pub struct DisplayRepeater<T>(T, usize);
│ ╰──+1: impl<T: Display> Display for DisplayRepeater<T> {
├──match_system.rs: 8
│ ├──-1:
│ ├──23: pub struct Directory {
│ ├──+1: pub path: PathBuf,
│ ├──-1:
│ ├──30: impl Directory {
│ ├──+1: pub fn new(path: &Path, links: bool) -> Result<Self, Message> {
│ ├──-1:
│ ├──41: pub struct File {
│ ├──+1: pub path: PathBuf,
│ ├──-1:
│ ├──47: impl File {
│ ├──+1: pub fn from_pathbuf(path: PathBuf, links: bool) -> Result<Self, Message> {
│ ├──-1: #[cfg_attr(test, derive(PartialEq, Debug))]
│ ├──73: pub struct Match {
│ ├──+1: pub regexp_id: usize,
│ ├──-1:
│ ├──79: impl Match {
│ ├──+1: pub fn new(regexp_id: usize, start: usize, end: usize) -> Self {
│ ├──-1:
│ ├──104: pub struct Line {
│ ├──+1: pub content: Vec<u8>,
│ ├──-1:
│ ├──111: impl Line {
│ ╰──+1: pub fn new(content: Vec<u8>, mut matches: Vec<Match>, line_num: usize) -> Self {
├──errors.rs: 4
│ ├──-1:
│ ├──14: pub struct Message {
│ ├──+1: pub mes: String,
│ ├──-1: }
│ ├──17: impl Error for Message {}
│ ├──+1:
│ ├──-1:
│ ├──34: impl fmt::Debug for Message {
│ ├──+1: fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
│ ├──-1:
│ ├──40: impl fmt::Display for Message {
│ ╰──+1: fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
├──matcher.rs: 5
│ ├──-1:
│ ├──32: struct Matcher {
│ ├──+1: patterns: Vec<String>,
│ ├──-1:
│ ├──64: impl Combined {
│ ├──+1: fn new(patterns: &[&str], use_pcre2: bool) -> Result<Self, Message> {
│ ├──-1:
│ ├──94: impl Individual {
│ ├──+1: fn new(patterns: &[String], use_pcre2: bool) -> Result<Self, Message> {
│ ├──-1:
│ ├──124: impl Matcher {
│ ├──+1: fn new(search: &SearchParams, root: &Path) -> Result<Self, Message> {
│ ├──-1:
│ ├──218: struct MatchSink<'a> {
│ ╰──+1: lines: Vec<Line>,
├──config.rs: 9
│ ├──-1: #[derive(Clone)]
│ ├──30: pub struct KeyBindings {
│ ├──+1: pub down: Vec<KeyCode>,
│ ├──-1: #[derive(Clone)]
│ ├──55: pub struct Characters {
│ ├──+1: pub bl: char,
│ ├──-1: #[derive(Clone)]
│ ├──76: pub struct Colors {
│ ├──+1: pub file: Color,
│ ├──-1:
│ ├──88: impl args::Color {
│ ├──+1: fn get(&self) -> Color {
│ ├──-1: #[derive(Clone)]
│ ├──107: pub struct SearchParams {
│ ├──+1: pub regexps: Vec<String>,
│ ├──-1: #[derive(Clone)]
│ ├──130: pub struct Config {
│ ├──+1: pub search: SearchParams,
│ ├──-1:
│ ├──457: struct NonSearchFields {
│ ├──+1: selection_file: Option<PathBuf>,
│ ├──-1:
│ ├──475: impl Config {
│ ├──+1: pub fn get_styling(matches: &ArgMatches) -> (bool, bool) {
│ ├──-1:
│ ├──784: impl SearchParams {
│ ╰──+1: pub fn has_expr(&self) -> bool {
├──args.rs: 11
│ ├──-1:
│ ├──25: impl ValueEnum for OpenStrategy {
│ ├──+1: fn value_variants<'a>() -> &'a [Self] {
│ ├──-1:
│ ├──59: impl ValueEnum for CompletionShell {
│ ├──+1: fn value_variants<'a>() -> &'a [Self] {
│ ├──-1:
│ ├──85: impl CompletionShell {
│ ├──+1: pub fn generate(&self, cmd: &mut Command, bin: &str, out: &mut dyn std::io::Write) {
│ ├──-1: #[derive(Clone)]
│ ├──152: pub struct ColorParser;
│ ├──+1:
│ ├──154: impl clap::builder::TypedValueParser for ColorParser {
│ ├──+1: type Value = Color;
│ ├──-1: #[derive(Clone)]
│ ├──211: pub struct KeyCodeParser;
│ ├──+1:
│ ├──213: impl clap::builder::TypedValueParser for KeyCodeParser {
│ ├──+1: type Value = KeyCode;
│ ├──-1: #[cfg_attr(test, derive(PartialEq, Debug))]
│ ├──296: pub struct ScopedRegexp {
│ ├──+1: pub glob: String,
│ ├──-1: #[derive(Clone)]
│ ├──302: pub struct RegexpGlobParser;
│ ├──+1:
│ ├──304: impl clap::builder::TypedValueParser for RegexpGlobParser {
│ ├──+1: type Value = ScopedRegexp;
│ ├──-1: )]
│ ├──454: pub struct Args {
│ ╰──+1: #[arg(
├──menu.rs: 10
│ ├──-1:
│ ├──59: impl ViewAnchor {
│ ├──+1: fn next(&mut self) {
│ ├──-1:
│ ├──76: impl FoldCycle {
│ ├──+1: fn next(&mut self) {
│ ├──-1:
│ ├──86: struct DoubleClick {
│ ├──+1: down_row: u16,
│ ├──-1:
│ ├──91: impl DoubleClick {
│ ├──+1: fn new() -> Self {
│ ├──-1:
│ ├──118: struct Window {
│ ├──+1: first: isize,
│ ├──-1:
│ ├──123: impl Window {
│ ├──+1: fn new() -> Self {
│ ├──-1:
│ ├──529: struct CurrentResults {
│ ├──+1: lines: Vec<Box<dyn Entry>>,
│ ├──-1:
│ ├──533: impl CurrentResults {
│ ├──+1: fn new(matches: Matches, config: Arc<Config>) -> io::Result<Self> {
│ ├──-1:
│ ├──541: pub struct Menu<'a, 'b> {
│ ├──+1: in_menu: bool,
│ ├──-1:
│ ├──1789: impl OpenStrategy {
│ ╰──+1: fn from(editor: &str) -> Self {
╰──writer.rs: 19
├──-1:
├──56: impl HighlightEvent<'_> {
├──+1: fn priority(&self) -> u8 {
├──-1:
├──190: pub struct OpenInfo<'a> {
├──+1: pub path: &'a Path,
├──-1:
├──203: pub struct WithFilter<'a> {
├──+1: pub entry: &'a dyn Entry,
├──-1:
├──208: impl Display for WithFilter<'_> {
├──+1: fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
├──-1:
├──214: struct PathDisplay {
├──+1: prefix: Option<Vec<PrefixComponent>>,
├──-1:
├──225: impl PathDisplay {
├──+1: fn new(
├──-1:
├──258: impl Entry for PathDisplay {
├──+1: fn render(&self, f: &mut fmt::Formatter, filter: &str) -> fmt::Result {
├──-1:
├──297: impl Display for PathDisplay {
├──+1: fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
├──-1:
├──355: struct LineDisplay {
├──+1: prefix: Vec<PrefixComponent>,
├──-1:
├──366: impl Entry for LineDisplay {
├──+1: fn render(&self, f: &mut fmt::Formatter, filter: &str) -> fmt::Result {
├──-1:
├──505: impl Display for LineDisplay {
├──+1: fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
├──-1:
├──511: struct LongBranchDisplay {
├──+1: prefix: Vec<PrefixComponent>,
├──-1:
├──518: impl Entry for LongBranchDisplay {
├──+1: fn render(&self, f: &mut fmt::Formatter, filter: &str) -> fmt::Result {
├──-1:
├──564: impl Display for LongBranchDisplay {
├──+1: fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
├──-1:
├──570: struct OverviewDisplay {
├──+1: dirs: usize,
├──-1:
├──579: impl Entry for OverviewDisplay {
├──+1: fn render(&self, f: &mut fmt::Formatter, filter: &str) -> fmt::Result {
├──-1:
├──620: impl Display for OverviewDisplay {
├──+1: fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
├──-1:
├──642: impl Directory {
├──+1: fn to_lines(
├──-1:
├──747: impl File {
╰──+1: fn to_lines(
tgrep Print src/menu.rs --trim --line-number --char-vertical=| --char-horizontal=- --char-top-left=+ --char-top-right=+ --char-bottom-left=+ --char-bottom-right=+ --char-tee=+
menu.rs
+--19: style::{Color, Print, ResetColor, SetBackgroundColor, SetForegroundColor},
+--403: Print(format!(
+--414: Print(format!(
+--426: Print(format!(
+--759: queue!(self.term, Print(WithFilter { entry, filter }))?;
+--762: queue!(self.term, Print(&cfg.chars.ellipsis))?;
+--781: Print(style::style_with(
+--789: queue!(self.term, Print(cfg.chars.selected_indicator.as_str()))?;
+--810: Print(cfg.chars.selected_indicator_clear.as_str()),
+--1166: Print(top),
+--1188: Print(display),
+--1284: Print(line)
+--1304: queue!(self.term, cursor::MoveTo(0, y), Print(msg))?;
+--1521: Print(cfg.chars.selected_indicator_clear.as_str())
tgrep --files --hidden --glob=!.git
treegrep
├──src
│ ├──match_system.rs
│ ├──menu.rs
│ ├──args.rs
│ ├──writer.rs
│ ├──main.rs
│ ├──errors.rs
│ ├──style.rs
│ ├──log.rs
│ ├──config.rs
│ ├──matcher.rs
│ ╰──term.rs
├──doc
│ ├──treegrep.vim9.txt
│ ╰──treegrep.nvim.txt
├──.github
│ ╰──workflows
│ ├──update_readme
│ ├──test.yml
│ ├──update_readme.yml
│ ╰──cr.yml
├──benchmarks
│ ├──runner
│ ╰──times
├──lua
│ ╰──treegrep.lua
├──plugin
│ ├──treegrep.el
│ ╰──treegrep.vim
├──tests
│ ├──pool
│ │ ╰──alice_adventures_in_wonderland_by_lewis_carroll.txt
│ ├──targets
│ │ ├──summary_dir
│ │ ├──files_1
│ │ ├──wide_2
│ │ ├──links_4
│ │ ├──links_3
│ │ ├──links_2
│ │ ├──menu_jump_2
│ │ ├──files_long_branch_expr_2
│ │ ├──summary_file
│ │ ├──menu_fold_cycle
│ │ ├──menu_navigate_1
│ │ ├──glob_exclusion
│ │ ├──regexp_glob_2
│ │ ├──no_matches
│ │ ├──files_long_branch_1
│ │ ├──context_b1
│ │ ├──context_a1
│ │ ├──files_long_branch_expr_count_2
│ │ ├──pcre2_lookbehind
│ │ ├──overview_dir
│ │ ├──menu_filter
│ │ ├──wide_1
│ │ ├──files_2
│ │ ├──menu_search_mode
│ │ ├──deep
│ │ ├──context_c1
│ │ ├──links_1
│ │ ├──menu_jump_1
│ │ ├──overview_file
│ │ ├──files_long_branch_expr_1
│ │ ├──overlapping
│ │ ├──menu_navigate_2
│ │ ├──file
│ │ ├──max_depth
│ │ ├──files_long_branch_2
│ │ ├──regexp_glob_1
│ │ ├──menu_custom_keys
│ │ ├──files_long_branch_expr_count_1
│ │ ╰──files_with_expr
│ ├──file_system.rs
│ ├──tests.rs
│ ├──tmux.rs
│ ╰──utils.rs
├──Cargo.lock
├──LICENSE
├──rustfmt.toml
├──README.md
├──Cargo.toml
╰──.gitignore
tgrep --files --branch-each=5 --hidden --glob=!.git
treegrep
├──src
│ ├──match_system.rs, menu.rs, args.rs, writer.rs, main.rs
│ ├──errors.rs, style.rs, log.rs, config.rs, matcher.rs
│ ╰──term.rs
├──doc
│ ╰──treegrep.vim9.txt, treegrep.nvim.txt
├──.github
│ ╰──workflows
│ ╰──update_readme, test.yml, update_readme.yml, cr.yml
├──benchmarks
│ ╰──runner, times
├──lua
│ ╰──treegrep.lua
├──plugin
│ ╰──treegrep.el, treegrep.vim
├──tests
│ ├──pool
│ │ ╰──alice_adventures_in_wonderland_by_lewis_carroll.txt
│ ├──targets
│ │ ├──summary_dir, files_1, wide_2, links_4, links_3
│ │ ├──links_2, menu_jump_2, files_long_branch_expr_2, summary_file, menu_fold_cycle
│ │ ├──menu_navigate_1, glob_exclusion, regexp_glob_2, no_matches, files_long_branch_1
│ │ ├──context_b1, context_a1, files_long_branch_expr_count_2, pcre2_lookbehind, overview_dir
│ │ ├──menu_filter, wide_1, files_2, menu_search_mode, deep
│ │ ├──context_c1, links_1, menu_jump_1, overview_file, files_long_branch_expr_1
│ │ ├──overlapping, menu_navigate_2, file, max_depth, files_long_branch_2
│ │ ╰──regexp_glob_1, menu_custom_keys, files_long_branch_expr_count_1, files_with_expr
│ ╰──utils.rs, tests.rs, file_system.rs, tmux.rs
├──README.md, .gitignore, LICENSE, rustfmt.toml, Cargo.toml
╰──Cargo.lock
tgrep --regexp-glob *.rs=_mouse --regexp-glob *.lua=path --line-number
treegrep
├──src
│ ├──term.rs
│ │ ├──20: with_mouse: bool,
│ │ ├──28: with_mouse: bool,
│ │ ├──38: with_mouse,
│ │ ├──59: if self.with_mouse {
│ │ ├──65: let with_mouse = self.with_mouse;
│ │ ├──68: Term::exit(&mut io::stderr(), with_mouse, with_alternate_screen).ok();
│ │ ├──77: fn exit<W>(w: &mut W, with_mouse: bool, with_alternate_screen: bool) -> io::Result<()>
│ │ ├──92: if with_mouse {
│ │ ╰──104: Term::exit(self, self.with_mouse, self.with_alternate_screen)?;
│ ├──args.rs
│ │ ╰──684: pub no_mouse: bool,
│ ╰──config.rs
│ ╰──572: mouse: !args.no_mouse,
╰──lua
╰──treegrep.lua
├──23: local current_file_path = debug.getinfo(1, 'S').source:sub(2)
├──24: local plugin_name = vim.fn.fnamemodify(current_file_path, ':t:r')
├──25: local project_root = vim.fs.abspath(vim.fs.dirname(vim.fs.dirname(current_file_path)))
├──26: local tgrep_bin = vim.fs.joinpath(project_root, 'target', 'release', 'tgrep')
╰──109: '--manifest-path=' .. vim.fn.fnameescape(vim.fs.joinpath(project_root, 'Cargo.toml'))
tgrep 2.2.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|--regexp <>|--regexp-glob <glob=regexp>|--files|--completions <>|--menu|--repeat> [POSITIONAL_PATH]
arguments:
[POSITIONAL_REGEXP]
a regex expression to search for
[POSITIONAL_PATH]
the path to search, if not provided, search the current directory
options:
-e, --regexp <>
a regex expression to search for (saved for repeat)
--regexp-glob <glob=regexp>
search for a regex expression only in files matching a glob (saved for repeat)
-p, --path <>
the path to search, if not provided, search the current directory (saved for repeat)
-s, --select
results are shown in a selection interface for opening
-m, --menu
open a search and selection interface
--live
trigger search on every keystroke in the menu
--live-delay <>
milliseconds to wait after the last keystroke before triggering a live search
-f, --files
if an expression is given, hide matched content, otherwise, show the files that would be searched (saved for repeat)
-., --hidden
search hidden files (saved for repeat)
-n, --line-number
show the line numbers of matches (saved for repeat)
-c, --count
display number of files matched in directory and number of lines matched in a file (saved for repeat)
-g, --glob <>
rules match .gitignore globs, but ! has inverted meaning, overrides other ignore logic (saved for repeat)
-l, --links
search linked paths (saved for repeat)
-o, --overview
conclude results with an overview (saved for repeat)
-S, --overview-only
only show the overview, not the results (saved for repeat)
-d, --max-depth <>
the max depth to search (saved for repeat)
-C, --context <>
number of lines to show before and after each match
-B, --before-context <>
number of lines to show before each match (saved for repeat)
-A, --after-context <>
number of lines to show after each match (saved for repeat)
--max-length <>
set the max length for a matched line (saved for repeat)
--no-ignore
disable ignore files (saved for repeat)
--pcre2
use PCRE2 instead of the default regex engine (saved for repeat)
--trim
trim whitespace at the beginning of lines (saved for repeat)
--auto-open
if there is only one match, open it in the configured editor
--repeat
repeats the last saved search
--branch-len <>
number of characters to show before a match
[default: 3]
--branch-each <>
number of files to print on each branch (saved for repeat)
[default: 1]
--no-color
disable colors
--no-bold
disable bold
--threads <>
set the number of threads to use
--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]
--completions <>
generate completions for given shell
[possible values: bash, elvish, fish, powershell, zsh, nushell]
--no-mouse
disable mouse events
--no-alternate-screen
disable the terminal alternate screen
--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(_)
--branch-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(_)
--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(_)
--filter-highlight-color <>
black, white, red, green, yellow, blue, magenta, cyan, grey, rgb(_._._), ansi(_)
--char-vertical <>
vertical branch character
[default: │]
--char-horizontal <>
horizontal branch character
[default: ─]
--char-top-left <>
top-left corner character
[default: ╭]
--char-top-right <>
top-right corner character
[default: ╮]
--char-bottom-left <>
bottom-left corner character
[default: ╰]
--char-bottom-right <>
bottom-right corner character
[default: ╯]
--char-tee <>
tee branch character
[default: ├]
--ellipsis <>
folded indicator
[default: ⤵]
--search-prompt <>
search mode prompt
[default: "➜ "]
--search-prompt-inactive <>
search prompt when not searching
[default: "- "]
--filter-prompt <>
filter mode prompt
[default: /]
--selected-indicator <>
selected indicator characters
[default: "─❱ "]
--key-down <>
move down
[default: down j n]
--key-up <>
move up
[default: up k p]
--key-big-down <>
big jump down
[default: J N]
--key-big-up <>
big jump up
[default: K P]
--key-down-path <>
move down to the next path
[default: } ]]
--key-up-path <>
move up to the previous path
[default: { []
--key-down-same-depth <>
move down to the next path at same depth
[default: ) d]
--key-up-same-depth <>
move up to the previous path at same depth
[default: ( u]
--key-top <>
move to the top
[default: home g <]
--key-bottom <>
move to the bottom
[default: end G >]
--key-page-down <>
page down
[default: pagedown f]
--key-page-up <>
page up
[default: pageup b]
--key-cycle-view <>
cycle cursor position (top/center/bottom)
[default: z l]
--key-help <>
show help
[default: h]
--key-quit <>
quit
[default: q]
--key-open <>
open selection
[default: enter]
--key-fold <>
fold/unfold path
[default: tab]
--key-fold-cycle <>
cycle global fold (dirs/files/none)
[default: Z]
--key-filter <>
filter within results
[default: / s]
--key-search <>
enter search mode
[default: :]
--key-submit-search <>
submit search query
[default: enter]
--selection-file <>
file to write selection to
--repeat-file <>
file to save and replay regexp searches
-h, --help
-V, --version
arguments are prefixed with the contents of the TREEGREP_DEFAULT_OPTS environment variable