diff --git a/examples/array_methods.ion b/examples/array_methods.ion index c15408ef99d0a8ffe9e866a7ab1c868d5c5a3933..62b1e99360ecbe8b48622eeded7b9c3f7e8666a6 100644 --- a/examples/array_methods.ion +++ b/examples/array_methods.ion @@ -1,6 +1,6 @@ -echo @split("onetwoone", "two") -echo @split_at("onetwoone", "3") -echo @graphemes("onetwo", "3") +echo @split("onetwoone" "two") +echo @split_at("onetwoone" "3") +echo @graphemes("onetwo" "3") echo @bytes("onetwo") echo @chars("onetwo") echo @lines($unescape("firstline\nsecondline")) diff --git a/examples/function_piping.ion b/examples/function_piping.ion index 89aeaf1f6d7cd871b1eb7d31b7c435bd6fb4f79e..0ae6ce50bc2326ef82ba9f851c7617c36c8c663b 100644 --- a/examples/function_piping.ion +++ b/examples/function_piping.ion @@ -13,7 +13,7 @@ square 5 | cat fn format_with pat read input - echo $join(@split(input), $pat) + echo $join(@split(input) $pat) end echo one two three four five | format_with "-" diff --git a/examples/let.ion b/examples/let.ion index 85e4a1fdb3adad4b29b42659fa409e666172cf19..a3d28da319eca956720f8afb0f566aa2b3345b47 100644 --- a/examples/let.ion +++ b/examples/let.ion @@ -48,4 +48,4 @@ let a = [ four five six ] -echo $join(a, "\n") +echo $join(a "\n") diff --git a/examples/methods.ion b/examples/methods.ion index be868a2d23a445b1f6c8599fd891b50194adccd9..3a7a80df7b1e8766212f674057992e32a4756fcb 100644 --- a/examples/methods.ion +++ b/examples/methods.ion @@ -1,10 +1,10 @@ let array = [ one two three four ] let space_string = $join(array) -let comma_string = $join(array, ', ') +let comma_string = $join(array ', ') echo $space_string echo $comma_string echo @split(space_string) -echo @split(comma_string, ', ') +echo @split(comma_string ', ') let array = ["one two" "three four" "five six" "seven eight" "nine ten"] echo $len(@array) @@ -18,31 +18,31 @@ for grapheme in 0..$len(string) echo $string[$grapheme] end -echo $replace("one two one two", one 1) -echo $replacen("one one one one", one 1 3) -echo $starts_with("one two", one) -echo $starts_with("one two", two) -echo $ends_with("one two", one) -echo $ends_with("one two", two) -echo $contains("one two three", two) -echo $contains("one two three", four) -echo $repeat("one ", 5) - -echo $join([one two three], "\n") -echo $join([one two three], "\t") -echo $join([one two three], '\\n') -echo $join([one two three], "\\\\n") -echo $replace($join([one two three], "\n"), "\n" "\t") +echo $replace("one two one two" one 1) +echo $replacen("one one one one" one 1 3) +echo $starts_with("one two" one) +echo $starts_with("one two" two) +echo $ends_with("one two" one) +echo $ends_with("one two" two) +echo $contains("one two three" two) +echo $contains("one two three" four) +echo $repeat("one " 5) + +echo $join([one two three] "\n") +echo $join([one two three] "\t") +echo $join([one two three] '\\n') +echo $join([one two three] "\\\\n") +echo $replace($join([one two three] "\n") "\n" "\t") let a = "applesauce" -let pos = $find(a, "s") -let array = [@split_at(a, $pos)] -echo $join(array, "\n") +let pos = $find(a "s") +let array = [@split_at(a $pos)] +echo $join(array "\n") let a = [1 2 3 4 5] let b = "1 2 3 4 5" -echo $join(@split(b, " "), $join(a, " ")) +echo $join(@split(b " ") $join(a " ")) -echo $regex_replace("one two onemy anemy town", "\ o|\ a" "\ e") +echo $regex_replace("one two onemy anemy town" "\ o|\ a" "\ e") echo $unescape('one two\"\tone') echo $escape("'one two'") diff --git a/examples/script_exec/array_methods.ion b/examples/script_exec/array_methods.ion index c15408ef99d0a8ffe9e866a7ab1c868d5c5a3933..62b1e99360ecbe8b48622eeded7b9c3f7e8666a6 100644 --- a/examples/script_exec/array_methods.ion +++ b/examples/script_exec/array_methods.ion @@ -1,6 +1,6 @@ -echo @split("onetwoone", "two") -echo @split_at("onetwoone", "3") -echo @graphemes("onetwo", "3") +echo @split("onetwoone" "two") +echo @split_at("onetwoone" "3") +echo @graphemes("onetwo" "3") echo @bytes("onetwo") echo @chars("onetwo") echo @lines($unescape("firstline\nsecondline")) diff --git a/manual/src/expansions/05-method.md b/manual/src/expansions/05-method.md index 95f276395618c4ac3332cd997e84399086257358..d32356e42408c6fc902ad833a541ef583fc72fa5 100644 --- a/manual/src/expansions/05-method.md +++ b/manual/src/expansions/05-method.md @@ -25,12 +25,12 @@ expressions as their arguments -- both for the input parameter, and any supplied control the behavior of the method. ```ion -echo $method($(cmd...), arg) +echo $method($(cmd...) arg) let string_var = "value in variable" echo $method(string_var) -echo $method("actual value", arg) +echo $method("actual value" arg) ``` ## Overloaded Methods @@ -55,7 +55,7 @@ is space-delimited. ```ion for elem in @split("some space-delimited values"); echo $elem; end -for elem in @split("some, comma-separated, values", ", "); echo $elem; end +for elem in @split("some, comma-separated, values" ", "); echo $elem; end ``` ## String Methods @@ -91,8 +91,8 @@ ends with it. Zero otherwise. #### Examples ```ion -echo $ends_with("FOOBAR", "BAR") -echo $ends_with("FOOBAR", "FOO") +echo $ends_with("FOOBAR" "BAR") +echo $ends_with("FOOBAR" "FOO") ``` #### Output @@ -110,8 +110,8 @@ contains with it. Zero otherwise. #### Examples ```ion -echo $contains("FOOBAR", "OOB") -echo $contains("FOOBAR", "foo") +echo $contains("FOOBAR" "OOB") +echo $contains("FOOBAR" "foo") ``` #### Output @@ -129,8 +129,8 @@ starts with it. Zero otherwise. #### Examples ```ion -echo $starts_with("FOOBAR", "FOO") -echo $starts_with("FOOBAR", "BAR") +echo $starts_with("FOOBAR" "FOO") +echo $starts_with("FOOBAR" "BAR") ``` #### Output @@ -202,7 +202,7 @@ be joined by a single space. Otherwise, each element will be joined with a given ```ion let array = [1 2 3 4 5] echo $join(array) -echo $join(array, ", ") +echo $join(array ", ") ``` #### Output @@ -220,8 +220,8 @@ string appears. It returns `-1` if it isn't contained. #### Examples ```ion -echo $find("FOOBAR", "OB") -echo $find("FOOBAR", "ob") +echo $find("FOOBAR" "OB") +echo $find("FOOBAR" "ob") ``` #### Output @@ -297,13 +297,13 @@ amount of times, where N is the supplied number. #### Examples ```ion -echo $repeat("abc, ", 3) +echo $repeat("abc, " 3) ``` #### Output ``` -abc, abc, abc +abc, abc, abc, ``` ### replace @@ -316,7 +316,7 @@ with, a new string will be returned with all matches replaced. ```ion let input = "one two one two" echo $replace(input, one 1) -echo $replace($replace(input, one 1), two 2) +echo $replace($replace(input one 1) two 2) ``` #### Output @@ -335,8 +335,8 @@ of matches. ```ion let input = "one two one two" -echo $replacen(input, "one" "three" 1) -echo $replacen(input, "two" "three" 2) +echo $replacen(input "one" "three" 1) +echo $replacen(input "two" "three" 2) ``` #### Output @@ -354,8 +354,8 @@ as a regex. #### Examples ```ion -echo $regex_replace("FOOBAR", "^F" "f") -echo $regex_replace("FOOBAR", "^f" "F") +echo $regex_replace("FOOBAR" "^F" "f") +echo $regex_replace("FOOBAR" "^f" "F") ``` #### Output @@ -492,7 +492,7 @@ whitespace characters. Useful for splitting simple tabular data. #### Examples ```ion -for data in @split("person, age, some data", ", ") +for data in @split("person, age, some data" ", ") echo $data end @@ -519,10 +519,10 @@ Defaults to string variables. The supplied string will be split in two pieces, f #### Examples ``` -echo @split_at("FOOBAR", "3") +echo @split_at("FOOBAR" "3") echo @split_at("FOOBAR") -echo @split_at("FOOBAR", "-1") -echo @split_at("FOOBAR", "8") +echo @split_at("FOOBAR" "-1") +echo @split_at("FOOBAR" "8") ``` #### Output @@ -611,4 +611,4 @@ echo @reverse([1 2 3]) ``` 3 2 1 -``` \ No newline at end of file +``` diff --git a/src/lib/parser/shell_expand/mod.rs b/src/lib/parser/shell_expand/mod.rs index 2104d20de954b27eb7b28255ef6478aa5c3012b9..71bdab105fbba8a108cebdeaae542eed43f3b9c0 100644 --- a/src/lib/parser/shell_expand/mod.rs +++ b/src/lib/parser/shell_expand/mod.rs @@ -904,7 +904,7 @@ mod test { fn inline_expression() { let cases = vec![ (array!["5"], "$len([0 1 2 3 4])"), - (array!["FxOxO"], "$join(@chars(FOO), 'x')"), + (array!["FxOxO"], "$join(@chars('FOO') 'x')"), ]; for (expected, input) in cases { assert_eq!(expected, expand_string(input, &VariableExpander, false)); diff --git a/src/lib/parser/shell_expand/words/mod.rs b/src/lib/parser/shell_expand/words/mod.rs index 79d6cfc82cbe08c930c6fd5668592276ab2fdc08..337323e47a2248673da764e5a52ea81ff206ebc9 100644 --- a/src/lib/parser/shell_expand/words/mod.rs +++ b/src/lib/parser/shell_expand/words/mod.rs @@ -24,6 +24,14 @@ bitflags! { } } +impl Flags { + pub(crate) fn new() -> Self { + Flags { + bits: 0, + } + } +} + #[derive(Debug, PartialEq, Clone)] pub(crate) enum WordToken<'a> { /// Represents a normal string who may contain a globbing character @@ -348,6 +356,7 @@ impl<'a, E: Expander + 'a> WordIterator<'a, E> { where I: Iterator<Item = u8>, { + let mut method_flags = Flags::new(); let mut start = self.read; self.read += 1; while let Some(character) = iterator.next() { @@ -359,7 +368,12 @@ impl<'a, E: Expander + 'a> WordIterator<'a, E> { let mut depth = 0; while let Some(character) = iterator.next() { match character { - b',' if depth == 0 => { + b'\'' => method_flags ^= Flags::SQUOTE, + b'"' => method_flags ^= Flags::DQUOTE, + b'[' if !method_flags.intersects(Flags::SQUOTE | Flags::DQUOTE) => depth += 1, + b']' if !method_flags.intersects(Flags::SQUOTE | Flags::DQUOTE) => depth -= 1, + b' ' if depth == 0 + && !method_flags.intersects(Flags::SQUOTE | Flags::DQUOTE) => { let variable = &self.data[start..self.read]; self.read += 1; start = self.read; @@ -475,6 +489,7 @@ impl<'a, E: Expander + 'a> WordIterator<'a, E> { where I: Iterator<Item = u8>, { + let mut method_flags = Flags::new(); let mut start = self.read; self.read += 1; while let Some(character) = iterator.next() { @@ -486,7 +501,12 @@ impl<'a, E: Expander + 'a> WordIterator<'a, E> { let mut depth = 0; while let Some(character) = iterator.next() { match character { - b',' if depth == 0 => { + b'\'' => method_flags ^= Flags::SQUOTE, + b'"' => method_flags ^= Flags::DQUOTE, + b'[' if !method_flags.intersects(Flags::SQUOTE | Flags::DQUOTE) => depth += 1, + b']' if !method_flags.intersects(Flags::SQUOTE | Flags::DQUOTE) => depth -= 1, + b' ' if depth == 0 + && !method_flags.intersects(Flags::SQUOTE | Flags::DQUOTE) => { let variable = &self.data[start..self.read]; self.read += 1; start = self.read; diff --git a/src/lib/parser/shell_expand/words/tests.rs b/src/lib/parser/shell_expand/words/tests.rs index 1c74638c983b59dbc24bb3ae3d80e27464c6ad45..723958e3c08450e73d50457294d1e4a52c81c3cc 100644 --- a/src/lib/parser/shell_expand/words/tests.rs +++ b/src/lib/parser/shell_expand/words/tests.rs @@ -17,7 +17,7 @@ fn compare(input: &str, expected: Vec<WordToken>) { #[test] fn string_method() { - let input = "$join(array, 'pattern') $join(array, 'pattern')"; + let input = "$join(array 'pattern') $join(array 'pattern')"; let expected = vec![ WordToken::StringMethod(StringMethod { method: "join",