From f730296e4564d87b4ddc62b17e54dc3601817adc Mon Sep 17 00:00:00 2001 From: Jonathan Turner Date: Thu, 29 Aug 2019 15:53:45 +1200 Subject: [PATCH 1/4] 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; From b6db233c73a2688767d711690ace7768baf817a5 Mon Sep 17 00:00:00 2001 From: Jonathan Turner Date: Fri, 30 Aug 2019 03:39:16 +1200 Subject: [PATCH 2/4] Start working on save --- src/commands/save.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/commands/save.rs b/src/commands/save.rs index da5c093502..52e1e97ef0 100644 --- a/src/commands/save.rs +++ b/src/commands/save.rs @@ -89,7 +89,7 @@ fn save( } let content = if !save_raw { - to_string_for(full_path.extension(), &input) + to_string_for(full_path.extension(), &input).await } else { string_from(&input) }; @@ -114,7 +114,7 @@ fn save( let input: Vec> = input.values.collect().await; let content = if !save_raw { - to_string_for(full_path.extension(), &input) + to_string_for(full_path.extension(), &input).await } else { string_from(&input) }; @@ -153,7 +153,7 @@ fn string_from(input: &Vec>) -> Result { Ok(save_data) } -fn to_string_for( +async fn to_string_for( ext: Option<&std::ffi::OsStr>, input: &Vec>, ) -> Result { From 761cc3db14fb728109d550cb28a696966149f217 Mon Sep 17 00:00:00 2001 From: Jonathan Turner Date: Sat, 31 Aug 2019 12:59:21 +1200 Subject: [PATCH 3/4] Finish up enter and save --- src/commands/classified.rs | 38 +------ src/commands/enter.rs | 105 +++++++++++++++++-- src/commands/save.rs | 205 +++++++++++++++++-------------------- 3 files changed, 197 insertions(+), 151 deletions(-) diff --git a/src/commands/classified.rs b/src/commands/classified.rs index cf3689c1e6..1430707637 100644 --- a/src/commands/classified.rs +++ b/src/commands/classified.rs @@ -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(); diff --git a/src/commands/enter.rs b/src/commands/enter.rs index 19f6b9c8cb..63316b7082 100644 --- a/src/commands/enter.rs +++ b/src/commands/enter.rs @@ -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, ) -> Result { + 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.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(), diff --git a/src/commands/save.rs b/src/commands/save.rs index 1ecd22e91f..11b245ef9c 100644 --- a/src/commands/save.rs +++ b/src/commands/save.rs @@ -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 { - 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 { 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> = input.values.collect().await; + let source_map = source_map.clone(); + let stream = async_stream_block! { + let input: Vec> = 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> = 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.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>) -> Result { @@ -153,66 +201,3 @@ fn string_from(input: &Vec>) -> Result { Ok(save_data) } - -async fn to_string_for( - ext: Option<&std::ffi::OsStr>, - input: &Vec>, -) -> Result { - 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) -} From 2cde4da43f08e0a91f77a14f9c8b733a36143c08 Mon Sep 17 00:00:00 2001 From: Jonathan Turner Date: Sat, 31 Aug 2019 13:35:53 +1200 Subject: [PATCH 4/4] Partially fix list support --- src/commands/open.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/commands/open.rs b/src/commands/open.rs index 012f398645..a085862cfe 100644 --- a/src/commands/open.rs +++ b/src/commands/open.rs @@ -103,6 +103,11 @@ fn run( let result_vec: Vec> = result.drain_vec().await; for res in result_vec { match res { + Ok(ReturnSuccess::Value(Tagged { item: Value::List(list), ..})) => { + for l in list { + yield Ok(ReturnSuccess::Value(l)); + } + } Ok(ReturnSuccess::Value(Tagged { item, .. })) => { yield Ok(ReturnSuccess::Value(Tagged { item: item, tag: contents_tag })); }