From f730296e4564d87b4ddc62b17e54dc3601817adc Mon Sep 17 00:00:00 2001 From: Jonathan Turner Date: Thu, 29 Aug 2019 15:53:45 +1200 Subject: [PATCH] WIP supporting from/to automatically --- src/cli.rs | 1 + src/commands.rs | 1 + src/commands/classified.rs | 24 ++--- src/commands/command.rs | 9 +- src/commands/cp.rs | 4 +- src/commands/enter.rs | 2 +- src/commands/from_yaml.rs | 20 +++++ src/commands/mkdir.rs | 4 +- src/commands/mv.rs | 4 +- src/commands/open.rs | 177 +++++++++---------------------------- src/commands/rm.rs | 4 +- src/commands/where_.rs | 2 +- src/parser/hir.rs | 6 +- src/prelude.rs | 2 +- 14 files changed, 90 insertions(+), 170 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index b650787d8d..46e4e338e8 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -194,6 +194,7 @@ pub async fn cli() -> Result<(), Box> { whole_stream_command(FromTOML), whole_stream_command(FromXML), whole_stream_command(FromYAML), + whole_stream_command(FromYML), whole_stream_command(Pick), whole_stream_command(Get), per_item_command(Remove), diff --git a/src/commands.rs b/src/commands.rs index d1d9297fd4..529baf359a 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -80,6 +80,7 @@ crate use from_json::FromJSON; crate use from_toml::FromTOML; crate use from_xml::FromXML; crate use from_yaml::FromYAML; +crate use from_yaml::FromYML; crate use get::Get; crate use last::Last; crate use lines::Lines; diff --git a/src/commands/classified.rs b/src/commands/classified.rs index f74bab2f0e..b831a8007a 100644 --- a/src/commands/classified.rs +++ b/src/commands/classified.rs @@ -162,7 +162,7 @@ impl InternalCommand { let full_path = std::path::PathBuf::from(cwd); - let (file_extension, contents, contents_tag, span_source) = + let (_file_extension, contents, contents_tag, span_source) = crate::commands::open::fetch( &full_path, &location, @@ -175,23 +175,11 @@ impl InternalCommand { context.add_span_source(uuid, span_source); } - match contents { - Value::Primitive(Primitive::String(string)) => { - let value = crate::commands::open::parse_string_as_value( - file_extension, - string, - contents_tag, - Span::unknown(), - )?; - - context - .shell_manager - .insert_at_current(Box::new(ValueShell::new(value))); - } - value => context.shell_manager.insert_at_current(Box::new( - ValueShell::new(value.tagged(contents_tag)), - )), - } + context + .shell_manager + .insert_at_current(Box::new(ValueShell::new( + contents.tagged(contents_tag), + ))) } } CommandAction::PreviousShell => { diff --git a/src/commands/command.rs b/src/commands/command.rs index 9c8e786a1a..404d1d6b89 100644 --- a/src/commands/command.rs +++ b/src/commands/command.rs @@ -512,7 +512,7 @@ pub trait PerItemCommand: Send + Sync { &self, call_info: &CallInfo, registry: &CommandRegistry, - shell_manager: &ShellManager, + raw_args: &RawCommandArgs, input: Tagged, ) -> Result; @@ -579,7 +579,7 @@ impl Command { .call_info .evaluate(®istry, &Scope::it_value(x.clone())) .unwrap(); - match command.run(&call_info, ®istry, &raw_args.shell_manager, x) { + match command.run(&call_info, ®istry, &raw_args, x) { Ok(o) => o, Err(e) => VecDeque::from(vec![ReturnValue::Err(e)]).to_output_stream(), } @@ -596,7 +596,10 @@ impl Command { .unwrap(); // We don't have an $it or block, so just execute what we have - match command.run(&call_info, ®istry, &raw_args.shell_manager, nothing) { + match command + .run(&call_info, ®istry, &raw_args, nothing) + .into() + { Ok(o) => o, Err(e) => OutputStream::one(Err(e)), } diff --git a/src/commands/cp.rs b/src/commands/cp.rs index 9ddbc8e4ae..ee1a289cd8 100644 --- a/src/commands/cp.rs +++ b/src/commands/cp.rs @@ -19,10 +19,10 @@ impl PerItemCommand for Cpy { &self, call_info: &CallInfo, _registry: &CommandRegistry, - shell_manager: &ShellManager, + raw_args: &RawCommandArgs, _input: Tagged, ) -> Result { - call_info.process(shell_manager, cp)?.run() + call_info.process(&raw_args.shell_manager, cp)?.run() } fn name(&self) -> &str { diff --git a/src/commands/enter.rs b/src/commands/enter.rs index 2e9d0fd01a..19f6b9c8cb 100644 --- a/src/commands/enter.rs +++ b/src/commands/enter.rs @@ -19,7 +19,7 @@ impl PerItemCommand for Enter { &self, call_info: &CallInfo, _registry: ®istry::CommandRegistry, - _shell_manager: &ShellManager, + _raw_args: &RawCommandArgs, _input: Tagged, ) -> Result { match call_info.args.expect_nth(0)? { diff --git a/src/commands/from_yaml.rs b/src/commands/from_yaml.rs index 349a6faeec..2294a39ee3 100644 --- a/src/commands/from_yaml.rs +++ b/src/commands/from_yaml.rs @@ -23,6 +23,26 @@ impl WholeStreamCommand for FromYAML { } } +pub struct FromYML; + +impl WholeStreamCommand for FromYML { + fn run( + &self, + args: CommandArgs, + registry: &CommandRegistry, + ) -> Result { + from_yaml(args, registry) + } + + fn name(&self) -> &str { + "from-yml" + } + + fn signature(&self) -> Signature { + Signature::build("from-yml") + } +} + fn convert_yaml_value_to_nu_value(v: &serde_yaml::Value, tag: impl Into) -> Tagged { let tag = tag.into(); diff --git a/src/commands/mkdir.rs b/src/commands/mkdir.rs index 5f92f1177b..96fd16afaf 100644 --- a/src/commands/mkdir.rs +++ b/src/commands/mkdir.rs @@ -16,10 +16,10 @@ impl PerItemCommand for Mkdir { &self, call_info: &CallInfo, _registry: &CommandRegistry, - shell_manager: &ShellManager, + raw_args: &RawCommandArgs, _input: Tagged, ) -> Result { - call_info.process(shell_manager, mkdir)?.run() + call_info.process(&raw_args.shell_manager, mkdir)?.run() } fn name(&self) -> &str { diff --git a/src/commands/mv.rs b/src/commands/mv.rs index 37384e6b34..af93dde382 100644 --- a/src/commands/mv.rs +++ b/src/commands/mv.rs @@ -29,10 +29,10 @@ impl PerItemCommand for Move { &self, call_info: &CallInfo, _registry: &CommandRegistry, - shell_manager: &ShellManager, + raw_args: &RawCommandArgs, _input: Tagged, ) -> Result { - call_info.process(shell_manager, mv)?.run() + call_info.process(&raw_args.shell_manager, mv)?.run() } } diff --git a/src/commands/open.rs b/src/commands/open.rs index cd3056e81d..012f398645 100644 --- a/src/commands/open.rs +++ b/src/commands/open.rs @@ -1,6 +1,7 @@ +use crate::commands::UnevaluatedCallInfo; use crate::context::SpanSource; use crate::errors::ShellError; -use crate::object::{Primitive, Value}; +use crate::object::Value; use crate::parser::hir::SyntaxType; use crate::parser::registry::Signature; use crate::prelude::*; @@ -25,15 +26,20 @@ impl PerItemCommand for Open { fn run( &self, call_info: &CallInfo, - _registry: &CommandRegistry, - shell_manager: &ShellManager, + registry: &CommandRegistry, + raw_args: &RawCommandArgs, _input: Tagged, ) -> Result { - run(call_info, shell_manager) + run(call_info, registry, raw_args) } } -fn run(call_info: &CallInfo, shell_manager: &ShellManager) -> Result { +fn run( + call_info: &CallInfo, + registry: &CommandRegistry, + raw_args: &RawCommandArgs, +) -> Result { + let shell_manager = &raw_args.shell_manager; let cwd = PathBuf::from(shell_manager.path()); let full_path = PathBuf::from(cwd); @@ -47,8 +53,9 @@ fn run(call_info: &CallInfo, shell_manager: &ShellManager) -> Result Result Result { - let value = parse_string_as_value(file_extension, string, contents_tag, name_span).unwrap(); + let tagged_contents = contents.tagged(contents_tag); - match value { - Tagged { - item: Value::List(list), - .. - } => { - for elem in list { - yield ReturnSuccess::value(elem); - } + 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, } - x => yield ReturnSuccess::value(x), - } - } - Value::Binary(binary) => { - let value = parse_binary_as_value(file_extension, binary, contents_tag, name_span).unwrap(); - - match value { - Tagged { - item: Value::List(list), - .. - } => { - for elem in list { - yield ReturnSuccess::value(elem); + }; + let mut result = converter.run(new_args.with_input(vec![tagged_contents]), ®istry); + let result_vec: Vec> = result.drain_vec().await; + for res in result_vec { + match res { + Ok(ReturnSuccess::Value(Tagged { item, .. })) => { + yield Ok(ReturnSuccess::Value(Tagged { item: item, tag: contents_tag })); } + x => yield x, } - x => yield ReturnSuccess::value(x), } + } else { + yield ReturnSuccess::value(tagged_contents); } - other => yield ReturnSuccess::value(other.tagged(contents_tag)), - }; + } else { + yield ReturnSuccess::value(tagged_contents); + } }; Ok(stream.to_output_stream()) @@ -419,104 +427,3 @@ fn read_be_u16(input: &[u8]) -> Option> { Some(result) } } - -pub fn parse_string_as_value( - extension: Option, - contents: String, - contents_tag: Tag, - name_span: Span, -) -> Result, ShellError> { - match extension { - Some(ref x) if x == "csv" => { - crate::commands::from_csv::from_csv_string_to_value(contents, false, contents_tag) - .map_err(move |_| { - ShellError::labeled_error( - "Could not open as CSV", - "could not open as CSV", - name_span, - ) - }) - } - Some(ref x) if x == "toml" => { - crate::commands::from_toml::from_toml_string_to_value(contents, contents_tag).map_err( - move |_| { - ShellError::labeled_error( - "Could not open as TOML", - "could not open as TOML", - name_span, - ) - }, - ) - } - Some(ref x) if x == "json" => { - crate::commands::from_json::from_json_string_to_value(contents, contents_tag).map_err( - move |_| { - ShellError::labeled_error( - "Could not open as JSON", - "could not open as JSON", - name_span, - ) - }, - ) - } - Some(ref x) if x == "ini" => crate::commands::from_ini::from_ini_string_to_value( - contents, - contents_tag, - ) - .map_err(move |_| { - ShellError::labeled_error("Could not open as INI", "could not open as INI", name_span) - }), - Some(ref x) if x == "xml" => crate::commands::from_xml::from_xml_string_to_value( - contents, - contents_tag, - ) - .map_err(move |_| { - ShellError::labeled_error("Could not open as XML", "could not open as XML", name_span) - }), - Some(ref x) if x == "yml" => { - crate::commands::from_yaml::from_yaml_string_to_value(contents, contents_tag).map_err( - move |_| { - ShellError::labeled_error( - "Could not open as YAML", - "could not open as YAML", - name_span, - ) - }, - ) - } - Some(ref x) if x == "yaml" => { - crate::commands::from_yaml::from_yaml_string_to_value(contents, contents_tag).map_err( - move |_| { - ShellError::labeled_error( - "Could not open as YAML", - "could not open as YAML", - name_span, - ) - }, - ) - } - _ => Ok(Value::string(contents).tagged(contents_tag)), - } -} - -pub fn parse_binary_as_value( - extension: Option, - contents: Vec, - contents_tag: Tag, - name_span: Span, -) -> Result, ShellError> { - match extension { - Some(ref x) if x == "bson" => { - crate::commands::from_bson::from_bson_bytes_to_value(contents, contents_tag).map_err( - move |_| { - ShellError::labeled_error( - "Could not open as BSON", - "could not open as BSON", - name_span, - ) - }, - ) - } - _ => Ok(Value::Binary(contents).tagged(contents_tag)), - } -} diff --git a/src/commands/rm.rs b/src/commands/rm.rs index 9bbc352879..36f7aa6d8a 100644 --- a/src/commands/rm.rs +++ b/src/commands/rm.rs @@ -28,10 +28,10 @@ impl PerItemCommand for Remove { &self, call_info: &CallInfo, _registry: &CommandRegistry, - shell_manager: &ShellManager, + raw_args: &RawCommandArgs, _input: Tagged, ) -> Result { - call_info.process(shell_manager, rm)?.run() + call_info.process(&raw_args.shell_manager, rm)?.run() } } diff --git a/src/commands/where_.rs b/src/commands/where_.rs index 4be427a4f8..f1d9b20023 100644 --- a/src/commands/where_.rs +++ b/src/commands/where_.rs @@ -19,7 +19,7 @@ impl PerItemCommand for Where { &self, call_info: &CallInfo, _registry: ®istry::CommandRegistry, - _shell_manager: &ShellManager, + _raw_args: &RawCommandArgs, input: Tagged, ) -> Result { let input_clone = input.clone(); diff --git a/src/parser/hir.rs b/src/parser/hir.rs index 2148a179f4..cb25c3458d 100644 --- a/src/parser/hir.rs +++ b/src/parser/hir.rs @@ -39,11 +39,11 @@ pub fn path(head: impl Into, tail: Vec>>) - #[derive(Debug, Clone, Eq, PartialEq, Getters, Serialize, Deserialize, new)] pub struct Call { #[get = "crate"] - head: Box, + pub head: Box, #[get = "crate"] - positional: Option>, + pub positional: Option>, #[get = "crate"] - named: Option, + pub named: Option, } impl Call { diff --git a/src/prelude.rs b/src/prelude.rs index 38b61be38f..f696b86d1e 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -51,7 +51,7 @@ crate use crate::cli::MaybeOwned; crate use crate::commands::command::{ CallInfo, CommandAction, CommandArgs, ReturnSuccess, ReturnValue, RunnableContext, }; -crate use crate::commands::PerItemCommand; +crate use crate::commands::{PerItemCommand, RawCommandArgs}; crate use crate::context::CommandRegistry; crate use crate::context::{Context, SpanSource}; crate use crate::env::host::handle_unexpected;