diff --git a/Cargo.lock b/Cargo.lock index e8714c13..f7207b6a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "aho-corasick" version = "0.6.6" diff --git a/src/cmd/mod.rs b/src/cmd/mod.rs index 921ad00b..a6fb7623 100644 --- a/src/cmd/mod.rs +++ b/src/cmd/mod.rs @@ -9,6 +9,7 @@ pub mod index; pub mod input; pub mod join; pub mod partition; +pub mod rename; pub mod reverse; pub mod sample; pub mod search; diff --git a/src/cmd/rename.rs b/src/cmd/rename.rs new file mode 100644 index 00000000..78f1452b --- /dev/null +++ b/src/cmd/rename.rs @@ -0,0 +1,65 @@ +use csv; + +use CliResult; +use config::{Config, Delimiter}; +use util; + +static USAGE: &'static str = " +Rename the columns of CSV data efficiently. + +This command lets you rename the columns in CSV data. You must specify +all of the headers, and separate them by a comma. + + Change the name of the columns: + $ xsv rename id,name,title + + Use column names that contains commas and conflict with the separator: + $ xsv rename '\"Date - Opening\",\"Date - Actual Closing\"' + +Usage: + xsv rename [options] [--] [] + xsv rename --help + +Common options: + -h, --help Display this message + -o, --output Write output to instead of stdout. + -d, --delimiter The field delimiter for reading CSV data. + Must be a single character. (default: ,) +"; + +#[derive(Deserialize)] +struct Args { + arg_input: Option, + arg_headers: String, + flag_output: Option, + flag_delimiter: Option, +} + +pub fn run(argv: &[&str]) -> CliResult<()> { + let args: Args = util::get_args(USAGE, argv)?; + + let rconfig = Config::new(&args.arg_input) + .delimiter(args.flag_delimiter); + + let mut rdr = rconfig.reader()?; + let mut wtr = Config::new(&args.flag_output).writer()?; + let headers = rdr.byte_headers()?; + + let mut new_rdr = csv::Reader::from_reader(args.arg_headers.as_bytes()); + let new_headers = new_rdr.byte_headers()?; + + if headers.len() != new_headers.len() { + return fail!("The length of the CSV headers is different from the provided one."); + } + + if !rconfig.no_headers { + wtr.write_record(new_headers)?; + } + + let mut record = csv::ByteRecord::new(); + while rdr.read_byte_record(&mut record)? { + wtr.write_record(&record)?; + } + wtr.flush()?; + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index 0f9cacfe..23e36c12 100644 --- a/src/main.rs +++ b/src/main.rs @@ -152,6 +152,7 @@ enum Command { Input, Join, Partition, + Rename, Reverse, Sample, Search, @@ -171,7 +172,7 @@ impl Command { if !argv[1].chars().all(char::is_lowercase) { return Err(CliError::Other(format!( - "xsv expects commands in lowercase. Did you mean '{}'?", + "xsv expects commands in lowercase. Did you mean '{}'?", argv[1].to_lowercase()).to_string())); } match self { @@ -187,6 +188,7 @@ impl Command { Command::Input => cmd::input::run(argv), Command::Join => cmd::join::run(argv), Command::Partition => cmd::partition::run(argv), + Command::Rename => cmd::rename::run(argv), Command::Reverse => cmd::reverse::run(argv), Command::Sample => cmd::sample::run(argv), Command::Search => cmd::search::run(argv),