From 96e61784cd6ae5fce744f18763c227bf5edc6053 Mon Sep 17 00:00:00 2001 From: Axel Lindeberg Date: Sat, 29 Jun 2019 11:55:39 +0200 Subject: [PATCH] Bug fix: Panic on empty input --- Cargo.lock | 2 ++ src/config.rs | 48 +++++++++++++++++++++++++++++++++++++ src/main.rs | 66 ++++++++------------------------------------------- 3 files changed, 60 insertions(+), 56 deletions(-) create mode 100644 src/config.rs diff --git a/Cargo.lock b/Cargo.lock index 4010f10..0d15ce2 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 = "ansi_term" version = "0.11.0" diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..0589cfe --- /dev/null +++ b/src/config.rs @@ -0,0 +1,48 @@ +use clap::{App, Arg}; + +pub struct Config { + pub minimize: bool, + pub separator: String, + pub file: Option, + pub outfile: Option, +} + +impl Config { + pub fn from_args() -> Config { + let args = App::new("mdtable") + .version("1.0.1") + .author("Axel Lindeberg") + .about("Makes creating tables in markdown much easier!") + .arg(Arg::with_name("minimize") + .help("Minimizes table output") + .long("minimize") + .short("m") + ) + .arg(Arg::with_name("file") + .help("Reads table values from this if given, stdin otherwise.") + .long("file") + .short("f") + .takes_value(true) + ) + .arg(Arg::with_name("outfile") + .help("Prints output to this if given, stdout otherwise.") + .long("out") + .short("o") + .takes_value(true) + ) + .arg(Arg::with_name("separator") + .help("String that separates values.") + .long("separator") + .short("s") + .default_value(",") + ) + .get_matches(); + + Config { + minimize: args.is_present("minimize"), + separator: args.value_of("separator").map(String::from).unwrap(), + file: args.value_of("file").map(String::from), + outfile: args.value_of("outfile").map(String::from), + } + } +} diff --git a/src/main.rs b/src/main.rs index 7b1823c..aa14c70 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,59 +1,13 @@ extern crate clap; extern crate pad; -use clap::{App, Arg}; -use pad::PadStr; +mod config; +use pad::PadStr; use std::io::{self, Result, BufRead, BufReader}; use std::fs::{self, File}; use std::cmp::max; - -type TableData = Vec>; - -struct Config { - minimize: bool, - separator: String, - file: Option, - outfile: Option, -} - -fn get_config() -> Config { - let args = App::new("mdtable") - .version("1.0.1") - .author("Axel Lindeberg") - .about("Makes creating tables in markdown much easier!") - .arg(Arg::with_name("minimize") - .help("Minimizes table output") - .long("minimize") - .short("m") - ) - .arg(Arg::with_name("file") - .help("Reads table values from this if given, stdin otherwise.") - .long("file") - .short("f") - .takes_value(true) - ) - .arg(Arg::with_name("outfile") - .help("Prints output to this if given, stdout otherwise.") - .long("out") - .short("o") - .takes_value(true) - ) - .arg(Arg::with_name("separator") - .help("String that separates values.") - .long("separator") - .short("s") - .default_value(",") - ) - .get_matches(); - - Config { - minimize: args.is_present("minimize"), - separator: args.value_of("separator").map(String::from).unwrap(), - file: args.value_of("file").map(String::from), - outfile: args.value_of("outfile").map(String::from), - } -} +use config::Config; fn read_lines(file: &Option) -> Result> { match file { @@ -74,8 +28,8 @@ fn read_lines(file: &Option) -> Result> { } } -fn parse_table_data(lines: &Vec, separator: &String) -> TableData { - let mut rows: TableData = lines.iter() +fn parse_table_data(lines: &Vec, separator: &String) -> Vec> { + let mut rows: Vec> = lines.iter() .map(|line| line .split(separator) .map(|word| word.trim()) @@ -86,14 +40,14 @@ fn parse_table_data(lines: &Vec, separator: &String) -> TableData { let max_len = rows.iter() .map(|row| row.len()) .max() - .unwrap(); + .unwrap_or(0); for row in &mut rows { row.resize(max_len, String::new()); } rows } -fn format_minimized(rows: &TableData) -> String { +fn format_minimized(rows: &Vec>) -> String { [ rows[0].join("|"), vec!["---"; rows[0].len()].join("|"), @@ -104,7 +58,7 @@ fn format_minimized(rows: &TableData) -> String { ].join("\n") } -fn format_pretty(data: &TableData) -> String { +fn format_pretty(data: &Vec>) -> String { let lengths = data.iter().fold( vec![1; data[0].len()], |lens, row| row.iter() @@ -136,12 +90,12 @@ fn format_pretty(data: &TableData) -> String { } fn main() -> Result<()> { - let config = get_config(); + let config = Config::from_args(); let lines = read_lines(&config.file)?; let data = parse_table_data(&lines, &config.separator); if data.len() < 2 || data[0].len() == 0 { - eprintln!("Table requires at least 2 rows (including header) and 1 column."); + eprintln!("Bad Input: Table requires at least 2 rows (including header) and 1 column."); std::process::exit(1); }