diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..c585e1b --- /dev/null +++ b/TODO.md @@ -0,0 +1,6 @@ + 1. parse cli parameters + 2. read from stdin + 3. split stdin into columns (column/awk commands) + 3. execute every field command on it's corresponding column + [ ] execute a command on first text column + 4. print resulting concatenated columns diff --git a/src/input.rs b/src/lib.rs similarity index 72% rename from src/input.rs rename to src/lib.rs index 74bf1d2..48e0d55 100644 --- a/src/input.rs +++ b/src/lib.rs @@ -3,12 +3,18 @@ use regex::Regex; use std::result; +use std::ops::Index; +use std::slice::SliceIndex; pub const DEFAULT_SEP_PATTERN: &str = r"[\t]+"; type Column = Vec; -type Columns = Vec; +// type Columns = Vec; + +#[derive(Clone, Debug)] +pub struct Columns(Vec); + type Result = result::Result; @@ -56,7 +62,36 @@ pub fn split_columns(text: &str, sep: &str) -> Result { eprintln!("{:?}", columns); - Ok(columns) + Ok(Columns(columns)) +} + +impl Columns { + + //NOTE: is there a way to auto implement what's implemented in the wrapped type self.0 ? + fn len(&self) -> usize { + self.0.len() + } +} + +// build Columns from &str +impl TryFrom<&str> for Columns { + type Error = String; + + fn try_from(value: &str) -> Result { + split_columns(value, DEFAULT_SEP_PATTERN) + } +} + +// impl Index to allow indexing in our wrapped Vector +impl Index for Columns +where + I: SliceIndex<[Column]>, +{ + type Output = I::Output; + + fn index(&self, index: I) -> &Self::Output { + self.0.index(index) + } } #[test] @@ -99,3 +134,9 @@ fn test_re_split() { eprintln!("{:?}", fields); assert!(false); } + +#[test] +fn test_columns_from_str() { + let res: Columns = "first column\tsecond column\t\tthird column".try_into().unwrap(); + assert_eq!(res.len(), 3); +} diff --git a/src/main.rs b/src/main.rs index 2ce2c29..b26653f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,10 +5,9 @@ * . execute arbitrary shell commands to manipulate input * . dynamically generate field parameters ? */ -mod input; use clap::Parser; -use input::DEFAULT_SEP_PATTERN; +use colmap::DEFAULT_SEP_PATTERN; #[derive(Parser)] /// colmap - map commands to columns of text input @@ -36,13 +35,6 @@ struct Cli { fn main() { let cli = Cli::parse(); - // 1. parse cli parameters - // 2. read from stdin - // 3. split stdin into columns (column/awk commands) - // 3. execute every field command on it's corresponding column - // [ ] execute a command on first text column - // 4. print resulting concatenated columns - // if let None = cli.f1.as_deref() { // eprintln!("no field --fX to operate on"); // process::exit(1);