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>,
65}
66
67impl Default for ExternalCompleterConfig {
68 fn default() -> Self {
69 Self {
70 enable: true,
71 max_results: 100,
72 completer: None,
73 }
74 }
75}
76
77impl UpdateFromValue for ExternalCompleterConfig {
78 fn update<'a>(
79 &mut self,
80 value: &'a Value,
81 path: &mut ConfigPath<'a>,
82 errors: &mut ConfigErrors,
83 ) {
84 let Value::Record { val: record, .. } = value else {
85 errors.type_mismatch(path, Type::record(), value);
86 return;
87 };
88
89 for (col, val) in record.iter() {
90 let path = &mut path.push(col);
91 match col.as_str() {
92 "completer" => match val {
93 Value::Nothing { .. } => self.completer = None,
94 Value::Closure { val, .. } => self.completer = Some(val.as_ref().clone()),
95 _ => errors.type_mismatch(path, Type::custom("closure or nothing"), val),
96 },
97 "max_results" => self.max_results.update(val, path, errors),
98 "enable" => self.enable.update(val, path, errors),
99 _ => errors.unknown_option(path, val),
100 }
101 }
102 }
103}
104
105#[derive(Clone, Debug, IntoValue, Serialize, Deserialize)]
106pub struct CompletionConfig {
107 pub sort: CompletionSort,
108 pub case_sensitive: bool,
109 pub quick: bool,
110 pub partial: bool,
111 pub persistent_menus: bool,
112 pub algorithm: CompletionAlgorithm,
113 pub external: ExternalCompleterConfig,
114 pub use_ls_colors: bool,
115 pub cache_size: i64,
117}
118
119impl Default for CompletionConfig {
120 fn default() -> Self {
121 Self {
122 sort: CompletionSort::default(),
123 case_sensitive: false,
124 quick: true,
125 partial: true,
126 persistent_menus: false,
127 algorithm: CompletionAlgorithm::default(),
128 external: ExternalCompleterConfig::default(),
129 use_ls_colors: true,
130 cache_size: 100,
131 }
132 }
133}
134
135impl UpdateFromValue for CompletionConfig {
136 fn update<'a>(
137 &mut self,
138 value: &'a Value,
139 path: &mut ConfigPath<'a>,
140 errors: &mut ConfigErrors,
141 ) {
142 let Value::Record { val: record, .. } = value else {
143 errors.type_mismatch(path, Type::record(), value);
144 return;
145 };
146
147 for (col, val) in record.iter() {
148 let path = &mut path.push(col);
149 match col.as_str() {
150 "sort" => self.sort.update(val, path, errors),
151 "quick" => self.quick.update(val, path, errors),
152 "partial" => self.partial.update(val, path, errors),
153 "persistent_menus" => self.persistent_menus.update(val, path, errors),
154 "algorithm" => self.algorithm.update(val, path, errors),
155 "case_sensitive" => self.case_sensitive.update(val, path, errors),
156 "external" => self.external.update(val, path, errors),
157 "use_ls_colors" => self.use_ls_colors.update(val, path, errors),
158 "cache_size" => self.cache_size.update(val, path, errors),
159 _ => errors.unknown_option(path, val),
160 }
161 }
162 }
163}