pub struct TextSearcher { /* private fields */ }Expand description
Text searcher that uses ripgrep as a library for fast text searching.
§Rust Book Reference
Chapter 5.3: Method Syntax https://doc.rust-lang.org/book/ch05-03-method-syntax.html
Chapter 10.2: Traits as Parameters https://doc.rust-lang.org/book/ch10-02-traits.html
§Educational Notes - The Builder Pattern
This struct demonstrates the builder pattern, a common Rust idiom for constructing complex objects with many optional parameters.
Key characteristics:
- Private fields prevent direct construction
new()provides sensible defaults- Builder methods take
mut selfand returnSelf - Final
search()method takes&self(doesn’t consume)
Why this pattern?
- Avoids constructors with many parameters
- Makes optional configuration explicit
- Enables method chaining for readability
- Compile-time validation of configuration
Implementations§
Source§impl TextSearcher
impl TextSearcher
Sourcepub fn new(base_dir: PathBuf) -> Self
pub fn new(base_dir: PathBuf) -> Self
Create a new TextSearcher with default settings.
§Rust Book Reference
Chapter 5.3: Method Syntax - Associated Functions https://doc.rust-lang.org/book/ch05-03-method-syntax.html#associated-functions
§Educational Notes - Builder Constructor
This is an associated function (not a method) that creates a new instance.
It’s called with TextSearcher::new(...) rather than on an instance.
Design decisions:
- Takes only required parameter (
base_dir) - Sets sensible defaults for all optional fields
- Returns owned
Self(not&Self)
Usage pattern:
let searcher = TextSearcher::new(PathBuf::from("/path"))
.case_sensitive(true) // Optional: override default
.respect_gitignore(false); // Optional: override defaultSourcepub fn respect_gitignore(self, value: bool) -> Self
pub fn respect_gitignore(self, value: bool) -> Self
Set whether to respect .gitignore files (default: true).
§Rust Book Reference
Chapter 5.3: Method Syntax https://doc.rust-lang.org/book/ch05-03-method-syntax.html
§Educational Notes - Builder Method Pattern
This method demonstrates the builder pattern’s key technique:
pub fn respect_gitignore(mut self, value: bool) -> Self {
// ^^^^^^^^ ^^^^^^
// Takes ownership Returns ownership
self.respect_gitignore = value;
self // Return modified self for chaining
}Why mut self instead of &mut self?
mut selftakes ownership, allowing method chaining&mut selfwould require explicit returns and be less ergonomic- Ownership transfer prevents using partially-configured builders
Method chaining:
TextSearcher::new(dir)
.respect_gitignore(false) // Consumes and returns Self
.case_sensitive(true) // Consumes and returns Self
.search("text") // Final method takes &selfSourcepub fn case_sensitive(self, value: bool) -> Self
pub fn case_sensitive(self, value: bool) -> Self
Set whether search is case-sensitive (default: false).
§Educational Notes
Same builder pattern as respect_gitignore(). Each builder method:
- Takes ownership of
self - Modifies the field
- Returns ownership for chaining
Sourcepub fn word_match(self, value: bool) -> Self
pub fn word_match(self, value: bool) -> Self
Set whether to match whole words only (default: false)
Sourcepub fn is_regex(self, value: bool) -> Self
pub fn is_regex(self, value: bool) -> Self
Set whether to treat the query as a regex (default: false)
Sourcepub fn add_exclusions(self, exclusions: Vec<String>) -> Self
pub fn add_exclusions(self, exclusions: Vec<String>) -> Self
Add exclusion patterns
Sourcepub fn search(&self, text: &str) -> Result<Vec<Match>>
pub fn search(&self, text: &str) -> Result<Vec<Match>>
Search for text and return all matches.
§Rust Book Reference
Chapter 16.2: Message Passing with Channels https://doc.rust-lang.org/book/ch16-02-message-passing.html
Chapter 13.1: Closures https://doc.rust-lang.org/book/ch13-01-closures.html
§Educational Notes - Concurrent Search with Channels
This method demonstrates concurrent programming using message passing:
- Create channel:
let (tx, rx) = mpsc::channel() - Spawn workers: Each thread gets a cloned sender (
tx.clone()) - Send results: Workers send matches through the channel
- Drop original sender: Critical for terminating the receiver
- Collect results: Main thread receives all matches
Why channels instead of shared state?
- No locks needed (no
Mutex) - Ownership prevents data races
- Natural producer-consumer pattern
- Rust’s type system ensures thread safety
§Arguments
text- The text to search for
§Returns
A vector of Match structs containing file path, line number, and content