mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 09:25:38 +02:00
Merge branch 'master' into light_tables
This commit is contained in:
@ -328,7 +328,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut ConfigDeserializer<'de> {
|
||||
let type_name = std::any::type_name::<V::Value>();
|
||||
let tagged_val_name = std::any::type_name::<Tagged<Value>>();
|
||||
|
||||
if name == tagged_val_name {
|
||||
if type_name == tagged_val_name {
|
||||
return visit::<Tagged<Value>, _>(value.val, name, fields, visitor);
|
||||
}
|
||||
|
||||
@ -467,3 +467,27 @@ impl<'a, 'de: 'a> de::SeqAccess<'de> for StructDeserializer<'a, 'de> {
|
||||
return Some(self.fields.len());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::any::type_name;
|
||||
#[test]
|
||||
fn check_type_name_properties() {
|
||||
// This ensures that certain properties for the
|
||||
// std::any::type_name function hold, that
|
||||
// this code relies on. The type_name docs explicitly
|
||||
// mention that the actual format of the output
|
||||
// is unspecified and change is likely.
|
||||
// This test makes sure that such change is detected
|
||||
// by this test failing, and not things silently breaking.
|
||||
// Specifically, we rely on this behaviour further above
|
||||
// in the file to special case Tagged<Value> parsing.
|
||||
let tuple = type_name::<()>();
|
||||
let tagged_tuple = type_name::<Tagged<()>>();
|
||||
let tagged_value = type_name::<Tagged<Value>>();
|
||||
assert!(tuple != tagged_tuple);
|
||||
assert!(tuple != tagged_value);
|
||||
assert!(tagged_tuple != tagged_value);
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ use std::path::{Path, PathBuf};
|
||||
|
||||
pub struct FilesystemShell {
|
||||
pub(crate) path: String,
|
||||
last_path: String,
|
||||
pub(crate) last_path: String,
|
||||
completer: NuCompleter,
|
||||
hinter: HistoryHinter,
|
||||
}
|
||||
@ -185,29 +185,20 @@ 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()) {
|
||||
Ok(p) => p,
|
||||
Err(_) => {
|
||||
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;
|
||||
if PathBuf::from("-") == target {
|
||||
PathBuf::from(&self.last_path)
|
||||
} else {
|
||||
let path = PathBuf::from(self.path());
|
||||
|
||||
match dunce::canonicalize(path.join(&target)) {
|
||||
Ok(p) => p,
|
||||
Err(_) => {
|
||||
return Err(ShellError::labeled_error(
|
||||
"Can not change to directory",
|
||||
"directory not found",
|
||||
v.span().clone(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -215,23 +206,12 @@ impl Shell for FilesystemShell {
|
||||
};
|
||||
|
||||
let mut stream = VecDeque::new();
|
||||
match std::env::set_current_dir(&path) {
|
||||
Ok(_) => {}
|
||||
Err(_) => {
|
||||
if let Some(directory) = args.nth(0) {
|
||||
return Err(ShellError::labeled_error(
|
||||
"Can not change to directory",
|
||||
"directory not found",
|
||||
directory.span(),
|
||||
));
|
||||
} else {
|
||||
return Err(ShellError::string("Can not change to directory"));
|
||||
}
|
||||
}
|
||||
}
|
||||
stream.push_back(ReturnSuccess::change_cwd(
|
||||
|
||||
stream.push_back(
|
||||
ReturnSuccess::change_cwd(
|
||||
path.to_string_lossy().to_string(),
|
||||
));
|
||||
|
||||
Ok(stream.into())
|
||||
}
|
||||
|
||||
|
@ -10,16 +10,24 @@ use crate::utils::ValueStructure;
|
||||
use std::ffi::OsStr;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone)]
|
||||
pub struct ValueShell {
|
||||
pub(crate) path: String,
|
||||
pub(crate) last_path: String,
|
||||
pub(crate) value: Tagged<Value>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for ValueShell {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "ValueShell @ {}", self.path)
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueShell {
|
||||
pub fn new(value: Tagged<Value>) -> ValueShell {
|
||||
ValueShell {
|
||||
path: "/".to_string(),
|
||||
last_path: "/".to_string(),
|
||||
value,
|
||||
}
|
||||
}
|
||||
@ -76,7 +84,7 @@ impl Shell for ValueShell {
|
||||
}
|
||||
|
||||
fn homedir(&self) -> Option<PathBuf> {
|
||||
dirs::home_dir()
|
||||
Some(PathBuf::from("/"))
|
||||
}
|
||||
|
||||
fn ls(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> {
|
||||
@ -126,6 +134,8 @@ impl Shell for ValueShell {
|
||||
|
||||
if target == PathBuf::from("..") {
|
||||
cwd.pop();
|
||||
} else if target == PathBuf::from("-") {
|
||||
cwd = PathBuf::from(&self.last_path);
|
||||
} else {
|
||||
match target.to_str() {
|
||||
Some(target) => match target.chars().nth(0) {
|
||||
@ -200,19 +210,16 @@ impl Shell for ValueShell {
|
||||
}
|
||||
|
||||
fn pwd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let path = PathBuf::from(&self.path());
|
||||
|
||||
let mut stream = VecDeque::new();
|
||||
stream.push_back(ReturnSuccess::value(
|
||||
Value::Primitive(Primitive::String(path.to_string_lossy().to_string()))
|
||||
.simple_spanned(args.call_info.name_span),
|
||||
));
|
||||
|
||||
stream.push_back(ReturnSuccess::value(Tagged::from_item(
|
||||
Value::string(self.path()),
|
||||
args.call_info.name_span,
|
||||
)));
|
||||
Ok(stream.into())
|
||||
}
|
||||
|
||||
fn set_path(&mut self, path: String) {
|
||||
let _ = std::env::set_current_dir(&path);
|
||||
self.last_path = self.path.clone();
|
||||
self.path = path.clone();
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user