From 2aab0015403a63ea2f85d3e7af232881c546086e Mon Sep 17 00:00:00 2001 From: Ryuichi Ueda Date: Wed, 31 Jan 2024 14:59:37 +0900 Subject: [PATCH] Implemented --- src/elements/command/simple.rs | 7 +++- src/elements/subword.rs | 3 ++ src/elements/subword/brace.rs | 39 ++++++++++++++++++ src/elements/subword/unquoted.rs | 14 ++++++- src/elements/word.rs | 28 +++++++++++++ test/test.bash | 68 ++++++++++++++++---------------- 6 files changed, 123 insertions(+), 36 deletions(-) diff --git a/src/elements/command/simple.rs b/src/elements/command/simple.rs index 3e79a7dd..a9216ec8 100644 --- a/src/elements/command/simple.rs +++ b/src/elements/command/simple.rs @@ -30,7 +30,12 @@ pub struct SimpleCommand { impl Command for SimpleCommand { fn exec(&mut self, core: &mut ShellCore, pipe: &mut Pipe) -> Option { - self.args = self.words.iter() + let mut words = vec![]; + for w in self.words.iter_mut() { + words.extend(w.brace_expansion()); + } + + self.args = words.iter() .filter(|w| w.text != "") .map(|w| w.text.clone()).collect(); diff --git a/src/elements/subword.rs b/src/elements/subword.rs index f360b2a9..a345836b 100644 --- a/src/elements/subword.rs +++ b/src/elements/subword.rs @@ -6,6 +6,7 @@ pub mod unquoted; use crate::{Feeder, ShellCore}; use crate::elements::subword::brace::BraceSubword; +use crate::elements::word::Word; use super::subword::unquoted::UnquotedSubword; use std::fmt; use std::fmt::Debug; @@ -18,6 +19,8 @@ impl Debug for dyn Subword { pub trait Subword { fn get_text(&self) -> String; + fn copy(&self) -> Box; + fn brace_expansion(&mut self, ans: &mut Vec); } pub fn parse(feeder: &mut Feeder, core: &mut ShellCore) -> Option> { diff --git a/src/elements/subword/brace.rs b/src/elements/subword/brace.rs index 7a5e0bba..a2b8032e 100644 --- a/src/elements/subword/brace.rs +++ b/src/elements/subword/brace.rs @@ -13,6 +13,26 @@ pub struct BraceSubword { impl Subword for BraceSubword { fn get_text(&self) -> String { self.text.clone() } + + fn copy(&self) -> Box { + Box::new( BraceSubword { + text: self.text.clone(), + words: self.words.iter().map(|w| w.copy()).collect(), + } ) + } + + fn brace_expansion(&mut self, lefts: &mut Vec) { + let mut rights = vec![]; + for w in self.words.iter_mut() { + rights.extend(w.brace_expansion()); + } + + let mut ans = vec![]; + for lf in lefts.iter_mut() { + ans.extend(self.add_expended(lf, &rights)); + } + *lefts = ans; + } } impl BraceSubword { @@ -23,6 +43,25 @@ impl BraceSubword { } } + fn add_expended(&mut self, left: &mut Word, rights: &Vec) -> Vec { + if self.words.len() < 2 { + left.add_text("{"); + } + + let mut ans = vec![]; + for rw in rights { + let mut lw = left.copy(); + lw.concat(&rw); + ans.push(lw); + } + + if self.words.len() < 2 { + ans.iter_mut().for_each(|w| w.add_text("}")); + } + + ans + } + fn eat_word(feeder: &mut Feeder, ans: &mut BraceSubword, core: &mut ShellCore) -> bool { match Word::parse(feeder, core) { Some(w) => { diff --git a/src/elements/subword/unquoted.rs b/src/elements/subword/unquoted.rs index 051e0b9a..94f6fac0 100644 --- a/src/elements/subword/unquoted.rs +++ b/src/elements/subword/unquoted.rs @@ -3,14 +3,26 @@ use crate::{ShellCore, Feeder}; use crate::elements::subword::Subword; +use crate::elements::word::Word; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct UnquotedSubword { text: String, } impl Subword for UnquotedSubword { fn get_text(&self) -> String { self.text.clone() } + + fn copy(&self) -> Box { + Box::new(self.clone()) + } + + fn brace_expansion(&mut self, ans: &mut Vec) { + for a in ans.iter_mut() { + a.subwords.push(self.copy()); + a.text += &self.text.clone(); + } + } } impl UnquotedSubword { diff --git a/src/elements/word.rs b/src/elements/word.rs index 1d4b48d6..6c7b42fd 100644 --- a/src/elements/word.rs +++ b/src/elements/word.rs @@ -19,6 +19,34 @@ impl Word { subwords: vec![], } } + pub fn copy(&self) -> Word { + Word { + text: self.text.clone(), + subwords: self.subwords.iter().map(|e| e.copy()).collect(), + } + } + + pub fn concat(&mut self, left: &Word) { + self.text += &left.text; + for e in left.subwords.iter() { + self.subwords.push(e.copy()); + } + } + + pub fn add_text(&mut self, s: &str) { + self.text += &s.to_string(); + self.subwords.push(Box::new(UnquotedSubword::new(s))); + } + + pub fn brace_expansion(&mut self) -> Vec { + let mut ans = vec![Word::new()]; + + for sub in self.subwords.iter_mut() { + sub.brace_expansion(&mut ans); + } + + ans + } pub fn parse(feeder: &mut Feeder, core: &mut ShellCore) -> Option { if feeder.starts_with("#") { diff --git a/test/test.bash b/test/test.bash index 3ba160d0..50e116cf 100755 --- a/test/test.bash +++ b/test/test.bash @@ -341,28 +341,28 @@ res=$($com <<< 'rm -f /tmp/rusty_bash ; while [ -f /tmp/rusty_bash ] ; do echo w # brace res=$($com <<< 'echo {a,b}c') -[ "$res" == "<{a,b}>c" ] || err $LINENO -#[ "$res" == "ac bc" ] || err $LINENO +#[ "$res" == "<{a,b}>c" ] || err $LINENO +[ "$res" == "ac bc" ] || err $LINENO res=$($com <<< 'echo c{a,b}') -[ "$res" == "c<{a,b}>" ] || err $LINENO -#[ "$res" == "ca cb" ] || err $LINENO +#[ "$res" == "c<{a,b}>" ] || err $LINENO +[ "$res" == "ca cb" ] || err $LINENO res=$($com <<< 'echo {{a},b}') -[ "$res" == "<{<{a}>,b}>" ] || err $LINENO -#[ "$res" == "{a} b" ] || err $LINENO +#[ "$res" == "<{<{a}>,b}>" ] || err $LINENO +[ "$res" == "{a} b" ] || err $LINENO res=$($com <<< 'echo {a,{b},c}') -[ "$res" == "<{a,<{b}>,c}>" ] || err $LINENO -#[ "$res" == "a {b} c" ] || err $LINENO +#[ "$res" == "<{a,<{b}>,c}>" ] || err $LINENO +[ "$res" == "a {b} c" ] || err $LINENO res=$($com <<< 'echo {a,b,c{d,e}f,g{h,i{j,k}}}') -[ "$res" == "<{a,b,c<{d,e}>f,g<{h,i<{j,k}>}>}>" ] || err $LINENO -#[ "$res" == "a b cdf cef gh gij gik" ] || err $LINENO +#[ "$res" == "<{a,b,c<{d,e}>f,g<{h,i<{j,k}>}>}>" ] || err $LINENO +[ "$res" == "a b cdf cef gh gij gik" ] || err $LINENO res=$($com <<< 'echo {a,b,c{d,e}f,g{h,i{j,k}}') -[ "$res" == "{a,b,c<{d,e}>f,g<{h,i<{j,k}>}>" ] || err $LINENO -#[ "$res" == "{a,b,cdf,gh {a,b,cdf,gij {a,b,cdf,gik {a,b,cef,gh {a,b,cef,gij {a,b,cef,gik" ] || err $LINENO +#[ "$res" == "{a,b,c<{d,e}>f,g<{h,i<{j,k}>}>" ] || err $LINENO +[ "$res" == "{a,b,cdf,gh {a,b,cdf,gij {a,b,cdf,gik {a,b,cef,gh {a,b,cef,gij {a,b,cef,gik" ] || err $LINENO res=$($com <<< 'echo c{a,b') [ "$res" == "c{a,b" ] || err $LINENO @@ -371,47 +371,47 @@ res=$($com <<< 'echo c{a,b,') [ "$res" == "c{a,b," ] || err $LINENO res=$($com <<< 'echo {{a,b},{c,d},') -[ "$res" == "{<{a,b}>,<{c,d}>," ] || err $LINENO -#[ "$res" == "{a,c, {a,d, {b,c, {b,d," ] || err $LINENO +#[ "$res" == "{<{a,b}>,<{c,d}>," ] || err $LINENO +[ "$res" == "{a,c, {a,d, {b,c, {b,d," ] || err $LINENO res=$($com <<< 'echo {{a,b},{c,d') -[ "$res" == "{<{a,b}>,{c,d" ] || err $LINENO -#[ "$res" == "{a,{c,d {b,{c,d" ] || err $LINENO +#[ "$res" == "{<{a,b}>,{c,d" ] || err $LINENO +[ "$res" == "{a,{c,d {b,{c,d" ] || err $LINENO res=$($com <<< 'echo {{a,b,{c,') [ "$res" == "{{a,b,{c," ] || err $LINENO res=$($com <<< 'echo {a}') -[ "$res" == "<{a}>" ] || err $LINENO -#[ "$res" == "{a}" ] || err $LINENO +#[ "$res" == "<{a}>" ] || err $LINENO +[ "$res" == "{a}" ] || err $LINENO res=$($com <<< 'echo {a,}') -[ "$res" == "<{a,}>" ] || err $LINENO -#[ "$res" == "a" ] || err $LINENO +#[ "$res" == "<{a,}>" ] || err $LINENO +[ "$res" == "a" ] || err $LINENO res=$($com <<< 'echo {a,b,}') -[ "$res" == "<{a,b,}>" ] || err $LINENO -#[ "$res" == "a b" ] || err $LINENO +#[ "$res" == "<{a,b,}>" ] || err $LINENO +[ "$res" == "a b" ] || err $LINENO res=$($com <<< 'echo {a,b,}c') -[ "$res" == "<{a,b,}>c" ] || err $LINENO -#[ "$res" == "ac bc c" ] || err $LINENO +#[ "$res" == "<{a,b,}>c" ] || err $LINENO +[ "$res" == "ac bc c" ] || err $LINENO res=$($com <<< 'echo {}') -[ "$res" == "{}" ] || err $LINENO #[ "$res" == "{}" ] || err $LINENO +[ "$res" == "{}" ] || err $LINENO res=$($com <<< 'echo {,}') -[ "$res" == "<{,}>" ] || err $LINENO -#[ "$res" == "" ] || err $LINENO +#[ "$res" == "<{,}>" ] || err $LINENO +[ "$res" == "" ] || err $LINENO res=$($com <<< 'echo {,,}') -[ "$res" == "<{,,}>" ] || err $LINENO -#[ "$res" == "" ] || err $LINENO +#[ "$res" == "<{,,}>" ] || err $LINENO +[ "$res" == "" ] || err $LINENO res=$($com <<< 'echo a{,,}b') -[ "$res" == "a<{,,}>b" ] || err $LINENO -#[ "$res" == "ab ab ab" ] || err $LINENO +#[ "$res" == "a<{,,}>b" ] || err $LINENO +[ "$res" == "ab ab ab" ] || err $LINENO res=$($com <<< 'echo {') [ "$res" == "{" ] || err $LINENO @@ -420,14 +420,14 @@ res=$($com <<< 'echo }') [ "$res" == "}" ] || err $LINENO res=$($com <<< 'echo {a,}{b,}') -[ "$res" == "<{a,}><{b,}>" ] || err $LINENO -#[ "$res" == "ab a b" ] || err $LINENO +#[ "$res" == "<{a,}><{b,}>" ] || err $LINENO +[ "$res" == "ab a b" ] || err $LINENO res=$($com <<< 'echo {},b}') [ "$res" == "{},b}" ] || err $LINENO res=$($com <<< 'echo a{},b}') -[ "$res" == "a<{},b}>" ] || err $LINENO +[ "$res" == "a} ab" ] || err $LINENO ### WHILE TEST ###