Unnamed repository; edit this file 'description' to name the repository.
Fix byte/char indexing mix-up in path completion
The positions passed to `Transaction::change_by_selection` should be character indexes. `edit_diff` is meant to track the number of characters that should be deleted to erase the file name that has been typed so far (if any). Mistakenly this was using `str::len` which is the byte count. This fixes a bug that could cause more text to be deleted than intended or a panic when completing a directory with multi-byte characters like 'éclair'. This change also moves the `edit_diff` binding out of the loop since it's now performing some non-trivial work (counting characters, where before it was just accessing the pre-computed number of bytes).
Michael Davis 2025-01-29
parent 8328c42 · commit c9dc940
-rw-r--r--helix-term/src/handlers/completion/path.rs10
1 files changed, 5 insertions, 5 deletions
diff --git a/helix-term/src/handlers/completion/path.rs b/helix-term/src/handlers/completion/path.rs
index 102de6b0..9fd24ac8 100644
--- a/helix-term/src/handlers/completion/path.rs
+++ b/helix-term/src/handlers/completion/path.rs
@@ -72,6 +72,11 @@ pub(crate) fn path_completion(
return Vec::new();
};
+ let edit_diff = typed_file_name
+ .as_ref()
+ .map(|s| s.chars().count())
+ .unwrap_or_default();
+
read_dir
.filter_map(Result::ok)
.filter_map(|dir_entry| {
@@ -88,11 +93,6 @@ pub(crate) fn path_completion(
let kind = path_kind(&md);
let documentation = path_documentation(&md, &dir_path.join(&file_name), kind);
- let edit_diff = typed_file_name
- .as_ref()
- .map(|f| f.len())
- .unwrap_or_default();
-
let transaction = Transaction::change_by_selection(&text, &selection, |range| {
let cursor = range.cursor(text.slice(..));
(cursor - edit_diff, cursor, Some((&file_name).into()))