From ec9d018546015808b11382bb8d23adc8077b0c6f Mon Sep 17 00:00:00 2001 From: Lionel Flandrin Date: Mon, 21 Jun 2021 16:40:27 +0100 Subject: [PATCH 1/2] Implement change_current_directory command --- helix-term/src/commands.rs | 33 ++++++++++++++++++++++++ helix-term/src/ui/mod.rs | 53 +++++++++++++++++++++++++++++++++++--- 2 files changed, 82 insertions(+), 4 deletions(-) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index f87a440da04a..7ee1da9ca95d 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -1309,6 +1309,32 @@ mod cmd { editor.set_status(editor.clipboard_provider.name().into()); } + fn change_current_directory(editor: &mut Editor, args: &[&str], _: PromptEvent) { + let dir = match args.first() { + Some(dir) => dir, + None => { + editor.set_error("target directory not provided".into()); + return; + } + }; + + if let Err(e) = std::env::set_current_dir(dir) { + editor.set_error(format!( + "Couldn't change the current working directory: {:?}", + e + )); + return; + } + + match std::env::current_dir() { + Ok(cwd) => editor.set_status(format!( + "Current working directory is now {}", + cwd.display() + )), + Err(e) => editor.set_error(format!("Couldn't get the new working directory: {}", e)), + } + } + pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[ TypableCommand { name: "quit", @@ -1471,6 +1497,13 @@ mod cmd { fun: show_clipboard_provider, completer: None, }, + TypableCommand { + name: "change-current-directory", + alias: Some("cd"), + doc: "Change the current working directory (:cd ).", + fun: change_current_directory, + completer: Some(completers::directory), + }, ]; pub static COMMANDS: Lazy> = Lazy::new(|| { diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs index c062bffe32c1..212ef53dfc93 100644 --- a/helix-term/src/ui/mod.rs +++ b/helix-term/src/ui/mod.rs @@ -154,8 +154,46 @@ pub mod completers { names } - // TODO: we could return an iter/lazy thing so it can fetch as many as it needs. pub fn filename(input: &str) -> Vec { + filename_impl(input, |entry| { + let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir()); + + if is_dir { + FileMatch::AcceptIncomplete + } else { + FileMatch::Accept + } + }) + } + + pub fn directory(input: &str) -> Vec { + filename_impl(input, |entry| { + let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir()); + + if is_dir { + FileMatch::Accept + } else { + FileMatch::Reject + } + }) + } + + #[derive(Copy, Clone, PartialEq, Eq)] + enum FileMatch { + /// Entry should be ignored + Reject, + /// Entry is usable but can't be the end (for instance if the entry is a directory and we + /// try to match a file) + AcceptIncomplete, + /// Entry is usable and can be the end of the match + Accept, + } + + // TODO: we could return an iter/lazy thing so it can fetch as many as it needs. + fn filename_impl(input: &str, filter_fn: F) -> Vec + where + F: Fn(&ignore::DirEntry) -> FileMatch, + { // Rust's filename handling is really annoying. use ignore::WalkBuilder; @@ -186,7 +224,13 @@ pub mod completers { .max_depth(Some(1)) .build() .filter_map(|file| { - file.ok().map(|entry| { + file.ok().and_then(|entry| { + let fmatch = filter_fn(&entry); + + if fmatch == FileMatch::Reject { + return None; + } + let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir()); let path = entry.path(); @@ -201,11 +245,12 @@ pub mod completers { path.strip_prefix(&dir).unwrap_or(path).to_path_buf() }; - if is_dir { + if fmatch == FileMatch::AcceptIncomplete { path.push(""); } + let path = path.to_str().unwrap().to_owned(); - (end.clone(), Cow::from(path)) + Some((end.clone(), Cow::from(path))) }) }) // TODO: unwrap or skip .filter(|(_, path)| !path.is_empty()) // TODO From 5aabb54b37c002b8fb9eb1a12036c696018d6bb2 Mon Sep 17 00:00:00 2001 From: Lionel Flandrin Date: Mon, 21 Jun 2021 16:49:21 +0100 Subject: [PATCH 2/2] Implement show_current_directory command --- helix-term/src/commands.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 7ee1da9ca95d..c4c24997f442 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -1335,6 +1335,15 @@ mod cmd { } } + fn show_current_directory(editor: &mut Editor, args: &[&str], _: PromptEvent) { + match std::env::current_dir() { + Ok(cwd) => editor.set_status(format!("Current working directory is {}", cwd.display())), + Err(e) => { + editor.set_error(format!("Couldn't get the current working directory: {}", e)) + } + } + } + pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[ TypableCommand { name: "quit", @@ -1504,6 +1513,13 @@ mod cmd { fun: change_current_directory, completer: Some(completers::directory), }, + TypableCommand { + name: "show-directory", + alias: Some("pwd"), + doc: "Show the current working directory.", + fun: show_current_directory, + completer: None, + }, ]; pub static COMMANDS: Lazy> = Lazy::new(|| {