add "-0" as short for --headerless in "from" commands (#3042)

* replace --headerless flags with --noheaders / -n

* Update from_csv.rs

Co-authored-by: Jonathan Turner <jonathandturner@users.noreply.github.com>
This commit is contained in:
Saeed Rasooli 2021-02-22 10:55:17 +03:30 committed by GitHub
parent b5ae024cc8
commit 42d18d2294
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 61 additions and 56 deletions

View File

@ -8,7 +8,7 @@ pub struct FromCSV;
#[derive(Deserialize)]
pub struct FromCSVArgs {
headerless: bool,
noheaders: bool,
separator: Option<Value>,
}
@ -27,9 +27,9 @@ impl WholeStreamCommand for FromCSV {
Some('s'),
)
.switch(
"headerless",
"noheaders",
"don't treat the first row as column names",
None,
Some('n'),
)
}
@ -50,7 +50,12 @@ impl WholeStreamCommand for FromCSV {
},
Example {
description: "Convert comma-separated data to a table, ignoring headers",
example: "open data.txt | from csv --headerless",
example: "open data.txt | from csv --noheaders",
result: None,
},
Example {
description: "Convert comma-separated data to a table, ignoring headers",
example: "open data.txt | from csv -n",
result: None,
},
Example {
@ -67,7 +72,7 @@ async fn from_csv(args: CommandArgs) -> Result<OutputStream, ShellError> {
let (
FromCSVArgs {
headerless,
noheaders,
separator,
},
input,
@ -95,7 +100,7 @@ async fn from_csv(args: CommandArgs) -> Result<OutputStream, ShellError> {
_ => ',',
};
from_delimited_data(headerless, sep, "CSV", input, name).await
from_delimited_data(noheaders, sep, "CSV", input, name).await
}
#[cfg(test)]

View File

@ -5,18 +5,18 @@ use nu_protocol::{TaggedDictBuilder, UntaggedValue, Value};
fn from_delimited_string_to_value(
s: String,
headerless: bool,
noheaders: bool,
separator: char,
tag: impl Into<Tag>,
) -> Result<Value, csv::Error> {
let mut reader = ReaderBuilder::new()
.has_headers(!headerless)
.has_headers(!noheaders)
.delimiter(separator as u8)
.from_reader(s.as_bytes());
let tag = tag.into();
let span = tag.span;
let headers = if headerless {
let headers = if noheaders {
(1..=reader.headers()?.len())
.map(|i| format!("Column{}", i))
.collect::<Vec<String>>()
@ -46,7 +46,7 @@ fn from_delimited_string_to_value(
}
pub async fn from_delimited_data(
headerless: bool,
noheaders: bool,
sep: char,
format_name: &'static str,
input: InputStream,
@ -56,7 +56,7 @@ pub async fn from_delimited_data(
let concat_string = input.collect_string(name_tag.clone()).await?;
let sample_lines = concat_string.item.lines().take(3).collect_vec().join("\n");
match from_delimited_string_to_value(concat_string.item, headerless, sep, name_tag.clone()) {
match from_delimited_string_to_value(concat_string.item, noheaders, sep, name_tag.clone()) {
Ok(x) => match x {
Value {
value: UntaggedValue::Table(list),

View File

@ -10,7 +10,7 @@ pub struct FromODS;
#[derive(Deserialize)]
pub struct FromODSArgs {
headerless: bool,
noheaders: bool,
}
#[async_trait]
@ -21,9 +21,9 @@ impl WholeStreamCommand for FromODS {
fn signature(&self) -> Signature {
Signature::build("from ods").switch(
"headerless",
"noheaders",
"don't treat the first row as column names",
None,
Some('n'),
)
}
@ -42,7 +42,7 @@ async fn from_ods(args: CommandArgs) -> Result<OutputStream, ShellError> {
let (
FromODSArgs {
headerless: _headerless,
noheaders: _noheaders,
},
input,
) = args.process().await?;

View File

@ -10,7 +10,7 @@ pub struct FromSSV;
#[derive(Deserialize)]
pub struct FromSSVArgs {
headerless: bool,
noheaders: bool,
#[serde(rename(deserialize = "aligned-columns"))]
aligned_columns: bool,
#[serde(rename(deserialize = "minimum-spaces"))]
@ -29,9 +29,9 @@ impl WholeStreamCommand for FromSSV {
fn signature(&self) -> Signature {
Signature::build(STRING_REPRESENTATION)
.switch(
"headerless",
"noheaders",
"don't treat the first row as column names",
None,
Some('n'),
)
.switch("aligned-columns", "assume columns are aligned", Some('a'))
.named(
@ -196,14 +196,14 @@ fn parse_separated_columns<'a>(
fn string_to_table(
s: &str,
headerless: bool,
noheaders: bool,
aligned_columns: bool,
split_at: usize,
) -> Vec<Vec<(String, String)>> {
let mut lines = s.lines().filter(|l| !l.trim().is_empty());
let separator = " ".repeat(std::cmp::max(split_at, 1));
let (ls, header_options) = if headerless {
let (ls, header_options) = if noheaders {
(lines, HeaderOptions::WithoutHeaders)
} else {
match lines.next() {
@ -223,13 +223,13 @@ fn string_to_table(
fn from_ssv_string_to_value(
s: &str,
headerless: bool,
noheaders: bool,
aligned_columns: bool,
split_at: usize,
tag: impl Into<Tag>,
) -> Value {
let tag = tag.into();
let rows = string_to_table(s, headerless, aligned_columns, split_at)
let rows = string_to_table(s, noheaders, aligned_columns, split_at)
.iter()
.map(|row| {
let mut tagged_dict = TaggedDictBuilder::new(&tag);
@ -251,7 +251,7 @@ async fn from_ssv(args: CommandArgs) -> Result<OutputStream, ShellError> {
let name = args.call_info.name_tag.clone();
let (
FromSSVArgs {
headerless,
noheaders,
aligned_columns,
minimum_spaces,
},
@ -266,7 +266,7 @@ async fn from_ssv(args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(
match from_ssv_string_to_value(
&concat_string.item,
headerless,
noheaders,
aligned_columns,
split_at,
name.clone(),
@ -323,7 +323,7 @@ mod tests {
}
#[test]
fn it_uses_first_row_as_data_when_headerless() {
fn it_uses_first_row_as_data_when_noheaders() {
let input = r#"
a b
1 2
@ -435,7 +435,7 @@ mod tests {
}
#[test]
fn it_handles_empty_values_when_headerless_and_aligned_columns() {
fn it_handles_empty_values_when_noheaders_and_aligned_columns() {
let input = r#"
a multi-word value b d
1 3-3 4
@ -479,11 +479,11 @@ mod tests {
kubernetes-ro component=apiserver,provider=kubernetes <none> 172.30.0.1 80/TCP
"#;
let aligned_columns_headerless = string_to_table(input, true, true, 2);
let separator_headerless = string_to_table(input, true, false, 2);
let aligned_columns_noheaders = string_to_table(input, true, true, 2);
let separator_noheaders = string_to_table(input, true, false, 2);
let aligned_columns_with_headers = string_to_table(input, false, true, 2);
let separator_with_headers = string_to_table(input, false, false, 2);
assert_eq!(aligned_columns_headerless, separator_headerless);
assert_eq!(aligned_columns_noheaders, separator_noheaders);
assert_eq!(aligned_columns_with_headers, separator_with_headers);
}

View File

@ -8,7 +8,7 @@ pub struct FromTSV;
#[derive(Deserialize)]
pub struct FromTSVArgs {
headerless: bool,
noheaders: bool,
}
#[async_trait]
@ -19,9 +19,9 @@ impl WholeStreamCommand for FromTSV {
fn signature(&self) -> Signature {
Signature::build("from tsv").switch(
"headerless",
"noheaders",
"don't treat the first row as column names",
None,
Some('n'),
)
}
@ -36,9 +36,9 @@ impl WholeStreamCommand for FromTSV {
async fn from_tsv(args: CommandArgs) -> Result<OutputStream, ShellError> {
let name = args.call_info.name_tag.clone();
let (FromTSVArgs { headerless }, input) = args.process().await?;
let (FromTSVArgs { noheaders }, input) = args.process().await?;
from_delimited_data(headerless, '\t', "TSV", input, name).await
from_delimited_data(noheaders, '\t', "TSV", input, name).await
}
#[cfg(test)]

View File

@ -10,7 +10,7 @@ pub struct FromXLSX;
#[derive(Deserialize)]
pub struct FromXLSXArgs {
headerless: bool,
noheaders: bool,
}
#[async_trait]
@ -21,9 +21,9 @@ impl WholeStreamCommand for FromXLSX {
fn signature(&self) -> Signature {
Signature::build("from xlsx").switch(
"headerless",
"noheaders",
"don't treat the first row as column names",
None,
Some('n'),
)
}
@ -41,7 +41,7 @@ async fn from_xlsx(args: CommandArgs) -> Result<OutputStream, ShellError> {
let span = tag.span;
let (
FromXLSXArgs {
headerless: _headerless,
noheaders: _noheaders,
},
input,
) = args.process().await?;

View File

@ -8,7 +8,7 @@ pub struct ToCSV;
#[derive(Deserialize)]
pub struct ToCSVArgs {
headerless: bool,
noheaders: bool,
separator: Option<Value>,
}
@ -27,9 +27,9 @@ impl WholeStreamCommand for ToCSV {
Some('s'),
)
.switch(
"headerless",
"noheaders",
"do not output the columns names as the first row",
None,
Some('n'),
)
}
@ -47,7 +47,7 @@ async fn to_csv(args: CommandArgs) -> Result<OutputStream, ShellError> {
let (
ToCSVArgs {
separator,
headerless,
noheaders,
},
input,
) = args.process().await?;
@ -74,7 +74,7 @@ async fn to_csv(args: CommandArgs) -> Result<OutputStream, ShellError> {
_ => ',',
};
to_delimited_data(headerless, sep, "CSV", input, name).await
to_delimited_data(noheaders, sep, "CSV", input, name).await
}
#[cfg(test)]

View File

@ -165,7 +165,7 @@ fn merge_descriptors(values: &[Value]) -> Vec<Spanned<String>> {
}
pub async fn to_delimited_data(
headerless: bool,
noheaders: bool,
sep: char,
format_name: &'static str,
input: InputStream,
@ -192,7 +192,7 @@ pub async fn to_delimited_data(
futures::stream::iter(to_process_input.into_iter().map(move |value| {
match from_value_to_delimited_string(&clone_tagged_value(&value), sep) {
Ok(mut x) => {
if headerless {
if noheaders {
if let Some(second_line) = x.find('\n') {
let start = second_line + 1;
x.replace_range(0..start, "");

View File

@ -8,7 +8,7 @@ pub struct ToTSV;
#[derive(Deserialize)]
pub struct ToTSVArgs {
headerless: bool,
noheaders: bool,
}
#[async_trait]
@ -19,9 +19,9 @@ impl WholeStreamCommand for ToTSV {
fn signature(&self) -> Signature {
Signature::build("to tsv").switch(
"headerless",
"noheaders",
"do not output the column names as the first row",
None,
Some('n'),
)
}
@ -36,9 +36,9 @@ impl WholeStreamCommand for ToTSV {
async fn to_tsv(args: CommandArgs) -> Result<OutputStream, ShellError> {
let name = args.call_info.name_tag.clone();
let (ToTSVArgs { headerless }, input) = args.process().await?;
let (ToTSVArgs { noheaders }, input) = args.process().await?;
to_delimited_data(headerless, '\t', "TSV", input, name).await
to_delimited_data(noheaders, '\t', "TSV", input, name).await
}
#[cfg(test)]

View File

@ -64,7 +64,7 @@ fn table_to_csv_text_skipping_headers_after_conversion() {
| str trim
| split column "," a b c d origin
| last 1
| to csv --headerless
| to csv --noheaders
"#
));
@ -198,7 +198,7 @@ fn from_csv_text_skipping_headers_to_table() {
cwd: dirs.test(), pipeline(
r#"
open los_tres_amigos.txt
| from csv --headerless
| from csv --noheaders
| get Column3
| count
"#

View File

@ -72,7 +72,7 @@ fn from_ssv_text_treating_first_line_as_data_with_flag() {
cwd: dirs.test(), pipeline(
r#"
open oc_get_svc.txt
| from ssv --headerless -a
| from ssv --noheaders -a
| first
| get Column1
"#
@ -82,7 +82,7 @@ fn from_ssv_text_treating_first_line_as_data_with_flag() {
cwd: dirs.test(), pipeline(
r#"
open oc_get_svc.txt
| from ssv --headerless
| from ssv --noheaders
| first
| get Column1

View File

@ -70,7 +70,7 @@ fn table_to_tsv_text_skipping_headers_after_conversion() {
| lines
| split column "\t" a b c d origin
| last 1
| to tsv --headerless
| to tsv --noheaders
"#
));
@ -121,7 +121,7 @@ fn from_tsv_text_skipping_headers_to_table() {
cwd: dirs.test(), pipeline(
r#"
open los_tres_amigos.txt
| from tsv --headerless
| from tsv --noheaders
| get Column3
| count
"#