Skip to content

Commit

Permalink
Use actual word boundaries when filtering completions
Browse files Browse the repository at this point in the history
Previously, this would only split words on upper-lower boundaries or
on `_`/`-`.

The result was that we would filter out completions too aggressively.
The filter works by taking a suggested completion, say `foo_bar_lol`, split
it up into words - `foo`, `bar, `lol` - and check whether any of the words
start with the same characters as what the user already typed: `fo`, or `bar`,
...

In the case of Ruby, though, `:` wasn't considered a word boundary. If the
LSP would return `:foobar` when the user typed `:foo`, we'd check if there are
any completions that match `foo` (because that's the current word) but
we'd compare against `foobar`, not `:` or `:foobar`.

With this change, we get more match candidates and thus more completions in Ruby.

Co-authored-by: Max <[email protected]>
  • Loading branch information
mrnugget and maxbrunsfeld committed Mar 11, 2024
1 parent e018b14 commit 66a0e4d
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 25 deletions.
41 changes: 16 additions & 25 deletions crates/editor/src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10680,32 +10680,23 @@ pub fn styled_runs_for_code_label<'a>(
}

pub(crate) fn split_words(text: &str) -> impl std::iter::Iterator<Item = &str> + '_ {
let mut index = 0;
let mut codepoints = text.char_indices().peekable();

std::iter::from_fn(move || {
let start_index = index;
while let Some((new_index, codepoint)) = codepoints.next() {
index = new_index + codepoint.len_utf8();
let current_upper = codepoint.is_uppercase();
let next_upper = codepoints
.peek()
.map(|(_, c)| c.is_uppercase())
.unwrap_or(false);

if !current_upper && next_upper {
return Some(&text[start_index..index]);
let mut prev_index = 0;
let mut prev_codepoint: Option<char> = None;
text.char_indices()
.chain([(text.len(), '\0')])
.filter_map(move |(index, codepoint)| {
let prev_codepoint = prev_codepoint.replace(codepoint)?;
let is_boundary = index == text.len()
|| !prev_codepoint.is_uppercase() && codepoint.is_uppercase()
|| !prev_codepoint.is_alphanumeric() && codepoint.is_alphanumeric();
if is_boundary {
let chunk = &text[prev_index..index];
prev_index = index;
Some(chunk)
} else {
None
}
}

index = text.len();
if start_index < text.len() {
return Some(&text[start_index..]);
}
None
})
.flat_map(|word| word.split_inclusive('_'))
.flat_map(|word| word.split_inclusive('-'))
})
}

trait RangeToAnchorExt {
Expand Down
2 changes: 2 additions & 0 deletions crates/editor/src/editor_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7423,6 +7423,8 @@ fn test_split_words() {
assert_eq!(split("Hello_World"), &["Hello_", "World"]);
assert_eq!(split("helloWOrld"), &["hello", "WOrld"]);
assert_eq!(split("helloworld"), &["helloworld"]);

assert_eq!(split(":do_the_thing"), &[":", "do_", "the_", "thing"]);
}

#[gpui::test]
Expand Down

0 comments on commit 66a0e4d

Please sign in to comment.