mirror of
https://github.com/uutils/coreutils
synced 2024-12-13 23:02:38 +00:00
Merge pull request #5078 from cakebaker/nl_allow_negative_values_for_i_and_v
nl: allow negative values for --line-increment and --starting-line-number
This commit is contained in:
commit
78fed70982
3 changed files with 80 additions and 30 deletions
|
@ -79,18 +79,6 @@ pub fn parse_options(settings: &mut crate::Settings, opts: &clap::ArgMatches) ->
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match opts.get_one::<String>(options::LINE_INCREMENT) {
|
|
||||||
None => {}
|
|
||||||
Some(val) => {
|
|
||||||
let conv: Option<u64> = val.parse().ok();
|
|
||||||
match conv {
|
|
||||||
None => {
|
|
||||||
errs.push(String::from("Illegal value for -i"));
|
|
||||||
}
|
|
||||||
Some(num) => settings.line_increment = num,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
match opts.get_one::<usize>(options::NUMBER_WIDTH) {
|
match opts.get_one::<usize>(options::NUMBER_WIDTH) {
|
||||||
None => {}
|
None => {}
|
||||||
Some(num) if *num > 0 => settings.number_width = *num,
|
Some(num) if *num > 0 => settings.number_width = *num,
|
||||||
|
@ -98,17 +86,11 @@ pub fn parse_options(settings: &mut crate::Settings, opts: &clap::ArgMatches) ->
|
||||||
"Invalid line number field width: ‘0’: Numerical result out of range",
|
"Invalid line number field width: ‘0’: Numerical result out of range",
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
match opts.get_one::<String>(options::STARTING_LINE_NUMBER) {
|
if let Some(num) = opts.get_one::<i64>(options::LINE_INCREMENT) {
|
||||||
None => {}
|
settings.line_increment = *num;
|
||||||
Some(val) => {
|
}
|
||||||
let conv: Option<u64> = val.parse().ok();
|
if let Some(num) = opts.get_one::<i64>(options::STARTING_LINE_NUMBER) {
|
||||||
match conv {
|
settings.starting_line_number = *num;
|
||||||
None => {
|
|
||||||
errs.push(String::from("Illegal value for -v"));
|
|
||||||
}
|
|
||||||
Some(num) => settings.starting_line_number = num,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
match opts.get_one::<String>(options::JOIN_BLANK_LINES) {
|
match opts.get_one::<String>(options::JOIN_BLANK_LINES) {
|
||||||
None => {}
|
None => {}
|
||||||
|
|
|
@ -29,8 +29,8 @@ pub struct Settings {
|
||||||
// The variable corresponding to -d
|
// The variable corresponding to -d
|
||||||
section_delimiter: [char; 2],
|
section_delimiter: [char; 2],
|
||||||
// The variables corresponding to the options -v, -i, -l, -w.
|
// The variables corresponding to the options -v, -i, -l, -w.
|
||||||
starting_line_number: u64,
|
starting_line_number: i64,
|
||||||
line_increment: u64,
|
line_increment: i64,
|
||||||
join_blank_lines: u64,
|
join_blank_lines: u64,
|
||||||
number_width: usize, // Used with String::from_char, hence usize.
|
number_width: usize, // Used with String::from_char, hence usize.
|
||||||
// The format of the number and the (default value for)
|
// The format of the number and the (default value for)
|
||||||
|
@ -208,7 +208,8 @@ pub fn uu_app() -> Command {
|
||||||
.short('i')
|
.short('i')
|
||||||
.long(options::LINE_INCREMENT)
|
.long(options::LINE_INCREMENT)
|
||||||
.help("line number increment at each line")
|
.help("line number increment at each line")
|
||||||
.value_name("NUMBER"),
|
.value_name("NUMBER")
|
||||||
|
.value_parser(clap::value_parser!(i64)),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::JOIN_BLANK_LINES)
|
Arg::new(options::JOIN_BLANK_LINES)
|
||||||
|
@ -244,7 +245,8 @@ pub fn uu_app() -> Command {
|
||||||
.short('v')
|
.short('v')
|
||||||
.long(options::STARTING_LINE_NUMBER)
|
.long(options::STARTING_LINE_NUMBER)
|
||||||
.help("first line number on each logical page")
|
.help("first line number on each logical page")
|
||||||
.value_name("NUMBER"),
|
.value_name("NUMBER")
|
||||||
|
.value_parser(clap::value_parser!(i64)),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::NUMBER_WIDTH)
|
Arg::new(options::NUMBER_WIDTH)
|
||||||
|
@ -267,7 +269,7 @@ fn nl<T: Read>(reader: &mut BufReader<T>, settings: &Settings) -> UResult<()> {
|
||||||
let line_no_width_initial = line_no_width;
|
let line_no_width_initial = line_no_width;
|
||||||
// Stores the smallest integer with one more digit than line_no, so that
|
// Stores the smallest integer with one more digit than line_no, so that
|
||||||
// when line_no >= line_no_threshold, we need to use one more digit.
|
// when line_no >= line_no_threshold, we need to use one more digit.
|
||||||
let mut line_no_threshold = 10u64.pow(line_no_width as u32);
|
let mut line_no_threshold = 10i64.pow(line_no_width as u32);
|
||||||
let mut empty_line_count: u64 = 0;
|
let mut empty_line_count: u64 = 0;
|
||||||
let fill_char = match settings.number_format {
|
let fill_char = match settings.number_format {
|
||||||
NumberFormat::RightZero => '0',
|
NumberFormat::RightZero => '0',
|
||||||
|
@ -329,7 +331,7 @@ fn nl<T: Read>(reader: &mut BufReader<T>, settings: &Settings) -> UResult<()> {
|
||||||
if settings.renumber {
|
if settings.renumber {
|
||||||
line_no = settings.starting_line_number;
|
line_no = settings.starting_line_number;
|
||||||
line_no_width = line_no_width_initial;
|
line_no_width = line_no_width_initial;
|
||||||
line_no_threshold = 10u64.pow(line_no_width as u32);
|
line_no_threshold = 10i64.pow(line_no_width as u32);
|
||||||
}
|
}
|
||||||
&settings.header_numbering
|
&settings.header_numbering
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// spell-checker:ignore ninvalid winvalid
|
// spell-checker:ignore iinvalid ninvalid vinvalid winvalid
|
||||||
use crate::common::util::TestScenario;
|
use crate::common::util::TestScenario;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -13,6 +13,7 @@ fn test_stdin_no_newline() {
|
||||||
.run()
|
.run()
|
||||||
.stdout_is(" 1\tNo Newline\n");
|
.stdout_is(" 1\tNo Newline\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_stdin_newline() {
|
fn test_stdin_newline() {
|
||||||
new_ucmd!()
|
new_ucmd!()
|
||||||
|
@ -167,3 +168,68 @@ fn test_number_separator() {
|
||||||
.stdout_is(" 1:-:test\n");
|
.stdout_is(" 1:-:test\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_starting_line_number() {
|
||||||
|
for arg in ["-v10", "--starting-line-number=10"] {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg(arg)
|
||||||
|
.pipe_in("test")
|
||||||
|
.succeeds()
|
||||||
|
.stdout_is(" 10\ttest\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_negative_starting_line_number() {
|
||||||
|
for arg in ["-v-10", "--starting-line-number=-10"] {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg(arg)
|
||||||
|
.pipe_in("test")
|
||||||
|
.succeeds()
|
||||||
|
.stdout_is(" -10\ttest\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_invalid_starting_line_number() {
|
||||||
|
for arg in ["-vinvalid", "--starting-line-number=invalid"] {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg(arg)
|
||||||
|
.fails()
|
||||||
|
.stderr_contains("invalid value 'invalid'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_line_increment() {
|
||||||
|
for arg in ["-i10", "--line-increment=10"] {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg(arg)
|
||||||
|
.pipe_in("a\nb")
|
||||||
|
.succeeds()
|
||||||
|
.stdout_is(" 1\ta\n 11\tb\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_negative_line_increment() {
|
||||||
|
// TODO make this test work with -10
|
||||||
|
for arg in ["-i-1", "--line-increment=-1"] {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg(arg)
|
||||||
|
.pipe_in("a\nb")
|
||||||
|
.succeeds()
|
||||||
|
.stdout_is(" 1\ta\n 0\tb\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_invalid_line_increment() {
|
||||||
|
for arg in ["-iinvalid", "--line-increment=invalid"] {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg(arg)
|
||||||
|
.fails()
|
||||||
|
.stderr_contains("invalid value 'invalid'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue