Skip to content

Commit 48a8d4e

Browse files
lalvarezt-bwlalvarezt
authored andcommitted
feat(parser): add shorthand support {n..m}
1 parent fcf0731 commit 48a8d4e

File tree

3 files changed

+62
-14
lines changed

3 files changed

+62
-14
lines changed

src/pipeline/mod.rs

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -656,10 +656,7 @@ mod tests {
656656
fn test_escaped_pipe() {
657657
let input = "foo|bar";
658658
// Replace pipe with dash
659-
assert_eq!(
660-
process(input, r"{replace:s/\|/-/}").unwrap(),
661-
"foo-bar"
662-
);
659+
assert_eq!(process(input, r"{replace:s/\|/-/}").unwrap(), "foo-bar");
663660
// Replace with escaped pipe in replacement
664661
assert_eq!(
665662
process(input, r"{replace:s/\|/\\\|/}").unwrap(),
@@ -676,15 +673,9 @@ mod tests {
676673
fn test_escaped_pipe_in_args() {
677674
let input = "a|b|c";
678675
// Split by pipe and join with dash
679-
assert_eq!(
680-
process(input, r"{split:\|:..|join:-}").unwrap(),
681-
"a-b-c"
682-
);
676+
assert_eq!(process(input, r"{split:\|:..|join:-}").unwrap(), "a-b-c");
683677
// Split by pipe and join with pipe
684-
assert_eq!(
685-
process(input, r"{split:\|:..|join:\|}").unwrap(),
686-
"a|b|c"
687-
);
678+
assert_eq!(process(input, r"{split:\|:..|join:\|}").unwrap(), "a|b|c");
688679
// Split by pipe and append/prepend with pipes
689680
assert_eq!(
690681
process(input, r"{split:\|:..|append:\|y|join:,}").unwrap(),
@@ -806,4 +797,36 @@ mod tests {
806797
"A-B-C"
807798
);
808799
}
800+
801+
#[test]
802+
fn test_shorthand_index() {
803+
let input = "a b c d e";
804+
// Test shorthand index
805+
assert_eq!(process(input, "{1}").unwrap(), "b");
806+
assert_eq!(process(input, "{-1}").unwrap(), "e");
807+
assert_eq!(process(input, "{0}").unwrap(), "a");
808+
809+
// Test shorthand ranges
810+
assert_eq!(process(input, "{1..3}").unwrap(), "b c");
811+
assert_eq!(process(input, "{1..=3}").unwrap(), "b c d");
812+
assert_eq!(process(input, "{..2}").unwrap(), "a b");
813+
assert_eq!(process(input, "{2..}").unwrap(), "c d e");
814+
assert_eq!(process(input, "{..=2}").unwrap(), "a b c");
815+
assert_eq!(process(input, "{..}").unwrap(), "a b c d e");
816+
assert_eq!(process(input, "{-2..}").unwrap(), "d e");
817+
assert_eq!(process(input, "{-3..-1}").unwrap(), "c d");
818+
assert_eq!(process(input, "{-3..=-1}").unwrap(), "c d e");
819+
820+
// Test with empty input
821+
assert_eq!(process("", "{1}").unwrap(), "");
822+
assert_eq!(process("", "{1..3}").unwrap(), "");
823+
assert_eq!(process("", "{..}").unwrap(), "");
824+
825+
// Test with single word
826+
assert_eq!(process("word", "{0}").unwrap(), "word");
827+
assert_eq!(process("word", "{1}").unwrap(), "word");
828+
assert_eq!(process("word", "{..}").unwrap(), "word");
829+
assert_eq!(process("word", "{0..}").unwrap(), "word");
830+
assert_eq!(process("word", "{..1}").unwrap(), "word");
831+
}
809832
}

src/pipeline/parser.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,20 @@ pub fn parse_template(template: &str) -> Result<Vec<StringOp>, String> {
2727
fn parse_operation(pair: pest::iterators::Pair<Rule>) -> Result<StringOp, String> {
2828
let inner = pair.into_inner().next().unwrap();
2929
match inner.as_rule() {
30+
Rule::shorthand_range => {
31+
let range = parse_range_spec(inner)?;
32+
Ok(StringOp::Split {
33+
sep: " ".to_string(),
34+
range,
35+
})
36+
}
37+
Rule::shorthand_index => {
38+
let idx = inner.as_str().parse().unwrap();
39+
Ok(StringOp::Split {
40+
sep: " ".to_string(),
41+
range: RangeSpec::Index(idx),
42+
})
43+
}
3044
Rule::split => {
3145
let mut parts = inner.into_inner();
3246
let sep = unescape(parts.next().unwrap().as_str());
@@ -139,4 +153,3 @@ fn unescape(s: &str) -> String {
139153
}
140154
out
141155
}
142-

src/pipeline/template.pest

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ template = { "{" ~ operation_list? ~ "}" }
55
operation_list = { operation ~ ("|" ~ operation)* }
66

77
operation = {
8+
shorthand_range |
9+
shorthand_index |
810
split |
911
join |
1012
slice |
@@ -17,6 +19,16 @@ operation = {
1719
prepend
1820
}
1921

22+
shorthand_index = { number }
23+
shorthand_range = {
24+
range_to_inclusive |
25+
range_to |
26+
range_inclusive |
27+
range_exclusive |
28+
range_from |
29+
range_full
30+
}
31+
2032
split = { "split" ~ ":" ~ arg ~ ":" ~ range_spec? }
2133
join = { "join" ~ ":" ~ arg }
2234
slice = { "slice" ~ ":" ~ range_spec }
@@ -54,4 +66,4 @@ range_to_inclusive = { "..=" ~ number }
5466
range_full = { ".." }
5567
index = { number }
5668

57-
number = @{ "-"? ~ ASCII_DIGIT+ }
69+
number = @{ "-"? ~ ASCII_DIGIT+ }

0 commit comments

Comments
 (0)