codesearch 0.1.9

A fast, intelligent CLI tool with multiple search modes (regex, fuzzy, semantic), code analysis, and dead code detection for popular programming languages
Documentation
//! Search Command Handlers
//!
//! Handles all search-related CLI commands.

use crate::export;
use crate::search::{list_files, print_results, print_search_stats, search_code};
use crate::types::SearchOptions;
use colored::*;
use std::path::Path;

/// Handle the search command
///
/// # Arguments
///
/// * `query` - The search pattern
/// * `path` - The directory to search in
/// * `options` - Search configuration options
/// * `no_line_numbers` - Whether to hide line numbers
/// * `format` - Output format (text/json)
/// * `stats` - Whether to show statistics
/// * `export_path` - Optional path to export results
///
/// # Returns
///
/// Result indicating success or error
///
/// # Examples
///
/// ```no_run
/// use codesearch::commands::search::handle_search_command;
/// use codesearch::types::SearchOptions;
/// use std::path::Path;
///
/// let options = SearchOptions::default();
/// handle_search_command(
///     "test",
///     Path::new("src"),
///     options,
///     false,
///     "text",
///     true,
///     None
/// ).unwrap();
/// ```
pub fn handle_search_command(
    query: &str,
    path: &Path,
    options: SearchOptions,
    no_line_numbers: bool,
    format: &str,
    stats: bool,
    export_path: Option<String>,
) -> Result<(), Box<dyn std::error::Error>> {
    let results = search_code(query, path, &options)?;

    if let Some(path) = export_path {
        export::export_results(&results, &path, query)?;
        println!("{}", format!("Results exported to: {}", path).green());
    } else {
        match format {
            "json" => {
                let json = serde_json::to_string_pretty(&results)?;
                println!("{}", json);
            }
            _ => {
                if results.is_empty() {
                    println!("{}", "No matches found.".dimmed());
                } else {
                    print_results(&results, !no_line_numbers, options.rank);
                    if stats {
                        print_search_stats(&results, query);
                    }
                }
            }
        }
    }

    Ok(())
}

/// Handle the files command
///
/// # Arguments
///
/// * `path` - The directory to list files from
/// * `extensions` - Optional list of file extensions to filter by
/// * `exclude` - Optional list of directories to exclude
///
/// # Returns
///
/// Result indicating success or error
pub fn handle_files_command(
    path: &Path,
    extensions: Option<Vec<String>>,
    exclude: Option<Vec<String>>,
) -> Result<(), Box<dyn std::error::Error>> {
    let files = list_files(path, extensions.as_deref(), exclude.as_deref())?;

    match extensions {
        Some(_) => {
            for file in files {
                println!("{}", file.path);
            }
        }
        None => {
            let json = serde_json::to_string_pretty(&files)?;
            println!("{}", json);
        }
    }

    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::fs;
    use tempfile::tempdir;

    #[test]
    fn test_handle_search_command() {
        let dir = tempdir().unwrap();
        fs::write(dir.path().join("test.rs"), "fn test() {}").unwrap();

        let options = SearchOptions::default();
        let result = handle_search_command("test", dir.path(), options, false, "text", false, None);

        assert!(result.is_ok());
    }
}