diff --git a/crates/nu-command/src/filesystem/save.rs b/crates/nu-command/src/filesystem/save.rs index 8f7dfcfa3a..8c964d1fe4 100644 --- a/crates/nu-command/src/filesystem/save.rs +++ b/crates/nu-command/src/filesystem/save.rs @@ -4,7 +4,7 @@ use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::{ Category, Example, PipelineData, ShellError, Signature, Spanned, SyntaxShape, Value, }; -use std::io::Write; +use std::io::{BufWriter, Write}; use std::path::Path; @@ -125,39 +125,71 @@ impl Command for Save { )), } } else { - match input.into_value(span) { - Value::String { val, .. } => { - if let Err(err) = file.write_all(val.as_bytes()) { - return Err(ShellError::IOError(err.to_string())); - } + match input { + PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::new(span)), + PipelineData::ExternalStream { + stdout: Some(mut stream), + .. + } => { + let mut writer = BufWriter::new(file); - Ok(PipelineData::new(span)) + stream + .try_for_each(move |result| { + let buf = match result { + Ok(v) => match v { + Value::String { val, .. } => val.into_bytes(), + Value::Binary { val, .. } => val, + _ => { + return Err(ShellError::UnsupportedInput( + format!("{:?} not supported", v.get_type()), + v.span()?, + )); + } + }, + Err(err) => return Err(err), + }; + + if let Err(err) = writer.write(&buf) { + return Err(ShellError::IOError(err.to_string())); + } + Ok(()) + }) + .map(|_| PipelineData::new(span)) } - Value::Binary { val, .. } => { - if let Err(err) = file.write_all(&val) { - return Err(ShellError::IOError(err.to_string())); + input => match input.into_value(span) { + Value::String { val, .. } => { + if let Err(err) = file.write_all(val.as_bytes()) { + return Err(ShellError::IOError(err.to_string())); + } + + Ok(PipelineData::new(span)) } + Value::Binary { val, .. } => { + if let Err(err) = file.write_all(&val) { + return Err(ShellError::IOError(err.to_string())); + } - Ok(PipelineData::new(span)) - } - Value::List { vals, .. } => { - let val = vals - .into_iter() - .map(|it| it.as_string()) - .collect::, ShellError>>()? - .join("\n") - + "\n"; - - if let Err(err) = file.write_all(val.as_bytes()) { - return Err(ShellError::IOError(err.to_string())); + Ok(PipelineData::new(span)) } + Value::List { vals, .. } => { + let val = vals + .into_iter() + .map(|it| it.as_string()) + .collect::, ShellError>>()? + .join("\n") + + "\n"; - Ok(PipelineData::new(span)) - } - v => Err(ShellError::UnsupportedInput( - format!("{:?} not supported", v.get_type()), - span, - )), + if let Err(err) = file.write_all(val.as_bytes()) { + return Err(ShellError::IOError(err.to_string())); + } + + Ok(PipelineData::new(span)) + } + v => Err(ShellError::UnsupportedInput( + format!("{:?} not supported", v.get_type()), + span, + )), + }, } } } diff --git a/crates/nu-command/tests/commands/save.rs b/crates/nu-command/tests/commands/save.rs index 2d3f8790ec..d06c04e4fc 100644 --- a/crates/nu-command/tests/commands/save.rs +++ b/crates/nu-command/tests/commands/save.rs @@ -1,36 +1,8 @@ -use nu_test_support::fs::{file_contents, Stub::FileWithContent}; +use nu_test_support::fs::file_contents; use nu_test_support::nu; use nu_test_support::playground::Playground; use std::io::Write; -#[test] -fn figures_out_intelligently_where_to_write_out_with_metadata() { - Playground::setup("save_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "cargo_sample.toml", - r#" - [package] - name = "nu" - version = "0.1.1" - authors = ["Yehuda Katz "] - description = "A shell for the GitHub era" - license = "ISC" - edition = "2018" - "#, - )]); - - let subject_file = dirs.test().join("cargo_sample.toml"); - - nu!( - cwd: dirs.root(), - "open save_test_1/cargo_sample.toml | save" - ); - - let actual = file_contents(&subject_file); - assert!(actual.contains("0.1.1")); - }) -} - #[test] fn writes_out_csv() { Playground::setup("save_test_2", |dirs, sandbox| {