nu_protocol/config/
history.rs

1use super::{config_update_string_enum, prelude::*};
2use crate as nu_protocol;
3
4#[derive(Clone, Copy, Debug, IntoValue, PartialEq, Eq, Serialize, Deserialize)]
5pub enum HistoryFileFormat {
6    /// Store history as an SQLite database with additional context
7    Sqlite,
8    /// store history as a plain text file where every line is one command (without any context such as timestamps)
9    Plaintext,
10}
11
12impl HistoryFileFormat {
13    pub fn default_file_name(self) -> std::path::PathBuf {
14        match self {
15            HistoryFileFormat::Plaintext => "history.txt",
16            HistoryFileFormat::Sqlite => "history.sqlite3",
17        }
18        .into()
19    }
20}
21
22impl FromStr for HistoryFileFormat {
23    type Err = &'static str;
24
25    fn from_str(s: &str) -> Result<Self, Self::Err> {
26        match s.to_ascii_lowercase().as_str() {
27            "sqlite" => Ok(Self::Sqlite),
28            "plaintext" => Ok(Self::Plaintext),
29            _ => Err("'sqlite' or 'plaintext'"),
30        }
31    }
32}
33
34impl UpdateFromValue for HistoryFileFormat {
35    fn update(&mut self, value: &Value, path: &mut ConfigPath, errors: &mut ConfigErrors) {
36        config_update_string_enum(self, value, path, errors)
37    }
38}
39
40#[derive(Clone, Copy, Debug, IntoValue, PartialEq, Eq, Serialize, Deserialize)]
41pub struct HistoryConfig {
42    pub max_size: i64,
43    pub sync_on_enter: bool,
44    pub file_format: HistoryFileFormat,
45    pub isolation: bool,
46}
47
48impl HistoryConfig {
49    pub fn file_path(&self) -> Option<std::path::PathBuf> {
50        nu_path::nu_config_dir().map(|mut history_path| {
51            history_path.push(self.file_format.default_file_name());
52            history_path.into()
53        })
54    }
55}
56
57impl Default for HistoryConfig {
58    fn default() -> Self {
59        Self {
60            max_size: 100_000,
61            sync_on_enter: true,
62            file_format: HistoryFileFormat::Plaintext,
63            isolation: false,
64        }
65    }
66}
67
68impl UpdateFromValue for HistoryConfig {
69    fn update<'a>(
70        &mut self,
71        value: &'a Value,
72        path: &mut ConfigPath<'a>,
73        errors: &mut ConfigErrors,
74    ) {
75        let Value::Record { val: record, .. } = value else {
76            errors.type_mismatch(path, Type::record(), value);
77            return;
78        };
79
80        for (col, val) in record.iter() {
81            let path = &mut path.push(col);
82            match col.as_str() {
83                "isolation" => self.isolation.update(val, path, errors),
84                "sync_on_enter" => self.sync_on_enter.update(val, path, errors),
85                "max_size" => self.max_size.update(val, path, errors),
86                "file_format" => self.file_format.update(val, path, errors),
87                _ => errors.unknown_option(path, val),
88            }
89        }
90    }
91}