Module clipivot::cli_settings

source ·
Expand description

Defines some basic settings surrounding a CSV file.

This is designed to make it simple for me to create new command-line interfaces for parsing CSVs. I built this specifically for the command-line tool I built for creating pivot tables. So far, I have not adapted the code at all, except to change the documentation and change the names on some of the functions.

The basic idea is that you can use this tool to convert ArgMatches from Clap (a command-line argument parser in Rust) into things that are more convenient from a back-end logic perspective.

For instance, say you have a Clap app that looks like this:

extern crate clap;
use clap:::{Arg, App};
let app = App::new("CSV Program")
                    .version("0.1.0")
                    .author("Max Lee<maxbmhlee@gmail.com")
                    .about("Selects fields from a CSV file")
                    .arg(Arg::with_name("filename")
                        .takes_value(true))
                    .arg(Arg::with_name("delimiter")
                        .takes_value(true))
                    .arg(Arg::with_name("noheader"))
                    .arg(Arg::with_name("fieldselect")
                        .multiple(true));
let matches = app.get_matches();

where “filename” refers to the name of your file (or None if you’re reading from standard input), “delimiter” refers to the single byte UTF-8 delimiter separating fields in each row, “noheader” refers to whether or not your file has a header row, and “fieldselect” refers to a list of fields from the CSV file that the user wants to do something based off (more on that in a bit).

In order to create a CsvSettings object and validate your delimiter, simply type

let filename = matches.value_of("filename");
let settings = CsvSettings::parse_new(
         &filename,
        matches.value_of("delimiter"),
        !matches.is_present("noheader")
    ).expect("Couldn't properly parse the delimiter");

From there, you can easily create a csv::Reader object:

if filename.is_some() {
    let mut rdr = settings.get_reader_from_path(&filename).expect("Couldn't read file");
} else {
    let mut rdr = settings.get_reader_from_stdin();
}

Finally, let’s say you want to allow a user to select a list of fields from a CSV file and do something based on the values of those fields. If the header row looks like this:

col1,col2,col1,col3

The user can enter one of the following things to select the first column:

  • col1
  • 0
  • col1[0]

Or, to grab the third column, the user can type

  • 2
  • col1[1]

And finally, assuming the user is allowed to select multiple columns, the user can type one of the following things to grab the first two columns in our file:

  • –option col1,col2
  • –option col1 col2
  • –option col1 –option col2

In order to convert the user’s selection into a list of unsigned integers so your program can more easily retrieve the value of a given row at a column the user selected, simply take one of the csv::Reader objects you created and type

let headers = rdr.headers().expect("Couldn't parse header");
let string_fields = matches.values_of("fieldselect")
    .unwrap_or(vec![]);
let index_vec = settings.get_field_indexes(
    &string_fileds, &headers.iter().collect()
).expect("Couldn't parse one or more of the fields");

Or, to select one column and return its index after parsing, type:

let colname = matches.value_of("selection").unwrap();
let col_idx = settings.get_field_index(colname, &headers.iter().collect());

One final thing: When it comes to field selection, CsvSettings keeps in mind whether or not you have a header row. If you don’t, it will require that all of your fields be unsigned integers between 0 and the total number of fields in the first row of your CSV file. And because the rdr.headers() method returns the first row of your file regardless of whether or not the file has a header row, you don’t need to change a line of code to get it to work.

Structs

  • The core struct of the settings module, providing general settings and utilities for writing CSV command-line tools.