From b3c623396f947042ffeb38f7e6da1e7784d26f9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20M=C3=BChmel?= Date: Wed, 22 Apr 2020 19:08:53 +0200 Subject: [PATCH] Fix to-csv command (#1635) * Fix --headerless option of to-csv and to-tsv Before to-csv --headerless split the "headerfull" output on lines, skipped the first, and then concatenated them together. That meant that all remaining output would be put on the same line, without any delimiter, making it unusable. Now we replace the range of the first line with the empty string, maintaining the rest of the output unchanged. * Remove extra space in indentation of to_delimited_data * Add --separator argument to to-csv This functionaliy has been present before, but wasn't exposed to the command. --- crates/nu-cli/src/commands/to_csv.rs | 19 ++++-- .../nu-cli/src/commands/to_delimited_data.rs | 65 ++++++++++--------- 2 files changed, 46 insertions(+), 38 deletions(-) diff --git a/crates/nu-cli/src/commands/to_csv.rs b/crates/nu-cli/src/commands/to_csv.rs index 6806313265..da82fd0b77 100644 --- a/crates/nu-cli/src/commands/to_csv.rs +++ b/crates/nu-cli/src/commands/to_csv.rs @@ -2,7 +2,7 @@ use crate::commands::to_delimited_data::to_delimited_data; use crate::commands::WholeStreamCommand; use crate::prelude::*; use nu_errors::ShellError; -use nu_protocol::{Primitive, Signature, UntaggedValue, Value}; +use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue, Value}; pub struct ToCSV; @@ -18,11 +18,18 @@ impl WholeStreamCommand for ToCSV { } fn signature(&self) -> Signature { - Signature::build("to-csv").switch( - "headerless", - "do not output the columns names as the first row", - None, - ) + Signature::build("to-csv") + .named( + "separator", + SyntaxShape::String, + "a character to separate columns, defaults to ','", + Some('s'), + ) + .switch( + "headerless", + "do not output the columns names as the first row", + None, + ) } fn usage(&self) -> &str { diff --git a/crates/nu-cli/src/commands/to_delimited_data.rs b/crates/nu-cli/src/commands/to_delimited_data.rs index 686a41b452..f8b8be6de4 100644 --- a/crates/nu-cli/src/commands/to_delimited_data.rs +++ b/crates/nu-cli/src/commands/to_delimited_data.rs @@ -175,40 +175,41 @@ pub fn to_delimited_data( let name_span = name_tag.span; let stream = async_stream! { - let input: Vec = input.collect().await; + let input: Vec = input.collect().await; - let to_process_input = if input.len() > 1 { - let tag = input[0].tag.clone(); - vec![Value { value: UntaggedValue::Table(input), tag } ] - } else if input.len() == 1 { - input - } else { - vec![] - }; + let to_process_input = if input.len() > 1 { + let tag = input[0].tag.clone(); + vec![Value { value: UntaggedValue::Table(input), tag } ] + } else if input.len() == 1 { + input + } else { + vec![] + }; - for value in to_process_input { - match from_value_to_delimited_string(&clone_tagged_value(&value), sep) { - Ok(x) => { - let converted = if headerless { - x.lines().skip(1).collect() - } else { - x - }; - yield ReturnSuccess::value(UntaggedValue::Primitive(Primitive::String(converted)).into_value(&name_tag)) - } - Err(x) => { - let expected = format!("Expected a table with {}-compatible structure from pipeline", format_name); - let requires = format!("requires {}-compatible input", format_name); - yield Err(ShellError::labeled_error_with_secondary( - expected, - requires, - name_span, - "originates from here".to_string(), - value.tag.span, - )) - } - } - } + for value in to_process_input { + match from_value_to_delimited_string(&clone_tagged_value(&value), sep) { + Ok(mut x) => { + if headerless { + x.find('\n').map(|second_line|{ + let start = second_line + 1; + x.replace_range(0..start, ""); + }); + } + yield ReturnSuccess::value(UntaggedValue::Primitive(Primitive::String(x)).into_value(&name_tag)) + } + Err(x) => { + let expected = format!("Expected a table with {}-compatible structure from pipeline", format_name); + let requires = format!("requires {}-compatible input", format_name); + yield Err(ShellError::labeled_error_with_secondary( + expected, + requires, + name_span, + "originates from here".to_string(), + value.tag.span, + )) + } + } + } }; Ok(stream.to_output_stream())