From a9cf444d399c88d7391ea0a208e1da3e792f32d4 Mon Sep 17 00:00:00 2001 From: Avril Date: Mon, 1 Jun 2020 18:32:36 +0100 Subject: [PATCH] finds run in path --- src/arg/mod.rs | 13 ++++-- src/arg/proc_args.rs | 94 ++++++++++++++++++++++++++++++++++++++++++-- src/main.rs | 3 +- 3 files changed, 101 insertions(+), 9 deletions(-) diff --git a/src/arg/mod.rs b/src/arg/mod.rs index 3b2fd94..6e3970c 100644 --- a/src/arg/mod.rs +++ b/src/arg/mod.rs @@ -1,6 +1,9 @@ use std::{ error, fmt, + path::{ + PathBuf, + }, }; #[cfg(feature = "broken-pipe")] @@ -14,6 +17,8 @@ pub struct ProcessArgs { pub name: String, pub args: Vec, + + name_real: Option, //get => `.name_path()` } mod proc_args; @@ -74,17 +79,17 @@ impl Operation &self.outputs } - pub fn validate(&self) -> Result<(), String> + pub fn validate(&mut 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)))?; + self.input.name_real = Some(self.input.verify().or_else(|err| Err(format!("bad input <{}>: {}", &self.input, err)))?); - for x in self.outputs.iter() + for x in self.outputs.iter_mut() { - x.verify().or_else(|err| Err(format!("bad output <{}>: {}", &x, err)))?; + x.name_real = Some(x.verify().or_else(|err| Err(format!("bad output <{}>: {}", &x, err)))?); } Ok(()) diff --git a/src/arg/proc_args.rs b/src/arg/proc_args.rs index 3621079..eb3543c 100644 --- a/src/arg/proc_args.rs +++ b/src/arg/proc_args.rs @@ -1,4 +1,7 @@ use super::*; +use std::{ + path::{Path,PathBuf,}, +}; impl ProcessArgs { @@ -23,14 +26,97 @@ impl ProcessArgs Ok(Self{ name, args, + name_real: None, }) } - pub fn verify(&self) -> Result<(), &'static str> + pub fn name_path(&self) -> Result<&Path, &'static str> { - //TODO: Check file path of executable - Ok(()) + if let Some(buf) = &self.name_real { + Ok(buf.as_ref()) + } else { + Err("No name_path specified, have you called `verify()`?") + } + } + + pub fn verify(&self) -> Result + { + if let Ok(spath) = std::env::var("PATH") { + if let Some(path) = find_somewhere(&self.name, spath.split(':')) { + Ok(path) + } else { + Err("File not found") + } + } else if Path::new(&self.name).exists() { + Ok(Path::new(&self.name).to_owned()) + } else { + Err("File not found and $PATH not found.") + } + } +} + +fn find_somewhere(name: T, places: U) -> Option +where T: AsRef, + U: Iterator, + V: AsRef +{ + let name = name.as_ref(); + + let pbuf = Path::new(&name); + if pbuf.exists() { + return Some(pbuf.to_owned()) + } + + for place in places + { + let place = place.as_ref(); + + let pbuf = Path::new(&place).join(&name); + if pbuf.exists() { + return Some(pbuf); + } + } + + None +} + +fn escape(s: &T) -> String +where T: AsRef + ?Sized +{ + let s = s.as_ref(); + let mut o = String::with_capacity(s.len()); + + for c in s.chars() { + match c { + '\\' => { + o.push('\\'); + o.push('\\'); + }, + '\'' => { + o.push('\\'); + o.push('\''); + }, + other => o.push(other), + }; } + + o } -//TODO: impl fmt::Display for ProcessArgs +use std::fmt; +impl fmt::Display for ProcessArgs +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result + { + write!(f, "{} ", self.name)?; + let len = self.args.len(); + for (i,x) in (0..len).zip(self.args.iter()) { + write!(f, "{}", &x)?; + if i < len-1 { + write!(f, " ")?; + } + } + + Ok(()) + } +} diff --git a/src/main.rs b/src/main.rs index fb90c0b..b654154 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,8 @@ mod arg; fn main() -> Result<(), Box> { let op = arg::parse()?; - //println!("{:?}", op); yay! + //TODO: Open input + println!("{:?}", op); Ok(()) }