From 8a33f7847bcb28e994727e6ca674a11c8d2f216e Mon Sep 17 00:00:00 2001 From: Yomain Date: Mon, 21 Apr 2025 21:35:32 +0200 Subject: [PATCH] fix: escape spaces in path completion --- helix-stdx/src/path.rs | 2 +- helix-term/src/handlers/completion/path.rs | 24 +++++++++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/helix-stdx/src/path.rs b/helix-stdx/src/path.rs index 53081b0f0..9b70b410d 100644 --- a/helix-stdx/src/path.rs +++ b/helix-stdx/src/path.rs @@ -210,7 +210,7 @@ pub fn get_truncated_path(path: impl AsRef) -> PathBuf { fn path_component_regex(windows: bool) -> String { // TODO: support backslash path escape on windows (when using git bash for example) let space_escape = if windows { r"[\^`]\s" } else { r"[\\]\s" }; - // partially baesd on what's allowed in an url but with some care to avoid + // partially based on what's allowed in an url but with some care to avoid // false positives (like any kind of brackets or quotes) r"[\w@.\-+#$%?!,;~&]|".to_owned() + space_escape } diff --git a/helix-term/src/handlers/completion/path.rs b/helix-term/src/handlers/completion/path.rs index c2ffa5efa..593e33695 100644 --- a/helix-term/src/handlers/completion/path.rs +++ b/helix-term/src/handlers/completion/path.rs @@ -14,6 +14,14 @@ use url::Url; use crate::handlers::completion::{item::CompletionResponse, CompletionItem, CompletionItems}; +fn unescape_spaces(string: &str) -> String { + string.replace("\\ ", " ").to_owned() +} + +fn escape_spaces(string: &str) -> String { + string.replace(' ', "\\ ").to_owned() +} + pub(crate) fn path_completion( selection: Selection, doc: &Document, @@ -32,14 +40,14 @@ pub(crate) fn path_completion( let (dir_path, typed_file_name) = get_path_suffix(line_until_cursor, false).and_then(|matched_path| { - let matched_path = Cow::from(matched_path); + let matched_path = unescape_spaces(&Cow::from(matched_path)); let path: Cow<_> = if matched_path.starts_with("file://") { - Url::from_str(&matched_path) + Url::from_str(matched_path.as_str()) .ok() .and_then(|url| url.to_file_path().ok())? .into() } else { - Path::new(&*matched_path).into() + Path::new(matched_path.as_str()).into() }; let path = path::expand(&path); let parent_dir = doc.path().and_then(|dp| dp.parent()); @@ -91,10 +99,12 @@ pub(crate) fn path_completion( let res: Vec<_> = read_dir .filter_map(Result::ok) .filter_map(|dir_entry| { - dir_entry - .metadata() - .ok() - .and_then(|md| Some((dir_entry.file_name().into_string().ok()?, md))) + dir_entry.metadata().ok().and_then(|md| { + Some(( + escape_spaces(dir_entry.file_name().into_string().ok()?.as_str()), + md, + )) + }) }) .map_while(|(file_name, md)| { if handle.is_canceled() {