grox

Crates.iogrox
lib.rsgrox
version0.10.0
created_at2025-03-24 03:46:29.489433+00
updated_at2025-08-02 02:38:17.240843+00
descriptionCommand-line tool that searches for regex matches in a file tree.
homepage
repositoryhttps://gitlab.com/nickeldan/grox
max_upload_size
id1603354
size65,770
Daniel Walker (nickeldan)

documentation

README

Grox is a command-line tool that searches a file tree for regex matches.

Usage

For example,

$ grox the
(0) ./lib.rs:21: ... g to only retrieve the first match per f ...
(1) ./lib.rs:29: /// Path to the file.
(2) ./lib.rs:31: ... e number (1-up) of the match.
(3) ./lib.rs:97: /// Sets the file pattern.
(4) ./lib.rs:106: ... e a directory from the search.
(5) ./lib.rs:110: ... wise extension of the starting direct ...
(6) ./lib.rs:110: ... y.  For example, if the starting direct ...
(7) ./lib.rs:110: ... tory is `../foo`, then an excluded dire ...
(8) ./lib.rs:115: /// Sets the maximum search d ...
(9) ./lib.rs:119: ... le, searches only the starting direct ...
(10) ./lib.rs:133: ... Attempts to build the searcher.
(11) ./lib.rs:137: ... ful and an error if the starting direct ...
(12) ./lib.rs:236: .and_then(OsStr::to_str ...
(13) ./lib.rs:237: .and_then(|name| name.ch ...
(14) ./lib.rs:493: ... oing to fold my clothes").unwrap();
(15) ./history.rs:11: /// Path to the starting direct ...
(16) ./history.rs:23: ... ies excluded from the search.
(17) ./history.rs:44: ... d an `io:Error` if the starting direct ...
(18) ./history.rs:75: ... / * `file` - Path to the file.
(19) ./history.rs:79: ... sful and an error otherwise.
(20) ./history.rs:85: ... / Add a location to the history object.
(21) ./history.rs:89: ... / * `file` - Path to the file.
(22) ./history.rs:94: ... an `io::Error` if the path couldn't be  ...
(23) ./history.rs:101: /// Save the history object t ...
(24) ./history.rs:105: ... / * `file` - Path to the file.
(25) ./history.rs:109: ... sful and an error otherwise.
(26) ./history.rs:121: /// Path to the file.
(27) ./open.rs:3: /// Facilitates the opening of a file  ...
(28) ./open.rs:5: /// Does the opener handle a g ...
(29) ./open.rs:9: ... ` - Name of/path to the editor.
(30) ./open.rs:16: /// Forms the `execv` argumen ...
(31) ./open.rs:20: ... / * `file` - Path to the file to be opened ...
(32) ./open.rs:25: ... s to `execv` minus the path to the edito ...
(33) ./open.rs:25: ... ` minus the path to the editor that shou ...
(34) ./open.rs:25: ... r that should go at the beginning.
(35) ./open.rs:257: ... t (if supported by the opener).
(36) ./main.rs:24: ... ory excluded from the search.  Can be sp ...
(37) ./main.rs:32: ... hort, help = "Open the file for the spec ...
(38) ./main.rs:32: ... "Open the file for the specified resul ...

By default the search starts with the current working directory. You can change this by -d DIRECTORY.

You can limit the directory search depth by -p DEPTH. A depth of 0 searches only the starting directory.

If you only want to get the names of the matching files, add -n:

$ grox the -n
(0) ./lib.rs
(1) ./history.rs
(2) ./open.rs
(3) ./main.rs

If you only want to search files whose names match a certain pattern, you can use -f:

$ grox some_pattern -f '\.rs$'

You can exclude directories from the search by -x:

$ grox some_pattern -x ./foo -x ./bar/baz

The excluded directories can either be absolute or relative to the starting directory. For example, -d ../foo -x bar -x /baz would ignore the directories ../foo/bar and /baz.

By default, grox will display up to 15 non-whitespace characters on either side of the matching text. You can change this value by setting the GROX_PADDING environment variable:

$ GROX_PADDING=30 grox the
(0) ./lib.rs:21: ... // Flag specifying to only retrieve the first match per file.
(1) ./lib.rs:29: /// Path to the file.
(2) ./lib.rs:31: /// Line number (1-up) of the match.
(3) ./lib.rs:97: /// Sets the file pattern.
(4) ./lib.rs:106: /// Exclude a directory from the search.
(5) ./lib.rs:110: ... .  Must be a string-wise extension of the starting directory.  For example,  ...
(6) ./lib.rs:110: ... tarting directory.  For example, if the starting directory is `../foo`, t ...
(7) ./lib.rs:110: ... he starting directory is `../foo`, then an excluded directory could be `.. ...
(8) ./lib.rs:115: /// Sets the maximum search depth.
(9) ./lib.rs:119: ... pth of 0, for example, searches only the starting directory.
(10) ./lib.rs:133: /// Attempts to build the searcher.
(11) ./lib.rs:137: ... archer if successful and an error if the starting directory couldn't be ac ...
(12) ./lib.rs:236: .and_then(OsStr::to_str)
(13) ./lib.rs:237: .and_then(|name| name.chars().next())
(14) ./lib.rs:493: ... m not a fool\nI'm going to fold my clothes").unwrap();
(15) ./history.rs:11: /// Path to the starting directory.
(16) ./history.rs:23: /// Directories excluded from the search.
(17) ./history.rs:44: ... t if successful and an `io:Error` if the starting directory couldn't be re ...
(18) ./history.rs:75: /// * `file` - Path to the file.
(19) ./history.rs:79: ... y object if successful and an error otherwise.
(20) ./history.rs:85: /// Add a location to the history object.
(21) ./history.rs:89: /// * `file` - Path to the file.
(22) ./history.rs:94: ... if successful and an `io::Error` if the path couldn't be resolved.
(23) ./history.rs:101: /// Save the history object to a file.
(24) ./history.rs:105: /// * `file` - Path to the file.
(25) ./history.rs:109: ... /// `()` if successful and an error otherwise.
(26) ./history.rs:121: /// Path to the file.
(27) ./open.rs:3: /// Facilitates the opening of a file with a provided ed ...
(28) ./open.rs:5: /// Does the opener handle a given editor?
(29) ./open.rs:9: /// * `editor` - Name of/path to the editor.
(30) ./open.rs:16: /// Forms the `execv` arguments for opening a fi ...
(31) ./open.rs:20: /// * `file` - Path to the file to be opened.
(32) ./open.rs:25: ... / Arguments to pass to `execv` minus the path to the editor that should go at  ...
(33) ./open.rs:25: ... s to pass to `execv` minus the path to the editor that should go at the beginn ...
(34) ./open.rs:25: ... e path to the editor that should go at the beginning.
(35) ./open.rs:257: ... ne` - Line to open at (if supported by the opener).
(36) ./main.rs:24: ... nd, help = "Directory excluded from the search.  Can be specified multiple  ...
(37) ./main.rs:32: #[arg(short, help = "Open the file for the specified result.")]
(38) ./main.rs:32: ... arg(short, help = "Open the file for the specified result.")]

A value of 0 will show the entire containing line.

Opening files

You can open the n-th match in an editor with the -l option. For example, say you found these matches:

$ grox some_pattern
(0) file1.txt:55: ...
(1) file2:txt:2: ...

If you wanted to open up file1.txt, you could run the search again with -l:

$ grox some_pattern -l 0

If the EDITOR environment variable is set, then Grox will use the specified executable. Otherwise, it will try to use less. You can manually specify the editor by

$ grox some_pattern -l 0 -e vim

If the chosen editor is one of the following, then Grox will open up the file to the line containing the match:

  • less
  • more
  • vi
  • vim
  • nvim
  • emacs
  • code
  • xed
  • subl

History

When you run a search without -l and stdout is a terminal, a history file is created at ~/.grox_history.json. If you then re-run the exact same search with -l, Grox will grab the result from the history file instead of re-running the search.

Every search that doesn't use -l will overwrite the history file if it exists. That is, only the most recent search is saved.

If you pass -c, then the the history file, if it exists, will be deleted before Grox does anything else.

Commit count: 40

cargo fmt