arg parse ok

master
Avril 4 years ago
commit 385d191f27
Signed by: flanchan
GPG Key ID: 284488987C31F630

2
.gitignore vendored

@ -0,0 +1,2 @@
/target
*~

5
Cargo.lock generated

@ -0,0 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "leaky-pipe"
version = "0.1.0"

@ -0,0 +1,15 @@
[package]
name = "leaky-pipe"
version = "0.1.0"
authors = ["Avril <flanchan@cumallover.me>"]
edition = "2018"
description = "Pipe a process to muliple output processies"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
default = ["broken-pipe"]
broken-pipe = []
[dependencies]

@ -0,0 +1,123 @@
use std::{
error,
fmt,
};
#[cfg(feature = "broken-pipe")]
pub const BROKEN_PIPE: char = '¦';
#[cfg(not(feature = "broken-pipe"))]
pub const BROKEN_PIPE: char = '|';
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ProcessArgs
{
pub name: String,
pub args: Vec<String>,
}
mod proc_args;
pub use proc_args::*;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Operation
{
input: ProcessArgs,
outputs: Vec<ProcessArgs>,
output_to_tty: bool,
}
#[derive(Clone, Debug)]
pub struct Error(String, String);
impl error::Error for Error{}
impl fmt::Display for Error
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "<{}>: {}", self.1, self.0)
}
}
impl Error
{
pub fn new<T>(message: T) -> Self
where T: AsRef<str>
{
Self(message.as_ref().to_owned(), program())
}
}
impl<T> From<T> for Error
where T: AsRef<str>
{
fn from(input: T) -> Self
{
Self::new(input)
}
}
impl Operation
{
pub fn new(input: ProcessArgs) -> Self
{
Self {
input,
outputs: Vec::new(),
output_to_tty: false,
}
}
pub fn parent(&self) -> &ProcessArgs
{
&self.input
}
pub fn children(&self) -> &Vec<ProcessArgs>
{
&self.outputs
}
pub fn validate(&self) -> Result<(), String>
{
if !self.output_to_tty && self.outputs.len()<1 {
return Err("Need at least one output.".to_owned());
}
self.input.verify().or_else(|err| Err(format!("bad input <{}>: {}", &self.input, err)))?;
for x in self.outputs.iter()
{
x.verify().or_else(|err| Err(format!("bad output <{}>: {}", &x, err)))?;
}
Ok(())
}
}
pub fn program() -> String
{
std::env::args().next().unwrap()
}
pub fn parse() -> Result<Operation, Error>
{
let mut iter = std::env::args();
let this = iter.next().unwrap();
let mut not_last = false;
let input = ProcessArgs::parse(&mut iter, &mut not_last).or(Err("Expected at least one input"))?;
if !not_last {
return Err(Error::new("Need at least one output."));
}
let mut output = Operation::new(input);
while let Ok(op) = ProcessArgs::parse(&mut iter, &mut not_last) {
output.outputs.push(op);
}
if not_last {
output.output_to_tty = true;
}
output.validate()?;
Ok(output)
}

@ -0,0 +1,36 @@
use super::*;
impl ProcessArgs
{
pub fn parse<T, U>(string: &mut T, not_last: &mut bool) -> Result<Self, &'static str>
where T: Iterator<Item=U>,
U: AsRef<str>
{
let name = string.next().ok_or("No process name")?.as_ref().to_owned();
let mut args = Vec::new();
*not_last = false;
while let Some(arg) = string.next() {
let arg = arg.as_ref();
let mut chars = arg.chars();
if let Some(BROKEN_PIPE) = chars.next() {
*not_last = true;
break;
} else {
args.push(arg.to_owned());
}
}
Ok(Self{
name,
args,
})
}
pub fn verify(&self) -> Result<(), &'static str>
{
//TODO: Check file path of executable
Ok(())
}
}
//TODO: impl fmt::Display for ProcessArgs

@ -0,0 +1,16 @@
#![allow(unused_variables)]
#![allow(dead_code)]
use std::{
error::Error,
};
mod arg;
fn main() -> Result<(), Box<dyn Error>> {
let op = arg::parse()?;
//println!("{:?}", op); yay!
Ok(())
}
Loading…
Cancel
Save