mirror of
https://github.com/nushell/nushell.git
synced 2024-12-26 00:50:03 +01:00
Finish up enter and save
This commit is contained in:
parent
fa2c6ec227
commit
761cc3db14
@ -146,41 +146,9 @@ impl InternalCommand {
|
||||
.insert_at_current(Box::new(ValueShell::new(value)));
|
||||
}
|
||||
CommandAction::EnterShell(location) => {
|
||||
let path = std::path::Path::new(&location);
|
||||
|
||||
if path.is_dir() {
|
||||
// If it's a directory, add a new filesystem shell
|
||||
context.shell_manager.insert_at_current(Box::new(
|
||||
FilesystemShell::with_location(
|
||||
location,
|
||||
context.registry().clone(),
|
||||
)?,
|
||||
));
|
||||
} else {
|
||||
// If it's a file, attempt to open the file as a value and enter it
|
||||
let cwd = context.shell_manager.path();
|
||||
|
||||
let full_path = std::path::PathBuf::from(cwd);
|
||||
|
||||
let (_file_extension, contents, contents_tag, span_source) =
|
||||
crate::commands::open::fetch(
|
||||
&full_path,
|
||||
&location,
|
||||
Span::unknown(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
if let Some(uuid) = contents_tag.origin {
|
||||
// If we have loaded something, track its source
|
||||
context.add_span_source(uuid, span_source);
|
||||
}
|
||||
|
||||
context
|
||||
.shell_manager
|
||||
.insert_at_current(Box::new(ValueShell::new(
|
||||
contents.tagged(contents_tag),
|
||||
)))
|
||||
}
|
||||
context.shell_manager.insert_at_current(Box::new(
|
||||
FilesystemShell::with_location(location, context.registry().clone())?,
|
||||
));
|
||||
}
|
||||
CommandAction::PreviousShell => {
|
||||
context.shell_manager.prev();
|
||||
|
@ -1,8 +1,10 @@
|
||||
use crate::commands::command::CommandAction;
|
||||
use crate::commands::PerItemCommand;
|
||||
use crate::commands::UnevaluatedCallInfo;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::registry;
|
||||
use crate::prelude::*;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub struct Enter;
|
||||
|
||||
@ -18,18 +20,109 @@ impl PerItemCommand for Enter {
|
||||
fn run(
|
||||
&self,
|
||||
call_info: &CallInfo,
|
||||
_registry: ®istry::CommandRegistry,
|
||||
_raw_args: &RawCommandArgs,
|
||||
registry: ®istry::CommandRegistry,
|
||||
raw_args: &RawCommandArgs,
|
||||
_input: Tagged<Value>,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let registry = registry.clone();
|
||||
let raw_args = raw_args.clone();
|
||||
match call_info.args.expect_nth(0)? {
|
||||
Tagged {
|
||||
item: Value::Primitive(Primitive::String(location)),
|
||||
..
|
||||
} => Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterShell(
|
||||
location.to_string(),
|
||||
)))]
|
||||
.into()),
|
||||
} => {
|
||||
let location = location.to_string();
|
||||
let location_clone = location.to_string();
|
||||
if PathBuf::from(location).is_dir() {
|
||||
Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterShell(
|
||||
location_clone,
|
||||
)))]
|
||||
.into())
|
||||
} else {
|
||||
let stream = async_stream_block! {
|
||||
// If it's a file, attempt to open the file as a value and enter it
|
||||
let cwd = raw_args.shell_manager.path();
|
||||
|
||||
let full_path = std::path::PathBuf::from(cwd);
|
||||
|
||||
let (file_extension, contents, contents_tag, span_source) =
|
||||
crate::commands::open::fetch(
|
||||
&full_path,
|
||||
&location_clone,
|
||||
Span::unknown(),
|
||||
)
|
||||
.await.unwrap();
|
||||
|
||||
if let Some(uuid) = contents_tag.origin {
|
||||
// If we have loaded something, track its source
|
||||
yield ReturnSuccess::action(CommandAction::AddSpanSource(
|
||||
uuid,
|
||||
span_source,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
match contents {
|
||||
Value::Primitive(Primitive::String(_)) => {
|
||||
let tagged_contents = contents.tagged(contents_tag);
|
||||
|
||||
if let Some(extension) = file_extension {
|
||||
let command_name = format!("from-{}", extension);
|
||||
if let Some(converter) =
|
||||
registry.get_command(&command_name)
|
||||
{
|
||||
let new_args = RawCommandArgs {
|
||||
host: raw_args.host,
|
||||
shell_manager: raw_args.shell_manager,
|
||||
call_info: UnevaluatedCallInfo {
|
||||
args: crate::parser::hir::Call {
|
||||
head: raw_args.call_info.args.head,
|
||||
positional: None,
|
||||
named: None,
|
||||
},
|
||||
source: raw_args.call_info.source,
|
||||
source_map: raw_args.call_info.source_map,
|
||||
name_span: raw_args.call_info.name_span,
|
||||
},
|
||||
};
|
||||
let mut result = converter.run(
|
||||
new_args.with_input(vec![tagged_contents]),
|
||||
®istry,
|
||||
);
|
||||
let result_vec: Vec<Result<ReturnSuccess, ShellError>> =
|
||||
result.drain_vec().await;
|
||||
for res in result_vec {
|
||||
match res {
|
||||
Ok(ReturnSuccess::Value(Tagged {
|
||||
item,
|
||||
..
|
||||
})) => {
|
||||
yield Ok(ReturnSuccess::Action(CommandAction::EnterValueShell(
|
||||
Tagged {
|
||||
item: item,
|
||||
tag: contents_tag,
|
||||
})));
|
||||
}
|
||||
x => yield x,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
yield Ok(ReturnSuccess::Action(CommandAction::EnterValueShell(tagged_contents)));
|
||||
}
|
||||
} else {
|
||||
yield Ok(ReturnSuccess::Action(CommandAction::EnterValueShell(tagged_contents)));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let tagged_contents = contents.tagged(contents_tag);
|
||||
|
||||
yield Ok(ReturnSuccess::Action(CommandAction::EnterValueShell(tagged_contents)));
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(stream.to_output_stream())
|
||||
}
|
||||
}
|
||||
x => Ok(
|
||||
vec![Ok(ReturnSuccess::Action(CommandAction::EnterValueShell(
|
||||
x.clone(),
|
||||
|
@ -1,8 +1,4 @@
|
||||
use crate::commands::to_csv::{to_string as to_csv_to_string, value_to_csv_value};
|
||||
use crate::commands::to_tsv::{to_string as to_tsv_to_string, value_to_tsv_value};
|
||||
use crate::commands::to_json::value_to_json_value;
|
||||
use crate::commands::to_toml::value_to_toml_value;
|
||||
use crate::commands::to_yaml::value_to_yaml_value;
|
||||
use crate::commands::UnevaluatedCallInfo;
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::errors::ShellError;
|
||||
use crate::object::Value;
|
||||
@ -33,7 +29,7 @@ impl WholeStreamCommand for Save {
|
||||
args: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
args.process(registry, save)?.run()
|
||||
Ok(args.process_raw(registry, save)?.run())
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,16 +43,19 @@ fn save(
|
||||
name,
|
||||
shell_manager,
|
||||
source_map,
|
||||
host,
|
||||
commands: registry,
|
||||
..
|
||||
}: RunnableContext,
|
||||
raw_args: RawCommandArgs,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let mut full_path = PathBuf::from(shell_manager.path());
|
||||
let name_span = name;
|
||||
|
||||
if path.is_none() {
|
||||
let source_map = source_map.clone();
|
||||
let stream = async_stream_block! {
|
||||
let input: Vec<Tagged<Value>> = input.values.collect().await;
|
||||
let source_map = source_map.clone();
|
||||
let stream = async_stream_block! {
|
||||
let input: Vec<Tagged<Value>> = input.values.collect().await;
|
||||
if path.is_none() {
|
||||
// If there is no filename, check the metadata for the origin filename
|
||||
if input.len() > 0 {
|
||||
let origin = input[0].origin();
|
||||
@ -88,50 +87,99 @@ fn save(
|
||||
name_span,
|
||||
));
|
||||
}
|
||||
|
||||
let content = if !save_raw {
|
||||
to_string_for(full_path.extension(), &input).await
|
||||
} else {
|
||||
string_from(&input)
|
||||
};
|
||||
|
||||
match content {
|
||||
Ok(save_data) => match std::fs::write(full_path, save_data) {
|
||||
Ok(o) => o,
|
||||
Err(e) => yield Err(ShellError::string(e.to_string())),
|
||||
},
|
||||
Err(e) => yield Err(ShellError::string(e.to_string())),
|
||||
} else {
|
||||
if let Some(file) = path {
|
||||
full_path.push(file.item());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Ok(OutputStream::new(stream))
|
||||
} else {
|
||||
if let Some(file) = path {
|
||||
full_path.push(file.item());
|
||||
}
|
||||
|
||||
let stream = async_stream_block! {
|
||||
let input: Vec<Tagged<Value>> = input.values.collect().await;
|
||||
|
||||
let content = if !save_raw {
|
||||
to_string_for(full_path.extension(), &input).await
|
||||
let content = if !save_raw {
|
||||
if let Some(extension) = full_path.extension() {
|
||||
let command_name = format!("to-{}", extension.to_str().unwrap());
|
||||
if let Some(converter) = registry.get_command(&command_name) {
|
||||
let new_args = RawCommandArgs {
|
||||
host: host,
|
||||
shell_manager: shell_manager,
|
||||
call_info: UnevaluatedCallInfo {
|
||||
args: crate::parser::hir::Call {
|
||||
head: raw_args.call_info.args.head,
|
||||
positional: None,
|
||||
named: None
|
||||
},
|
||||
source: raw_args.call_info.source,
|
||||
source_map: raw_args.call_info.source_map,
|
||||
name_span: raw_args.call_info.name_span,
|
||||
}
|
||||
};
|
||||
let mut result = converter.run(new_args.with_input(input), ®istry);
|
||||
let result_vec: Vec<Result<ReturnSuccess, ShellError>> = result.drain_vec().await;
|
||||
let mut result_string = String::new();
|
||||
for res in result_vec {
|
||||
match res {
|
||||
Ok(ReturnSuccess::Value(Tagged { item: Value::Primitive(Primitive::String(s)), .. })) => {
|
||||
result_string.push_str(&s);
|
||||
}
|
||||
_ => {
|
||||
yield Err(ShellError::labeled_error(
|
||||
"Save could not successfully save",
|
||||
"unexpected data during saveS",
|
||||
name_span,
|
||||
));
|
||||
},
|
||||
}
|
||||
}
|
||||
Ok(result_string)
|
||||
} else {
|
||||
let mut result_string = String::new();
|
||||
for res in input {
|
||||
match res {
|
||||
Tagged { item: Value::Primitive(Primitive::String(s)), .. } => {
|
||||
result_string.push_str(&s);
|
||||
}
|
||||
_ => {
|
||||
yield Err(ShellError::labeled_error(
|
||||
"Save could not successfully save",
|
||||
"unexpected data during saveS",
|
||||
name_span,
|
||||
));
|
||||
},
|
||||
}
|
||||
}
|
||||
Ok(result_string)
|
||||
}
|
||||
} else {
|
||||
string_from(&input)
|
||||
};
|
||||
|
||||
match content {
|
||||
Ok(save_data) => match std::fs::write(full_path, save_data) {
|
||||
Ok(o) => o,
|
||||
Err(e) => yield Err(ShellError::string(e.to_string())),
|
||||
},
|
||||
Err(e) => yield Err(ShellError::string(e.to_string())),
|
||||
let mut result_string = String::new();
|
||||
for res in input {
|
||||
match res {
|
||||
Tagged { item: Value::Primitive(Primitive::String(s)), .. } => {
|
||||
result_string.push_str(&s);
|
||||
}
|
||||
_ => {
|
||||
yield Err(ShellError::labeled_error(
|
||||
"Save could not successfully save",
|
||||
"unexpected data during saveS",
|
||||
name_span,
|
||||
));
|
||||
},
|
||||
}
|
||||
}
|
||||
Ok(result_string)
|
||||
}
|
||||
|
||||
} else {
|
||||
string_from(&input)
|
||||
};
|
||||
|
||||
Ok(OutputStream::new(stream))
|
||||
}
|
||||
match content {
|
||||
Ok(save_data) => match std::fs::write(full_path, save_data) {
|
||||
Ok(o) => o,
|
||||
Err(e) => yield Err(ShellError::string(e.to_string())),
|
||||
},
|
||||
Err(e) => yield Err(ShellError::string(e.to_string())),
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Ok(OutputStream::new(stream))
|
||||
}
|
||||
|
||||
fn string_from(input: &Vec<Tagged<Value>>) -> Result<String, ShellError> {
|
||||
@ -153,66 +201,3 @@ fn string_from(input: &Vec<Tagged<Value>>) -> Result<String, ShellError> {
|
||||
|
||||
Ok(save_data)
|
||||
}
|
||||
|
||||
async fn to_string_for(
|
||||
ext: Option<&std::ffi::OsStr>,
|
||||
input: &Vec<Tagged<Value>>,
|
||||
) -> Result<String, ShellError> {
|
||||
let contents = match ext {
|
||||
Some(x) if x == "csv" => {
|
||||
if input.len() != 1 {
|
||||
return Err(ShellError::string(
|
||||
"saving to csv requires a single object (or use --raw)",
|
||||
));
|
||||
}
|
||||
to_csv_to_string(&value_to_csv_value(&input[0]))?
|
||||
}
|
||||
Some(x) if x == "tsv" => {
|
||||
if input.len() != 1 {
|
||||
return Err(ShellError::string(
|
||||
"saving to tsv requires a single object (or use --raw)",
|
||||
));
|
||||
}
|
||||
to_tsv_to_string(&value_to_tsv_value(&input[0]))?
|
||||
}
|
||||
Some(x) if x == "toml" => {
|
||||
if input.len() != 1 {
|
||||
return Err(ShellError::string(
|
||||
"saving to toml requires a single object (or use --raw)",
|
||||
));
|
||||
}
|
||||
toml::to_string(&value_to_toml_value(&input[0]))?
|
||||
}
|
||||
Some(x) if x == "json" => {
|
||||
if input.len() != 1 {
|
||||
return Err(ShellError::string(
|
||||
"saving to json requires a single object (or use --raw)",
|
||||
));
|
||||
}
|
||||
serde_json::to_string(&value_to_json_value(&input[0]))?
|
||||
}
|
||||
Some(x) if x == "yml" => {
|
||||
if input.len() != 1 {
|
||||
return Err(ShellError::string(
|
||||
"saving to yml requires a single object (or use --raw)",
|
||||
));
|
||||
}
|
||||
serde_yaml::to_string(&value_to_yaml_value(&input[0]))?
|
||||
}
|
||||
Some(x) if x == "yaml" => {
|
||||
if input.len() != 1 {
|
||||
return Err(ShellError::string(
|
||||
"saving to yaml requires a single object (or use --raw)",
|
||||
));
|
||||
}
|
||||
serde_yaml::to_string(&value_to_yaml_value(&input[0]))?
|
||||
}
|
||||
_ => {
|
||||
return Err(ShellError::string(
|
||||
"tried saving a single object with an unrecognized format.",
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
Ok(contents)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user