diff --git a/numbat-cli/src/completer.rs b/numbat-cli/src/completer.rs index 43dfd24a..b249bbd7 100644 --- a/numbat-cli/src/completer.rs +++ b/numbat-cli/src/completer.rs @@ -131,7 +131,7 @@ impl Completer for NumbatCompleter { candidates .map(|w| Pair { display: w.to_string(), - replacement: w.to_string(), + replacement: w, }) .collect(), )) diff --git a/numbat/src/lib.rs b/numbat/src/lib.rs index 20055bd7..dcaf42b4 100644 --- a/numbat/src/lib.rs +++ b/numbat/src/lib.rs @@ -47,6 +47,8 @@ mod unit_registry; pub mod value; mod vm; +use std::borrow::Cow; + use bytecode_interpreter::BytecodeInterpreter; use column_formatter::ColumnFormatter; use currency::ExchangeRatesCache; @@ -200,15 +202,6 @@ impl Context { } pub fn print_environment(&self) -> Markup { - let mut functions: Vec<_> = self.function_names().collect(); - functions.sort(); - let mut dimensions = Vec::from(self.dimension_names()); - dimensions.sort(); - let mut units = Vec::from(self.unit_names()); - units.sort(); - let mut variables: Vec<_> = self.variable_names().collect(); - variables.sort(); - let mut output = m::empty(); output += m::emphasized("List of functions:") + m::nl(); @@ -253,11 +246,11 @@ impl Context { /// Gets completions for the given word_part /// /// If `add_paren` is true, then an opening paren will be added to the end of function names - pub fn get_completions_for<'a>( + pub fn get_completions_for( &self, - word_part: &'a str, + word_part: &str, add_paren: bool, - ) -> impl Iterator + 'a { + ) -> impl Iterator { const COMMON_METRIC_PREFIXES: &[&str] = &[ "pico", "nano", "micro", "milli", "centi", "kilo", "mega", "giga", "tera", ]; @@ -270,53 +263,60 @@ impl Context { }) .collect(); - let mut words: Vec<_> = KEYWORDS.iter().map(|k| k.to_string()).collect(); + let mut words = Vec::new(); + + let mut add_if_valid = |word: Cow<'_, str>| { + if word.starts_with(word_part) { + words.push(word.into_owned()); + } + }; + + for kw in KEYWORDS { + add_if_valid((*kw).into()); + } for (patterns, _) in UNICODE_INPUT { for pattern in *patterns { - words.push(pattern.to_string()); + add_if_valid((*pattern).into()); } } - { - for variable in self.variable_names() { - words.push(variable.clone()); - } + for variable in self.variable_names() { + add_if_valid(variable.into()); + } - for function in self.function_names() { - if add_paren { - words.push(format!("{function}(")); - } else { - words.push(function.to_string()); - } + for mut function in self.function_names() { + if add_paren { + function.push('('); } + add_if_valid(function.into()); + } - for dimension in self.dimension_names() { - words.push(dimension.clone()); - } + for dimension in self.dimension_names() { + add_if_valid(dimension.into()); + } - for (_, (_, meta)) in self.unit_representations() { - for (unit, accepts_prefix) in meta.aliases { - words.push(unit.clone()); - - // Add some of the common long prefixes for units that accept them. - // We do not add all possible prefixes here in order to keep the - // number of completions to a reasonable size. Also, we do not add - // short prefixes for units that accept them, as that leads to lots - // and lots of 2-3 character words. - if accepts_prefix.long && meta.metric_prefixes { - for prefix in &metric_prefixes { - words.push(format!("{prefix}{unit}")); - } + for (_, (_, meta)) in self.unit_representations() { + for (unit, accepts_prefix) in meta.aliases { + // Add some of the common long prefixes for units that accept them. + // We do not add all possible prefixes here in order to keep the + // number of completions to a reasonable size. Also, we do not add + // short prefixes for units that accept them, as that leads to lots + // and lots of 2-3 character words. + if accepts_prefix.long && meta.metric_prefixes { + for prefix in &metric_prefixes { + add_if_valid(format!("{prefix}{unit}").into()); } } + + add_if_valid(unit.into()); } } words.sort(); words.dedup(); - words.into_iter().filter(move |w| w.starts_with(word_part)) + words.into_iter() } pub fn print_info_for_keyword(&mut self, keyword: &str) -> Markup {