xerg/
lib.rs

1//! # XGrep - A High-Performance Rust Grep Implementation
2//!
3//! XGrep is a fast, parallel grep implementation written in Rust that searches for patterns
4//! in files and directories with syntax highlighting and detailed search statistics.
5//!
6//! ## Features
7//!
8//! - **Parallel Processing**: Multi-core file processing with intelligent thread pool management
9//! - **Pattern Matching**: Regular expression engine with optimized performance
10//! - **Structured Streaming**: Organized results with comprehensive statistics and timing
11//! - **Directory Traversal**: Recursive scanning with symlink support
12//! - **Colorized Output**: Customizable syntax highlighting (red, green, blue, bold)
13//! - **Search Statistics**: Structured result format with timing metrics using `--stats`
14//!
15//! ## Usage
16//!
17//! ```no_run
18//! use xerg::{run, colors::Color};
19//! use std::path::PathBuf;
20//!
21//! let dir = PathBuf::from(".");
22//! let pattern = "use";
23//! let color = Color::Blue;
24//! let show_stats = true;
25//!
26//! run(&dir, pattern, &color, show_stats);
27//! ```
28//!
29//! ## Architecture
30//!
31//! The library is organized into several focused modules:
32//!
33//! - [`colors`]: ANSI color management and formatting
34//! - [`crawler`]: Directory traversal with symlink support
35//! - [`highlighter`]: Regex-based text highlighting
36//! - [`result`]: Message handling and statistics result formatting
37//! - [`search`]: Formatted parallel file processing (use --formatted flag)
38//! - [`search_xtreme`]: **Ultra-fast raw output mode for maximum speed** (default)
39
40pub mod colors;
41pub mod crawler;
42pub mod highlighter;
43pub mod result;
44pub mod search;
45pub mod search_xtreme;
46
47use crate::colors::Color;
48use crate::crawler::get_files;
49use crate::result::{print_result, print_xtreme_stats};
50use crate::search::search_files;
51use crate::search_xtreme::search_files_xtreme;
52use std::path::PathBuf;
53use std::time::Instant;
54
55pub fn run(dir: &PathBuf, pattern: &str, color: &Color, show_stats: bool) {
56    let start_time = Instant::now();
57    let files = get_files(dir);
58    let rx = search_files(&files, pattern, color, show_stats);
59
60    print_result(rx, show_stats, start_time);
61}
62
63pub fn run_xtreme(dir: &PathBuf, pattern: &str, color: &Color, show_stats: bool) {
64    let start_time = Instant::now();
65    let files = get_files(dir);
66    let (files_processed, lines, matches, skipped) =
67        search_files_xtreme(&files, pattern, color, show_stats);
68
69    if show_stats {
70        print_xtreme_stats(files_processed, lines, matches, skipped, start_time);
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77    use std::fs::File;
78    use std::io::Write;
79    use tempdir::TempDir;
80
81    #[test]
82    fn test_run_integration() {
83        // Test the main run function integrates all modules correctly
84        let temp_dir = TempDir::new("lib_test").unwrap();
85        let test_file = temp_dir.path().join("test.txt");
86
87        let mut file = File::create(&test_file).unwrap();
88        writeln!(file, "Hello world").unwrap();
89        writeln!(file, "This is a test").unwrap();
90
91        let pattern = "Hello";
92        let color = Color::Red;
93
94        // Test that run function completes without panicking
95        // This tests integration of crawler::get_files and search::search_files
96        run(&temp_dir.path().to_path_buf(), pattern, &color, false);
97    }
98
99    #[test]
100    fn test_run_with_single_file() {
101        // Test run function with a single file instead of directory
102        let temp_dir = TempDir::new("lib_single_test").unwrap();
103        let test_file = temp_dir.path().join("single.txt");
104
105        let mut file = File::create(&test_file).unwrap();
106        writeln!(file, "Pattern match here").unwrap();
107
108        let pattern = "Pattern";
109        let color = Color::Blue;
110
111        // Test run with single file path
112        run(&test_file, pattern, &color, false);
113    }
114
115    #[test]
116    fn test_run_with_no_matches() {
117        // Test run function when no matches are found
118        let temp_dir = TempDir::new("lib_no_match_test").unwrap();
119        let test_file = temp_dir.path().join("nomatch.txt");
120
121        let mut file = File::create(&test_file).unwrap();
122        writeln!(file, "This file has no pattern").unwrap();
123
124        let pattern = "NonExistentPattern";
125        let color = Color::Green;
126
127        // Should handle no matches gracefully
128        run(&temp_dir.path().to_path_buf(), pattern, &color, false);
129    }
130
131    #[test]
132    fn test_run_different_colors() {
133        // Test run function with all color variants
134        let temp_dir = TempDir::new("lib_colors_test").unwrap();
135        let test_file = temp_dir.path().join("colors.txt");
136
137        let mut file = File::create(&test_file).unwrap();
138        writeln!(file, "Test pattern").unwrap();
139
140        let pattern = "pattern";
141
142        // Test all color variants
143        run(&temp_dir.path().to_path_buf(), pattern, &Color::Red, false);
144        run(
145            &temp_dir.path().to_path_buf(),
146            pattern,
147            &Color::Green,
148            false,
149        );
150        run(&temp_dir.path().to_path_buf(), pattern, &Color::Blue, false);
151        run(&temp_dir.path().to_path_buf(), pattern, &Color::Bold, false);
152    }
153}