use new path detection and expansions in goto_file

This commit is contained in:
Pascal Kuthe 2024-10-06 19:46:08 +02:00 committed by Philipp Mildenberger
parent a3e12ac7ef
commit 133460626e

View File

@ -6,7 +6,7 @@
use futures_util::FutureExt; use futures_util::FutureExt;
use helix_event::status; use helix_event::status;
use helix_stdx::{ use helix_stdx::{
path::expand_tilde, path::{self, find_paths},
rope::{self, RopeSliceExt}, rope::{self, RopeSliceExt},
}; };
use helix_vcs::{FileChange, Hunk}; use helix_vcs::{FileChange, Hunk};
@ -1272,53 +1272,31 @@ fn goto_file_impl(cx: &mut Context, action: Action) {
.unwrap_or_default(); .unwrap_or_default();
let paths: Vec<_> = if selections.len() == 1 && primary.len() == 1 { let paths: Vec<_> = if selections.len() == 1 && primary.len() == 1 {
// Secial case: if there is only one one-width selection, try to detect the let mut pos = primary.cursor(text.slice(..));
// path under the cursor. pos = text.char_to_byte(pos);
let is_valid_path_char = |c: &char| { let search_start = text
#[cfg(target_os = "windows")] .line_to_byte(text.byte_to_line(pos))
let valid_chars = &[ .max(pos.saturating_sub(1000));
'@', '/', '\\', '.', '-', '_', '+', '#', '$', '%', '{', '}', '[', ']', ':', '!', let search_end = text
'~', '=', .line_to_byte(text.byte_to_line(pos) + 1)
]; .min(pos + 1000);
#[cfg(not(target_os = "windows"))] let search_range = text.slice(search_start..search_end);
let valid_chars = &['@', '/', '.', '-', '_', '+', '#', '$', '%', '~', '=', ':']; // we also allow paths that are next to the cursor (can be ambigous but
// rarely so in practice) so that gf on quoted/braced path works (not sure about this
valid_chars.contains(c) || c.is_alphabetic() || c.is_numeric() // but apparently that is how gf has worked historically in helix)
}; let path = find_paths(search_range, true)
.inspect(|mat| println!("{mat:?} {:?}", pos - search_start))
let cursor_pos = primary.cursor(text.slice(..)); .take_while(|range| search_start + range.start <= pos + 1)
let pre_cursor_pos = cursor_pos.saturating_sub(1); .find(|range| pos <= search_start + range.end)
let post_cursor_pos = cursor_pos + 1; .map(|range| Cow::from(search_range.byte_slice(range)));
let start_pos = if is_valid_path_char(&text.char(cursor_pos)) { log::debug!("goto_file auto-detected path: {path:?}");
cursor_pos let path = path.unwrap_or_else(|| primary.fragment(text.slice(..)));
} else if is_valid_path_char(&text.char(pre_cursor_pos)) { vec![path.into_owned()]
pre_cursor_pos
} else {
post_cursor_pos
};
let prefix_len = text
.chars_at(start_pos)
.reversed()
.take_while(is_valid_path_char)
.count();
let postfix_len = text
.chars_at(start_pos)
.take_while(is_valid_path_char)
.count();
let path: String = text
.slice((start_pos - prefix_len)..(start_pos + postfix_len))
.into();
log::debug!("goto_file auto-detected path: {}", path);
vec![path]
} else { } else {
// Otherwise use each selection, trimmed. // Otherwise use each selection, trimmed.
selections selections
.fragments(text.slice(..)) .fragments(text.slice(..))
.map(|sel| sel.trim().to_string()) .map(|sel| sel.trim().to_owned())
.filter(|sel| !sel.is_empty()) .filter(|sel| !sel.is_empty())
.collect() .collect()
}; };
@ -1329,7 +1307,7 @@ fn goto_file_impl(cx: &mut Context, action: Action) {
continue; continue;
} }
let path = expand_tilde(Cow::from(PathBuf::from(sel))); let path = path::expand(&sel);
let path = &rel_path.join(path); let path = &rel_path.join(path);
if path.is_dir() { if path.is_dir() {
let picker = ui::file_picker(path.into(), &cx.editor.config()); let picker = ui::file_picker(path.into(), &cx.editor.config());