From 6b6c745ed024686c94472c8eee9ff1869fae118d Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy <mmstickman@gmail.com> Date: Sun, 22 Jul 2018 17:29:11 -0600 Subject: [PATCH] Apply rustfmt --- build.rs | 6 +- members/braces/src/lib.rs | 2 +- members/builtins/src/calc.rs | 2 +- members/builtins/src/random.rs | 2 +- members/builtins/src/test.rs | 17 +- members/lexers/src/assignments/keys.rs | 36 +- members/lexers/src/assignments/mod.rs | 30 +- members/lexers/src/assignments/operator.rs | 40 ++- members/lexers/src/assignments/primitive.rs | 32 +- members/lexers/src/lib.rs | 4 +- members/ranges/src/parse.rs | 4 +- members/sys/src/sys/redox/mod.rs | 14 +- members/sys/src/sys/unix/mod.rs | 57 ++- src/lib/builtins/command_info.rs | 6 +- src/lib/builtins/exec.rs | 2 +- src/lib/builtins/exists.rs | 89 +++-- src/lib/builtins/is.rs | 22 +- src/lib/builtins/job_control.rs | 5 +- src/lib/builtins/man_pages.rs | 1 - src/lib/builtins/mod.rs | 24 +- src/lib/builtins/set.rs | 10 +- src/lib/builtins/source.rs | 2 +- src/lib/builtins/status.rs | 2 +- src/lib/lib.rs | 2 +- src/lib/parser/assignments/actions.rs | 56 +-- src/lib/parser/assignments/checker.rs | 27 +- src/lib/parser/assignments/mod.rs | 3 +- src/lib/parser/loops.rs | 8 +- src/lib/parser/mod.rs | 7 +- src/lib/parser/pipelines/collector.rs | 35 +- src/lib/parser/pipelines/mod.rs | 8 +- src/lib/parser/shell_expand/mod.rs | 94 +++-- .../shell_expand/words/methods/arrays.rs | 21 +- .../parser/shell_expand/words/methods/mod.rs | 4 +- .../shell_expand/words/methods/strings.rs | 64 ++-- src/lib/parser/shell_expand/words/mod.rs | 42 ++- src/lib/parser/shell_expand/words/tests.rs | 8 +- src/lib/parser/statement/case.rs | 18 +- src/lib/parser/statement/functions.rs | 2 +- src/lib/parser/statement/mod.rs | 3 +- src/lib/parser/statement/parse.rs | 21 +- src/lib/parser/statement/splitter.rs | 89 +++-- src/lib/shell/assignments.rs | 326 +++++++++++------- src/lib/shell/binary/mod.rs | 15 +- src/lib/shell/binary/prompt.rs | 2 +- src/lib/shell/binary/readln.rs | 5 +- src/lib/shell/completer.rs | 21 +- src/lib/shell/directory_stack.rs | 31 +- src/lib/shell/flow.rs | 58 ++-- src/lib/shell/flow_control.rs | 18 +- src/lib/shell/history.rs | 46 ++- src/lib/shell/job.rs | 15 +- src/lib/shell/mod.rs | 86 +++-- src/lib/shell/pipe_exec/foreground.rs | 8 +- src/lib/shell/pipe_exec/mod.rs | 6 +- src/lib/shell/plugins/string.rs | 3 +- src/lib/shell/signals.rs | 2 +- src/lib/shell/variables/mod.rs | 298 +++++++++------- src/lib/types.rs | 35 +- src/main.rs | 9 +- 60 files changed, 1154 insertions(+), 751 deletions(-) diff --git a/build.rs b/build.rs index c3760a51..34086f58 100644 --- a/build.rs +++ b/build.rs @@ -4,7 +4,11 @@ // const MIN_VERSION: &'static str = "1.19.0"; use std::{ - env, fs::File, io::{self, Read, Write}, path::Path, process::Command, + env, + fs::File, + io::{self, Read, Write}, + path::Path, + process::Command, }; fn main() { diff --git a/members/braces/src/lib.rs b/members/braces/src/lib.rs index b9ef13b4..0b304f3b 100644 --- a/members/braces/src/lib.rs +++ b/members/braces/src/lib.rs @@ -1,6 +1,6 @@ extern crate permutate; -extern crate smallvec; extern crate small; +extern crate smallvec; use permutate::Permutator; use smallvec::SmallVec; diff --git a/members/builtins/src/calc.rs b/members/builtins/src/calc.rs index 537e767a..f1ae0e8e 100644 --- a/members/builtins/src/calc.rs +++ b/members/builtins/src/calc.rs @@ -1,6 +1,6 @@ use calculate::{eval, eval_polish, CalcError, Value}; -use std::io::{self, Write}; use small; +use std::io::{self, Write}; const REPL_GUIDE: &'static str = r#"ion-calc Type in expressions to have them evaluated. diff --git a/members/builtins/src/random.rs b/members/builtins/src/random.rs index 63219b25..8dc6b0bf 100644 --- a/members/builtins/src/random.rs +++ b/members/builtins/src/random.rs @@ -1,6 +1,6 @@ use rand::{thread_rng, Rng}; -use std::io::{self, Write}; use small; +use std::io::{self, Write}; #[allow(unused_must_use)] fn rand_list(args: &[small::String]) -> Result<(), small::String> { diff --git a/members/builtins/src/test.rs b/members/builtins/src/test.rs index 8b931f47..c4e0e6d7 100644 --- a/members/builtins/src/test.rs +++ b/members/builtins/src/test.rs @@ -114,8 +114,7 @@ AUTHOR Written by Michael Murphy. "#; -const QUICK_GUIDE: &'static str = -r#"Usage: test [EXPRESSION] +const QUICK_GUIDE: &'static str = r#"Usage: test [EXPRESSION] Try 'test --help' for more information."#; pub fn test(args: &[small::String]) -> Result<bool, small::String> { @@ -223,7 +222,10 @@ fn get_modified_file_time(filename: &str) -> Option<SystemTime> { } /// Attempt to parse a &str as a usize. -fn parse_integers(left: &str, right: &str) -> Result<(Option<isize>, Option<isize>), small::String> { +fn parse_integers( + left: &str, + right: &str, +) -> Result<(Option<isize>, Option<isize>), small::String> { let parse_integer = |input: &str| -> Result<Option<isize>, small::String> { match input .parse::<isize>() @@ -385,18 +387,13 @@ fn test_strings() { fn test_empty_str() { let eval = |args: Vec<small::String>| evaluate_arguments(&args); assert_eq!(eval(vec!["".into()]), Ok(false)); - assert_eq!( - eval(vec!["c".into(), "=".into(), "".into()]), - Ok(false) - ); + assert_eq!(eval(vec!["c".into(), "=".into(), "".into()]), Ok(false)); } #[test] fn test_integers_arguments() { fn vec_string(args: &[&str]) -> Vec<small::String> { - args.iter() - .map(|s| (*s).into()) - .collect() + args.iter().map(|s| (*s).into()).collect() } // Equal To assert_eq!( diff --git a/members/lexers/src/assignments/keys.rs b/members/lexers/src/assignments/keys.rs index 2b297c0f..398aca2a 100644 --- a/members/lexers/src/assignments/keys.rs +++ b/members/lexers/src/assignments/keys.rs @@ -1,5 +1,5 @@ -use std::fmt::{self, Display, Formatter}; use super::Primitive; +use std::fmt::{self, Display, Formatter}; /// Keys are used in assignments to define which variable will be set, and whether the correct /// types are being assigned. @@ -64,7 +64,9 @@ impl<'a> KeyIterator<'a> { loop { let mut eol = self.read + 1 >= self.data.len(); - if self.data.as_bytes()[self.read] == b']' && (eol || self.data.as_bytes()[self.read + 1] == b' ') { + if self.data.as_bytes()[self.read] == b']' + && (eol || self.data.as_bytes()[self.read + 1] == b' ') + { let kind = match &self.data[index_ident_start..self.read] { "" => Primitive::AnyArray, s => Primitive::Indexed(s.to_owned(), Box::new(Primitive::Any)), @@ -72,7 +74,9 @@ impl<'a> KeyIterator<'a> { self.read += 1; break Ok(Key { name, kind }); - } else if self.data.as_bytes()[self.read] == b']' && self.data.as_bytes()[self.read + 1] == b':' { + } else if self.data.as_bytes()[self.read] == b']' + && self.data.as_bytes()[self.read + 1] == b':' + { let index_ident_end = self.read; self.read += 2; @@ -86,8 +90,12 @@ impl<'a> KeyIterator<'a> { "" => Primitive::AnyArray, s => match Primitive::parse(&self.data[index_ident_end + 2..self.read]) { Some(kind) => Primitive::Indexed(s.to_owned(), Box::new(kind)), - None => break Err(TypeError::Invalid(self.data[index_ident_end + 1..self.read].into())), - } + None => { + break Err(TypeError::Invalid( + self.data[index_ident_end + 1..self.read].into(), + )) + } + }, }; break Ok(Key { name, kind }); @@ -164,11 +172,11 @@ mod tests { #[test] fn key_parsing() { - let mut parser = KeyIterator::new("a:int b[] c:bool d e:int[] \ - f[0] g[$index] h[1]:int \ - i:hmap[] j:hmap[float] k:hmap[int[]] l:hmap[hmap[bool[]]] \ - m:bmap[] n:bmap[int] o:bmap[float[]] p:bmap[hmap[bool]] \ - d:a"); + let mut parser = KeyIterator::new( + "a:int b[] c:bool d e:int[] f[0] g[$index] h[1]:int i:hmap[] j:hmap[float] \ + k:hmap[int[]] l:hmap[hmap[bool[]]] m:bmap[] n:bmap[int] o:bmap[float[]] \ + p:bmap[hmap[bool]] d:a", + ); assert_eq!( parser.next().unwrap(), Ok(Key { @@ -250,7 +258,9 @@ mod tests { parser.next().unwrap(), Ok(Key { name: "l", - kind: Primitive::HashMap(Box::new(Primitive::HashMap(Box::new(Primitive::BooleanArray)))), + kind: Primitive::HashMap(Box::new(Primitive::HashMap(Box::new( + Primitive::BooleanArray + )))), },) ); assert_eq!( @@ -278,7 +288,9 @@ mod tests { parser.next().unwrap(), Ok(Key { name: "p", - kind: Primitive::BTreeMap(Box::new(Primitive::HashMap(Box::new(Primitive::Boolean)))), + kind: Primitive::BTreeMap(Box::new(Primitive::HashMap(Box::new( + Primitive::Boolean + )))), },) ); assert_eq!(parser.next().unwrap(), Err(TypeError::Invalid("a".into()))); diff --git a/members/lexers/src/assignments/mod.rs b/members/lexers/src/assignments/mod.rs index c128309c..2197820f 100644 --- a/members/lexers/src/assignments/mod.rs +++ b/members/lexers/src/assignments/mod.rs @@ -2,13 +2,17 @@ mod keys; mod operator; mod primitive; -pub use self::keys::{Key, KeyBuf, KeyIterator, TypeError}; -pub use self::operator::Operator; -pub use self::primitive::Primitive; +pub use self::{ + keys::{Key, KeyBuf, KeyIterator, TypeError}, + operator::Operator, + primitive::Primitive, +}; /// Given an valid assignment expression, this will split it into `keys`, /// `operator`, `values`. -pub fn assignment_lexer<'a>(statement: &'a str) -> (Option<&'a str>, Option<Operator>, Option<&'a str>) { +pub fn assignment_lexer<'a>( + statement: &'a str, +) -> (Option<&'a str>, Option<Operator>, Option<&'a str>) { let statement = statement.trim(); if statement.is_empty() { return (None, None, None); @@ -35,7 +39,7 @@ pub fn assignment_lexer<'a>(statement: &'a str) -> (Option<&'a str>, Option<Oper operator = Some(op); start = read; read = found; - break + break; } } } @@ -59,10 +63,10 @@ pub fn assignment_lexer<'a>(statement: &'a str) -> (Option<&'a str>, Option<Oper fn find_operator(bytes: &[u8], read: usize) -> Option<(Operator, usize)> { if bytes.len() <= read + 3 { None - } else if bytes[read+1] == b'=' { + } else if bytes[read + 1] == b'=' { Operator::parse_single(bytes[read]).map(|op| (op, read + 2)) - } else if bytes[read+2] == b'=' { - Operator::parse_double(&bytes[read..read+2]).map(|op| (op, read + 3)) + } else if bytes[read + 2] == b'=' { + Operator::parse_double(&bytes[read..read + 2]).map(|op| (op, read + 3)) } else { None } @@ -74,14 +78,8 @@ mod tests { #[test] fn assignment_splitting() { - assert_eq!( - assignment_lexer(""), - (None, None, None) - ); - assert_eq!( - assignment_lexer("abc"), - (Some("abc"), None, None) - ); + assert_eq!(assignment_lexer(""), (None, None, None)); + assert_eq!(assignment_lexer("abc"), (Some("abc"), None, None)); assert_eq!( assignment_lexer("abc+=def"), diff --git a/members/lexers/src/assignments/operator.rs b/members/lexers/src/assignments/operator.rs index 96126a72..9512d3cc 100644 --- a/members/lexers/src/assignments/operator.rs +++ b/members/lexers/src/assignments/operator.rs @@ -21,35 +21,39 @@ impl Operator { b'-' => Some(Operator::Subtract), b'/' => Some(Operator::Divide), b'*' => Some(Operator::Multiply), - _ => None, + _ => None, } } pub(crate) fn parse_double(data: &[u8]) -> Option<Operator> { match data { - b"//" => Some(Operator::IntegerDivide), - b"**" => Some(Operator::Exponent), - b"++" => Some(Operator::Concatenate), - b"::" => Some(Operator::ConcatenateHead), + b"//" => Some(Operator::IntegerDivide), + b"**" => Some(Operator::Exponent), + b"++" => Some(Operator::Concatenate), + b"::" => Some(Operator::ConcatenateHead), b"\\\\" => Some(Operator::Filter), - _ => None, + _ => None, } } } impl Display for Operator { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{}", match *self { - Operator::Add => "+=", - Operator::Concatenate => "++=", - Operator::ConcatenateHead => "::=", - Operator::Filter => "\\\\=", - Operator::Divide => "/=", - Operator::Equal => "=", - Operator::Exponent => "**=", - Operator::IntegerDivide => "//=", - Operator::Multiply => "*=", - Operator::Subtract => "-=", - }) + write!( + f, + "{}", + match *self { + Operator::Add => "+=", + Operator::Concatenate => "++=", + Operator::ConcatenateHead => "::=", + Operator::Filter => "\\\\=", + Operator::Divide => "/=", + Operator::Equal => "=", + Operator::Exponent => "**=", + Operator::IntegerDivide => "//=", + Operator::Multiply => "*=", + Operator::Subtract => "-=", + } + ) } } diff --git a/members/lexers/src/assignments/primitive.rs b/members/lexers/src/assignments/primitive.rs index 001a519b..c81fccfc 100644 --- a/members/lexers/src/assignments/primitive.rs +++ b/members/lexers/src/assignments/primitive.rs @@ -34,22 +34,26 @@ impl Primitive { fn parse_inner_hash_map(inner: &str) -> Option<Primitive> { match inner { "" => Some(Primitive::HashMap(Box::new(Primitive::Any))), - _ => Primitive::parse(inner).map(|p| Primitive::HashMap(Box::new(p))) + _ => Primitive::parse(inner).map(|p| Primitive::HashMap(Box::new(p))), } } fn parse_inner_btree_map(inner: &str) -> Option<Primitive> { match inner { "" => Some(Primitive::BTreeMap(Box::new(Primitive::Any))), - _ => Primitive::parse(inner).map(|p| Primitive::BTreeMap(Box::new(p))) + _ => Primitive::parse(inner).map(|p| Primitive::BTreeMap(Box::new(p))), } } let res = if kind.starts_with("hmap[") { let kind = &kind[5..]; - kind.rfind(']').map(|found| &kind[..found]).and_then(parse_inner_hash_map) + kind.rfind(']') + .map(|found| &kind[..found]) + .and_then(parse_inner_hash_map) } else if kind.starts_with("bmap[") { let kind = &kind[5..]; - kind.rfind(']').map(|found| &kind[..found]).and_then(parse_inner_btree_map) + kind.rfind(']') + .map(|found| &kind[..found]) + .and_then(parse_inner_btree_map) } else { None }; @@ -77,18 +81,14 @@ impl Display for Primitive { Primitive::Integer => write!(f, "int"), Primitive::IntegerArray => write!(f, "int[]"), Primitive::StrArray => write!(f, "str[]"), - Primitive::HashMap(ref kind) => { - match **kind { - Primitive::Any | Primitive::Str => write!(f, "hmap[]"), - ref kind => write!(f, "hmap[{}]", kind), - } - } - Primitive::BTreeMap(ref kind) => { - match **kind { - Primitive::Any | Primitive::Str => write!(f, "bmap[]"), - ref kind => write!(f, "bmap[{}]", kind), - } - } + Primitive::HashMap(ref kind) => match **kind { + Primitive::Any | Primitive::Str => write!(f, "hmap[]"), + ref kind => write!(f, "hmap[{}]", kind), + }, + Primitive::BTreeMap(ref kind) => match **kind { + Primitive::Any | Primitive::Str => write!(f, "bmap[]"), + ref kind => write!(f, "bmap[{}]", kind), + }, Primitive::Indexed(_, ref kind) => write!(f, "{}", kind), } } diff --git a/members/lexers/src/lib.rs b/members/lexers/src/lib.rs index 647eabfb..d522ad86 100644 --- a/members/lexers/src/lib.rs +++ b/members/lexers/src/lib.rs @@ -1,8 +1,8 @@ #[macro_use] extern crate bitflags; -pub mod assignments; pub mod arguments; +pub mod assignments; pub mod designators; -pub use self::{assignments::*, arguments::*, designators::*}; +pub use self::{arguments::*, assignments::*, designators::*}; diff --git a/members/ranges/src/parse.rs b/members/ranges/src/parse.rs index 5d361910..9f246042 100644 --- a/members/ranges/src/parse.rs +++ b/members/ranges/src/parse.rs @@ -122,7 +122,9 @@ fn char_range<'a>( } stepped_range_chars(start, end, char_step) } else { - Some(Box::new(Some((start as char).to_string().into()).into_iter())) + Some(Box::new( + Some((start as char).to_string().into()).into_iter(), + )) } } diff --git a/members/sys/src/sys/redox/mod.rs b/members/sys/src/sys/redox/mod.rs index f519b9de..130b8b68 100644 --- a/members/sys/src/sys/redox/mod.rs +++ b/members/sys/src/sys/redox/mod.rs @@ -2,9 +2,8 @@ extern crate libc; extern crate syscall; use std::{ - env::{split_paths, remove_var, var, vars}, - io, - mem, + env::{remove_var, split_paths, var, vars}, + io, mem, os::unix::{ffi::OsStrExt, io::RawFd}, path::PathBuf, process::exit, @@ -288,12 +287,7 @@ pub mod variables { } pub mod env { - use std::{ - env, - path::PathBuf, - }; + use std::{env, path::PathBuf}; - pub fn home_dir() -> Option<PathBuf> { - env::var_os("HOME").map(PathBuf::from) - } + pub fn home_dir() -> Option<PathBuf> { env::var_os("HOME").map(PathBuf::from) } } diff --git a/members/sys/src/sys/unix/mod.rs b/members/sys/src/sys/unix/mod.rs index 1e6787f6..0e8b66fe 100644 --- a/members/sys/src/sys/unix/mod.rs +++ b/members/sys/src/sys/unix/mod.rs @@ -38,10 +38,22 @@ pub const STDIN_FILENO: i32 = libc::STDIN_FILENO; #[cfg(target_os = "linux")] fn errno() -> i32 { unsafe { *libc::__errno_location() } } -#[cfg(any(target_os = "openbsd", target_os = "bitrig", target_os = "android"))] +#[cfg( + any( + target_os = "openbsd", + target_os = "bitrig", + target_os = "android" + ) +)] fn errno() -> i32 { unsafe { *libc::__errno() } } -#[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))] +#[cfg( + any( + target_os = "macos", + target_os = "ios", + target_os = "freebsd" + ) +)] fn errno() -> i32 { unsafe { *libc::__error() } } #[cfg(target_os = "dragonfly")] @@ -393,17 +405,27 @@ pub mod env { }; pub fn home_dir() -> Option<PathBuf> { - return env::var_os("HOME").or_else(|| unsafe { - fallback() - }).map(PathBuf::from); - - #[cfg(any(target_os = "android", - target_os = "ios", - target_os = "emscripten"))] + return env::var_os("HOME") + .or_else(|| unsafe { fallback() }) + .map(PathBuf::from); + + #[cfg( + any( + target_os = "android", + target_os = "ios", + target_os = "emscripten" + ) + )] unsafe fn fallback() -> Option<OsString> { None } - #[cfg(not(any(target_os = "android", - target_os = "ios", - target_os = "emscripten")))] + #[cfg( + not( + any( + target_os = "android", + target_os = "ios", + target_os = "emscripten" + ) + ) + )] unsafe fn fallback() -> Option<OsString> { let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) { n if n < 0 => 512 as usize, @@ -412,13 +434,18 @@ pub mod env { let mut buf = Vec::with_capacity(amt); let mut passwd: libc::passwd = mem::zeroed(); let mut result = ptr::null_mut(); - match libc::getpwuid_r(libc::getuid(), &mut passwd, buf.as_mut_ptr(), - buf.capacity(), &mut result) { + match libc::getpwuid_r( + libc::getuid(), + &mut passwd, + buf.as_mut_ptr(), + buf.capacity(), + &mut result, + ) { 0 if !result.is_null() => { let ptr = passwd.pw_dir as *const _; let bytes = CStr::from_ptr(ptr).to_bytes().to_vec(); Some(OsStringExt::from_vec(bytes)) - }, + } _ => None, } } diff --git a/src/lib/builtins/command_info.rs b/src/lib/builtins/command_info.rs index b6a12424..3482bc93 100644 --- a/src/lib/builtins/command_info.rs +++ b/src/lib/builtins/command_info.rs @@ -1,5 +1,5 @@ use builtins::man_pages::*; -use shell::{status::*, flow_control::Function, Shell}; +use shell::{flow_control::Function, status::*, Shell}; use small; use sys; use types; @@ -22,7 +22,7 @@ pub(crate) fn which(args: &[small::String], shell: &mut Shell) -> Result<i32, () match c_type.as_ref() { "alias" => if let Some(alias) = shell.variables.get::<types::Alias>(&**command) { println!("{}: alias to {}", command, &*alias); - } + }, "function" => println!("{}: function", command), "builtin" => println!("{}: built-in shell command", command), _path => println!("{}", _path), @@ -47,7 +47,7 @@ pub(crate) fn find_type(args: &[small::String], shell: &mut Shell) -> Result<i32 match c_type.as_ref() { "alias" => if let Some(alias) = shell.variables.get::<types::Alias>(&**command) { println!("{} is aliased to `{}`", command, &*alias); - } + }, // TODO Make it print the function. "function" => println!("{} is a function", command), "builtin" => println!("{} is a shell builtin", command), diff --git a/src/lib/builtins/exec.rs b/src/lib/builtins/exec.rs index b91593e9..29fe57eb 100644 --- a/src/lib/builtins/exec.rs +++ b/src/lib/builtins/exec.rs @@ -1,6 +1,6 @@ use builtins::man_pages::{check_help, MAN_EXEC}; -use small; use shell::Shell; +use small; use std::error::Error; use sys::execve; diff --git a/src/lib/builtins/exists.rs b/src/lib/builtins/exists.rs index fcd16618..847a46f6 100644 --- a/src/lib/builtins/exists.rs +++ b/src/lib/builtins/exists.rs @@ -1,14 +1,8 @@ use std::{fs, os::unix::fs::PermissionsExt}; #[cfg(test)] -use shell::{ - self, - flow_control::Statement, -}; -use shell::{ - flow_control::Function, - Shell, -}; +use shell::{self, flow_control::Statement}; +use shell::{flow_control::Function, Shell}; use small; use types; @@ -157,27 +151,43 @@ fn test_evaluate_arguments() { assert_eq!(evaluate_arguments(&[], &shell), Ok(false)); // multiple arguments // ignores all but the first argument - assert_eq!(evaluate_arguments(&["foo".into(), "bar".into()], &shell), Ok(true)); + assert_eq!( + evaluate_arguments(&["foo".into(), "bar".into()], &shell), + Ok(true) + ); // check `exists STRING` assert_eq!(evaluate_arguments(&["".into()], &shell), Ok(false)); assert_eq!(evaluate_arguments(&["string".into()], &shell), Ok(true)); - assert_eq!(evaluate_arguments(&["string with space".into()], &shell), Ok(true)); - assert_eq!(evaluate_arguments(&["-startswithdash".into()], &shell), Ok(true)); + assert_eq!( + evaluate_arguments(&["string with space".into()], &shell), + Ok(true) + ); + assert_eq!( + evaluate_arguments(&["-startswithdash".into()], &shell), + Ok(true) + ); // check `exists -a` // no argument means we treat it as a string assert_eq!(evaluate_arguments(&["-a".into()], &shell), Ok(true)); - shell - .variables - .set("emptyarray", types::Array::new()); - assert_eq!(evaluate_arguments(&["-a".into(), "emptyarray".into()], &shell), Ok(false)); + shell.variables.set("emptyarray", types::Array::new()); + assert_eq!( + evaluate_arguments(&["-a".into(), "emptyarray".into()], &shell), + Ok(false) + ); let mut array = types::Array::new(); array.push("element".into()); shell.variables.set("array", array); - assert_eq!(evaluate_arguments(&["-a".into(), "array".into()], &shell), Ok(true)); + assert_eq!( + evaluate_arguments(&["-a".into(), "array".into()], &shell), + Ok(true) + ); shell.variables.remove_variable("array"); - assert_eq!(evaluate_arguments(&["-a".into(), "array".into()], &shell), Ok(false)); + assert_eq!( + evaluate_arguments(&["-a".into(), "array".into()], &shell), + Ok(false) + ); // check `exists -b` // TODO: see test_binary_is_in_path() @@ -190,7 +200,10 @@ fn test_evaluate_arguments() { evaluate_arguments(&["-b".into(), "executable_file".into()], &shell), Ok(true) ); - assert_eq!(evaluate_arguments(&["-b".into(), "empty_file".into()], &shell), Ok(false)); + assert_eq!( + evaluate_arguments(&["-b".into(), "empty_file".into()], &shell), + Ok(false) + ); assert_eq!( evaluate_arguments(&["-b".into(), "file_does_not_exist".into()], &shell), Ok(false) @@ -203,7 +216,10 @@ fn test_evaluate_arguments() { // check `exists -d` // no argument means we treat it as a string assert_eq!(evaluate_arguments(&["-d".into()], &shell), Ok(true)); - assert_eq!(evaluate_arguments(&["-d".into(), "testing/".into()], &shell), Ok(true)); + assert_eq!( + evaluate_arguments(&["-d".into(), "testing/".into()], &shell), + Ok(true) + ); assert_eq!( evaluate_arguments(&["-d".into(), "testing/empty_file".into()], &shell), Ok(false) @@ -216,7 +232,10 @@ fn test_evaluate_arguments() { // check `exists -f` // no argument means we treat it as a string assert_eq!(evaluate_arguments(&["-f".into()], &shell), Ok(true)); - assert_eq!(evaluate_arguments(&["-f".into(), "testing/".into()], &shell), Ok(false)); + assert_eq!( + evaluate_arguments(&["-f".into(), "testing/".into()], &shell), + Ok(false) + ); assert_eq!( evaluate_arguments(&["-f".into(), "testing/empty_file".into()], &shell), Ok(true) @@ -230,17 +249,29 @@ fn test_evaluate_arguments() { // no argument means we treat it as a string assert_eq!(evaluate_arguments(&["-s".into()], &shell), Ok(true)); shell.set("emptyvar", "".to_string()); - assert_eq!(evaluate_arguments(&["-s".into(), "emptyvar".into()], &shell), Ok(false)); + assert_eq!( + evaluate_arguments(&["-s".into(), "emptyvar".into()], &shell), + Ok(false) + ); shell.set("testvar", "foobar".to_string()); - assert_eq!(evaluate_arguments(&["-s".into(), "testvar".into()], &shell), Ok(true)); + assert_eq!( + evaluate_arguments(&["-s".into(), "testvar".into()], &shell), + Ok(true) + ); shell.variables.remove_variable("testvar"); - assert_eq!(evaluate_arguments(&["-s".into(), "testvar".into()], &shell), Ok(false)); + assert_eq!( + evaluate_arguments(&["-s".into(), "testvar".into()], &shell), + Ok(false) + ); // also check that it doesn't trigger on arrays let mut array = types::Array::new(); array.push("element".into()); shell.variables.remove_variable("array"); shell.variables.set("array", array); - assert_eq!(evaluate_arguments(&["-s".into(), "array".into()], &shell), Ok(false)); + assert_eq!( + evaluate_arguments(&["-s".into(), "array".into()], &shell), + Ok(false) + ); // check `exists --fn` let name_str = "test_function"; @@ -259,9 +290,15 @@ fn test_evaluate_arguments() { Function::new(Some(description), name.clone(), args, statements), ); - assert_eq!(evaluate_arguments(&["--fn".into(), name_str.into()], &shell), Ok(true)); + assert_eq!( + evaluate_arguments(&["--fn".into(), name_str.into()], &shell), + Ok(true) + ); shell.variables.remove_variable(name_str); - assert_eq!(evaluate_arguments(&["--fn".into(), name_str.into()], &shell), Ok(false)); + assert_eq!( + evaluate_arguments(&["--fn".into(), name_str.into()], &shell), + Ok(false) + ); // check invalid flags / parameters (should all be treated as strings and // therefore succeed) diff --git a/src/lib/builtins/is.rs b/src/lib/builtins/is.rs index 5712753b..a84771f6 100644 --- a/src/lib/builtins/is.rs +++ b/src/lib/builtins/is.rs @@ -1,6 +1,6 @@ use shell::Shell; -use types; use small; +use types; pub(crate) fn is(args: &[small::String], shell: &mut Shell) -> Result<(), String> { match args.len() { @@ -61,12 +61,24 @@ fn test_is() { is(&vec_string(&["is", "not", "$x", "$x"]), &mut shell), Err("".to_string()) ); - assert_eq!(is(&vec_string(&["is", "not", "2", "1"]), &mut shell), Ok(())); - assert_eq!(is(&vec_string(&["is", "not", "$x", "$y"]), &mut shell), Ok(())); + assert_eq!( + is(&vec_string(&["is", "not", "2", "1"]), &mut shell), + Ok(()) + ); + assert_eq!( + is(&vec_string(&["is", "not", "$x", "$y"]), &mut shell), + Ok(()) + ); // Three arguments - assert_eq!(is(&vec_string(&["is", "1", "2"]), &mut shell), Err("".to_string())); - assert_eq!(is(&vec_string(&["is", "$x", "$y"]), &mut shell), Err("".to_string())); + assert_eq!( + is(&vec_string(&["is", "1", "2"]), &mut shell), + Err("".to_string()) + ); + assert_eq!( + is(&vec_string(&["is", "$x", "$y"]), &mut shell), + Err("".to_string()) + ); assert_eq!(is(&vec_string(&["is", " ", " "]), &mut shell), Ok(())); assert_eq!(is(&vec_string(&["is", "$x", "$x"]), &mut shell), Ok(())); diff --git a/src/lib/builtins/job_control.rs b/src/lib/builtins/job_control.rs index ed318b13..8825d746 100644 --- a/src/lib/builtins/job_control.rs +++ b/src/lib/builtins/job_control.rs @@ -2,7 +2,10 @@ //! control in the shell. use shell::{ - job_control::{JobControl, ProcessState}, signals, status::*, Shell, + job_control::{JobControl, ProcessState}, + signals, + status::*, + Shell, }; use small; use smallvec::SmallVec; diff --git a/src/lib/builtins/man_pages.rs b/src/lib/builtins/man_pages.rs index 33a93f5c..50eb1760 100644 --- a/src/lib/builtins/man_pages.rs +++ b/src/lib/builtins/man_pages.rs @@ -10,7 +10,6 @@ pub(crate) fn check_help(args: &[small::String], man_page: &'static str) -> bool false } - pub(crate) const MAN_STATUS: &str = r#"NAME status - Evaluates the current runtime status diff --git a/src/lib/builtins/mod.rs b/src/lib/builtins/mod.rs index 7d6d6393..2a1bb31f 100644 --- a/src/lib/builtins/mod.rs +++ b/src/lib/builtins/mod.rs @@ -14,16 +14,30 @@ mod status; use ion_builtins::{calc, conditionals, echo, random, test}; use self::{ - command_info::*, echo::echo, exec::exec, - exists::exists, functions::fn_, is::is, man_pages::*, source::source, - status::status, test::test, variables::{alias, drop_alias, drop_array, drop_variable}, + command_info::*, + echo::echo, + exec::exec, + exists::exists, + functions::fn_, + is::is, + man_pages::*, + source::source, + status::status, + test::test, + variables::{alias, drop_alias, drop_array, drop_variable}, }; -use std::{error::Error, io::{self, Write}}; +use std::{ + error::Error, + io::{self, Write}, +}; use parser::Terminator; use shell::{ - self, fork_function::fork_function, job_control::{JobControl, ProcessState}, status::*, + self, + fork_function::fork_function, + job_control::{JobControl, ProcessState}, + status::*, FlowLogic, Shell, ShellHistory, }; use small; diff --git a/src/lib/builtins/set.rs b/src/lib/builtins/set.rs index 38e41a8e..016a6613 100644 --- a/src/lib/builtins/set.rs +++ b/src/lib/builtins/set.rs @@ -1,8 +1,8 @@ use liner::KeyBindings; use shell::{flags::*, Shell}; -use types; use small; use std::iter; +use types; enum PositionalArgs { UnsetIfNone, @@ -80,11 +80,11 @@ pub(crate) fn set(args: &[small::String], shell: &mut Shell) -> i32 { // This used to take a `&[String]` but cloned them all, so although // this is non-ideal and could probably be better done with `Rc`, it // hasn't got any slower. - let arguments: types::Array = iter::once(command) - .chain(args_iter.cloned()) - .collect(); + let arguments: types::Array = iter::once(command).chain(args_iter.cloned()).collect(); match kind { - UnsetIfNone => { shell.variables.set("args", arguments); } + UnsetIfNone => { + shell.variables.set("args", arguments); + } RetainIfNone => if arguments.len() != 1 { shell.variables.set("args", arguments); }, diff --git a/src/lib/builtins/source.rs b/src/lib/builtins/source.rs index 85a7ca23..6ef0e822 100644 --- a/src/lib/builtins/source.rs +++ b/src/lib/builtins/source.rs @@ -1,6 +1,6 @@ use shell::{FlowLogic, Shell}; -use std::{fs::File, io::Read}; use small; +use std::{fs::File, io::Read}; /// Evaluates the given file and returns 'SUCCESS' if it succeeds. pub(crate) fn source(shell: &mut Shell, arguments: &[small::String]) -> Result<(), String> { diff --git a/src/lib/builtins/status.rs b/src/lib/builtins/status.rs index ea28e536..3ea2fba1 100644 --- a/src/lib/builtins/status.rs +++ b/src/lib/builtins/status.rs @@ -1,4 +1,4 @@ -use builtins::man_pages::{MAN_STATUS}; +use builtins::man_pages::MAN_STATUS; use shell::Shell; use small; diff --git a/src/lib/lib.rs b/src/lib/lib.rs index b652e910..4dff149b 100644 --- a/src/lib/lib.rs +++ b/src/lib/lib.rs @@ -21,11 +21,11 @@ extern crate smallvec; extern crate unicode_segmentation; extern crate xdg; -extern crate ion_sys as sys; extern crate ion_braces as braces; extern crate ion_builtins; extern crate ion_lexers as lexers; extern crate ion_ranges as ranges; +extern crate ion_sys as sys; #[macro_use] pub mod types; diff --git a/src/lib/parser/assignments/actions.rs b/src/lib/parser/assignments/actions.rs index c997b919..03d45fed 100644 --- a/src/lib/parser/assignments/actions.rs +++ b/src/lib/parser/assignments/actions.rs @@ -1,5 +1,8 @@ -use lexers::{ArgumentSplitter, assignments::{Key, KeyIterator, Operator, Primitive, TypeError}}; use super::checker::*; +use lexers::{ + assignments::{Key, KeyIterator, Operator, Primitive, TypeError}, + ArgumentSplitter, +}; use std::fmt::{self, Display, Formatter}; #[derive(Debug, PartialEq)] @@ -17,10 +20,16 @@ impl<'a> Display for AssignmentError<'a> { write!(f, "expected {}, but received {}", expected, actual) } AssignmentError::TypeError(ref type_err) => write!(f, "{}", type_err), - AssignmentError::ExtraValues(ref prevkey, ref prevval) => write!(f, "extra values were supplied, and thus ignored. \ - Previous assignment: '{}' = '{}'", prevkey, prevval), - AssignmentError::ExtraKeys(ref prevkey, ref prevval) => write!(f, "extra keys were supplied, and thus ignored. \ - Previous assignment: '{}' = '{}'", prevkey, prevval), + AssignmentError::ExtraValues(ref prevkey, ref prevval) => write!( + f, + "extra values were supplied, and thus ignored. Previous assignment: '{}' = '{}'", + prevkey, prevval + ), + AssignmentError::ExtraKeys(ref prevkey, ref prevval) => write!( + f, + "extra keys were supplied, and thus ignored. Previous assignment: '{}' = '{}'", + prevkey, prevval + ), } } } @@ -58,22 +67,19 @@ impl<'a> Iterator for AssignmentActions<'a> { let next_key = self.keys.next(); let next_value = self.values.next(); match (next_key, next_value) { - (Some(key), Some(value)) => { - match key { - Ok(key) => { - self.prevkey = key.name; - self.prevval = value; - Some(Action::new(key, self.operator, value)) - } - Err(why) => Some(Err(AssignmentError::TypeError(why))), + (Some(key), Some(value)) => match key { + Ok(key) => { + self.prevkey = key.name; + self.prevval = value; + Some(Action::new(key, self.operator, value)) } - } - (None, Some(_)) => { - Some(Err(AssignmentError::ExtraValues(self.prevkey, self.prevval))) - } - (Some(_), None) => { - Some(Err(AssignmentError::ExtraKeys(self.prevkey, self.prevval))) - } + Err(why) => Some(Err(AssignmentError::TypeError(why))), + }, + (None, Some(_)) => Some(Err(AssignmentError::ExtraValues( + self.prevkey, + self.prevval, + ))), + (Some(_), None) => Some(Err(AssignmentError::ExtraKeys(self.prevkey, self.prevval))), _ => None, } } @@ -106,8 +112,8 @@ impl<'a> Action<'a> { Ok(Action::UpdateArray(var, operator, value)) } else { Err(AssignmentError::InvalidValue(var.kind, Primitive::Any)) - } - Primitive::Indexed(_, _) => Ok(Action::UpdateArray(var, operator, value)), + }, + Primitive::Indexed(..) => Ok(Action::UpdateArray(var, operator, value)), Primitive::Any if is_array(value) => Ok(Action::UpdateArray(var, operator, value)), Primitive::Any => Ok(Action::UpdateString(var, operator, value)), _ if is_array(value) => { @@ -125,11 +131,7 @@ mod tests { fn split(input: &str) -> (String, Operator, String) { let (keys, op, vals) = assignment_lexer(input); - ( - keys.unwrap().into(), - op.unwrap(), - vals.unwrap().into(), - ) + (keys.unwrap().into(), op.unwrap(), vals.unwrap().into()) } #[test] diff --git a/src/lib/parser/assignments/checker.rs b/src/lib/parser/assignments/checker.rs index 1589d2b1..243a8ad2 100644 --- a/src/lib/parser/assignments/checker.rs +++ b/src/lib/parser/assignments/checker.rs @@ -1,8 +1,8 @@ use super::super::{expand_string, Expander}; use lexers::assignments::{Primitive, TypeError}; use shell::variables::VariableType; -use types; use std::iter::Iterator; +use types; #[derive(PartialEq, Clone, Copy, Debug)] enum IsArrayHelper { @@ -143,14 +143,20 @@ fn is_float_array(value: VariableType) -> Result<VariableType, ()> { } fn get_string<E: Expander>(shell: &E, value: &str) -> VariableType { - VariableType::Str(types::Str::from(expand_string(value, shell, false).join(" "))) + VariableType::Str(types::Str::from( + expand_string(value, shell, false).join(" "), + )) } fn get_array<E: Expander>(shell: &E, value: &str) -> VariableType { VariableType::Array(expand_string(value, shell, false)) } -fn get_hash_map<E: Expander>(shell: &E, expression: &str, inner_kind: &Primitive) -> Result<VariableType, TypeError> { +fn get_hash_map<E: Expander>( + shell: &E, + expression: &str, + inner_kind: &Primitive, +) -> Result<VariableType, TypeError> { let array = expand_string(expression, shell, false); let mut hmap = types::HashMap::with_capacity_and_hasher(array.len(), Default::default()); @@ -174,16 +180,19 @@ fn get_hash_map<E: Expander>(shell: &E, expression: &str, inner_kind: &Primitive Err(type_error) => return Err(type_error), _ => (), } - } else { - return Err(TypeError::BadValue(inner_kind.clone())) + return Err(TypeError::BadValue(inner_kind.clone())); } } Ok(VariableType::HashMap(hmap)) } -fn get_btree_map<E: Expander>(shell: &E, expression: &str, inner_kind: &Primitive) -> Result<VariableType, TypeError> { +fn get_btree_map<E: Expander>( + shell: &E, + expression: &str, + inner_kind: &Primitive, +) -> Result<VariableType, TypeError> { let array = expand_string(expression, shell, false); let mut bmap = types::BTreeMap::new(); @@ -207,9 +216,8 @@ fn get_btree_map<E: Expander>(shell: &E, expression: &str, inner_kind: &Primitiv Err(type_error) => return Err(type_error), _ => (), } - } else { - return Err(TypeError::BadValue(inner_kind.clone())) + return Err(TypeError::BadValue(inner_kind.clone())); } } @@ -240,7 +248,8 @@ pub(crate) fn value_check<E: Expander>( Primitive::StrArray if is_array => Ok(get_array!()), Primitive::Boolean if !is_array => { let value = get_string!(); - let value = is_boolean_string(&value).map_err(|_| TypeError::BadValue(expected.clone()))?; + let value = + is_boolean_string(&value).map_err(|_| TypeError::BadValue(expected.clone()))?; Ok(VariableType::Str(value.into())) } Primitive::BooleanArray if is_array => { diff --git a/src/lib/parser/assignments/mod.rs b/src/lib/parser/assignments/mod.rs index fb853171..4a460f3e 100644 --- a/src/lib/parser/assignments/mod.rs +++ b/src/lib/parser/assignments/mod.rs @@ -1,5 +1,6 @@ mod actions; mod checker; pub(crate) use self::{ - actions::{Action, AssignmentActions}, checker::{is_array, value_check} + actions::{Action, AssignmentActions}, + checker::{is_array, value_check}, }; diff --git a/src/lib/parser/loops.rs b/src/lib/parser/loops.rs index d1e24aec..318b2f20 100644 --- a/src/lib/parser/loops.rs +++ b/src/lib/parser/loops.rs @@ -96,13 +96,7 @@ mod tests { #[test] fn for_normal() { let variables = Variables::default(); - let output = vec![ - "1".into(), - "2".into(), - "3".into(), - "4".into(), - "5".into(), - ]; + let output = vec!["1".into(), "2".into(), "3".into(), "4".into(), "5".into()]; assert_eq!( ForExpression::new(&output.clone(), &VariableExpander(variables)), ForExpression::Multiple(output) diff --git a/src/lib/parser/mod.rs b/src/lib/parser/mod.rs index c28a4b18..6b6af9d7 100644 --- a/src/lib/parser/mod.rs +++ b/src/lib/parser/mod.rs @@ -7,7 +7,8 @@ mod statement; pub use self::quotes::Terminator; pub(crate) use self::{ - loops::ForExpression, shell_expand::{expand_string, Expander, Select}, + loops::ForExpression, + shell_expand::{expand_string, Expander, Select}, statement::{parse_and_validate, StatementSplitter}, }; @@ -15,7 +16,5 @@ pub(crate) use self::{ pub mod fuzzing { use super::*; - pub fn statement_parse(data: &str) { - statement::parse::parse(data); - } + pub fn statement_parse(data: &str) { statement::parse::parse(data); } } diff --git a/src/lib/parser/pipelines/collector.rs b/src/lib/parser/pipelines/collector.rs index 8393bbe4..9f74ea2d 100644 --- a/src/lib/parser/pipelines/collector.rs +++ b/src/lib/parser/pipelines/collector.rs @@ -142,8 +142,9 @@ impl<'a> Collector<'a> { bytes.next(); bytes.next(); if let Some(cmd) = self.arg(&mut bytes)? { - if let Some(x) = inputs.as_mut() - { x.push(Input::HereString(cmd.into())) }; + if let Some(x) = inputs.as_mut() { + x.push(Input::HereString(cmd.into())) + }; } else { return Err("expected string argument after '<<<'"); } @@ -162,14 +163,19 @@ impl<'a> Collector<'a> { }; let heredoc = heredoc.lines().skip(1).collect::<Vec<&str>>(); if heredoc.len() > 1 { - let herestring = - Input::HereString(heredoc[..heredoc.len() - 1].join("\n").into()); - if let Some(x) = inputs.as_mut() { x.push(herestring.clone()) }; + let herestring = Input::HereString( + heredoc[..heredoc.len() - 1].join("\n").into(), + ); + if let Some(x) = inputs.as_mut() { + x.push(herestring.clone()) + }; } } } else if let Some(file) = self.arg(&mut bytes)? { // Otherwise interpret it as stdin redirection - if let Some(x) = inputs.as_mut() { x.push(Input::File(file.into())) }; + if let Some(x) = inputs.as_mut() { + x.push(Input::File(file.into())) + }; } else { return Err("expected file argument after redirection for input"); } @@ -259,7 +265,7 @@ impl<'a> Collector<'a> { bytes.next(); } else { break; - } + }, // This is a tricky one: we only end the argment if `^` is followed by a // redirection character b'^' => { @@ -366,7 +372,7 @@ impl<'a> Collector<'a> { I: Iterator<Item = (usize, u8)>, { while let Some(&(i, b)) = bytes.peek() { - // We return an inclusive range to keep the quote type intact + // We return an inclusive range to keep the quote type intact if let b'\'' = b { bytes.next(); return Ok(&self.data[start..i + 1]); @@ -394,7 +400,8 @@ impl<'a> Collector<'a> { #[cfg(test)] mod tests { use parser::{ - pipelines::{Input, PipeItem, Pipeline, RedirectFrom, Redirection}, statement::parse, + pipelines::{Input, PipeItem, Pipeline, RedirectFrom, Redirection}, + statement::parse, }; use shell::{flow_control::Statement, Job, JobKind}; use types::Array; @@ -448,7 +455,10 @@ mod tests { if let Statement::Pipeline(pipeline) = parse("echo $(echo one $(echo two) three)") { let items = pipeline.items; assert_eq!("echo", items[0].job.args[0].as_str()); - assert_eq!("$(echo one $(echo two) three)", items[0].job.args[1].as_str()); + assert_eq!( + "$(echo one $(echo two) three)", + items[0].job.args[1].as_str() + ); } else { assert!(false); } @@ -459,7 +469,10 @@ mod tests { if let Statement::Pipeline(pipeline) = parse("echo @(echo one @(echo two) three)") { let items = pipeline.items; assert_eq!("echo", items[0].job.args[0].as_str()); - assert_eq!("@(echo one @(echo two) three)", items[0].job.args[1].as_str()); + assert_eq!( + "@(echo one @(echo two) three)", + items[0].job.args[1].as_str() + ); } else { assert!(false); } diff --git a/src/lib/parser/pipelines/mod.rs b/src/lib/parser/pipelines/mod.rs index 107be704..d0de63ae 100644 --- a/src/lib/parser/pipelines/mod.rs +++ b/src/lib/parser/pipelines/mod.rs @@ -51,12 +51,16 @@ impl PipeItem { for input in &mut self.inputs { *input = match input { Input::File(ref s) => Input::File(expand_string(s, shell, false).join(" ").into()), - Input::HereString(ref s) => Input::HereString(expand_string(s, shell, true).join(" ").into()), + Input::HereString(ref s) => { + Input::HereString(expand_string(s, shell, true).join(" ").into()) + } }; } for output in &mut self.outputs { - output.file = expand_string(output.file.as_str(), shell, false).join(" ").into(); + output.file = expand_string(output.file.as_str(), shell, false) + .join(" ") + .into(); } } diff --git a/src/lib/parser/shell_expand/mod.rs b/src/lib/parser/shell_expand/mod.rs index 8e4c468f..97e180fb 100644 --- a/src/lib/parser/shell_expand/mod.rs +++ b/src/lib/parser/shell_expand/mod.rs @@ -5,8 +5,8 @@ mod words; pub(crate) use self::words::{Select, WordIterator, WordToken}; use braces::{self, BraceToken}; -use ranges::{parse_range, Index, Range}; use glob::glob; +use ranges::{parse_range, Index, Range}; use small; use std::{ptr, str}; use types::{self, Array}; @@ -117,7 +117,11 @@ fn expand_brace<E: Expander>( } } -fn array_expand<E: Expander>(elements: &[&str], expand_func: &E, selection: Select) -> types::Array { +fn array_expand<E: Expander>( + elements: &[&str], + expand_func: &E, + selection: Select, +) -> types::Array { match selection { Select::None => types::Array::new(), Select::All => elements @@ -211,21 +215,27 @@ pub(crate) fn expand_string<E: Expander>( if key.contains(' ') { for index in key.split(' ') { let select = index.parse::<Select>().unwrap_or(Select::None); - token_buffer.push( - WordToken::ArrayVariable( - data, - contains_quote, - select, - ) - ); + token_buffer.push(WordToken::ArrayVariable( + data, + contains_quote, + select, + )); token_buffer.push(WordToken::Whitespace(" ")); } token_buffer.pop(); // Pop out the last unneeded whitespace token } else { - token_buffer.push(WordToken::ArrayVariable(data, contains_quote, Select::Key(key))); + token_buffer.push(WordToken::ArrayVariable( + data, + contains_quote, + Select::Key(key), + )); } } else { - token_buffer.push(WordToken::ArrayVariable(data, contains_quote, selection)); + token_buffer.push(WordToken::ArrayVariable( + data, + contains_quote, + selection, + )); } } _ => token_buffer.push(word), @@ -378,36 +388,41 @@ fn expand_braces<E: Expander>( } } - expanded_words.into_iter().fold(types::Array::new(), |mut array, word| { - if word.find('*').is_some() { - if let Ok(mut paths) = glob(&word) { - match paths.next() { - Some(path) => if let Ok(path_buf) = path { - array.push((*path_buf.to_string_lossy()).into()); - } else { - array.push("".into()); - }, - None => array.push(word), - } - for path in paths { - if let Ok(path_buf) = path { - array.push((*path_buf.to_string_lossy()).into()); - } else { - array.push("".into()); + expanded_words + .into_iter() + .fold(types::Array::new(), |mut array, word| { + if word.find('*').is_some() { + if let Ok(mut paths) = glob(&word) { + match paths.next() { + Some(path) => if let Ok(path_buf) = path { + array.push((*path_buf.to_string_lossy()).into()); + } else { + array.push("".into()); + }, + None => array.push(word), + } + for path in paths { + if let Ok(path_buf) = path { + array.push((*path_buf.to_string_lossy()).into()); + } else { + array.push("".into()); + } } + } else { + array.push(word); } + array } else { array.push(word); + array } - array - } else { - array.push(word); - array - } - }) + }) } -fn expand_single_array_token<E: Expander>(token: &WordToken, expand_func: &E) -> Option<types::Array> { +fn expand_single_array_token<E: Expander>( + token: &WordToken, + expand_func: &E, +) -> Option<types::Array> { let mut output = small::String::new(); match *token { WordToken::Array(ref elements, ref index) => { @@ -415,7 +430,9 @@ fn expand_single_array_token<E: Expander>(token: &WordToken, expand_func: &E) -> } WordToken::ArrayVariable(array, quoted, ref index) => { match expand_func.array(array, index.clone()) { - Some(ref array) if quoted => ::std::iter::once(Some(small::String::from(array.join(" ")))).collect(), + Some(ref array) if quoted => { + ::std::iter::once(Some(small::String::from(array.join(" ")))).collect() + } Some(array) => Some(array), None => Some(types::Array::new()), } @@ -424,7 +441,12 @@ fn expand_single_array_token<E: Expander>(token: &WordToken, expand_func: &E) -> Select::None => Some(types::Array::new()), Select::All => { expand_process(&mut output, command, Select::All, expand_func, false); - Some(output.split_whitespace().map(From::from).collect::<types::Array>()) + Some( + output + .split_whitespace() + .map(From::from) + .collect::<types::Array>(), + ) } Select::Index(Index::Forward(id)) => { expand_process(&mut output, command, Select::All, expand_func, false); diff --git a/src/lib/parser/shell_expand/words/methods/arrays.rs b/src/lib/parser/shell_expand/words/methods/arrays.rs index 77428336..4918e59b 100644 --- a/src/lib/parser/shell_expand/words/methods/arrays.rs +++ b/src/lib/parser/shell_expand/words/methods/arrays.rs @@ -1,8 +1,10 @@ use super::{ super::{ - super::{expand_string, is_expression, Expander}, Select, SelectWithSize, + super::{expand_string, is_expression, Expander}, + Select, SelectWithSize, }, - strings::unescape, Pattern, + strings::unescape, + Pattern, }; use ranges::Index; use small; @@ -30,7 +32,8 @@ impl<'a> ArrayMethod<'a> { Ok(variable .lines() .into_iter() - .map(|line| types::Str::from(line)) .collect()) + .map(|line| types::Str::from(line)) + .collect()) } fn chars<E: Expander>(&self, expand_func: &E) -> Result<Array, &'static str> { @@ -86,9 +89,7 @@ impl<'a> ArrayMethod<'a> { let res = match (&self.pattern, self.selection.clone()) { (_, Select::None) => Some("".into()).into_iter().collect(), (&Pattern::StringPattern(pattern), Select::All) => variable - .split(unescape( - &expand_string(pattern, expand_func, false).join(" ") - )?.as_str()) + .split(unescape(&expand_string(pattern, expand_func, false).join(" "))?.as_str()) .map(From::from) .collect(), (&Pattern::Whitespace, Select::All) => variable @@ -97,9 +98,7 @@ impl<'a> ArrayMethod<'a> { .map(From::from) .collect(), (&Pattern::StringPattern(pattern), Select::Index(Index::Forward(id))) => variable - .split(&unescape( - &expand_string(pattern, expand_func, false).join(" ") - )?.as_str()) + .split(&unescape(&expand_string(pattern, expand_func, false).join(" "))?.as_str()) .nth(id) .map(From::from) .into_iter() @@ -112,9 +111,7 @@ impl<'a> ArrayMethod<'a> { .into_iter() .collect(), (&Pattern::StringPattern(pattern), Select::Index(Index::Backward(id))) => variable - .rsplit(&unescape( - &expand_string(pattern, expand_func, false).join(" ") - )?.as_str()) + .rsplit(&unescape(&expand_string(pattern, expand_func, false).join(" "))?.as_str()) .nth(id) .map(From::from) .into_iter() diff --git a/src/lib/parser/shell_expand/words/methods/mod.rs b/src/lib/parser/shell_expand/words/methods/mod.rs index 2068be11..57f576a4 100644 --- a/src/lib/parser/shell_expand/words/methods/mod.rs +++ b/src/lib/parser/shell_expand/words/methods/mod.rs @@ -1,11 +1,11 @@ mod arrays; mod strings; -pub(crate) use self::{arrays::ArrayMethod, strings::StringMethod}; use self::strings::unescape; +pub(crate) use self::{arrays::ArrayMethod, strings::StringMethod}; -use lexers::ArgumentSplitter; use super::{expand_string, Expander}; +use lexers::ArgumentSplitter; use small; #[derive(Debug, PartialEq, Clone)] diff --git a/src/lib/parser/shell_expand/words/methods/strings.rs b/src/lib/parser/shell_expand/words/methods/strings.rs index 4a689742..c6acd7aa 100644 --- a/src/lib/parser/shell_expand/words/methods/strings.rs +++ b/src/lib/parser/shell_expand/words/methods/strings.rs @@ -1,14 +1,15 @@ use super::{ super::{ - super::{expand_string, is_expression, slice, Expander}, Select, + super::{expand_string, is_expression, slice, Expander}, + Select, }, MethodArgs, }; use parser::assignments::is_array; use regex::Regex; use shell::plugins::methods::{self, MethodArguments, StringMethodPlugins}; -use std::path::Path; use small; +use std::path::Path; use sys; use unicode_segmentation::UnicodeSegmentation; @@ -300,33 +301,42 @@ impl<'a> StringMethod<'a> { small::String::new() }; let second_array = pattern.array(); - let first_maybe:Option<String> = if first_str != "" {Some(first_str.to_string())} else if first_str == "" {None} else {None}; + let first_maybe: Option<String> = if first_str != "" { + Some(first_str.to_string()) + } else if first_str == "" { + None + } else { + None + }; match first_maybe { Some(first) => output.push_str(&first), None => { - let split_and_cleaned_second = second_array.flat_map(|elem| - // Note that these commas should probably not be here and that this is the wrong place to handle this - if elem != "" && elem != "," { - let elem_str = elem.to_string(); - // If the separation commas are properly removed from the pattern, then the cleaning on the next 7 lines is unnecessary - let elem_str_clean = if elem_str.ends_with(",") { + let split_and_cleaned_second = second_array + .flat_map(|elem| { + // Note that these commas should probably not be here and that this + // is the wrong place to handle this + if elem != "" && elem != "," { + let elem_str = elem.to_string(); + // If the separation commas are properly removed from the pattern, then the cleaning on the next 7 lines is unnecessary + let elem_str_clean = if elem_str.ends_with(",") { let comma_pos = elem_str.rfind(",").unwrap(); let (clean, _) = elem_str.split_at(comma_pos); clean.to_owned() } else { elem_str }; - Some(elem_str_clean) - } else { - None - } - ).collect::<Vec<String>>(); + Some(elem_str_clean) + } else { + None + } + }) + .collect::<Vec<String>>(); let second_leading_defined = split_and_cleaned_second.first(); match second_leading_defined { Some(second) => output.push_str(&second), None => return, }; - }, + } }; } method => { @@ -863,16 +873,16 @@ mod test { assert_eq!(&*output, "baz"); } - /*#[test] //This one fails, but it ain't my fault, so I'm comenting out the test for now - fn test_or_no_pattern() { - let mut output = small::String::new(); - let method = StringMethod { - method: "or", - variable: "$FOO", - pattern: "\"\"", - selection: Select::All, - }; - method.handle(&mut output, &VariableExpander); - assert_eq!(&*output, "FOOBAR"); - }*/ + // #[test] //This one fails, but it ain't my fault, so I'm comenting out the test for now + // fn test_or_no_pattern() { + // let mut output = small::String::new(); + // let method = StringMethod { + // method: "or", + // variable: "$FOO", + // pattern: "\"\"", + // selection: Select::All, + // }; + // method.handle(&mut output, &VariableExpander); + // assert_eq!(&*output, "FOOBAR"); + // } } diff --git a/src/lib/parser/shell_expand/words/mod.rs b/src/lib/parser/shell_expand/words/mod.rs index ab35e9a5..79d6cfc8 100644 --- a/src/lib/parser/shell_expand/words/mod.rs +++ b/src/lib/parser/shell_expand/words/mod.rs @@ -3,9 +3,9 @@ mod methods; mod tests; pub(crate) use self::methods::{ArrayMethod, Pattern, StringMethod}; -pub use ranges::{Select, SelectWithSize}; -use lexers::ArgumentSplitter; use super::{expand_string, Expander}; +use lexers::ArgumentSplitter; +pub use ranges::{Select, SelectWithSize}; use shell::escape::unescape; use std::borrow::Cow; @@ -47,7 +47,7 @@ pub(crate) struct WordIterator<'a, E: Expander + 'a> { read: usize, flags: Flags, expanders: &'a E, - do_glob: bool, + do_glob: bool, } impl<'a, E: Expander + 'a> WordIterator<'a, E> { @@ -172,7 +172,7 @@ impl<'a, E: Expander + 'a> WordIterator<'a, E> { b',' if !self.flags.intersects(Flags::SQUOTE | Flags::DQUOTE) && level == 0 => { elements.push(&self.data[start..self.read]); start = self.read + 1; - }, + } b'{' if !self.flags.intersects(Flags::SQUOTE | Flags::DQUOTE) => level += 1, b'}' if !self.flags.intersects(Flags::SQUOTE | Flags::DQUOTE) => if level == 0 { elements.push(&self.data[start..self.read]); @@ -763,7 +763,10 @@ impl<'a, E: Expander + 'a> Iterator for WordIterator<'a, E> { match character { _ if self.flags.contains(Flags::BACKSL) => self.flags ^= Flags::BACKSL, b'\\' if !self.flags.contains(Flags::SQUOTE) => { - pub(crate) fn maybe_unescape(input: &str, contains_escapeable: bool) -> Cow<str> { + pub(crate) fn maybe_unescape( + input: &str, + contains_escapeable: bool, + ) -> Cow<str> { if !contains_escapeable { input.into() } else { @@ -777,7 +780,16 @@ impl<'a, E: Expander + 'a> Iterator for WordIterator<'a, E> { if self.flags.contains(Flags::DQUOTE) { let _ = iterator.next(); self.read += 1; - return Some(WordToken::Normal(maybe_unescape(&self.data[start..self.read], next.map_or(true, |c| c == b'$' || c == b'@' || c == b'\\' || c == b'"')), glob, tilde)); + return Some(WordToken::Normal( + maybe_unescape( + &self.data[start..self.read], + next.map_or(true, |c| { + c == b'$' || c == b'@' || c == b'\\' || c == b'"' + }), + ), + glob, + tilde, + )); } } b'\'' if !self.flags.contains(Flags::DQUOTE) => { @@ -793,7 +805,11 @@ impl<'a, E: Expander + 'a> Iterator for WordIterator<'a, E> { return Some(WordToken::Normal(output.into(), glob, tilde)); } b' ' | b'{' if !self.flags.intersects(Flags::SQUOTE | Flags::DQUOTE) => { - return Some(WordToken::Normal(unescape(&self.data[start..self.read]), glob, tilde)) + return Some(WordToken::Normal( + unescape(&self.data[start..self.read]), + glob, + tilde, + )) } b'$' | b'@' if !self.flags.contains(Flags::SQUOTE) => { if let Some(&character) = self.data.as_bytes().get(self.read) { @@ -814,7 +830,11 @@ impl<'a, E: Expander + 'a> Iterator for WordIterator<'a, E> { if self.glob_check(&mut iterator) { glob = self.do_glob; } else { - return Some(WordToken::Normal(self.data[start..self.read].into(), glob, tilde)); + return Some(WordToken::Normal( + self.data[start..self.read].into(), + glob, + tilde, + )); } } b'*' | b'?' if !self.flags.contains(Flags::SQUOTE) => { @@ -828,7 +848,11 @@ impl<'a, E: Expander + 'a> Iterator for WordIterator<'a, E> { if start == self.read { None } else { - Some(WordToken::Normal(unescape(&self.data[start..]), glob, tilde)) + Some(WordToken::Normal( + unescape(&self.data[start..]), + glob, + tilde, + )) } } } diff --git a/src/lib/parser/shell_expand/words/tests.rs b/src/lib/parser/shell_expand/words/tests.rs index b4ac797e..1c74638c 100644 --- a/src/lib/parser/shell_expand/words/tests.rs +++ b/src/lib/parser/shell_expand/words/tests.rs @@ -1,6 +1,6 @@ use super::*; -use types::{self, Array}; use ranges::{Index, Range}; +use types::{self, Array}; struct Empty; @@ -94,9 +94,9 @@ fn array_process_within_string_process() { WordToken::Process( "let free=[@(free -h)]; echo @free[6]@free[8]/@free[7]", false, - Select::All - ) - ] + Select::All, + ), + ], ) } diff --git a/src/lib/parser/statement/case.rs b/src/lib/parser/statement/case.rs index df4771fc..52fb6d26 100644 --- a/src/lib/parser/statement/case.rs +++ b/src/lib/parser/statement/case.rs @@ -22,7 +22,9 @@ impl<'a> Display for CaseError<'a> { } } -pub(crate) fn parse_case(data: &str,) -> Result<(Option<&str>, Option<&str>, Option<String>), CaseError> { +pub(crate) fn parse_case( + data: &str, +) -> Result<(Option<&str>, Option<&str>, Option<String>), CaseError> { let mut splitter = ArgumentSplitter::new(data); // let argument = splitter.next().ok_or(CaseError::Empty)?; let mut argument = None; @@ -34,12 +36,14 @@ pub(crate) fn parse_case(data: &str,) -> Result<(Option<&str>, Option<&str>, Opt binding = Some(splitter.next().ok_or(CaseError::NoBindVariable)?); match splitter.next() { Some("if") => { - // Joining by folding is more efficient than collecting into Vec and then joining - let mut string = splitter.fold(String::with_capacity(5), |mut state, element| { - state.push_str(element); - state.push(' '); - state - }); + // Joining by folding is more efficient than collecting into Vec and then + // joining + let mut string = + splitter.fold(String::with_capacity(5), |mut state, element| { + state.push_str(element); + state.push(' '); + state + }); string.pop(); // Pop out the unneeded ' ' character if string.is_empty() { return Err(CaseError::NoConditional); diff --git a/src/lib/parser/statement/functions.rs b/src/lib/parser/statement/functions.rs index 6d5cc8b1..9268ae8a 100644 --- a/src/lib/parser/statement/functions.rs +++ b/src/lib/parser/statement/functions.rs @@ -20,7 +20,7 @@ pub(crate) fn collect_arguments(args: KeyIterator) -> Result<Vec<KeyBuf>, TypeEr #[cfg(test)] mod tests { use lexers::assignments::{KeyBuf, Primitive}; - use parser::statement::functions::{collect_arguments, parse_function}; + use parser::statement::functions::{collect_arguments, parse_function}; #[test] fn function_parsing() { diff --git a/src/lib/parser/statement/mod.rs b/src/lib/parser/statement/mod.rs index f306575a..5113e11a 100644 --- a/src/lib/parser/statement/mod.rs +++ b/src/lib/parser/statement/mod.rs @@ -7,7 +7,8 @@ pub mod parse; mod splitter; pub(crate) use self::{ - parse::parse, splitter::{StatementVariant, StatementError, StatementSplitter}, + parse::parse, + splitter::{StatementError, StatementSplitter, StatementVariant}, }; use shell::flow_control::Statement; diff --git a/src/lib/parser/statement/parse.rs b/src/lib/parser/statement/parse.rs index cae756f2..31d75cfe 100644 --- a/src/lib/parser/statement/parse.rs +++ b/src/lib/parser/statement/parse.rs @@ -1,8 +1,9 @@ -use lexers::{assignment_lexer, ArgumentSplitter}; use super::{ super::pipelines::{self, Pipeline}, - case, functions::{collect_arguments, parse_function}, + case, + functions::{collect_arguments, parse_function}, }; +use lexers::{assignment_lexer, ArgumentSplitter}; use shell::flow_control::{Case, ElseIf, ExportAction, LocalAction, Statement}; use small; use std::char; @@ -96,7 +97,7 @@ pub(crate) fn parse(code: &str) -> Statement { } else if cmd.starts_with("if ") { return Statement::ElseIf(ElseIf { expression: Box::new(parse(cmd[3..].trim_left())), - success: Vec::new() + success: Vec::new(), }); } } @@ -207,9 +208,7 @@ pub(crate) fn parse(code: &str) -> Statement { _ if cmd.starts_with("not ") => { return Statement::Not(Box::new(parse(cmd[3..].trim_left()))) } - _ if cmd.starts_with("! ") => { - return Statement::Not(Box::new(parse(cmd[1..].trim_left()))) - } + _ if cmd.starts_with("! ") => return Statement::Not(Box::new(parse(cmd[1..].trim_left()))), _ if cmd.eq("not") | cmd.eq("!") => return Statement::Not(Box::new(Statement::Default)), _ => (), } @@ -235,13 +234,9 @@ mod tests { let correct_parse = Statement::If { expression: Box::new(Statement::Pipeline(Pipeline { items: vec![PipeItem { - job: Job::new( - vec![ - "test".into(), - "1".into(), - "-eq".into(), - "2".into(), - ].into_iter() + job: Job::new( + vec!["test".into(), "1".into(), "-eq".into(), "2".into()] + .into_iter() .collect(), JobKind::Last, ), diff --git a/src/lib/parser/statement/splitter.rs b/src/lib/parser/statement/splitter.rs index f02b8dd7..5828867d 100644 --- a/src/lib/parser/statement/splitter.rs +++ b/src/lib/parser/statement/splitter.rs @@ -3,7 +3,8 @@ // - Validate syntax in methods use std::{ - fmt::{self, Display, Formatter}, u16, + fmt::{self, Display, Formatter}, + u16, }; bitflags! { @@ -266,17 +267,16 @@ impl<'a> Iterator for StatementSplitter<'a> { } } b')' => self.paren_level -= 1, - b';' if !self.flags.contains(Flags::DQUOTE) && self.paren_level == 0 => - { + b';' if !self.flags.contains(Flags::DQUOTE) && self.paren_level == 0 => { let statement = self.get_statement(Flags::empty()); return match error { Some(error) => Some(Err(error)), None => Some(Ok(statement)), - } + }; } - b'&' if !self.flags.contains(Flags::DQUOTE) && self.paren_level == 0 => - { - if bytes.peek() == Some(&b'&') { // Detecting if there is a 2nd `&` character + b'&' if !self.flags.contains(Flags::DQUOTE) && self.paren_level == 0 => { + if bytes.peek() == Some(&b'&') { + // Detecting if there is a 2nd `&` character let statement = self.get_statement(Flags::AND); self.read += 1; // Have `read` skip the 2nd `&` character after reading return match error { @@ -285,9 +285,9 @@ impl<'a> Iterator for StatementSplitter<'a> { }; } } - b'|' if !self.flags.contains(Flags::DQUOTE) && self.paren_level == 0 => - { - if bytes.peek() == Some(&b'|') { // Detecting if there is a 2nd `|` character + b'|' if !self.flags.contains(Flags::DQUOTE) && self.paren_level == 0 => { + if bytes.peek() == Some(&b'|') { + // Detecting if there is a 2nd `|` character let statement = self.get_statement(Flags::OR); self.read += 1; // Have `read` skip the 2nd `|` character after reading return match error { @@ -297,7 +297,8 @@ impl<'a> Iterator for StatementSplitter<'a> { } } - b'#' if self.read == 1 || (!self.flags.contains(Flags::DQUOTE) && self.paren_level == 0 + b'#' if self.read == 1 + || (!self.flags.contains(Flags::DQUOTE) && self.paren_level == 0 && match self.data.as_bytes()[self.read - 2] { b' ' | b'\t' => true, _ => false, @@ -351,9 +352,7 @@ impl<'a> Iterator for StatementSplitter<'a> { self.read = self.data.len(); match error { Some(error) => Some(Err(error)), - None if self.paren_level != 0 => { - Some(Err(StatementError::UnterminatedSubshell)) - } + None if self.paren_level != 0 => Some(Err(StatementError::UnterminatedSubshell)), None if self.flags.contains(Flags::METHOD) => { Some(Err(StatementError::UnterminatedMethod)) } @@ -389,8 +388,7 @@ impl<'a> Iterator for StatementSplitter<'a> { #[test] fn syntax_errors() { let command = "echo (echo one); echo $( (echo one); echo ) two; echo $(echo one"; - let results = StatementSplitter::new(command) - .collect::<Vec<_>>(); + let results = StatementSplitter::new(command).collect::<Vec<_>>(); assert_eq!(results[0], Err(StatementError::InvalidCharacter('(', 6))); assert_eq!(results[1], Err(StatementError::InvalidCharacter('(', 26))); assert_eq!(results[2], Err(StatementError::InvalidCharacter(')', 43))); @@ -415,8 +413,14 @@ fn syntax_errors() { fn methods() { let command = "echo $join(array, ', '); echo @join(var, ', ')"; let statements = StatementSplitter::new(command).collect::<Vec<_>>(); - assert_eq!(statements[0], Ok(StatementVariant::Default("echo $join(array, ', ')"))); - assert_eq!(statements[1], Ok(StatementVariant::Default("echo @join(var, ', ')"))); + assert_eq!( + statements[0], + Ok(StatementVariant::Default("echo $join(array, ', ')")) + ); + assert_eq!( + statements[1], + Ok(StatementVariant::Default("echo @join(var, ', ')")) + ); assert_eq!(statements.len(), 2); } @@ -432,7 +436,10 @@ fn processes() { fn array_processes() { let command = "echo @(echo one; sleep 1); echo @(echo one; sleep 1)"; for statement in StatementSplitter::new(command) { - assert_eq!(statement, Ok(StatementVariant::Default("echo @(echo one; sleep 1)"))); + assert_eq!( + statement, + Ok(StatementVariant::Default("echo @(echo one; sleep 1)")) + ); } } @@ -449,8 +456,14 @@ fn quotes() { let command = "echo \"This ;'is a test\"; echo 'This ;\" is also a test'"; let results = StatementSplitter::new(command).collect::<Vec<_>>(); assert_eq!(results.len(), 2); - assert_eq!(results[0], Ok(StatementVariant::Default("echo \"This ;'is a test\""))); - assert_eq!(results[1], Ok(StatementVariant::Default("echo 'This ;\" is also a test'"))); + assert_eq!( + results[0], + Ok(StatementVariant::Default("echo \"This ;'is a test\"")) + ); + assert_eq!( + results[1], + Ok(StatementVariant::Default("echo 'This ;\" is also a test'")) + ); } #[test] @@ -458,7 +471,10 @@ fn comments() { let command = "echo $(echo one # two); echo three # four"; let results = StatementSplitter::new(command).collect::<Vec<_>>(); assert_eq!(results.len(), 2); - assert_eq!(results[0], Ok(StatementVariant::Default("echo $(echo one # two)"))); + assert_eq!( + results[0], + Ok(StatementVariant::Default("echo $(echo one # two)")) + ); assert_eq!(results[1], Ok(StatementVariant::Default("echo three"))); } @@ -501,9 +517,28 @@ fn variants() { let command = r#"echo "Hello!"; echo "How are you doing?" && echo "I'm just an ordinary test." || echo "Helping by making sure your code works right."; echo "Have a good day!""#; let results = StatementSplitter::new(command).collect::<Vec<_>>(); assert_eq!(results.len(), 5); - assert_eq!(results[0], Ok(StatementVariant::Default(r#"echo "Hello!""#))); - assert_eq!(results[1], Ok(StatementVariant::Default(r#"echo "How are you doing?""#))); - assert_eq!(results[2], Ok(StatementVariant::And(r#"echo "I'm just an ordinary test.""#))); - assert_eq!(results[3], Ok(StatementVariant::Or(r#"echo "Helping by making sure your code works right.""#))); - assert_eq!(results[4], Ok(StatementVariant::Default(r#"echo "Have a good day!""#))); + assert_eq!( + results[0], + Ok(StatementVariant::Default(r#"echo "Hello!""#)) + ); + assert_eq!( + results[1], + Ok(StatementVariant::Default(r#"echo "How are you doing?""#)) + ); + assert_eq!( + results[2], + Ok(StatementVariant::And( + r#"echo "I'm just an ordinary test.""# + )) + ); + assert_eq!( + results[3], + Ok(StatementVariant::Or( + r#"echo "Helping by making sure your code works right.""# + )) + ); + assert_eq!( + results[4], + Ok(StatementVariant::Default(r#"echo "Have a good day!""#)) + ); } diff --git a/src/lib/shell/assignments.rs b/src/lib/shell/assignments.rs index cf4de527..64fb3a34 100644 --- a/src/lib/shell/assignments.rs +++ b/src/lib/shell/assignments.rs @@ -1,20 +1,24 @@ use super::{ - flow_control::{ExportAction, LocalAction}, status::*, Shell, + flow_control::{ExportAction, LocalAction}, + status::*, + Shell, }; use itoa; use lexers::assignments::{Operator, Primitive}; use parser::assignments::*; +use shell::{history::ShellHistory, variables::VariableType}; use small; -use shell::{ - history::ShellHistory, - variables::VariableType -}; -use types; use std::{ collections::HashMap, - env, ffi::OsStr, fmt::{self, Display}, io::{self, BufWriter, Write}, mem, - os::unix::ffi::OsStrExt, str + env, + ffi::OsStr, + fmt::{self, Display}, + io::{self, BufWriter, Write}, + mem, + os::unix::ffi::OsStrExt, + str, }; +use types; fn list_vars(shell: &Shell) { let stdout = io::stdout(); @@ -143,7 +147,10 @@ impl VariableStore for Shell { list_vars(&self); return SUCCESS; } - LocalAction::Assign(ref keys, op, ref vals) => (AssignmentActions::new(keys, op, vals), AssignmentActions::new(keys, op, vals)), + LocalAction::Assign(ref keys, op, ref vals) => ( + AssignmentActions::new(keys, op, vals), + AssignmentActions::new(keys, op, vals), + ), }; for action in actions_step1 { match action { @@ -173,7 +180,7 @@ impl VariableStore for Shell { return FAILURE; } _ => (), - } + }, Operator::Concatenate => match value_check(self, &expression, &key.kind) { Ok(VariableType::Array(values)) => { match self.variables.get_mut(key.name) { @@ -181,7 +188,11 @@ impl VariableStore for Shell { array.extend(values); } None => { - eprintln!("ion: assignment error: {}: cannot concatenate non-array variable", key.name); + eprintln!( + "ion: assignment error: {}: cannot concatenate \ + non-array variable", + key.name + ); return FAILURE; } _ => (), @@ -192,50 +203,62 @@ impl VariableStore for Shell { return FAILURE; } _ => (), - } - Operator::ConcatenateHead => match value_check(self, &expression, &key.kind) { - Ok(VariableType::Array(values)) => { - match self.variables.get_mut(key.name) { - Some(VariableType::Array(ref mut array)) => { - for (index, value) in values.into_iter().enumerate() { - array.insert(index, value); + }, + Operator::ConcatenateHead => { + match value_check(self, &expression, &key.kind) { + Ok(VariableType::Array(values)) => { + match self.variables.get_mut(key.name) { + Some(VariableType::Array(ref mut array)) => { + for (index, value) in values.into_iter().enumerate() { + array.insert(index, value); + } } + None => { + eprintln!( + "ion: assignment error: {}: cannot head \ + concatenate non-array variable", + key.name + ); + return FAILURE; + } + _ => (), } - None => { - eprintln!("ion: assignment error: {}: cannot head concatenate non-array variable", key.name); - return FAILURE; - } - _ => (), } + Err(why) => { + eprintln!("ion: assignment error: {}: {}", key.name, why); + return FAILURE; + } + _ => (), } - Err(why) => { - eprintln!("ion: assignment error: {}: {}", key.name, why); - return FAILURE; - } - _ => (), } Operator::Filter => match value_check(self, &expression, &key.kind) { - Ok(VariableType::Array(values)) => { - match self.variables.get_mut(key.name) { - Some(VariableType::Array(ref mut array)) => { - *array = array.iter() - .filter(|item| values.iter().all(|value| *item != value)) - .cloned() - .collect(); - } - None => { - eprintln!("ion: assignment error: {}: cannot head concatenate non-array variable", key.name); - return FAILURE; - } - _ => (), + Ok(VariableType::Array(values)) => match self + .variables + .get_mut(key.name) + { + Some(VariableType::Array(ref mut array)) => { + *array = array + .iter() + .filter(|item| values.iter().all(|value| *item != value)) + .cloned() + .collect(); } - } + None => { + eprintln!( + "ion: assignment error: {}: cannot head concatenate \ + non-array variable", + key.name + ); + return FAILURE; + } + _ => (), + }, Err(why) => { eprintln!("ion: assignment error: {}: {}", key.name, why); return FAILURE; } _ => (), - } + }, _ => (), } } @@ -258,7 +281,11 @@ impl VariableStore for Shell { array.push(value); } None => { - eprintln!("ion: assignment error: {}: cannot concatenate non-array variable", key.name); + eprintln!( + "ion: assignment error: {}: cannot concatenate \ + non-array variable", + key.name + ); return FAILURE; } _ => (), @@ -271,7 +298,11 @@ impl VariableStore for Shell { array.insert(0, value); } None => { - eprintln!("ion: assignment error: {}: cannot head concatenate non-array variable", key.name); + eprintln!( + "ion: assignment error: {}: cannot head \ + concatenate non-array variable", + key.name + ); return FAILURE; } _ => (), @@ -281,10 +312,18 @@ impl VariableStore for Shell { Operator::Filter => { match self.variables.get_mut(key.name) { Some(VariableType::Array(ref mut array)) => { - *array = array.iter().filter(move |item| **item != value).cloned().collect(); + *array = array + .iter() + .filter(move |item| **item != value) + .cloned() + .collect(); } None => { - eprintln!("ion: assignment error: {}: cannot head concatenate non-array variable", key.name); + eprintln!( + "ion: assignment error: {}: cannot head \ + concatenate non-array variable", + key.name + ); return FAILURE; } _ => (), @@ -296,49 +335,66 @@ impl VariableStore for Shell { match self.variables.get_mut(key.name) { Some(VariableType::Str(lhs)) => { let result = math(&lhs, &key.kind, operator, &value, |value| { - collected.insert(key.name, VariableType::Str(unsafe { - str::from_utf8_unchecked(value) - }.into())); + collected.insert( + key.name, + VariableType::Str( + unsafe { str::from_utf8_unchecked(value) }.into(), + ), + ); }); if let Err(why) = result { eprintln!("ion: assignment error: {}", why); return FAILURE; } - }, + } Some(VariableType::Array(array)) => { let value = match value.parse::<f64>() { Ok(n) => n, Err(_) => { - eprintln!("ion: assignment error: value is not a float"); + eprintln!( + "ion: assignment error: value is not a float" + ); return FAILURE; } }; - let action: Box<Fn(f64) -> f64> = match operator { - Operator::Add => Box::new(|src| src + value), - Operator::Divide => Box::new(|src| src / value), + let action: Box< + Fn(f64) -> f64, + > = match operator { + Operator::Add => Box::new(|src| src + value), + Operator::Divide => Box::new(|src| src / value), Operator::Subtract => Box::new(|src| src - value), Operator::Multiply => Box::new(|src| src * value), _ => { - eprintln!("ion: assignment error: operator does not work on arrays"); + eprintln!( + "ion: assignment error: operator does not work on \ + arrays" + ); return FAILURE; } }; for element in array { match element.parse::<f64>() { - Ok(number) => *element = action(number).to_string().into(), + Ok(number) => { + *element = action(number).to_string().into() + } Err(_) => { - eprintln!("ion: assignment error: {} is not a float", element); + eprintln!( + "ion: assignment error: {} is not a float", + element + ); return FAILURE; } - } } - }, + } _ => { - eprintln!("ion: assignment error: type does not support this operator"); + eprintln!( + "ion: assignment error: type does not support this \ + operator" + ); return FAILURE; } } @@ -359,88 +415,94 @@ impl VariableStore for Shell { for action in actions_step2 { match action { - Ok(Action::UpdateArray(key, _, _)) => { - match collected.remove(key.name) { - hmap @ Some(VariableType::HashMap(_)) => { - if let Primitive::HashMap(_) = key.kind { - self.variables.set(key.name, hmap.unwrap()); - } else if let Primitive::Indexed(_, _) = key.kind { - eprintln!("ion: cannot insert hmap into index"); - return FAILURE; - } + Ok(Action::UpdateArray(key, ..)) => match collected.remove(key.name) { + hmap @ Some(VariableType::HashMap(_)) => { + if let Primitive::HashMap(_) = key.kind { + self.variables.set(key.name, hmap.unwrap()); + } else if let Primitive::Indexed(..) = key.kind { + eprintln!("ion: cannot insert hmap into index"); + return FAILURE; } - bmap @ Some(VariableType::BTreeMap(_)) => { - if let Primitive::BTreeMap(_) = key.kind { - self.variables.set(key.name, bmap.unwrap()); - } else if let Primitive::Indexed(_, _) = key.kind { - eprintln!("ion: cannot insert bmap into index"); - return FAILURE; - } + } + bmap @ Some(VariableType::BTreeMap(_)) => { + if let Primitive::BTreeMap(_) = key.kind { + self.variables.set(key.name, bmap.unwrap()); + } else if let Primitive::Indexed(..) = key.kind { + eprintln!("ion: cannot insert bmap into index"); + return FAILURE; } - array @ Some(VariableType::Array(_)) => { - if let Primitive::Indexed(_, _) = key.kind { - eprintln!("ion: multi-dimensional arrays are not yet supported"); - return FAILURE; - } else { - self.variables.set(key.name, array.unwrap()); - } + } + array @ Some(VariableType::Array(_)) => { + if let Primitive::Indexed(..) = key.kind { + eprintln!("ion: multi-dimensional arrays are not yet supported"); + return FAILURE; + } else { + self.variables.set(key.name, array.unwrap()); } - Some(VariableType::Str(value)) => { - if let Primitive::Indexed(ref index_value, ref index_kind) = key.kind { - match value_check(self, index_value, index_kind) { - Ok(VariableType::Str(ref index)) => { - match self.variables.get_mut(key.name) { - Some(VariableType::HashMap(hmap)) => { - hmap.entry(index.clone()).or_insert(VariableType::Str(value)); - } - Some(VariableType::BTreeMap(bmap)) => { - bmap.entry(index.clone()).or_insert(VariableType::Str(value)); - } - Some(VariableType::Array(array)) => { - let index_num = match index.parse::<usize>() { - Ok(num) => num, - Err(_) => { - eprintln!("ion: index variable does not contain a numeric value: {}", index); - return FAILURE; - } - }; - if let Some(val) = array.get_mut(index_num) { - *val = value; + } + Some(VariableType::Str(value)) => { + if let Primitive::Indexed(ref index_value, ref index_kind) = key.kind { + match value_check(self, index_value, index_kind) { + Ok(VariableType::Str(ref index)) => { + match self.variables.get_mut(key.name) { + Some(VariableType::HashMap(hmap)) => { + hmap.entry(index.clone()) + .or_insert(VariableType::Str(value)); + } + Some(VariableType::BTreeMap(bmap)) => { + bmap.entry(index.clone()) + .or_insert(VariableType::Str(value)); + } + Some(VariableType::Array(array)) => { + let index_num = match index.parse::<usize>() { + Ok(num) => num, + Err(_) => { + eprintln!( + "ion: index variable does not contain a \ + numeric value: {}", + index + ); + return FAILURE; } + }; + if let Some(val) = array.get_mut(index_num) { + *val = value; } - _ => (), } + _ => (), } - Ok(VariableType::Array(_)) => { - eprintln!("ion: index variable cannot be an array"); - return FAILURE; - } - Ok(VariableType::HashMap(_)) => { - eprintln!("ion: index variable cannot be a hmap"); - return FAILURE; - } - Ok(VariableType::BTreeMap(_)) => { - eprintln!("ion: index variable cannot be a bmap"); - return FAILURE; - } - Err(why) => { - eprintln!("ion: assignment error: {}: {}", key.name, why); - return FAILURE; - } - _ => (), } + Ok(VariableType::Array(_)) => { + eprintln!("ion: index variable cannot be an array"); + return FAILURE; + } + Ok(VariableType::HashMap(_)) => { + eprintln!("ion: index variable cannot be a hmap"); + return FAILURE; + } + Ok(VariableType::BTreeMap(_)) => { + eprintln!("ion: index variable cannot be a bmap"); + return FAILURE; + } + Err(why) => { + eprintln!("ion: assignment error: {}: {}", key.name, why); + return FAILURE; + } + _ => (), } } - _ => () } - } - Ok(Action::UpdateString(key, _, _)) => { - match collected.remove(key.name) { - str_ @ Some(VariableType::Str(_)) => { self.variables.set(key.name, str_.unwrap()); } - array @ Some(VariableType::Array(_)) => { self.variables.set(key.name, array.unwrap()); } - _ => () + _ => (), + }, + Ok(Action::UpdateString(key, ..)) => match collected.remove(key.name) { + str_ @ Some(VariableType::Str(_)) => { + self.variables.set(key.name, str_.unwrap()); } - } + array @ Some(VariableType::Array(_)) => { + self.variables.set(key.name, array.unwrap()); + } + _ => (), + }, _ => unreachable!(), } } @@ -564,7 +626,7 @@ fn math<'a, F: FnMut(&[u8])>( return Err(MathError::Unsupported); }, Operator::Equal => writefn(value.as_bytes()), - _ => return Err(MathError::Unsupported) + _ => return Err(MathError::Unsupported), }; Ok(()) diff --git a/src/lib/shell/binary/mod.rs b/src/lib/shell/binary/mod.rs index 96c41862..c3124e32 100644 --- a/src/lib/shell/binary/mod.rs +++ b/src/lib/shell/binary/mod.rs @@ -5,13 +5,14 @@ mod readln; mod terminate; use self::{ - prompt::{prompt, prompt_fn}, readln::readln, + prompt::{prompt, prompt_fn}, + readln::readln, terminate::{terminate_quotes, terminate_script_quotes}, }; use super::{flow_control::Statement, status::*, FlowLogic, Shell, ShellHistory}; -use types; use liner::{Buffer, Context}; use std::{env, fs::File, io::ErrorKind, iter, path::Path, process, sync::Mutex}; +use types; pub const MAN_ION: &str = r#"NAME ion - ion shell @@ -98,7 +99,9 @@ impl Binary for Shell { let mut context = Context::new(); context.word_divider_fn = Box::new(word_divide); if "1" == self.get_str_or_empty("HISTFILE_ENABLED") { - let path = self.get::<types::Str>("HISTFILE").expect("shell didn't set HISTFILE"); + let path = self + .get::<types::Str>("HISTFILE") + .expect("shell didn't set HISTFILE"); context.history.set_file_name(Some(path.to_string())); if !Path::new(path.as_str()).exists() { eprintln!("ion: creating history file at \"{}\"", path); @@ -127,8 +130,10 @@ impl Binary for Shell { self.evaluate_init_file(); - self.variables - .set("args", iter::once(env::args().next().unwrap().into()).collect::<types::Array>()); + self.variables.set( + "args", + iter::once(env::args().next().unwrap().into()).collect::<types::Array>(), + ); loop { if let Some(command) = self.readln() { diff --git a/src/lib/shell/binary/prompt.rs b/src/lib/shell/binary/prompt.rs index 8935dbb4..53fa49ad 100644 --- a/src/lib/shell/binary/prompt.rs +++ b/src/lib/shell/binary/prompt.rs @@ -1,5 +1,5 @@ -use shell::{Capture, Function, Shell}; use parser::shell_expand::expand_string; +use shell::{Capture, Function, Shell}; use std::{io::Read, process}; use sys; diff --git a/src/lib/shell/binary/readln.rs b/src/lib/shell/binary/readln.rs index e2e2610e..91ba2fcb 100644 --- a/src/lib/shell/binary/readln.rs +++ b/src/lib/shell/binary/readln.rs @@ -1,7 +1,10 @@ use super::super::{completer::*, Binary, DirectoryStack, Shell, Variables}; use liner::{BasicCompleter, CursorPosition, Event, EventKind}; use std::{ - env, io::{self, ErrorKind, Write}, mem, path::PathBuf, + env, + io::{self, ErrorKind, Write}, + mem, + path::PathBuf, }; use sys; use types; diff --git a/src/lib/shell/completer.rs b/src/lib/shell/completer.rs index eef3b2a4..8ac651c7 100644 --- a/src/lib/shell/completer.rs +++ b/src/lib/shell/completer.rs @@ -1,4 +1,8 @@ -use super::{directory_stack::DirectoryStack, escape::{escape, unescape}, variables::Variables}; +use super::{ + directory_stack::DirectoryStack, + escape::{escape, unescape}, + variables::Variables, +}; use glob::glob; use liner::{Completer, FilenameCompleter}; use smallvec::SmallVec; @@ -74,9 +78,9 @@ impl Completer for IonFileCompleter { for completion in iterator { completions.push([start, &completion[expanded.len()..]].concat()); } - // To save processing time, we should get obtain the index position where our - // search pattern begins, and re-use that index to slice the completions so - // that we may re-add the tilde character with the completion that follows. + // To save processing time, we should get obtain the index position where our + // search pattern begins, and re-use that index to slice the completions so + // that we may re-add the tilde character with the completion that follows. } else if let Some(completion) = iterator.next() { if let Some(e_index) = expanded.rfind(search) { completions.push(escape(&[tilde, &completion[e_index..]].concat())); @@ -95,9 +99,12 @@ impl Completer for IonFileCompleter { } } -fn filename_completion<'a, LC>(start: &'a str, liner_complete: LC) -> impl Iterator<Item = String> + 'a +fn filename_completion<'a, LC>( + start: &'a str, + liner_complete: LC, +) -> impl Iterator<Item = String> + 'a where - LC: Fn(&str) -> Vec<String> + 'a + LC: Fn(&str) -> Vec<String> + 'a, { let unescaped_start = unescape(start); @@ -135,7 +142,7 @@ where let iter_inner_glob: Box<Iterator<Item = String>> = match globs { Some(iter) => Box::new(iter), - None => Box::new(iter::once(escape(start))) + None => Box::new(iter::once(escape(start))), }; // Use Liner::Completer as well, to preserve the previous behaviour diff --git a/src/lib/shell/directory_stack.rs b/src/lib/shell/directory_stack.rs index 4fd17824..c7f5b2a8 100644 --- a/src/lib/shell/directory_stack.rs +++ b/src/lib/shell/directory_stack.rs @@ -2,21 +2,23 @@ use super::{ status::{FAILURE, SUCCESS}, variables::Variables, }; -use sys::env as sys_env; use std::{ - borrow::Cow, collections::VecDeque, env::{self, set_current_dir}, + borrow::Cow, + collections::VecDeque, + env::{self, set_current_dir}, path::{Component, Path, PathBuf}, }; +use sys::env as sys_env; fn set_current_dir_ion(dir: &Path) -> Result<(), Cow<'static, str>> { - set_current_dir(dir) - .map_err(|why| Cow::Owned(format!("{}", why)))?; + set_current_dir(dir).map_err(|why| Cow::Owned(format!("{}", why)))?; env::set_var( "OLDPWD", - env::var("PWD").ok() + env::var("PWD") + .ok() .and_then(|pwd| if pwd.is_empty() { None } else { Some(pwd) }) - .unwrap_or_else(|| "?".into()) + .unwrap_or_else(|| "?".into()), ); env::set_var("PWD", dir.to_str().unwrap_or_else(|| "?".into())); @@ -198,9 +200,13 @@ impl DirectoryStack { } fn get_previous_dir(&self) -> Option<String> { - env::var("OLDPWD").ok().and_then(|pwd| - if pwd.is_empty() || pwd == "?" { None } else { Some(pwd) } - ) + env::var("OLDPWD").ok().and_then(|pwd| { + if pwd.is_empty() || pwd == "?" { + None + } else { + Some(pwd) + } + }) } fn switch_to_previous_directory( @@ -339,12 +345,7 @@ impl DirectoryStack { count_from_front = x; num = y; } - None => { - return Err(Cow::Owned(format!( - "ion: popd: {}: invalid argument", - arg - ))) - } + None => return Err(Cow::Owned(format!("ion: popd: {}: invalid argument", arg))), }; } } diff --git a/src/lib/shell/flow.rs b/src/lib/shell/flow.rs index 6750de0f..02a8d80c 100644 --- a/src/lib/shell/flow.rs +++ b/src/lib/shell/flow.rs @@ -1,19 +1,19 @@ use super::{ flags::*, flow_control::{collect_cases, collect_if, collect_loops, Case, ElseIf, Function, Statement}, - job_control::JobControl, status::*, Shell, + job_control::JobControl, + status::*, + Shell, }; use parser::{ - assignments::is_array, expand_string, parse_and_validate, pipelines::Pipeline, - ForExpression, StatementSplitter, -}; -use shell::{ - assignments::VariableStore, - variables::VariableType, + assignments::is_array, expand_string, parse_and_validate, pipelines::Pipeline, ForExpression, + StatementSplitter, }; +use shell::{assignments::VariableStore, variables::VariableType}; use small; use std::{ - io::{stdout, Write}, iter, mem, + io::{stdout, Write}, + iter, mem, }; use types; @@ -621,7 +621,10 @@ impl FlowLogic for Shell { while let Some(statement) = iterator.next() { match self.execute_statement(&mut iterator, statement) { Condition::NoOp => {} - cond => { condition = Some(cond); break; }, + cond => { + condition = Some(cond); + break; + } } } @@ -636,7 +639,7 @@ impl FlowLogic for Shell { // in a case statement). For example, checking to see if the value // "foo" matches the pattern "bar" would be invoked like so : // ```ignore - // matches("foo", "bar") + // matches("foo", "bar") // ``` fn matches(lhs: &types::Array, rhs: &types::Array) -> bool { for v in lhs { @@ -684,9 +687,15 @@ impl FlowLogic for Shell { if let Some(ref bind) = case.binding { if let Some(value) = previous_bind { match value { - str_ @ VariableType::Str(_) => { self.set(bind, str_); } - array @ VariableType::Array(_) => { self.variables.set(bind, array); } - map @ VariableType::HashMap(_) => { self.variables.set(bind, map); } + str_ @ VariableType::Str(_) => { + self.set(bind, str_); + } + array @ VariableType::Array(_) => { + self.variables.set(bind, array); + } + map @ VariableType::HashMap(_) => { + self.variables.set(bind, map); + } _ => (), } } @@ -724,9 +733,15 @@ impl FlowLogic for Shell { if let Some(ref bind) = case.binding { if let Some(value) = previous_bind { match value { - str_ @ VariableType::Str(_) => { self.set(bind, str_); } - array @ VariableType::Array(_) => { self.set(bind, array); } - map @ VariableType::HashMap(_) => { self.set(bind, map); } + str_ @ VariableType::Str(_) => { + self.set(bind, str_); + } + array @ VariableType::Array(_) => { + self.set(bind, array); + } + map @ VariableType::HashMap(_) => { + self.set(bind, map); + } _ => (), } } @@ -742,8 +757,7 @@ impl FlowLogic for Shell { fn on_command(&mut self, command_string: &str) { self.break_flow = false; - let mut iterator = - StatementSplitter::new(command_string).map(parse_and_validate); + let mut iterator = StatementSplitter::new(command_string).map(parse_and_validate); // If the value is set to `0`, this means that we don't need to append to an // existing partial statement block in memory, but can read and execute @@ -922,10 +936,10 @@ impl FlowLogic for Shell { } Statement::And(box_stmt) => if let SUCCESS = shell.previous_status { execute_final(shell, *box_stmt); - } + }, Statement::Or(box_stmt) => if let FAILURE = shell.previous_status { execute_final(shell, *box_stmt); - } + }, Statement::Not(box_stmt) => { execute_final(shell, *box_stmt); match shell.previous_status { @@ -933,9 +947,7 @@ impl FlowLogic for Shell { SUCCESS => shell.previous_status = FAILURE, _ => (), } - shell - .variables - .set("?", shell.previous_status.to_string()); + shell.variables.set("?", shell.previous_status.to_string()); } _ => (), } diff --git a/src/lib/shell/flow_control.rs b/src/lib/shell/flow_control.rs index 40226401..ccfd8ec6 100644 --- a/src/lib/shell/flow_control.rs +++ b/src/lib/shell/flow_control.rs @@ -1,10 +1,10 @@ -use shell::{flow::FlowLogic, Shell}; +use lexers::assignments::{KeyBuf, Operator, Primitive}; use parser::{assignments::*, pipelines::Pipeline}; +use shell::{flow::FlowLogic, Shell}; use small; use smallvec::SmallVec; use std::fmt::{self, Display, Formatter}; use types; -use lexers::assignments::{KeyBuf, Operator, Primitive}; #[derive(Debug, PartialEq, Clone)] pub(crate) struct ElseIf { @@ -170,7 +170,11 @@ impl Display for FunctionError { } impl Function { - pub(crate) fn execute<S: AsRef<str>>(self, shell: &mut Shell, args: &[S]) -> Result<(), FunctionError> { + pub(crate) fn execute<S: AsRef<str>>( + self, + shell: &mut Shell, + args: &[S], + ) -> Result<(), FunctionError> { if args.len() - 1 != self.args.len() { return Err(FunctionError::InvalidArgumentCount); } @@ -193,7 +197,9 @@ impl Function { values.push((type_.clone(), value)); } - let index = shell.variables.index_scope_for_var(&name) + let index = shell + .variables + .index_scope_for_var(&name) .expect("execute called with invalid function"); // Pop off all scopes since function temporarily @@ -212,7 +218,9 @@ impl Function { Ok(()) } - pub(crate) fn get_description<'a>(&'a self) -> Option<&'a small::String> { self.description.as_ref() } + pub(crate) fn get_description<'a>(&'a self) -> Option<&'a small::String> { + self.description.as_ref() + } pub(crate) fn new( description: Option<small::String>, diff --git a/src/lib/shell/history.rs b/src/lib/shell/history.rs index a88ef353..4e75815f 100644 --- a/src/lib/shell/history.rs +++ b/src/lib/shell/history.rs @@ -1,8 +1,8 @@ use shell::{status::*, Shell}; use regex::Regex; -use std::io::{self, Write}; use small; +use std::io::{self, Write}; use types; bitflags! { @@ -109,7 +109,15 @@ impl ShellHistory for Shell { if self.should_save_command(command) { // Mark the command in the context history self.set_context_history_from_vars(); - if let Err(err) = self.context.as_ref().unwrap().lock().unwrap().history.push(command.into()) { + if let Err(err) = self + .context + .as_ref() + .unwrap() + .lock() + .unwrap() + .history + .push(command.into()) + { eprintln!("ion: {}", err); } } @@ -126,7 +134,11 @@ impl ShellHistory for Shell { context.history.set_max_size(max_history_size); if &*variables.get_str_or_empty("HISTFILE_ENABLED") == "1" { - context.history.set_file_name(variables.get::<types::Str>("HISTFILE").map(|v| v.to_string())); + context.history.set_file_name( + variables + .get::<types::Str>("HISTFILE") + .map(|v| v.to_string()), + ); let max_histfile_size = variables .get_str_or_empty("HISTFILE_SIZE") @@ -168,11 +180,14 @@ impl ShellHistoryPrivate for Shell { // Here we allow to also ignore the setting of the local variable because we // assume the user entered the leading whitespace on purpose. - if ignore.contains(IgnoreFlags::WHITESPACE) && command.chars().next().map_or(false, |b| b.is_whitespace()) { + if ignore.contains(IgnoreFlags::WHITESPACE) + && command.chars().next().map_or(false, |b| b.is_whitespace()) + { return false; } - if ignore.contains(IgnoreFlags::NO_SUCH_COMMAND) && self.previous_status == NO_SUCH_COMMAND { + if ignore.contains(IgnoreFlags::NO_SUCH_COMMAND) && self.previous_status == NO_SUCH_COMMAND + { return false; } @@ -180,20 +195,21 @@ impl ShellHistoryPrivate for Shell { if let Some(ref context) = self.context { let mut context = context.lock().unwrap(); let buffers = &mut context.history.buffers; - *buffers = buffers.into_iter().filter_map(|buffer| { - let hist_command = buffer.lines().concat(); - if hist_command != command { - Some((*buffer).clone()) - } else { - None - } - }) - .collect(); + *buffers = buffers + .into_iter() + .filter_map(|buffer| { + let hist_command = buffer.lines().concat(); + if hist_command != command { + Some((*buffer).clone()) + } else { + None + } + }) + .collect(); return true; } else { return false; } - } if let Some(ref regexes) = *regexes { diff --git a/src/lib/shell/job.rs b/src/lib/shell/job.rs index 4a4b6635..1a7fe265 100644 --- a/src/lib/shell/job.rs +++ b/src/lib/shell/job.rs @@ -127,7 +127,8 @@ impl TeeItem { /// never be `RedirectFrom`::Both` pub(crate) fn write_to_all(&mut self, extra: Option<RedirectFrom>) -> ::std::io::Result<()> { use std::{ - io::{self, Read, Write}, os::unix::io::*, + io::{self, Read, Write}, + os::unix::io::*, }; fn write_out<R>(source: &mut R, sinks: &mut [File]) -> io::Result<()> where @@ -225,27 +226,21 @@ impl RefinedJob { ref stdin, ref stdout, ref stderr, - } => { - shell.exec_external(&name, &args[1..], stdin, stdout, stderr) - } + } => shell.exec_external(&name, &args[1..], stdin, stdout, stderr), RefinedJob::Builtin { main, ref args, ref stdin, ref stdout, ref stderr, - } => { - shell.exec_builtin(main, &**args, stdout, stderr, stdin) - } + } => shell.exec_builtin(main, &**args, stdout, stderr, stdin), RefinedJob::Function { ref name, ref args, ref stdin, ref stdout, ref stderr, - } => { - shell.exec_function(name, args, stdout, stderr, stdin) - } + } => shell.exec_function(name, args, stdout, stderr, stdin), _ => panic!("exec job should not be able to be called on Cat or Tee jobs"), } } diff --git a/src/lib/shell/mod.rs b/src/lib/shell/mod.rs index c06c75b9..08d7a44e 100644 --- a/src/lib/shell/mod.rs +++ b/src/lib/shell/mod.rs @@ -18,21 +18,25 @@ pub mod status; pub mod variables; pub use self::{ - binary::Binary, fork::{Capture, Fork, IonResult}, + binary::Binary, + fork::{Capture, Fork, IonResult}, }; pub(crate) use self::{ - flow::FlowLogic, history::{IgnoreSetting, ShellHistory}, job::{Job, JobKind}, + flow::FlowLogic, + history::{IgnoreSetting, ShellHistory}, + job::{Job, JobKind}, pipe_exec::{foreground, job_control}, }; use self::{ - directory_stack::DirectoryStack, flags::*, - flow_control::{FlowControl, Function, FunctionError}, foreground::ForegroundSignals, - job_control::{BackgroundProcess, JobControl}, pipe_exec::PipelineExecution, status::*, - variables::{ - Variables, - VariableType, - } + directory_stack::DirectoryStack, + flags::*, + flow_control::{FlowControl, Function, FunctionError}, + foreground::ForegroundSignals, + job_control::{BackgroundProcess, JobControl}, + pipe_exec::PipelineExecution, + status::*, + variables::{VariableType, Variables}, }; use builtins::{BuiltinMap, BUILTINS}; use lexers::ArgumentSplitter; @@ -45,7 +49,8 @@ use std::{ ops::Deref, path::Path, process, - sync::{atomic::Ordering, Arc, Mutex}, time::SystemTime, + sync::{atomic::Ordering, Arc, Mutex}, + time::SystemTime, }; use sys; use types::{self, Array}; @@ -178,7 +183,11 @@ impl Shell { /// A method for executing a function with the given `name`, using `args` as the input. /// If the function does not exist, an `IonError::DoesNotExist` is returned. - pub fn execute_function<S: AsRef<str>>(&mut self, name: &str, args: &[S]) -> Result<i32, IonError> { + pub fn execute_function<S: AsRef<str>>( + &mut self, + name: &str, + args: &[S], + ) -> Result<i32, IonError> { self.variables .get::<Function>(name) .ok_or(IonError::DoesNotExist) @@ -290,7 +299,10 @@ impl Shell { Some(self.execute_pipeline(pipeline)) } // Branch else if -> input == shell function and set the exit_status - } else if let Some(function) = self.variables.get::<Function>(&pipeline.items[0].job.command) { + } else if let Some(function) = self + .variables + .get::<Function>(&pipeline.items[0].job.command) + { if !pipeline.requires_piping() { let args = pipeline.items[0].job.args.deref(); match function.execute(self, args) { @@ -327,9 +339,14 @@ impl Shell { elapsed_time.as_secs(), elapsed_time.subsec_nanos() ); - context.lock().unwrap().history.push(summary.into()).unwrap_or_else(|err| { - eprintln!("ion: history append: {}", err); - }); + context + .lock() + .unwrap() + .history + .push(summary.into()) + .unwrap_or_else(|err| { + eprintln!("ion: history append: {}", err); + }); } } } @@ -448,7 +465,8 @@ impl<'a> Expander for Shell { if quoted { self.get::<types::Str>(name) } else { - self.get::<types::Str>(name).map(|x| x.ascii_replace('\n', ' ')) + self.get::<types::Str>(name) + .map(|x| x.ascii_replace('\n', ' ')) } } @@ -457,10 +475,12 @@ impl<'a> Expander for Shell { if let Some(array) = self.variables.get::<types::Array>(name) { match selection { Select::All => return Some(array.clone()), - Select::Index(id) => return id - .resolve(array.len()) - .and_then(|n| array.get(n)) - .map(|x| types::Array::from_iter(Some(x.to_owned()))), + Select::Index(id) => { + return id + .resolve(array.len()) + .and_then(|n| array.get(n)) + .map(|x| types::Array::from_iter(Some(x.to_owned()))) + } Select::Range(range) => if let Some((start, length)) = range.bounds(array.len()) { if array.len() > start { return Some( @@ -470,9 +490,9 @@ impl<'a> Expander for Shell { .take(length) .map(|x| x.to_owned()) .collect::<types::Array>(), - ) + ); } - } + }, _ => (), } } else if let Some(hmap) = self.variables.get::<types::HashMap>(name) { @@ -483,7 +503,9 @@ impl<'a> Expander for Shell { let f = format!("{}", value); match *value { VariableType::Str(_) => array.push(f.into()), - VariableType::Array(_) | VariableType::HashMap(_) | VariableType::BTreeMap(_) => { + VariableType::Array(_) + | VariableType::HashMap(_) + | VariableType::BTreeMap(_) => { for split in f.split_whitespace() { array.push(split.into()); } @@ -491,10 +513,13 @@ impl<'a> Expander for Shell { _ => (), } } - return Some(array) + return Some(array); } Select::Key(key) => { - return Some(array![format!("{}", hmap.get(&*key).unwrap_or(&VariableType::Str("".into())))]) + return Some(array![format!( + "{}", + hmap.get(&*key).unwrap_or(&VariableType::Str("".into())) + )]) } _ => (), } @@ -506,7 +531,9 @@ impl<'a> Expander for Shell { let f = format!("{}", value); match *value { VariableType::Str(_) => array.push(f.into()), - VariableType::Array(_) | VariableType::HashMap(_) | VariableType::BTreeMap(_) => { + VariableType::Array(_) + | VariableType::HashMap(_) + | VariableType::BTreeMap(_) => { for split in f.split_whitespace() { array.push(split.into()); } @@ -514,10 +541,13 @@ impl<'a> Expander for Shell { _ => (), } } - return Some(array) + return Some(array); } Select::Key(key) => { - return Some(array![format!("{}", bmap.get(&*key).unwrap_or(&VariableType::Str("".into())))]) + return Some(array![format!( + "{}", + bmap.get(&*key).unwrap_or(&VariableType::Str("".into())) + )]) } _ => (), } diff --git a/src/lib/shell/pipe_exec/foreground.rs b/src/lib/shell/pipe_exec/foreground.rs index bda43e5b..ea7dc969 100644 --- a/src/lib/shell/pipe_exec/foreground.rs +++ b/src/lib/shell/pipe_exec/foreground.rs @@ -24,7 +24,9 @@ pub(crate) struct ForegroundSignals { } impl ForegroundSignals { - pub(crate) fn was_grabbed(&self, pid: u32) -> bool { self.grab.load(Ordering::SeqCst) as u32 == pid } + pub(crate) fn was_grabbed(&self, pid: u32) -> bool { + self.grab.load(Ordering::SeqCst) as u32 == pid + } pub(crate) fn was_processed(&self) -> Option<BackgroundResult> { let reply = self.reply.load(Ordering::SeqCst) as u8; @@ -51,7 +53,9 @@ impl ForegroundSignals { self.reply.store(REPLIED as usize, Ordering::SeqCst); } - pub(crate) fn signal_to_grab(&self, pid: u32) { self.grab.store(pid as usize, Ordering::SeqCst); } + pub(crate) fn signal_to_grab(&self, pid: u32) { + self.grab.store(pid as usize, Ordering::SeqCst); + } pub(crate) fn new() -> ForegroundSignals { ForegroundSignals { diff --git a/src/lib/shell/pipe_exec/mod.rs b/src/lib/shell/pipe_exec/mod.rs index 99c38d2b..1229519a 100644 --- a/src/lib/shell/pipe_exec/mod.rs +++ b/src/lib/shell/pipe_exec/mod.rs @@ -680,7 +680,11 @@ impl PipelineExecution for Shell { builtins::builtin_cd, iter::once("cd".into()).chain(job.args.drain()).collect(), ) - } else if self.variables.get::<Function>(job.args[0].as_str()).is_some() { + } else if self + .variables + .get::<Function>(job.args[0].as_str()) + .is_some() + { RefinedJob::function(job.args[0].clone().into(), job.args.drain().collect()) } else if let Some(builtin) = job.builtin { RefinedJob::builtin(builtin, job.args.drain().collect()) diff --git a/src/lib/shell/plugins/string.rs b/src/lib/shell/plugins/string.rs index 20b90efb..a587ec0b 100644 --- a/src/lib/shell/plugins/string.rs +++ b/src/lib/shell/plugins/string.rs @@ -1,5 +1,6 @@ use std::{ - fmt::{self, Display, Formatter}, io, + fmt::{self, Display, Formatter}, + io, }; use types; diff --git a/src/lib/shell/signals.rs b/src/lib/shell/signals.rs index 7bd0480e..c5a44ac0 100644 --- a/src/lib/shell/signals.rs +++ b/src/lib/shell/signals.rs @@ -4,7 +4,7 @@ //! children of the shell. // use std::sync::atomic::{ATOMIC_U8_INIT, AtomicU8}; -use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize}; +use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT}; use sys; diff --git a/src/lib/shell/variables/mod.rs b/src/lib/shell/variables/mod.rs index 93c86039..e3001b08 100644 --- a/src/lib/shell/variables/mod.rs +++ b/src/lib/shell/variables/mod.rs @@ -9,13 +9,12 @@ use fnv::FnvHashMap; use liner::Context; use std::{ any::TypeId, - env, - fmt, + env, fmt, io::{self, BufRead}, mem, - ops::{Deref, DerefMut} + ops::{Deref, DerefMut}, }; -use sys::{self, geteuid, getpid, getuid, is_root, variables as self_sys, env as sys_env}; +use sys::{self, env as sys_env, geteuid, getpid, getuid, is_root, variables as self_sys}; use types::{self, Array}; use unicode_segmentation::UnicodeSegmentation; use xdg::BaseDirectories; @@ -84,57 +83,46 @@ impl From<VariableType> for Function { fn from(var: VariableType) -> Self { match var { VariableType::Function(function) => function, - _ => Function::new(Default::default(), Default::default(), Default::default(), Default::default()), + _ => Function::new( + Default::default(), + Default::default(), + Default::default(), + Default::default(), + ), } } } impl<'a> From<&'a str> for VariableType { - fn from(string: &'a str) -> Self { - VariableType::Str(string.into()) - } + fn from(string: &'a str) -> Self { VariableType::Str(string.into()) } } impl From<types::Str> for VariableType { - fn from(string: types::Str) -> Self { - VariableType::Str(string) - } + fn from(string: types::Str) -> Self { VariableType::Str(string) } } impl From<String> for VariableType { - fn from(string: String) -> Self { - VariableType::Str(string.into()) - } + fn from(string: String) -> Self { VariableType::Str(string.into()) } } impl From<types::Alias> for VariableType { - fn from(alias: types::Alias) -> Self { - VariableType::Alias(alias) - } + fn from(alias: types::Alias) -> Self { VariableType::Alias(alias) } } impl From<types::Array> for VariableType { - fn from(array: types::Array) -> Self { - VariableType::Array(array) - } + fn from(array: types::Array) -> Self { VariableType::Array(array) } } impl From<types::HashMap> for VariableType { - fn from(hmap: types::HashMap) -> Self { - VariableType::HashMap(hmap) - } + fn from(hmap: types::HashMap) -> Self { VariableType::HashMap(hmap) } } impl From<types::BTreeMap> for VariableType { - fn from(bmap: types::BTreeMap) -> Self { - VariableType::BTreeMap(bmap) - } + fn from(bmap: types::BTreeMap) -> Self { VariableType::BTreeMap(bmap) } } impl From<Function> for VariableType { - fn from(function: Function) -> Self { - VariableType::Function(function) - } + fn from(function: Function) -> Self { VariableType::Function(function) } } impl fmt::Display for VariableType { @@ -144,24 +132,28 @@ impl fmt::Display for VariableType { VariableType::Alias(ref alias) => write!(f, "{}", **alias), VariableType::Array(ref array) => write!(f, "{}", array.join(" ")), VariableType::HashMap(ref map) => { - let mut format = map.into_iter().fold(String::new(), |mut format, (_, var_type)| { - format.push_str(&format!("{}", var_type)); - format.push(' '); - format - }); + let mut format = + map.into_iter() + .fold(String::new(), |mut format, (_, var_type)| { + format.push_str(&format!("{}", var_type)); + format.push(' '); + format + }); format.pop(); write!(f, "{}", format) } VariableType::BTreeMap(ref map) => { - let mut format = map.into_iter().fold(String::new(), |mut format, (_, var_type)| { - format.push_str(&format!("{}", var_type)); - format.push(' '); - format - }); + let mut format = + map.into_iter() + .fold(String::new(), |mut format, (_, var_type)| { + format.push_str(&format!("{}", var_type)); + format.push(' '); + format + }); format.pop(); write!(f, "{}", format) } - _ => write!(f, "") + _ => write!(f, ""), } } } @@ -171,20 +163,17 @@ pub struct Scope { vars: FnvHashMap<types::Str, VariableType>, /// This scope is on a namespace boundary. /// Any previous scopes need to be accessed through `super::`. - namespace: bool + namespace: bool, } impl Deref for Scope { type Target = FnvHashMap<types::Str, VariableType>; - fn deref(&self) -> &Self::Target { - &self.vars - } + + fn deref(&self) -> &Self::Target { &self.vars } } impl DerefMut for Scope { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.vars - } + fn deref_mut(&mut self) -> &mut Self::Target { &mut self.vars } } #[derive(Clone, Debug)] @@ -196,8 +185,12 @@ pub struct Variables { impl Default for Variables { fn default() -> Self { - let mut map: FnvHashMap<types::Str, VariableType> = FnvHashMap::with_capacity_and_hasher(64, Default::default()); - map.insert("DIRECTORY_STACK_SIZE".into(), VariableType::Str("1000".into())); + let mut map: FnvHashMap<types::Str, VariableType> = + FnvHashMap::with_capacity_and_hasher(64, Default::default()); + map.insert( + "DIRECTORY_STACK_SIZE".into(), + VariableType::Str("1000".into()), + ); map.insert("HISTORY_SIZE".into(), VariableType::Str("1000".into())); map.insert("HISTFILE_SIZE".into(), VariableType::Str("100000".into())); map.insert( @@ -206,7 +199,7 @@ impl Default for Variables { "${x::1B}]0;${USER}: \ ${PWD}${x::07}${c::0x55,bold}${USER}${c::default}:${c::0x4B}${SWD}${c::default}# \ ${c::reset}" - .into() + .into(), ), ); @@ -221,18 +214,28 @@ impl Default for Variables { ); map.insert( "EUID".into(), - VariableType::Str(geteuid().ok().map_or("?".into(), |id| id.to_string().into())), + VariableType::Str( + geteuid() + .ok() + .map_or("?".into(), |id| id.to_string().into()), + ), ); // Initialize the HISTFILE variable if let Ok(base_dirs) = BaseDirectories::with_prefix("ion") { if let Ok(path) = base_dirs.place_data_file("history") { - map.insert("HISTFILE".into(), VariableType::Str(path.to_str().unwrap_or("?").into())); + map.insert( + "HISTFILE".into(), + VariableType::Str(path.to_str().unwrap_or("?").into()), + ); map.insert("HISTFILE_ENABLED".into(), VariableType::Str("1".into())); } } - map.insert("HISTORY_IGNORE".into(), VariableType::Array(array!["no_such_command", "whitespace", "duplicates"])); + map.insert( + "HISTORY_IGNORE".into(), + VariableType::Array(array!["no_such_command", "whitespace", "duplicates"]), + ); // Initialize the HOME variable sys_env::home_dir().map_or_else( @@ -244,12 +247,12 @@ impl Default for Variables { env::set_var("HOST", &self_sys::get_host_name().unwrap_or("?".to_owned())); Variables { - flags: 0, - scopes: vec![Scope { - vars: map, - namespace: false + flags: 0, + scopes: vec![Scope { + vars: map, + namespace: false, }], - current: 0 + current: 0, } } } @@ -262,7 +265,7 @@ impl Variables { if self.current >= self.scopes.len() { self.scopes.push(Scope { vars: FnvHashMap::with_capacity_and_hasher(64, Default::default()), - namespace: namespace + namespace, }); } else { self.scopes[self.current].namespace = namespace; @@ -276,11 +279,11 @@ impl Variables { pub fn pop_scopes<'a>(&'a mut self, index: usize) -> impl Iterator<Item = Scope> + 'a { self.current = index; - self.scopes.drain(index+1..) + self.scopes.drain(index + 1..) } pub fn append_scopes(&mut self, scopes: Vec<Scope>) { - self.scopes.drain(self.current+1..); + self.scopes.drain(self.current + 1..); self.current += scopes.len(); self.scopes.extend(scopes); } @@ -314,9 +317,7 @@ impl Variables { if name.starts_with("global::") { name = &name["global::".len()..]; // Go up as many namespaces as possible - up_namespace = self.scopes() - .filter(|scope| scope.namespace) - .count() as isize; + up_namespace = self.scopes().filter(|scope| scope.namespace).count() as isize; } else { while name.starts_with("super::") { name = &name["super::".len()..]; @@ -327,7 +328,7 @@ impl Variables { match scope.get(name) { val @ Some(VariableType::Function(_)) => return val, val @ Some(_) if up_namespace == 0 => return val, - _ => () + _ => (), } if scope.namespace { up_namespace -= 1; @@ -386,10 +387,12 @@ impl Variables { "" => if let Some(home) = sys_env::home_dir() { return Some(home.to_string_lossy().to_string() + remainder); }, - "+" => return Some(match env::var("PWD") { - Ok(var) => var + remainder, - _ => ["?", remainder].concat() - }), + "+" => { + return Some(match env::var("PWD") { + Ok(var) => var + remainder, + _ => ["?", remainder].concat(), + }) + } "-" => if let Some(oldpwd) = self.get::<types::Str>("OLDPWD") { return Some(oldpwd.to_string() + remainder); }, @@ -440,12 +443,13 @@ impl Variables { pub fn string_vars(&self) -> impl Iterator<Item = (&types::Str, &types::Str)> { self.scopes() .map(|map| { - map.iter() - .filter_map(|(key, val)| if let VariableType::Str(val) = val { + map.iter().filter_map(|(key, val)| { + if let VariableType::Str(val) = val { Some((key, val)) } else { None - }) + } + }) }) .flat_map(|f| f) } @@ -466,22 +470,33 @@ impl Variables { // If the parsed name contains the '::' pattern, then a namespace was // designated. Find it. match name.find("::").map(|pos| (&name[..pos], &name[pos + 2..])) { - Some(("c", variable)) | Some(("color", variable)) => Colors::collect(variable).into_string().map(|s| T::from(VariableType::Str(s.into()))), - Some(("x", variable)) | Some(("hex", variable)) => match u8::from_str_radix(variable, 16) { - Ok(c) => Some(T::from(VariableType::Str((c as char).to_string().into()))), - Err(why) => { - eprintln!("ion: hex parse error: {}: {}", variable, why); - None + Some(("c", variable)) | Some(("color", variable)) => Colors::collect(variable) + .into_string() + .map(|s| T::from(VariableType::Str(s.into()))), + Some(("x", variable)) | Some(("hex", variable)) => { + match u8::from_str_radix(variable, 16) { + Ok(c) => Some(T::from(VariableType::Str((c as char).to_string().into()))), + Err(why) => { + eprintln!("ion: hex parse error: {}: {}", variable, why); + None + } } - }, - Some(("env", variable)) => env::var(variable).map(Into::into).ok().map(|s| T::from(VariableType::Str(s))), + } + Some(("env", variable)) => env::var(variable) + .map(Into::into) + .ok() + .map(|s| T::from(VariableType::Str(s))), Some(("super", _)) | Some(("global", _)) | None => { // Otherwise, it's just a simple variable name. match self.get_ref(name) { - Some(VariableType::Str(val)) => Some(T::from(VariableType::Str(val.clone()))), - _ => env::var(name).ok().map(|s| T::from(VariableType::Str(s.into()))), + Some(VariableType::Str(val)) => { + Some(T::from(VariableType::Str(val.clone()))) + } + _ => env::var(name) + .ok() + .map(|s| T::from(VariableType::Str(s.into()))), } - }, + } Some((_, variable)) => { if is_root() { eprintln!("ion: root is not allowed to execute plugins"); @@ -491,7 +506,7 @@ impl Variables { if !self.has_plugin_support() { eprintln!( "ion: plugins are disabled. Considering enabling them with `let \ - NS_PLUGINS = 1`" + NS_PLUGINS = 1`" ); return None; } @@ -516,28 +531,38 @@ impl Variables { } } else if specified_type == TypeId::of::<types::Alias>() { match self.get_ref(name) { - Some(VariableType::Alias(alias)) => Some(T::from(VariableType::Alias((*alias).clone()))), - _ => None + Some(VariableType::Alias(alias)) => { + Some(T::from(VariableType::Alias((*alias).clone()))) + } + _ => None, } } else if specified_type == TypeId::of::<types::Array>() { match self.get_ref(name) { - Some(VariableType::Array(array)) => Some(T::from(VariableType::Array(array.clone()))), - _ => None + Some(VariableType::Array(array)) => { + Some(T::from(VariableType::Array(array.clone()))) + } + _ => None, } } else if specified_type == TypeId::of::<types::HashMap>() { match self.get_ref(name) { - Some(VariableType::HashMap(hmap)) => Some(T::from(VariableType::HashMap(hmap.clone()))), - _ => None + Some(VariableType::HashMap(hmap)) => { + Some(T::from(VariableType::HashMap(hmap.clone()))) + } + _ => None, } } else if specified_type == TypeId::of::<types::BTreeMap>() { match self.get_ref(name) { - Some(VariableType::BTreeMap(bmap)) => Some(T::from(VariableType::BTreeMap(bmap.clone()))), - _ => None + Some(VariableType::BTreeMap(bmap)) => { + Some(T::from(VariableType::BTreeMap(bmap.clone()))) + } + _ => None, } } else if specified_type == TypeId::of::<Function>() { match self.get_ref(name) { - Some(VariableType::Function(func)) => Some(T::from(VariableType::Function(func.clone()))), - _ => None + Some(VariableType::Function(func)) => { + Some(T::from(VariableType::Function(func.clone()))) + } + _ => None, } } else { None @@ -632,26 +657,36 @@ impl Variables { match action { Some(Action::UpperAction(action)) => upper_action = Some((action, var)), Some(Action::ReplaceAlias(alias)) => match var { - VariableType::Alias(mut alias_) => { mem::replace(alias, alias_); } - _ => unreachable!() - } + VariableType::Alias(mut alias_) => { + mem::replace(alias, alias_); + } + _ => unreachable!(), + }, Some(Action::ReplaceArray(array)) => match var { - VariableType::Array(mut array_) => { mem::replace(array, array_); } - _ => unreachable!() - } + VariableType::Array(mut array_) => { + mem::replace(array, array_); + } + _ => unreachable!(), + }, Some(Action::ReplaceString(str_)) => match var { - VariableType::Str(mut var_str) => { mem::replace(str_, var_str); } - _ => unreachable!() - } + VariableType::Str(mut var_str) => { + mem::replace(str_, var_str); + } + _ => unreachable!(), + }, Some(Action::ReplaceFunction(func)) => match var { - VariableType::Function(mut func_) => { mem::replace(func, func_); } - _ => unreachable!() - } + VariableType::Function(mut func_) => { + mem::replace(func, func_); + } + _ => unreachable!(), + }, Some(Action::ReplaceHMap(hmap)) => match var { - VariableType::HashMap(mut hmap_) => { mem::replace(hmap, hmap_); } - _ => unreachable!() - } - None => () + VariableType::HashMap(mut hmap_) => { + mem::replace(hmap, hmap_); + } + _ => unreachable!(), + }, + None => (), } } @@ -662,32 +697,38 @@ impl Variables { Some((UpperAction::Shadow, var)) => { self.shadow(name.into(), var); } - None => () + None => (), } } pub fn aliases(&self) -> impl Iterator<Item = (&types::Str, &types::Str)> { - self.scopes.iter().rev() + self.scopes + .iter() + .rev() .map(|map| { - map.iter() - .filter_map(|(key, possible_alias)| if let VariableType::Alias(alias) = possible_alias { + map.iter().filter_map(|(key, possible_alias)| { + if let VariableType::Alias(alias) = possible_alias { Some((key, &**alias)) } else { None - }) + } + }) }) .flat_map(|f| f) } pub fn functions(&self) -> impl Iterator<Item = (&types::Str, &Function)> { - self.scopes.iter().rev() + self.scopes + .iter() + .rev() .map(|map| { - map.iter() - .filter_map(|(key, val)| if let VariableType::Function(val) = val { + map.iter().filter_map(|(key, val)| { + if let VariableType::Function(val) = val { Some((key, val)) } else { None - }) + } + }) }) .flat_map(|f| f) } @@ -741,14 +782,17 @@ impl Variables { } pub fn arrays(&self) -> impl Iterator<Item = (&types::Str, &types::Array)> { - self.scopes.iter().rev() + self.scopes + .iter() + .rev() .map(|map| { - map.iter() - .filter_map(|(key, val)| if let VariableType::Array(val) = val { + map.iter().filter_map(|(key, val)| { + if let VariableType::Array(val) = val { Some((key, val)) } else { None - }) + } + }) }) .flat_map(|f| f) } @@ -795,9 +839,7 @@ mod tests { struct VariableExpander(pub Variables); impl Expander for VariableExpander { - fn string(&self, var: &str, _: bool) -> Option<types::Str> { - self.0.get::<types::Str>(var) - } + fn string(&self, var: &str, _: bool) -> Option<types::Str> { self.0.get::<types::Str>(var) } } #[test] @@ -830,7 +872,7 @@ mod tests { types::Str::from("v/l/nix"), match variables.get::<types::Str>("MWD") { Some(string) => string, - None => panic!("no value returned") + None => panic!("no value returned"), } ); } @@ -845,7 +887,7 @@ mod tests { types::Str::from("/var/log"), match variables.get::<types::Str>("MWD") { Some(string) => string, - None => panic!("no value returned") + None => panic!("no value returned"), } ); } diff --git a/src/lib/types.rs b/src/lib/types.rs index 643c57a2..05826d50 100644 --- a/src/lib/types.rs +++ b/src/lib/types.rs @@ -1,8 +1,11 @@ use fnv::FnvHashMap; +use shell::variables::VariableType; use small; use smallvec::SmallVec; -use shell::variables::VariableType; -use std::{collections::BTreeMap as StdBTreeMap, ops::{Deref, DerefMut}}; +use std::{ + collections::BTreeMap as StdBTreeMap, + ops::{Deref, DerefMut}, +}; pub type Array = SmallVec<[Str; 4]>; pub type HashMap = FnvHashMap<Str, VariableType>; @@ -13,29 +16,21 @@ pub type Str = small::String; pub struct Alias(pub Str); impl Alias { - pub fn empty() -> Self { - Alias(Str::with_capacity(0)) - } + pub fn empty() -> Self { Alias(Str::with_capacity(0)) } } impl Deref for Alias { type Target = Str; - fn deref(&self) -> &Self::Target { - &self.0 - } + fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for Alias { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } + fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } impl Into<Str> for Alias { - fn into(self) -> Str { - self.0 - } + fn into(self) -> Str { self.0 } } /// Construct a new Array containing the given arguments @@ -43,15 +38,19 @@ impl Into<Str> for Alias { /// `array!` acts like the standard library's `vec!` macro, and can be thought /// of as a shorthand for: /// ```ignore,rust -/// Array::from_vec(vec![...]) +/// Array::from_vec(vec![...]) /// ``` /// Additionally it will call `Into::into` on each of its members so that one /// can pass in any type with some `To<SmallString>` implementation; they will /// automatically be converted to owned SmallStrings. /// ```ignore,rust -/// let verbose = Array::from_vec(vec!["foo".into(), "bar".into(), -/// "baz".into(), "zar".into(), -/// "doz".into()]); +/// let verbose = Array::from_vec(vec![ +/// "foo".into(), +/// "bar".into(), +/// "baz".into(), +/// "zar".into(), +/// "doz".into(), +/// ]); /// let concise = array!["foo", "bar", "baz", "zar", "doz"]; /// assert_eq!(verbose, concise); /// ``` diff --git a/src/main.rs b/src/main.rs index 27314b92..43d984b8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,14 +5,15 @@ extern crate smallvec; use ion_shell::{flags::NO_EXEC, Binary, JobControl, ShellBuilder, MAN_ION}; use smallvec::SmallVec; use std::{ - env, error::Error, io::{stdout, stdin, Write, BufRead, BufReader}, iter::FromIterator, + env, + error::Error, + io::{stdin, stdout, BufRead, BufReader, Write}, + iter::FromIterator, }; fn main() { let stdin_is_a_tty = sys::isatty(sys::STDIN_FILENO); - let mut shell = ShellBuilder::new() - .install_signal_handler() - .block_signals(); + let mut shell = ShellBuilder::new().install_signal_handler().block_signals(); if stdin_is_a_tty { shell = shell.set_unique_pid(); -- GitLab