Skip to content

Commit b56174d

Browse files
Lionel FlandrinCBenoit
authored andcommitted
Implement change_current_directory command
1 parent 866b32b commit b56174d

File tree

2 files changed

+82
-4
lines changed

2 files changed

+82
-4
lines changed

helix-term/src/commands.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,6 +1360,32 @@ mod cmd {
13601360
editor.set_status(editor.clipboard_provider.name().into());
13611361
}
13621362

1363+
fn change_current_directory(editor: &mut Editor, args: &[&str], _: PromptEvent) {
1364+
let dir = match args.first() {
1365+
Some(dir) => dir,
1366+
None => {
1367+
editor.set_error("target directory not provided".into());
1368+
return;
1369+
}
1370+
};
1371+
1372+
if let Err(e) = std::env::set_current_dir(dir) {
1373+
editor.set_error(format!(
1374+
"Couldn't change the current working directory: {:?}",
1375+
e
1376+
));
1377+
return;
1378+
}
1379+
1380+
match std::env::current_dir() {
1381+
Ok(cwd) => editor.set_status(format!(
1382+
"Current working directory is now {}",
1383+
cwd.display()
1384+
)),
1385+
Err(e) => editor.set_error(format!("Couldn't get the new working directory: {}", e)),
1386+
}
1387+
}
1388+
13631389
pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
13641390
TypableCommand {
13651391
name: "quit",
@@ -1529,6 +1555,13 @@ mod cmd {
15291555
fun: show_clipboard_provider,
15301556
completer: None,
15311557
},
1558+
TypableCommand {
1559+
name: "change-current-directory",
1560+
alias: Some("cd"),
1561+
doc: "Change the current working directory (:cd <dir>).",
1562+
fun: change_current_directory,
1563+
completer: Some(completers::directory),
1564+
},
15321565
];
15331566

15341567
pub static COMMANDS: Lazy<HashMap<&'static str, &'static TypableCommand>> = Lazy::new(|| {

helix-term/src/ui/mod.rs

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,46 @@ pub mod completers {
152152
names
153153
}
154154

155-
// TODO: we could return an iter/lazy thing so it can fetch as many as it needs.
156155
pub fn filename(input: &str) -> Vec<Completion> {
156+
filename_impl(input, |entry| {
157+
let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir());
158+
159+
if is_dir {
160+
FileMatch::AcceptIncomplete
161+
} else {
162+
FileMatch::Accept
163+
}
164+
})
165+
}
166+
167+
pub fn directory(input: &str) -> Vec<Completion> {
168+
filename_impl(input, |entry| {
169+
let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir());
170+
171+
if is_dir {
172+
FileMatch::Accept
173+
} else {
174+
FileMatch::Reject
175+
}
176+
})
177+
}
178+
179+
#[derive(Copy, Clone, PartialEq, Eq)]
180+
enum FileMatch {
181+
/// Entry should be ignored
182+
Reject,
183+
/// Entry is usable but can't be the end (for instance if the entry is a directory and we
184+
/// try to match a file)
185+
AcceptIncomplete,
186+
/// Entry is usable and can be the end of the match
187+
Accept,
188+
}
189+
190+
// TODO: we could return an iter/lazy thing so it can fetch as many as it needs.
191+
fn filename_impl<F>(input: &str, filter_fn: F) -> Vec<Completion>
192+
where
193+
F: Fn(&ignore::DirEntry) -> FileMatch,
194+
{
157195
// Rust's filename handling is really annoying.
158196

159197
use ignore::WalkBuilder;
@@ -184,7 +222,13 @@ pub mod completers {
184222
.max_depth(Some(1))
185223
.build()
186224
.filter_map(|file| {
187-
file.ok().map(|entry| {
225+
file.ok().and_then(|entry| {
226+
let fmatch = filter_fn(&entry);
227+
228+
if fmatch == FileMatch::Reject {
229+
return None;
230+
}
231+
188232
let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir());
189233

190234
let path = entry.path();
@@ -199,11 +243,12 @@ pub mod completers {
199243
path.strip_prefix(&dir).unwrap_or(path).to_path_buf()
200244
};
201245

202-
if is_dir {
246+
if fmatch == FileMatch::AcceptIncomplete {
203247
path.push("");
204248
}
249+
205250
let path = path.to_str().unwrap().to_owned();
206-
(end.clone(), Cow::from(path))
251+
Some((end.clone(), Cow::from(path)))
207252
})
208253
}) // TODO: unwrap or skip
209254
.filter(|(_, path)| !path.is_empty()) // TODO

0 commit comments

Comments
 (0)