Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

turbogrep (tgrep)

A multi-threaded, memory-mapped grep clone written in Rust. A multi-threaded, memory-mapped grep clone written in Rust. Demonstrates fearless concurrency, zero-copy I/O, custom error types, and clap-based CLI design.

What it demonstrates

  • Memory-mapped I/O (memmap2): files are mapped rather than read into a heap buffer, so a multi-gigabyte file costs a page-table entry to open, not a multi-gigabyte allocation. Search runs directly against the mapped bytes.
  • Work-stealing concurrency (rayon + crossbeam-channel): a rayon thread pool searches files in parallel across however many threads you give it; each worker hands its results to a single printer thread over an unbounded crossbeam channel, so output never interleaves and no lock is held around stdout.
  • Structured error handling (thiserror for library-style errors in error.rs, anyhow with context at the application boundary in main.rs).
  • CLI parsing (clap, derive API) with grep-familiar flags.

Build

cargo build --release

The binary is produced at target/release/tgrep.

Usage

tgrep [OPTIONS] <PATTERN> [PATHS]...

Common flags:

Flag Meaning
-i, --ignore-case case insensitive search
-F, --fixed-strings treat pattern as a literal string, not a regex
-w, --word-regexp match whole words only
-c, --count print per-file match counts instead of lines
-A/-B/-C <N> lines of context after / before / both
-t, --type <ext> restrict to a file extension, repeatable
--hidden include hidden files and skip the default ignore list
--binary also search files that look like binaries
-j, --threads <N> worker thread count, defaults to logical CPU count
--stats print a files searched / matched / elapsed summary to stderr

By default, tgrep skips hidden files and the usual noise directories (.git, target, node_modules, .venv, __pycache__, .idea, .vscode), and skips files that look binary (a null byte in the first 8 KB). Both are overridable with --hidden and --binary.

Exit codes follow grep's convention: 0 if something matched, 1 if nothing matched, 2 on an error (bad pattern, unreadable path, etc).

Examples

tgrep "TODO" src
tgrep -i -c "error" . -t rs -t toml
tgrep -F -w "mmap" src --stats
tgrep -C 2 "fn main" src/main.rs

Project layout

src/
  main.rs      wires the CLI, thread pool, and printer together
  cli.rs       clap argument definitions
  walker.rs    directory traversal and file filtering
  searcher.rs  per-file memory-mapped search
  output.rs    the printer thread and colored formatting
  error.rs     thiserror error types for I/O and mmap failures

Known limitations

  • Match byte-offsets are computed against the raw file bytes and then rendered against a lossily-decoded String. For files that are not valid UTF-8, the replacement character (\u{FFFD}) is a different byte width than the original byte, so a highlighted range can be off by a character or two on those lines. Valid UTF-8 and ASCII files, which is the large majority of source code and logs, are unaffected.
  • No .gitignore-aware filtering (only the fixed default-ignore list above). Adding that would mean pulling in the ignore crate, which is ripgrep's own crate for exactly this.

About

A multi-threaded, memory-mapped grep clone

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages