Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-term/src/commands/typed.rs')
-rw-r--r--helix-term/src/commands/typed.rs142
1 files changed, 124 insertions, 18 deletions
diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs
index 5597d586..cf9f8b8c 100644
--- a/helix-term/src/commands/typed.rs
+++ b/helix-term/src/commands/typed.rs
@@ -1228,26 +1228,20 @@ fn show_clipboard_provider(
Ok(())
}
-fn change_current_directory(
- cx: &mut compositor::Context,
- args: Args,
- event: PromptEvent,
-) -> anyhow::Result<()> {
- if event != PromptEvent::Validate {
- return Ok(());
+/// Helper function to parse the first argument as a directory
+#[inline]
+fn parse_first_arg_as_dir(args: &Args, last_cwd: Option<PathBuf>) -> anyhow::Result<PathBuf> {
+ match args.first().map(AsRef::as_ref) {
+ Some("-") => last_cwd.ok_or_else(|| anyhow!("No previous working directory")),
+ Some(path) => Ok(helix_stdx::path::expand_tilde(Path::new(path)).into_owned()),
+ None => Ok(home_dir()?),
}
+}
- let dir = match args.first().map(AsRef::as_ref) {
- Some("-") => cx
- .editor
- .get_last_cwd()
- .map(|path| Cow::Owned(path.to_path_buf()))
- .ok_or_else(|| anyhow!("No previous working directory"))?,
- Some(path) => helix_stdx::path::expand_tilde(Path::new(path)),
- None => Cow::Owned(home_dir()?),
- };
-
- cx.editor.set_cwd(&dir).map_err(|err| {
+/// Helper function to apply a directory change for an already-parsed Path ref
+#[inline]
+fn apply_directory_change(cx: &mut compositor::Context, dir: &Path) -> anyhow::Result<()> {
+ cx.editor.set_cwd(dir).map_err(|err| {
anyhow!(
"Could not change working directory to '{}': {err}",
dir.display()
@@ -1262,6 +1256,85 @@ fn change_current_directory(
Ok(())
}
+fn change_current_directory(
+ cx: &mut compositor::Context,
+ args: Args,
+ event: PromptEvent,
+) -> anyhow::Result<()> {
+ if event != PromptEvent::Validate {
+ return Ok(());
+ }
+
+ let dir = parse_first_arg_as_dir(&args, cx.editor.get_last_cwd().map(|p| p.to_path_buf()))?;
+
+ apply_directory_change(cx, &dir)
+}
+
+fn show_directory_stack(
+ cx: &mut compositor::Context,
+ _args: Args,
+ event: PromptEvent,
+) -> anyhow::Result<()> {
+ if event != PromptEvent::Validate {
+ return Ok(());
+ }
+
+ let serialized_stack = cx
+ .editor
+ .dir_stack
+ .iter()
+ .map(|p| p.display().to_string())
+ .collect::<Vec<_>>()
+ .join(" ");
+
+ if !serialized_stack.is_empty() {
+ cx.editor.set_status(serialized_stack);
+ } else {
+ cx.editor.set_error("Stack is empty");
+ }
+
+ Ok(())
+}
+
+fn push_directory(
+ cx: &mut compositor::Context,
+ args: Args,
+ event: PromptEvent,
+) -> anyhow::Result<()> {
+ if event != PromptEvent::Validate {
+ return Ok(());
+ }
+
+ // avoid an unbounded directory stack and reallocs for perf
+ if cx.editor.dir_stack.len() == cx.editor.dir_stack.capacity() {
+ cx.editor.dir_stack.pop_back();
+ }
+
+ cx.editor
+ .dir_stack
+ .push_front(helix_stdx::env::current_working_dir());
+
+ change_current_directory(cx, args, event)
+}
+
+fn pop_directory(
+ cx: &mut compositor::Context,
+ _args: Args,
+ event: PromptEvent,
+) -> anyhow::Result<()> {
+ if event != PromptEvent::Validate {
+ return Ok(());
+ }
+
+ if let Some(dir) = cx.editor.dir_stack.pop_front() {
+ apply_directory_change(cx, &dir)?;
+ } else {
+ cx.editor.set_error("Stack is empty");
+ }
+
+ Ok(())
+}
+
fn show_current_directory(
cx: &mut compositor::Context,
_args: Args,
@@ -3349,6 +3422,39 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
},
},
TypableCommand {
+ name: "show-directory-stack",
+ aliases: &[],
+ doc: "Show the directory stack as a <space> delimited string.",
+ fun: show_directory_stack,
+ completer: CommandCompleter::none(),
+ signature: Signature {
+ positionals: (0, Some(0)),
+ ..Signature::DEFAULT
+ },
+ },
+ TypableCommand {
+ name: "push-directory",
+ aliases: &["pushd"],
+ doc: "Save and then change the current directory.",
+ fun: push_directory,
+ completer: CommandCompleter::positional(&[completers::directory]),
+ signature: Signature {
+ positionals: (1, Some(1)),
+ ..Signature::DEFAULT
+ },
+ },
+ TypableCommand {
+ name: "pop-directory",
+ aliases: &["popd"],
+ doc: "Remove the top entry from the directory stack, and cd to the new top directory..",
+ fun: pop_directory,
+ completer: CommandCompleter::none(),
+ signature: Signature {
+ positionals: (0, Some(0)),
+ ..Signature::DEFAULT
+ },
+ },
+ TypableCommand {
name: "show-directory",
aliases: &["pwd"],
doc: "Show the current working directory.",