Implement cd - to return to the last path for the FilesystemShell

This commit is contained in:
Odin Dutton 2019-09-08 15:10:08 +10:00
parent ede45e21de
commit 159cf27e39
2 changed files with 57 additions and 2 deletions

View File

@ -15,6 +15,7 @@ use std::path::{Path, PathBuf};
pub struct FilesystemShell { pub struct FilesystemShell {
pub(crate) path: String, pub(crate) path: String,
last_path: String,
completer: NuCompleter, completer: NuCompleter,
hinter: HistoryHinter, hinter: HistoryHinter,
} }
@ -29,6 +30,7 @@ impl Clone for FilesystemShell {
fn clone(&self) -> Self { fn clone(&self) -> Self {
FilesystemShell { FilesystemShell {
path: self.path.clone(), path: self.path.clone(),
last_path: self.path.clone(),
completer: NuCompleter { completer: NuCompleter {
file_completer: FilenameCompleter::new(), file_completer: FilenameCompleter::new(),
commands: self.completer.commands.clone(), commands: self.completer.commands.clone(),
@ -44,6 +46,7 @@ impl FilesystemShell {
Ok(FilesystemShell { Ok(FilesystemShell {
path: path.to_string_lossy().to_string(), path: path.to_string_lossy().to_string(),
last_path: path.to_string_lossy().to_string(),
completer: NuCompleter { completer: NuCompleter {
file_completer: FilenameCompleter::new(), file_completer: FilenameCompleter::new(),
commands, commands,
@ -56,8 +59,10 @@ impl FilesystemShell {
path: String, path: String,
commands: CommandRegistry, commands: CommandRegistry,
) -> Result<FilesystemShell, std::io::Error> { ) -> Result<FilesystemShell, std::io::Error> {
let last_path = path.clone();
Ok(FilesystemShell { Ok(FilesystemShell {
path, path,
last_path,
completer: NuCompleter { completer: NuCompleter {
file_completer: FilenameCompleter::new(), file_completer: FilenameCompleter::new(),
commands, commands,
@ -182,14 +187,29 @@ impl Shell for FilesystemShell {
Some(v) => { Some(v) => {
let target = v.as_path()?; let target = v.as_path()?;
let path = PathBuf::from(self.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, Ok(p) => p,
Err(_) => { Err(_) => {
return Err(ShellError::labeled_error( let error = Err(ShellError::labeled_error(
"Can not change to directory", "Can not change to directory",
"directory not found", "directory not found",
v.span().clone(), 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 pathbuf
} }
}; };
self.last_path = self.path.clone();
self.path = path.to_string_lossy().to_string(); self.path = path.to_string_lossy().to_string();
} }

View File

@ -1,5 +1,7 @@
mod helpers; mod helpers;
use helpers::Playground;
#[test] #[test]
fn cd_directory_not_found() { fn cd_directory_not_found() {
let actual = nu_error!( let actual = nu_error!(
@ -10,3 +12,35 @@ fn cd_directory_not_found() {
assert!(actual.contains("dir_that_does_not_exist")); assert!(actual.contains("dir_that_does_not_exist"));
assert!(actual.contains("directory not found")); 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());
})
}