Skip to main content

greplm_core/
config.rs

1//! Index configuration persisted at `.greplm/config.toml`.
2
3use serde::{Deserialize, Serialize};
4use std::path::Path;
5
6use crate::error::{Error, Result};
7
8/// Which ingest read backend to use.
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
10#[serde(rename_all = "kebab-case")]
11pub enum Backend {
12    /// Portable rayon-based read pool (all platforms).
13    #[default]
14    Auto,
15    /// Force the portable backend.
16    Rayon,
17    /// Linux io_uring backend (requires the `io-uring` build feature).
18    IoUring,
19}
20
21/// Persistent project configuration.
22#[derive(Debug, Clone, Serialize, Deserialize)]
23#[serde(default)]
24pub struct Config {
25    /// Glob patterns to include (empty = all text files).
26    pub include: Vec<String>,
27    /// Extra glob patterns to exclude (on top of .gitignore).
28    pub exclude: Vec<String>,
29    /// Skip files larger than this many bytes.
30    pub max_file_size: u64,
31    /// Honor `.gitignore` / `.ignore` files during the walk.
32    pub respect_gitignore: bool,
33    /// Index hidden files and directories.
34    pub index_hidden: bool,
35    /// Ingest read backend.
36    pub backend: Backend,
37    /// Merge segments automatically once this many accumulate.
38    pub merge_threshold: usize,
39}
40
41impl Default for Config {
42    fn default() -> Self {
43        Self {
44            include: Vec::new(),
45            exclude: vec![
46                "**/.git/**".to_string(),
47                "**/node_modules/**".to_string(),
48                "**/target/**".to_string(),
49                "**/.greplm/**".to_string(),
50            ],
51            max_file_size: 4 * 1024 * 1024,
52            respect_gitignore: true,
53            index_hidden: false,
54            backend: Backend::Auto,
55            merge_threshold: 16,
56        }
57    }
58}
59
60impl Config {
61    pub fn load(path: &Path) -> Result<Config> {
62        match std::fs::read_to_string(path) {
63            Ok(s) => Ok(toml::from_str(&s)?),
64            Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(Config::default()),
65            Err(e) => Err(Error::io(path, e)),
66        }
67    }
68
69    pub fn save(&self, path: &Path) -> Result<()> {
70        let s = toml::to_string_pretty(self)?;
71        std::fs::write(path, s).map_err(|e| Error::io(path, e))
72    }
73}