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