mirror of
https://github.com/helix-editor/helix.git
synced 2024-11-23 01:46:18 +04:00
Implement change_current_directory command
This commit is contained in:
parent
866b32b5d7
commit
b56174d738
@ -1360,6 +1360,32 @@ fn show_clipboard_provider(editor: &mut Editor, _: &[&str], _: PromptEvent) {
|
|||||||
editor.set_status(editor.clipboard_provider.name().into());
|
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] = &[
|
pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
|
||||||
TypableCommand {
|
TypableCommand {
|
||||||
name: "quit",
|
name: "quit",
|
||||||
@ -1529,6 +1555,13 @@ fn show_clipboard_provider(editor: &mut Editor, _: &[&str], _: PromptEvent) {
|
|||||||
fun: show_clipboard_provider,
|
fun: show_clipboard_provider,
|
||||||
completer: None,
|
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(|| {
|
pub static COMMANDS: Lazy<HashMap<&'static str, &'static TypableCommand>> = Lazy::new(|| {
|
||||||
|
@ -152,8 +152,46 @@ pub fn theme(input: &str) -> Vec<Completion> {
|
|||||||
names
|
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> {
|
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.
|
// Rust's filename handling is really annoying.
|
||||||
|
|
||||||
use ignore::WalkBuilder;
|
use ignore::WalkBuilder;
|
||||||
@ -184,7 +222,13 @@ pub fn filename(input: &str) -> Vec<Completion> {
|
|||||||
.max_depth(Some(1))
|
.max_depth(Some(1))
|
||||||
.build()
|
.build()
|
||||||
.filter_map(|file| {
|
.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 is_dir = entry.file_type().map_or(false, |entry| entry.is_dir());
|
||||||
|
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
@ -199,11 +243,12 @@ pub fn filename(input: &str) -> Vec<Completion> {
|
|||||||
path.strip_prefix(&dir).unwrap_or(path).to_path_buf()
|
path.strip_prefix(&dir).unwrap_or(path).to_path_buf()
|
||||||
};
|
};
|
||||||
|
|
||||||
if is_dir {
|
if fmatch == FileMatch::AcceptIncomplete {
|
||||||
path.push("");
|
path.push("");
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = path.to_str().unwrap().to_owned();
|
let path = path.to_str().unwrap().to_owned();
|
||||||
(end.clone(), Cow::from(path))
|
Some((end.clone(), Cow::from(path)))
|
||||||
})
|
})
|
||||||
}) // TODO: unwrap or skip
|
}) // TODO: unwrap or skip
|
||||||
.filter(|(_, path)| !path.is_empty()) // TODO
|
.filter(|(_, path)| !path.is_empty()) // TODO
|
||||||
|
Loading…
Reference in New Issue
Block a user