mirror of
https://github.com/nushell/nushell.git
synced 2025-08-17 18:11:25 +02:00
Add a matches method instead of remove_last
This commit is contained in:
@ -59,7 +59,7 @@ impl CommandCompletion {
|
|||||||
.max_results
|
.max_results
|
||||||
> executables.len() as i64
|
> executables.len() as i64
|
||||||
{
|
{
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
let Ok(name) = item.file_name().into_string() else {
|
let Ok(name) = item.file_name().into_string() else {
|
||||||
continue;
|
continue;
|
||||||
@ -72,8 +72,12 @@ impl CommandCompletion {
|
|||||||
} else {
|
} else {
|
||||||
name.clone()
|
name.clone()
|
||||||
};
|
};
|
||||||
if matcher.add(
|
if matcher.matches(&name) && is_executable::is_executable(item.path()) {
|
||||||
name.clone(),
|
executables.insert(name.clone());
|
||||||
|
// This causes the matcher to match the executable name twice,
|
||||||
|
// but it's likely a cost we can eat
|
||||||
|
matcher.add(
|
||||||
|
name,
|
||||||
SemanticSuggestion {
|
SemanticSuggestion {
|
||||||
suggestion: Suggestion {
|
suggestion: Suggestion {
|
||||||
value,
|
value,
|
||||||
@ -84,12 +88,7 @@ impl CommandCompletion {
|
|||||||
// TODO: is there a way to create a test?
|
// TODO: is there a way to create a test?
|
||||||
kind: None,
|
kind: None,
|
||||||
},
|
},
|
||||||
) {
|
);
|
||||||
if is_executable::is_executable(item.path()) {
|
|
||||||
executables.insert(name);
|
|
||||||
} else {
|
|
||||||
matcher.remove_last();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@ enum State<T> {
|
|||||||
items: Vec<(String, T)>,
|
items: Vec<(String, T)>,
|
||||||
},
|
},
|
||||||
Fuzzy {
|
Fuzzy {
|
||||||
|
matcher: Box<SkimMatcherV2>,
|
||||||
/// Holds (haystack, item, score)
|
/// Holds (haystack, item, score)
|
||||||
items: Vec<(String, T, i64)>,
|
items: Vec<(String, T, i64)>,
|
||||||
},
|
},
|
||||||
@ -57,63 +58,74 @@ impl<T> NuMatcher<T> {
|
|||||||
needle: lowercase_needle,
|
needle: lowercase_needle,
|
||||||
state: State::Prefix { items: Vec::new() },
|
state: State::Prefix { items: Vec::new() },
|
||||||
},
|
},
|
||||||
MatchAlgorithm::Fuzzy => NuMatcher {
|
MatchAlgorithm::Fuzzy => {
|
||||||
|
let mut matcher = SkimMatcherV2::default();
|
||||||
|
if options.case_sensitive {
|
||||||
|
matcher = matcher.respect_case();
|
||||||
|
} else {
|
||||||
|
matcher = matcher.ignore_case();
|
||||||
|
};
|
||||||
|
NuMatcher {
|
||||||
options,
|
options,
|
||||||
needle: orig_needle.to_owned(),
|
needle: orig_needle.to_owned(),
|
||||||
state: State::Fuzzy { items: Vec::new() },
|
state: State::Fuzzy {
|
||||||
|
matcher: Box::new(matcher),
|
||||||
|
items: Vec::new(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Add the given item if the given haystack matches.
|
/// Add the given item if the given haystack matches.
|
||||||
///
|
///
|
||||||
/// Returns whether the item was added.
|
/// Returns whether the item was added.
|
||||||
pub fn add(&mut self, haystack: String, item: T) -> bool {
|
pub fn add(&mut self, haystack: String, item: T) -> bool {
|
||||||
|
let haystack = trim_quotes_str(&haystack);
|
||||||
match &mut self.state {
|
match &mut self.state {
|
||||||
State::Prefix { items } => {
|
State::Prefix { items } => {
|
||||||
let haystack = trim_quotes_str(&haystack).to_owned();
|
let haystack = if self.options.case_sensitive {
|
||||||
let haystack_lowercased = if self.options.case_sensitive {
|
Cow::Borrowed(haystack)
|
||||||
Cow::Borrowed(&haystack)
|
|
||||||
} else {
|
} else {
|
||||||
Cow::Owned(haystack.to_folded_case())
|
Cow::Owned(haystack.to_folded_case())
|
||||||
};
|
};
|
||||||
let matches = if self.options.positional {
|
let matches = if self.options.positional {
|
||||||
haystack_lowercased.starts_with(self.needle.as_str())
|
haystack.starts_with(self.needle.as_str())
|
||||||
} else {
|
} else {
|
||||||
haystack_lowercased.contains(self.needle.as_str())
|
haystack.contains(self.needle.as_str())
|
||||||
};
|
};
|
||||||
if matches {
|
if matches {
|
||||||
items.push((haystack, item));
|
items.push((haystack.to_string(), item));
|
||||||
}
|
}
|
||||||
matches
|
matches
|
||||||
}
|
}
|
||||||
State::Fuzzy { items } => {
|
State::Fuzzy { items, matcher } => {
|
||||||
let mut matcher = SkimMatcherV2::default();
|
let Some(score) = matcher.fuzzy_match(haystack, &self.needle) else {
|
||||||
if self.options.case_sensitive {
|
|
||||||
matcher = matcher.respect_case();
|
|
||||||
} else {
|
|
||||||
matcher = matcher.ignore_case();
|
|
||||||
};
|
|
||||||
let Some(score) = matcher.fuzzy_match(&haystack, &self.needle) else {
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
items.push((haystack, item, score));
|
items.push((haystack.to_string(), item, score));
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove the last added item. This is useful if you want to filter matched
|
/// Returns whether the item was added.
|
||||||
/// completions by some expensive condition. You can call `add`, run the expensive condition,
|
pub fn matches(&mut self, haystack: &str) -> bool {
|
||||||
/// then call `remove_last` if the expensive condition is false.
|
let haystack = trim_quotes_str(haystack).to_owned();
|
||||||
pub fn remove_last(&mut self) {
|
|
||||||
match &mut self.state {
|
match &mut self.state {
|
||||||
State::Prefix { items } => {
|
State::Prefix { .. } => {
|
||||||
items.pop();
|
let haystack = if self.options.case_sensitive {
|
||||||
|
Cow::Borrowed(&haystack)
|
||||||
|
} else {
|
||||||
|
Cow::Owned(haystack.to_folded_case())
|
||||||
|
};
|
||||||
|
if self.options.positional {
|
||||||
|
haystack.starts_with(self.needle.as_str())
|
||||||
|
} else {
|
||||||
|
haystack.contains(self.needle.as_str())
|
||||||
}
|
}
|
||||||
State::Fuzzy { items } => {
|
|
||||||
items.pop();
|
|
||||||
}
|
}
|
||||||
|
State::Fuzzy { matcher, .. } => matcher.fuzzy_match(&haystack, &self.needle).is_some(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user