mirror of
https://github.com/ilyakooo0/helix.git
synced 2024-11-29 05:27:07 +03:00
Implement change_current_directory command
This commit is contained in:
parent
866b32b5d7
commit
b56174d738
@ -1360,6 +1360,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",
|
||||
@ -1529,6 +1555,13 @@ mod cmd {
|
||||
fun: show_clipboard_provider,
|
||||
completer: None,
|
||||
},
|
||||
TypableCommand {
|
||||
name: "change-current-directory",
|
||||
alias: Some("cd"),
|
||||
doc: "Change the current working directory (:cd <dir>).",
|
||||
fun: change_current_directory,
|
||||
completer: Some(completers::directory),
|
||||
},
|
||||
];
|
||||
|
||||
pub static COMMANDS: Lazy<HashMap<&'static str, &'static TypableCommand>> = Lazy::new(|| {
|
||||
|
@ -152,8 +152,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<Completion> {
|
||||
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<Completion> {
|
||||
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<F>(input: &str, filter_fn: F) -> Vec<Completion>
|
||||
where
|
||||
F: Fn(&ignore::DirEntry) -> FileMatch,
|
||||
{
|
||||
// Rust's filename handling is really annoying.
|
||||
|
||||
use ignore::WalkBuilder;
|
||||
@ -184,7 +222,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();
|
||||
@ -199,11 +243,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
|
||||
|
Loading…
Reference in New Issue
Block a user