From 159cf27e39322e0c3b28beec9214b972dc8757a2 Mon Sep 17 00:00:00 2001 From: Odin Dutton Date: Sun, 8 Sep 2019 15:10:08 +1000 Subject: [PATCH] Implement `cd -` to return to the last path for the FilesystemShell --- src/shell/filesystem_shell.rs | 25 +++++++++++++++++++++++-- tests/command_cd_tests.rs | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/shell/filesystem_shell.rs b/src/shell/filesystem_shell.rs index 1bb7796b5d..5908784640 100644 --- a/src/shell/filesystem_shell.rs +++ b/src/shell/filesystem_shell.rs @@ -15,6 +15,7 @@ use std::path::{Path, PathBuf}; pub struct FilesystemShell { pub(crate) path: String, + last_path: String, completer: NuCompleter, hinter: HistoryHinter, } @@ -29,6 +30,7 @@ impl Clone for FilesystemShell { fn clone(&self) -> Self { FilesystemShell { path: self.path.clone(), + last_path: self.path.clone(), completer: NuCompleter { file_completer: FilenameCompleter::new(), commands: self.completer.commands.clone(), @@ -44,6 +46,7 @@ impl FilesystemShell { Ok(FilesystemShell { path: path.to_string_lossy().to_string(), + last_path: path.to_string_lossy().to_string(), completer: NuCompleter { file_completer: FilenameCompleter::new(), commands, @@ -56,8 +59,10 @@ impl FilesystemShell { path: String, commands: CommandRegistry, ) -> Result { + let last_path = path.clone(); Ok(FilesystemShell { path, + last_path, completer: NuCompleter { file_completer: FilenameCompleter::new(), commands, @@ -182,14 +187,29 @@ impl Shell for FilesystemShell { Some(v) => { let target = v.as_path()?; let path = PathBuf::from(self.path()); - match dunce::canonicalize(path.join(target).as_path()) { + match dunce::canonicalize(path.join(&target).as_path()) { Ok(p) => p, Err(_) => { - return Err(ShellError::labeled_error( + let error = Err(ShellError::labeled_error( "Can not change to directory", "directory not found", v.span().clone(), )); + + if let Some(t) = target.to_str() { + if t == "-" { + match dunce::canonicalize(PathBuf::from(self.last_path.clone()).as_path()) { + Ok(p) => p, + Err(_) => { + return error; + } + } + } else { + return error; + } + } else { + return error; + } } } } @@ -959,6 +979,7 @@ impl Shell for FilesystemShell { pathbuf } }; + self.last_path = self.path.clone(); self.path = path.to_string_lossy().to_string(); } diff --git a/tests/command_cd_tests.rs b/tests/command_cd_tests.rs index 216bcc8c80..7c1a9f6b85 100644 --- a/tests/command_cd_tests.rs +++ b/tests/command_cd_tests.rs @@ -1,5 +1,7 @@ mod helpers; +use helpers::Playground; + #[test] fn cd_directory_not_found() { let actual = nu_error!( @@ -10,3 +12,35 @@ fn cd_directory_not_found() { assert!(actual.contains("dir_that_does_not_exist")); assert!(actual.contains("directory not found")); } + +#[test] +fn cd_back() { + Playground::setup("cd_test_back", |dirs, sandbox| { + sandbox + .mkdir("andres") + .mkdir("odin"); + + let odin = dirs.test().join("odin"); + let andres = dirs.test().join("andres"); + + nu!( + cwd: dirs.test(), + r#" + cd odin + mkdir a + cd ../andres + mkdir b + cd - + mkdir c + mkdir - + cd - + mkdir d + "# + ); + + assert!(odin.join("a").exists()); + assert!(andres.join("b").exists()); + assert!(odin.join("c").exists()); + assert!(odin.join("-").join("d").exists()); + }) +}