mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-29 12:07:46 +00:00
sort: implement -k and -t support (#1996)
* sort: implement basic -k and -t support This allows to specify keys after the -k flag and a custom field separator using -t. Support for options for specific keys is still missing, and the -b flag is not passed down correctly. * sort: implement support for key options * remove unstable feature use * don't pipe in input when we expect a failure * only tokenize when needed, remove a clone() * improve comments * fix clippy lints * re-add test * buffer writes to stdout * fix ignore_non_printing and make the test fail in case it is broken :) * move attribute to the right position * add more tests * add my name to the copyright section * disallow dead code * move a comment * re-add a loc * use smallvec for a perf improvement in the common case * add BENCHMARKING.md * add ignore_case to benchmarks
This commit is contained in:
parent
e1221ef3f8
commit
49c9d8c901
5 changed files with 742 additions and 141 deletions
|
@ -185,10 +185,10 @@ fn test_dictionary_order2() {
|
|||
fn test_non_printing_chars() {
|
||||
for non_printing_chars_param in vec!["-i"] {
|
||||
new_ucmd!()
|
||||
.pipe_in("a👦🏻aa b\naaaa b")
|
||||
.pipe_in("a👦🏻aa\naaaa")
|
||||
.arg(non_printing_chars_param)
|
||||
.succeeds()
|
||||
.stdout_only("aaaa b\na👦🏻aa b\n");
|
||||
.stdout_only("a👦🏻aa\naaaa\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,6 +307,166 @@ fn test_numeric_unique_ints2() {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keys_open_ended() {
|
||||
let input = "aa bb cc\ndd aa ff\ngg aa cc\n";
|
||||
new_ucmd!()
|
||||
.args(&["-k", "2.2"])
|
||||
.pipe_in(input)
|
||||
.succeeds()
|
||||
.stdout_only("gg aa cc\ndd aa ff\naa bb cc\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keys_closed_range() {
|
||||
let input = "aa bb cc\ndd aa ff\ngg aa cc\n";
|
||||
new_ucmd!()
|
||||
.args(&["-k", "2.2,2.2"])
|
||||
.pipe_in(input)
|
||||
.succeeds()
|
||||
.stdout_only("dd aa ff\ngg aa cc\naa bb cc\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keys_multiple_ranges() {
|
||||
let input = "aa bb cc\ndd aa ff\ngg aa cc\n";
|
||||
new_ucmd!()
|
||||
.args(&["-k", "2,2", "-k", "3,3"])
|
||||
.pipe_in(input)
|
||||
.succeeds()
|
||||
.stdout_only("gg aa cc\ndd aa ff\naa bb cc\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keys_no_field_match() {
|
||||
let input = "aa aa aa aa\naa bb cc\ndd aa ff\n";
|
||||
new_ucmd!()
|
||||
.args(&["-k", "4,4"])
|
||||
.pipe_in(input)
|
||||
.succeeds()
|
||||
.stdout_only("aa bb cc\ndd aa ff\naa aa aa aa\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keys_no_char_match() {
|
||||
let input = "aaa\nba\nc\n";
|
||||
new_ucmd!()
|
||||
.args(&["-k", "1.2"])
|
||||
.pipe_in(input)
|
||||
.succeeds()
|
||||
.stdout_only("c\nba\naaa\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keys_custom_separator() {
|
||||
let input = "aaxbbxcc\nddxaaxff\nggxaaxcc\n";
|
||||
new_ucmd!()
|
||||
.args(&["-k", "2.2,2.2", "-t", "x"])
|
||||
.pipe_in(input)
|
||||
.succeeds()
|
||||
.stdout_only("ddxaaxff\nggxaaxcc\naaxbbxcc\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keys_invalid_field() {
|
||||
new_ucmd!()
|
||||
.args(&["-k", "1."])
|
||||
.fails()
|
||||
.stderr_only("sort: error: failed to parse character index for key `1.`: cannot parse integer from empty string");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keys_invalid_field_option() {
|
||||
new_ucmd!()
|
||||
.args(&["-k", "1.1x"])
|
||||
.fails()
|
||||
.stderr_only("sort: error: invalid option for key: `x`");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keys_invalid_field_zero() {
|
||||
new_ucmd!()
|
||||
.args(&["-k", "0.1"])
|
||||
.fails()
|
||||
.stderr_only("sort: error: field index was 0");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keys_with_options() {
|
||||
let input = "aa 3 cc\ndd 1 ff\ngg 2 cc\n";
|
||||
for param in &[
|
||||
&["-k", "2,2n"][..],
|
||||
&["-k", "2n,2"][..],
|
||||
&["-k", "2,2", "-n"][..],
|
||||
] {
|
||||
new_ucmd!()
|
||||
.args(param)
|
||||
.pipe_in(input)
|
||||
.succeeds()
|
||||
.stdout_only("dd 1 ff\ngg 2 cc\naa 3 cc\n");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keys_with_options_blanks_start() {
|
||||
let input = "aa 3 cc\ndd 1 ff\ngg 2 cc\n";
|
||||
for param in &[&["-k", "2b,2"][..], &["-k", "2,2", "-b"][..]] {
|
||||
new_ucmd!()
|
||||
.args(param)
|
||||
.pipe_in(input)
|
||||
.succeeds()
|
||||
.stdout_only("dd 1 ff\ngg 2 cc\naa 3 cc\n");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keys_with_options_blanks_end() {
|
||||
let input = "a b
|
||||
a b
|
||||
a b
|
||||
";
|
||||
new_ucmd!()
|
||||
.args(&["-k", "1,2.1b", "-s"])
|
||||
.pipe_in(input)
|
||||
.succeeds()
|
||||
.stdout_only(
|
||||
"a b
|
||||
a b
|
||||
a b
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keys_stable() {
|
||||
let input = "a b
|
||||
a b
|
||||
a b
|
||||
";
|
||||
new_ucmd!()
|
||||
.args(&["-k", "1,2.1", "-s"])
|
||||
.pipe_in(input)
|
||||
.succeeds()
|
||||
.stdout_only(
|
||||
"a b
|
||||
a b
|
||||
a b
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keys_empty_match() {
|
||||
let input = "a a a a
|
||||
aaaa
|
||||
";
|
||||
new_ucmd!()
|
||||
.args(&["-k", "1,1", "-t", "a"])
|
||||
.pipe_in(input)
|
||||
.succeeds()
|
||||
.stdout_only(input);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zero_terminated() {
|
||||
test_helper("zero-terminated", "-z");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue