yarg cmd execution prototype

- handle multiple yarg command son columns
main
blob42 3 months ago
parent 2cd29789c3
commit 14cd0990b6

@ -1,6 +1,12 @@
1.  parse cli parameters
2.  read from stdin
3.  split stdin into columns
3.  map (execute) commands to fields
- [ ] execute a command on first text column
4. print resulting concatenated columns
-  parse cli parameters
-  read from stdin
-  split stdin into columns
- handle different separator types
- handle commands with args
- detect if cmd has more than one arg
-  map (execute) commands to fields
- [ ] execute a command on first text column
- print resulting concatenated columns
- delimiter: use regex or literal char/str

@ -26,7 +26,7 @@ impl Deref for Columns {
}
// build Columns from &str
// build Columns from &str
impl TryFrom<&str> for Columns {
type Error = anyhow::Error;

@ -13,6 +13,7 @@ use yargs::{DEFAULT_SEP_PATTERN, stdin};
use yargs::parse::InputText;
use anyhow::Result;
use std::io::{BufRead, Read, BufReader, stdin, Write};
use std::os;
use std::process::{self, Command, Stdio};
@ -30,7 +31,7 @@ use std::process::{self, Command, Stdio};
#[command(author="blob42")]
#[command(version="0.1")]
struct Cli {
/// Regex used to to split input into columns
/// Regex used for splitting the input into columns
#[arg(default_value=DEFAULT_SEP_PATTERN)]
#[arg(short)]
delimiter: String,
@ -110,7 +111,49 @@ fn main() -> Result<()> {
} else {
// Handle yargs
// For each columns of text, execute the arg command on
// the columns lines (xargs)
// the column lines
// naive implementation
// TODO: map input columns into output processed commands
for (i, yarg) in cli.yargs.into_iter().enumerate() {
// let yarg_cmd = &yarg.split_whitespace().nth(0).unwrap_or(&yarg);
// dbg!(yarg_cmd);
// let yarg_args: Vec<&str> = yarg.split_whitespace().skip(1).collect();
// dbg!(yarg_args);
// for each yarg split into cmd, args
let mut yarg_cmd = Command::new(&yarg.split_whitespace().nth(0).unwrap_or(&yarg))
.args(yarg.split_whitespace().skip(1))
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.expect(&format!("Failed to exec {yarg}"));
let mut yarg_stdin = yarg_cmd.stdin.take().expect("failed to open stdin");
let _columns = columns.clone();
// yarg_stdin.write_all(columns[i].join("\n").as_bytes())?;
// TODO!: use https://crates.io/crates/subprocess to spawn shell
// expl: using a long `awk ..` will fail if args are split on space the cmd needs to be
// passed as is to a subshell
std::thread::spawn(move || {
yarg_stdin.write_all(_columns[i].join("\n").as_bytes()).expect("Failed to write to stdin");
});
// gather output from child
let output = yarg_cmd.wait_with_output()
.expect(format!("failed to read stdout for {}", yarg).as_str());
// TODO: gather output into column similar to input print into column format
println!("{}", String::from_utf8_lossy(&output.stdout));
}
process::exit(0);
// we know we have at least one elm
let yarg = cli.yargs.first().unwrap();

@ -22,7 +22,7 @@ fn run_command(test_file: &str, cmd: &mut Command) -> AssertResult
// empty stdin should return an empty line
#[test]
fn pass(){
fn no_stdin_no_args(){
let mut cmd = Command::cargo_bin("yargs").unwrap();
let assert = cmd
.write_stdin("")
@ -30,13 +30,11 @@ fn pass(){
assert.stdout("");
}
#[test]
// input with many columns
// no positional arguments
// behaves like cat
fn pass_columns_no_args() -> TestResult {
#[test]
fn stdin_no_args() -> TestResult {
let input = Path::new("tests/inputs/input1");
let mut cmd = Command::cargo_bin("yargs").unwrap();
@ -48,39 +46,38 @@ fn pass_columns_no_args() -> TestResult {
}
#[test]
// should if more yargs provided than detected columns
fn fail_yargs_mismatch1() -> TestResult {
let input = Path::new("tests/inputs/input1");
let mut cmd = Command::cargo_bin("yargs").unwrap();
let assert = cmd
.args(["one", "two"])
.pipe_stdin(input)?
.assert();
assert.failure();
Ok(())
}
// n args <= n cols
#[test]
fn cli_pass2() {
let mut cmd = Command::cargo_bin("yargs").unwrap();
cmd.args(["-d", r"\s"])
.args(["1", "2", "3", "4", "5", "6"]);
cmd.args(["-d", r"\s+"])
.args(vec!["true"; 6]);
run_command("tests/inputs/input1", &mut cmd).unwrap()
.success();
}
#[test]
#[should_panic]
// more arguments passed than columns
// should fail if more yargs provided than detected columns
// the input text has 7 columns, we pass 8 yargs
// delimiter: space
#[test]
fn cli_fail1() {
let mut cmd = Command::cargo_bin("yargs").unwrap();
cmd.args(["-d", r"\s"])
.args(["1", "2", "3", "4", "5", "6", "7", "8"]);
cmd.args(["-d", r"\s+"])
.args(vec!["arg"; 8]);
run_command("tests/inputs/input1", &mut cmd).unwrap()
.failure();
}
// should execute yarg corresponding to column
// first yarg transforms col to uppercase
// second yarg reverses the text
#[test]
fn cli_exec_yarg() {
let mut cmd = Command::cargo_bin("yargs").unwrap();
cmd.args(["-d", r"\s+"])
.args(["tr '[:lower:]' '[:upper:]'", "rev"]);
run_command("tests/inputs/input2_spaces", &mut cmd).unwrap()
.success()
.stdout(read_to_string(Path::new("tests/outputs/output2_spaces")).unwrap());
}

@ -0,0 +1,2 @@
file1 300
file2 400

@ -0,0 +1,2 @@
FILE1 003
FILE2 004
Loading…
Cancel
Save