semantic_search_cli/
lib.rs

1//! # Semantic Search CLI
2//!
3//! This library provides basic functionality for the semantic search CLI.
4
5#![deny(missing_docs)]
6#![warn(clippy::all, clippy::nursery, clippy::cargo)]
7#![allow(clippy::multiple_crate_versions, reason = "Dependencies")]
8
9pub mod commands;
10mod config;
11mod util;
12
13use anyhow::Result;
14use argh::FromArgs;
15use commands::Command;
16pub use config::{Config, parse_config};
17use log::{debug, info, warn};
18
19/// 🔎 Semantic search.
20#[derive(FromArgs, Debug)]
21#[argh(help_triggers("-h", "--help"))]
22pub struct Args {
23    /// the command to execute.
24    #[argh(subcommand)]
25    pub command: Command,
26}
27
28/// Execute the command.
29///
30/// # Errors
31///
32/// Returns an [IO error](std::io::Error) if reading or writing fails.
33#[allow(clippy::future_not_send, reason = "Main function")]
34pub async fn execute(command: Command, config: Config) -> Result<()> {
35    debug!("Executing command: {:?}", command);
36    debug!("Config: {:?}", config);
37
38    match command {
39        Command::Index(index) => {
40            info!("Indexing files...");
41            let summary = index.execute(config).await?;
42            let attention_required = summary.changed + summary.new > 0;
43            info!("Indexing complete!");
44            if attention_required {
45                info!(
46                    "Summary: {} file(s) changed, {} file(s) created, {} file(s) deleted. 📝",
47                    summary.changed, summary.new, summary.deleted
48                );
49            } else if summary.deleted > 0 {
50                info!("{} file(s) deleted since last index. 🗑️", summary.deleted);
51            } else {
52                info!("No changes detected. ☕");
53            }
54        }
55        Command::Search(search) => {
56            let results = search.execute(config).await?;
57            for (file_path, similarity) in results {
58                let percent = similarity * 100.0;
59                println!("{percent:.2}%: {file_path}");
60            }
61        }
62        Command::Telegram(telegram) => telegram.execute(config).await?,
63        Command::Serve(serve) => serve.execute(config).await?,
64    };
65
66    Ok(())
67}