-
-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Extended LIST Syntax #8
Comments
just a idea. I want to keep compatibility with
|
My new idea is this.
Keep On the other hand,
Syntax parser can be implemented something like that. diff --git a/src/list/ranges.rs b/src/list/ranges.rs
index 85b20fe..6f71bf5 100644
--- a/src/list/ranges.rs
+++ b/src/list/ranges.rs
@@ -1,10 +1,8 @@
/*
- * This file is part of the uutils coreutils package.
+ * This file is based on the uutils coreutils package.
*
- * (c) Rolf Morel <[email protected]>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
+ * For the full copyright and license information about
+ * the original file, please view the LICENSE
*/
use std::str::FromStr;
@@ -13,6 +11,17 @@ use std::str::FromStr;
pub struct Range {
pub low: usize,
pub high: usize,
+ pub join: RangeJoin,
+}
+
+#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
+pub enum RangeJoin {
+ /// 1-5 .. Just select from 1 to 5 (default)
+ Normal,
+ /// 1~5 .. from 1 to 5 are explicitly merged
+ Merge,
+ /// 1:5 .. from 1 to 5 are explicitly split
+ Split,
}
impl FromStr for Range {
@@ -20,8 +29,20 @@ impl FromStr for Range {
fn from_str(s: &str) -> Result<Range, &'static str> {
use std::usize::MAX;
-
- let mut parts = s.splitn(2, '-');
+ let join: RangeJoin;
+
+ // check if s includes a ~ or a - and split on that
+ // if not, assume it's a single number
+ let mut parts = if s.contains('~') {
+ join = RangeJoin::Merge;
+ s.splitn(2, '~')
+ } else if s.contains(':') {
+ join = RangeJoin::Split;
+ s.splitn(2, ':')
+ } else {
+ join = RangeJoin::Normal;
+ s.splitn(2, '-')
+ };
let field = "fields and positions are numbered from 1";
let order = "high end of range less than low end";
@@ -31,7 +52,7 @@ impl FromStr for Range {
(Some(nm), None) => {
if let Ok(nm) = nm.parse::<usize>() {
if nm > 0 {
- Ok(Range { low: nm, high: nm })
+ Ok(Range { low: nm, high: nm, join: RangeJoin::Normal })
} else {
Err(field)
}
@@ -42,7 +63,7 @@ impl FromStr for Range {
(Some(n), Some(m)) if m.is_empty() => {
if let Ok(low) = n.parse::<usize>() {
if low > 0 {
- Ok(Range { low, high: MAX - 1 })
+ Ok(Range { low, high: MAX - 1, join })
} else {
Err(field)
}
@@ -53,7 +74,7 @@ impl FromStr for Range {
(Some(n), Some(m)) if n.is_empty() => {
if let Ok(high) = m.parse::<usize>() {
if high > 0 {
- Ok(Range { low: 1, high })
+ Ok(Range { low: 1, high, join })
} else {
Err(field)
}
@@ -64,7 +85,7 @@ impl FromStr for Range {
(Some(n), Some(m)) => match (n.parse::<usize>(), m.parse::<usize>()) {
(Ok(low), Ok(high)) => {
if low > 0 && low <= high {
- Ok(Range { low, high })
+ Ok(Range { low, high, join })
} else if low == 0 {
Err(field)
} else {
@@ -111,11 +132,14 @@ pub fn complement(ranges: &[Range]) -> Vec<Range> {
use std::usize;
let mut complements = Vec::with_capacity(ranges.len() + 1);
+ // Use the default join type to keep back compatibility
+ const DEF_JOIN: RangeJoin = RangeJoin::Normal;
if !ranges.is_empty() && ranges[0].low > 1 {
complements.push(Range {
low: 1,
high: ranges[0].low - 1,
+ join: DEF_JOIN,
});
}
@@ -127,6 +151,7 @@ pub fn complement(ranges: &[Range]) -> Vec<Range> {
complements.push(Range {
low: left.high + 1,
high: right.low - 1,
+ join: DEF_JOIN,
});
}
}
@@ -135,6 +160,7 @@ pub fn complement(ranges: &[Range]) -> Vec<Range> {
complements.push(Range {
low: last.high + 1,
high: usize::MAX - 1,
+ join: DEF_JOIN,
});
}
} diff --git a/src/list/converter.rs b/src/list/converter.rs
index b2841c1..5e17b1a 100644
--- a/src/list/converter.rs
+++ b/src/list/converter.rs
@@ -11,10 +11,80 @@ pub fn to_ranges(list: &str, complement: bool) -> Result<Vec<Range>, String> {
#[cfg(test)]
mod test {
use super::*;
+ use ranges::RangeJoin::{Merge, Normal, Split};
#[test]
fn test_to_ranges() {
let range = to_ranges("2-5,1-8", false).unwrap();
assert_eq!(range[0].low, 1);
assert_eq!(range[0].high, 8);
}
+ #[test]
+ fn test_to_ranges_merge_unmerge() {
+ let range = to_ranges("1-3,4~6", false).unwrap();
+ assert_eq!(range[0].low, 1);
+ assert_eq!(range[0].high, 3);
+ assert_eq!(range[0].join, Normal);
+ assert_eq!(range[1].low, 4);
+ assert_eq!(range[1].high, 6);
+ assert_eq!(range[1].join, Merge);
+ }
+ #[test]
+ fn test_to_ranges_unsort() {
+ let range = to_ranges("4,1-3,5~7", false).unwrap();
+ println!("{:?}", range);
+ assert_eq!(range[0].low, 1);
+ assert_eq!(range[0].high, 3);
+ assert_eq!(range[0].join, Normal);
+ assert_eq!(range[1].low, 4);
+ assert_eq!(range[1].high, 4);
+ assert_eq!(range[1].join, Normal);
+ assert_eq!(range[2].low, 5);
+ assert_eq!(range[2].high, 7);
+ assert_eq!(range[2].join, Merge);
+ }
+ #[test]
+ fn test_to_ranges_split() {
+ let range = to_ranges("1,2,3,4", false).unwrap();
+ println!("{:?}", range);
+ for i in 0..4 {
+ assert_eq!(range[i].low, i + 1);
+ assert_eq!(range[i].high, i + 1);
+ assert_eq!(range[i].join, Normal);
+ }
+ }
+ #[test]
+ fn test_to_ranges_split_unsort() {
+ let range = to_ranges("5,3,4,1,2", false).unwrap();
+ println!("{:?}", range);
+ for i in 0..5 {
+ assert_eq!(range[i].low, i + 1);
+ assert_eq!(range[i].high, i + 1);
+ assert_eq!(range[i].join, Normal);
+ }
+ }
+ #[test]
+ fn test_to_ranges_overwrap() {
+ let range = to_ranges("1-3,2~5", false).unwrap();
+ println!("{:?}", range);
+ assert_eq!(range[0].low, 1);
+ assert_eq!(range[0].high, 5);
+ assert_eq!(range[0].join, Normal);
+ }
+ #[test]
+ fn test_to_ranges_three_different_range() {
+ let range = to_ranges("1-3,5:10,12,13~15", false).unwrap();
+ println!("{:?}", range);
+ assert_eq!(range[0].low, 1);
+ assert_eq!(range[0].high, 3);
+ assert_eq!(range[0].join, Normal);
+ assert_eq!(range[1].low, 5);
+ assert_eq!(range[1].high, 10);
+ assert_eq!(range[1].join, Split);
+ assert_eq!(range[2].low, 12);
+ assert_eq!(range[2].high, 12);
+ assert_eq!(range[2].join, Normal);
+ assert_eq!(range[3].low, 13);
+ assert_eq!(range[3].high, 15);
+ assert_eq!(range[3].join, Merge);
+ }
} |
echo ABCDE | teip -c '1,3,$-1'
=> [A]B[C][D]E
$-1
supposed to be 4, because$
means the number of field.Instead of
-
,..
is used for specifying the range.1..3
=>1,2,3
The text was updated successfully, but these errors were encountered: