Skip to content

Commit 1a090d1

Browse files
committed
Set match_indices for fuzzy-matched suggestions
1 parent 649ee03 commit 1a090d1

11 files changed

+90
-42
lines changed

crates/nu-cli/src/completions/attribute_completions.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ impl Completer for AttributeCompletion {
4444
});
4545
}
4646

47-
matcher.results()
47+
matcher.suggestion_results()
4848
}
4949
}
5050

@@ -80,6 +80,6 @@ impl Completer for AttributableCompletion {
8080
});
8181
}
8282

83-
matcher.results()
83+
matcher.suggestion_results()
8484
}
8585
}

crates/nu-cli/src/completions/cell_path_completions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ impl Completer for CellPathCompletion<'_> {
7272
for suggestion in get_suggestions_by_value(&value, current_span) {
7373
matcher.add_semantic_suggestion(suggestion);
7474
}
75-
matcher.results()
75+
matcher.suggestion_results()
7676
}
7777
}
7878

crates/nu-cli/src/completions/command_completions.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,12 @@ impl Completer for CommandCompletion {
146146
};
147147

148148
let mut res = Vec::new();
149-
for cmd_name in matcher.results() {
150-
if let Some(sugg) = internal_suggs
149+
for (cmd_name, indices) in matcher.results() {
150+
if let Some(mut sugg) = internal_suggs
151151
.remove(&cmd_name)
152152
.or_else(|| external_suggs.remove(&cmd_name))
153153
{
154+
sugg.suggestion.match_indices = indices;
154155
res.push(sugg);
155156
}
156157
}

crates/nu-cli/src/completions/completion_common.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ fn complete_rec(
123123

124124
if has_more {
125125
let mut completions = vec![];
126-
for built in matcher.results() {
126+
for (built, _) in matcher.results() {
127127
completions.extend(complete_rec(
128128
&partial[1..],
129129
&[built],
@@ -135,7 +135,11 @@ fn complete_rec(
135135
}
136136
completions
137137
} else {
138-
matcher.results()
138+
matcher
139+
.results()
140+
.into_iter()
141+
.map(|(built, _)| built)
142+
.collect()
139143
}
140144
}
141145

crates/nu-cli/src/completions/completion_options.rs

Lines changed: 66 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ enum State<T> {
4848
Fuzzy {
4949
matcher: Matcher,
5050
atom: Atom,
51-
/// Holds (haystack, item, score)
52-
items: Vec<(String, T, u16)>,
51+
/// Holds (haystack, item, score, match_indices)
52+
items: Vec<(String, T, u16, Vec<usize>)>,
5353
},
5454
}
5555

@@ -161,7 +161,13 @@ impl<T> NuMatcher<'_, T> {
161161
return false;
162162
};
163163
if let Some(item) = item {
164-
items.push((haystack.to_string(), item, score));
164+
let indices = indices
165+
.iter()
166+
.map(|i| {
167+
usize::try_from(*i).expect("should be on at least a 32-bit system")
168+
})
169+
.collect();
170+
items.push((haystack.to_string(), item, score, indices));
165171
}
166172
true
167173
}
@@ -180,10 +186,9 @@ impl<T> NuMatcher<'_, T> {
180186
self.matches_aux(haystack, None)
181187
}
182188

183-
/// Get all the items that matched (sorted)
184-
pub fn results(self) -> Vec<T> {
185-
match self.state {
186-
State::Prefix { mut items, .. } | State::Substring { mut items, .. } => {
189+
fn sort(&mut self) {
190+
match &mut self.state {
191+
State::Prefix { items, .. } | State::Substring { items, .. } => {
187192
items.sort_by(|(haystack1, _), (haystack2, _)| {
188193
let cmp_sensitive = haystack1.cmp(haystack2);
189194
if self.options.case_sensitive {
@@ -195,26 +200,33 @@ impl<T> NuMatcher<'_, T> {
195200
.then(cmp_sensitive)
196201
}
197202
});
198-
items.into_iter().map(|(_, item)| item).collect::<Vec<_>>()
199203
}
200-
State::Fuzzy { mut items, .. } => {
201-
match self.options.sort {
202-
CompletionSort::Alphabetical => {
203-
items.sort_by(|(haystack1, _, _), (haystack2, _, _)| {
204-
haystack1.cmp(haystack2)
205-
});
206-
}
207-
CompletionSort::Smart => {
208-
items.sort_by(|(haystack1, _, score1), (haystack2, _, score2)| {
209-
score2.cmp(score1).then(haystack1.cmp(haystack2))
210-
});
211-
}
204+
State::Fuzzy { items, .. } => match self.options.sort {
205+
CompletionSort::Alphabetical => {
206+
items.sort_by(|(haystack1, _, _, _), (haystack2, _, _, _)| {
207+
haystack1.cmp(haystack2)
208+
});
212209
}
213-
items
214-
.into_iter()
215-
.map(|(_, item, _)| item)
216-
.collect::<Vec<_>>()
217-
}
210+
CompletionSort::Smart => {
211+
items.sort_by(|(haystack1, _, score1, _), (haystack2, _, score2, _)| {
212+
score2.cmp(score1).then(haystack1.cmp(haystack2))
213+
});
214+
}
215+
},
216+
}
217+
}
218+
219+
pub fn results(mut self) -> Vec<(T, Option<Vec<usize>>)> {
220+
self.sort();
221+
match self.state {
222+
State::Prefix { items, .. } | State::Substring { items, .. } => items
223+
.into_iter()
224+
.map(|(_, item)| (item, None))
225+
.collect::<Vec<_>>(),
226+
State::Fuzzy { items, .. } => items
227+
.into_iter()
228+
.map(|(_, item, _, indices)| (item, Some(indices)))
229+
.collect::<Vec<_>>(),
218230
}
219231
}
220232
}
@@ -224,6 +236,17 @@ impl NuMatcher<'_, SemanticSuggestion> {
224236
let value = sugg.suggestion.value.to_string();
225237
self.add(value, sugg)
226238
}
239+
240+
/// Get all the items that matched (sorted)
241+
pub fn suggestion_results(self) -> Vec<SemanticSuggestion> {
242+
self.results()
243+
.into_iter()
244+
.map(|(mut sugg, indices)| {
245+
sugg.suggestion.match_indices = indices;
246+
sugg
247+
})
248+
.collect()
249+
}
227250
}
228251

229252
impl From<CompletionAlgorithm> for MatchAlgorithm {
@@ -311,10 +334,11 @@ mod test {
311334
};
312335
let mut matcher = NuMatcher::new(needle, &options);
313336
matcher.add(haystack, haystack);
337+
let results: Vec<_> = matcher.results().iter().map(|r| r.0).collect();
314338
if should_match {
315-
assert_eq!(vec![haystack], matcher.results());
339+
assert_eq!(vec![haystack], results);
316340
} else {
317-
assert_ne!(vec![haystack], matcher.results());
341+
assert_ne!(vec![haystack], results);
318342
}
319343
}
320344

@@ -329,7 +353,14 @@ mod test {
329353
matcher.add(item, item);
330354
}
331355
// Sort by score, then in alphabetical order
332-
assert_eq!(vec!["fob", "foo bar", "foo/bar"], matcher.results());
356+
assert_eq!(
357+
vec![
358+
("fob", Some(vec![0, 1, 2])),
359+
("foo bar", Some(vec![0, 1, 4])),
360+
("foo/bar", Some(vec![0, 1, 4]))
361+
],
362+
matcher.results()
363+
);
333364
}
334365

335366
#[test]
@@ -347,6 +378,12 @@ mod test {
347378
matcher.add(item, item);
348379
}
349380
// Make sure the spaces are respected
350-
assert_eq!(vec!["'i love spaces' so much"], matcher.results());
381+
assert_eq!(
382+
vec![(
383+
"'i love spaces' so much",
384+
Some(vec![0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
385+
)],
386+
matcher.results()
387+
);
351388
}
352389
}

crates/nu-cli/src/completions/custom_completions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ impl<T: Completer> Completer for CustomCompletion<T> {
158158
for sugg in suggestions {
159159
matcher.add_semantic_suggestion(sugg);
160160
}
161-
matcher.results()
161+
matcher.suggestion_results()
162162
} else {
163163
suggestions
164164
.into_iter()

crates/nu-cli/src/completions/dotnu_completions.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,13 @@ impl Completer for DotNuCompletion {
8787
);
8888
}
8989
}
90-
completions.extend(matcher.results());
90+
completions.extend(
91+
matcher
92+
.results()
93+
.into_iter()
94+
.map(|(s, _)| s)
95+
.collect::<Vec<_>>(),
96+
);
9197
}
9298

9399
// Fetch the files

crates/nu-cli/src/completions/flag_completions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,6 @@ impl Completer for FlagCompletion {
5353
}
5454
add_suggestion(format!("--{}", named.long), named.desc.clone());
5555
}
56-
matcher.results()
56+
matcher.suggestion_results()
5757
}
5858
}

crates/nu-cli/src/completions/operator_completions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,6 @@ impl Completer for OperatorCompletion<'_> {
274274
kind: Some(SuggestionKind::Operator),
275275
});
276276
}
277-
matcher.results()
277+
matcher.suggestion_results()
278278
}
279279
}

crates/nu-cli/src/completions/static_completions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,6 @@ impl Completer for StaticCompletion {
5959
}
6060
}
6161

62-
matcher.results()
62+
matcher.suggestion_results()
6363
}
6464
}

0 commit comments

Comments
 (0)