You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
2.9 KiB
Rust
113 lines
2.9 KiB
Rust
/* TODO:
|
|
* . add clap for CLI flags
|
|
* . read input as column field1920s
|
|
* . test splitting input into fields
|
|
* . execute arbitrary shell commands to manipulate input
|
|
* . dynamically generate field parameters ?
|
|
*/
|
|
|
|
#![allow(unused_imports)]
|
|
use clap::{Parser,CommandFactory};
|
|
use clap::error::ErrorKind;
|
|
use yargs::{DEFAULT_SEP_PATTERN, stdin};
|
|
use yargs::parse::InputText;
|
|
use anyhow::Result;
|
|
use std::io::{BufRead, Read, BufReader, stdin};
|
|
use std::process;
|
|
|
|
|
|
#[derive(Parser)]
|
|
/// yargs - map commands to columns of text input
|
|
///
|
|
/// The yargs command maps commands to text columns, it works like `xargs` for tabular text. Input
|
|
/// is parsed into columns then passed to commands specified by the user. Commands are mapped to
|
|
/// specific columns using positional
|
|
/// arguments.
|
|
///
|
|
/// The first command is applied to the first column, the second command to the second column, etc.
|
|
#[derive(Debug)]
|
|
#[command(name="yargs")]
|
|
#[command(author="blob42")]
|
|
#[command(version="0.1")]
|
|
struct Cli {
|
|
/// Regex used to to split input into columns
|
|
#[arg(default_value=DEFAULT_SEP_PATTERN)]
|
|
#[arg(short)]
|
|
delimiter: String,
|
|
|
|
//TODO:
|
|
// -f --field
|
|
// skip fields with `-`
|
|
|
|
#[arg(short, long, action = clap::ArgAction::Count)]
|
|
verbose: u8,
|
|
|
|
/// execute CMD each column of input. 0 < N_CMD < NB_COLUMNS
|
|
yargs: Vec<String>
|
|
}
|
|
|
|
fn main() -> Result<()> {
|
|
let cli = Cli::parse();
|
|
|
|
// if let None = cli.f1.as_deref() {
|
|
// eprintln!("no field --fX to operate on");
|
|
// process::exit(1);
|
|
// }
|
|
|
|
|
|
if cli.verbose > 0 {
|
|
eprintln!("======\nDEBUG:\n");
|
|
eprintln!("{:?}", cli);
|
|
|
|
for cmd in &cli.yargs {
|
|
println!("- {}", cmd);
|
|
}
|
|
}
|
|
|
|
|
|
// input validation
|
|
// take input text, split_columns, nb yargs <= nb columns
|
|
// Validate that the number of positional args <= nb of text columns
|
|
// ex: input: hello foo bar
|
|
// --
|
|
// possible ways to call the app:
|
|
// $ echo 'hello foo bar' | yargs cat rev 'tr -d b'
|
|
// $ echo 'hello foo bar' | yargs cat rev
|
|
// $ echo 'hello foo bar' | yargs cat
|
|
// let mut cmd = Cli::command();
|
|
|
|
// Read commands as positional args
|
|
|
|
// Read input from stdin
|
|
let raw_input = stdin::read_stdin()?;
|
|
let input_text = InputText::new(&raw_input, &cli.delimiter);
|
|
|
|
let n_cols = match input_text.n_cols() {
|
|
Err(e) => {
|
|
eprintln!("error parsing input: {}", e);
|
|
process::exit(1)
|
|
},
|
|
Ok(n) => n,
|
|
};
|
|
|
|
// Check that n args <= input cols
|
|
if cli.yargs.len() > input_text.n_cols()? {
|
|
// panic!("too many arguments");
|
|
eprint!("too many arguments for delimiter={:?}", input_text.sep);
|
|
process::exit(1);
|
|
}
|
|
|
|
if cli.verbose > 0 {
|
|
eprintln!("detected {n_cols} colunms");
|
|
eprintln!("======");
|
|
}
|
|
|
|
assert!(input_text.n_cols()? >= cli.yargs.len());
|
|
|
|
// TODO: RESULT
|
|
print!("{}", raw_input);
|
|
|
|
|
|
Ok(())
|
|
}
|