nu_protocol/config/
completions.rs

1use super::{config_update_string_enum, prelude::*};
2use crate as nu_protocol;
3use crate::engine::Closure;
4
5#[derive(Clone, Copy, Debug, Default, IntoValue, PartialEq, Eq, Serialize, Deserialize)]
6pub enum CompletionAlgorithm {
7    #[default]
8    Prefix,
9    Fuzzy,
10}
11
12impl FromStr for CompletionAlgorithm {
13    type Err = &'static str;
14
15    fn from_str(s: &str) -> Result<Self, Self::Err> {
16        match s.to_ascii_lowercase().as_str() {
17            "prefix" => Ok(Self::Prefix),
18            "fuzzy" => Ok(Self::Fuzzy),
19            _ => Err("'prefix' or 'fuzzy'"),
20        }
21    }
22}
23
24impl UpdateFromValue for CompletionAlgorithm {
25    fn update(&mut self, value: &Value, path: &mut ConfigPath, errors: &mut ConfigErrors) {
26        config_update_string_enum(self, value, path, errors)
27    }
28}
29
30#[derive(Clone, Copy, Debug, Default, IntoValue, PartialEq, Eq, Serialize, Deserialize)]
31pub enum CompletionSort {
32    #[default]
33    Smart,
34    Alphabetical,
35}
36
37impl FromStr for CompletionSort {
38    type Err = &'static str;
39
40    fn from_str(s: &str) -> Result<Self, Self::Err> {
41        match s.to_ascii_lowercase().as_str() {
42            "smart" => Ok(Self::Smart),
43            "alphabetical" => Ok(Self::Alphabetical),
44            _ => Err("'smart' or 'alphabetical'"),
45        }
46    }
47}
48
49impl UpdateFromValue for CompletionSort {
50    fn update(&mut self, value: &Value, path: &mut ConfigPath, errors: &mut ConfigErrors) {
51        config_update_string_enum(self, value, path, errors)
52    }
53}
54
55#[derive(Clone, Debug, IntoValue, Serialize, Deserialize)]
56pub struct ExternalCompleterConfig {
57    pub enable: bool,
58    pub max_results: i64,
59    pub completer: Option<Closure>,
60}
61
62impl Default for ExternalCompleterConfig {
63    fn default() -> Self {
64        Self {
65            enable: true,
66            max_results: 100,
67            completer: None,
68        }
69    }
70}
71
72impl UpdateFromValue for ExternalCompleterConfig {
73    fn update<'a>(
74        &mut self,
75        value: &'a Value,
76        path: &mut ConfigPath<'a>,
77        errors: &mut ConfigErrors,
78    ) {
79        let Value::Record { val: record, .. } = value else {
80            errors.type_mismatch(path, Type::record(), value);
81            return;
82        };
83
84        for (col, val) in record.iter() {
85            let path = &mut path.push(col);
86            match col.as_str() {
87                "completer" => match val {
88                    Value::Nothing { .. } => self.completer = None,
89                    Value::Closure { val, .. } => self.completer = Some(val.as_ref().clone()),
90                    _ => errors.type_mismatch(path, Type::custom("closure or nothing"), val),
91                },
92                "max_results" => self.max_results.update(val, path, errors),
93                "enable" => self.enable.update(val, path, errors),
94                _ => errors.unknown_option(path, val),
95            }
96        }
97    }
98}
99
100#[derive(Clone, Debug, IntoValue, Serialize, Deserialize)]
101pub struct CompletionConfig {
102    pub sort: CompletionSort,
103    pub case_sensitive: bool,
104    pub quick: bool,
105    pub partial: bool,
106    pub algorithm: CompletionAlgorithm,
107    pub external: ExternalCompleterConfig,
108    pub use_ls_colors: bool,
109}
110
111impl Default for CompletionConfig {
112    fn default() -> Self {
113        Self {
114            sort: CompletionSort::default(),
115            case_sensitive: false,
116            quick: true,
117            partial: true,
118            algorithm: CompletionAlgorithm::default(),
119            external: ExternalCompleterConfig::default(),
120            use_ls_colors: true,
121        }
122    }
123}
124
125impl UpdateFromValue for CompletionConfig {
126    fn update<'a>(
127        &mut self,
128        value: &'a Value,
129        path: &mut ConfigPath<'a>,
130        errors: &mut ConfigErrors,
131    ) {
132        let Value::Record { val: record, .. } = value else {
133            errors.type_mismatch(path, Type::record(), value);
134            return;
135        };
136
137        for (col, val) in record.iter() {
138            let path = &mut path.push(col);
139            match col.as_str() {
140                "sort" => self.sort.update(val, path, errors),
141                "quick" => self.quick.update(val, path, errors),
142                "partial" => self.partial.update(val, path, errors),
143                "algorithm" => self.algorithm.update(val, path, errors),
144                "case_sensitive" => self.case_sensitive.update(val, path, errors),
145                "external" => self.external.update(val, path, errors),
146                "use_ls_colors" => self.use_ls_colors.update(val, path, errors),
147                _ => errors.unknown_option(path, val),
148            }
149        }
150    }
151}