Skip to content

albertize/gref

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

67 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GREF

MIT License Rust

A fast, interactive search and replace tool for your terminal — built for speed. No TUI framework — raw ANSI escapes and platform FFI for maximum performance and minimal binary size.


GREF Demo

Features

  • 🚀 Buffered search engine: whole-buffer regex matching with SIMD-accelerated literal pre-filtering (memchr::memmem)
  • 🖥️ Interactive TUI for previewing and selecting replacements
  • 🧠 Smart selection: choose lines to replace, bulk select/deselect
  • 🛡️ Atomic file writes for safe replacements (temp file + rename)
  • 🎨 Flicker-free rendering via cursor-home + line-level clearing
  • 🏃 Tiny binary: only regex + memchr (transitive), release builds with LTO and strip
  • 🔤 UTF-8 safe: proper char-boundary handling for multi-byte content
  • 📁 Project level filtering: .gitignore, .ignore, .grefignore support with hierarchical merging
  • 👻 Hidden file skipping: dot-prefix (Unix) and FILE_ATTRIBUTE_HIDDEN (Windows)
  • 🔍 Smart binary detection: known extensions via lookup, unknown extensions via SIMD null-byte scan on already-loaded buffer

Install

Download pre-built binaries

Go to Releases and download the binary for your platform:

OS amd64 arm64
Linux gref-linux-amd64 gref-linux-arm64
macOS gref-darwin-amd64 gref-darwin-arm64
Windows gref-windows-amd64 gref-windows-arm64

Build from source

cargo install --path .

Build and install locally

cargo build --release
cargo install --path .

Usage

gref [options] <pattern> [replacement] [directory]

Options

  • -h, --help : Show help message and exit
  • -i, --ignore-case : Ignore case in pattern matching
  • -e, --exclude : Exclude path, file or extension (comma separated, e.g. .git,*.log,media/)
  • --hidden : Include hidden files and directories (default outside Git repo roots)
  • --no-ignore : Don't respect .gitignore, .ignore, and .grefignore files

Arguments

  • <pattern>: Regex pattern to search for
  • [replacement]: Replacement string (if omitted, search-only mode)
  • [directory]: Directory to search (default: current directory)

Examples

gref foo bar src      # Replace 'foo' with 'bar' in src directory
gref foo              # Search for 'foo' only
gref -i Foo           # Case-insensitive search for 'Foo'
gref -e .git,*.log    # Exclude .git folders and .log files
gref --hidden foo     # Include hidden files in search
gref --no-ignore foo  # Ignore .gitignore rules
gref --help           # Show help message

Keyboard Controls

Key Action
/ or j/k Move cursor up/down
/ or h/l Scroll horizontally
Home/End Scroll to start/end of line
Space Select/deselect a result for replacement
a Select all results
n Deselect all results
Enter Confirm selected replacements
Esc Cancel confirmation
q / Ctrl+C Exit

Project Structure

src/
  main.rs          CLI entry, regex compile, search, model init, app::run()
  lib.rs           Public module re-exports (enables integration tests)
  cli.rs           Manual argument parsing (no clap). Flags: -i, -e, --hidden, --no-ignore
  model.rs         SearchResult, AppState, AppMode, Model
  search.rs        Pipelined walk + parallel bytes::Regex search, literal prefilter
  replace.rs       Atomic file replacement via temp file + rename
  term.rs          Raw mode FFI (Windows/Unix), ANSI escapes, Key enum, paint()
  ui.rs            Screen rendering (pure function → String), line truncation
  app.rs           Event loop: render → read_key → dispatch → state update
  exclude.rs       Path exclusion (dir/, *.ext, exact filename)
  filedetect.rs    Text vs binary detection (extension lookup + SIMD null-byte scan)
  gitignore.rs     .gitignore/.ignore/.grefignore parsing, glob→regex, hierarchical merging
tests/
  stress_tests.rs  98 edge-case and stress tests across all modules

Performance

  • Whole-buffer regex search: feeds entire file buffers to find_iter() — lets the regex engine's SIMD/Teddy/Aho-Corasick optimizations skip non-matching regions at hardware speed
  • SIMD literal pre-filtering: memchr::memmem::Finder rejects files that lack a literal substring before engaging the regex engine
  • Pipelined parallel search: file walker dispatches jobs immediately via channel; worker threads start searching as files are discovered
  • Zero-copy path filtering: OsStr-based hidden/skip/gitignore checks run before entry.path() allocates the full PathBuf
  • Deferred binary detection: known extensions classified without I/O; unknown extensions checked via SIMD null-byte scan on already-loaded buffer
  • Atomic replacements: writes to temp file, then renames over original
  • Flicker-free TUI: single locked stdout write per frame — no full-screen clear
  • Minimal footprint: only regex + memchr; no TUI framework, async runtime, or allocator

Building & Testing

cargo build                    # Dev build
cargo build --release          # Release (strip=true, lto=true, opt-level=3)
cargo test                     # 41 unit + 98 stress/edge-case tests
cargo clippy                   # Must pass with 0 warnings

Contributing

Contributions are welcome! Please submit issues or pull requests for bug fixes, features, or improvements.


License

MIT License

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages