diff --git a/src/uu/pr/src/pr.rs b/src/uu/pr/src/pr.rs index def105ae50d..543ae805787 100644 --- a/src/uu/pr/src/pr.rs +++ b/src/uu/pr/src/pr.rs @@ -83,6 +83,7 @@ struct OutputOptions { col_sep_for_printing: String, line_width: Option, expand_tabs: Option, + omit_pagination: bool, } /// One line of an input file, annotated with file, page, and line number. @@ -431,7 +432,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { /// # Arguments /// * `args` - Command line arguments fn recreate_arguments(args: &[String]) -> Vec { - let column_page_option = Regex::new(r"^[-+]\d+.*").unwrap(); + let column_page_option = Regex::new(r"^([-+])(\d+)(.*)$").unwrap(); let num_regex = Regex::new(r"^[^-]\d*$").unwrap(); let n_regex = Regex::new(r"^-n\s*$").unwrap(); let e_regex = Regex::new(r"^-e").unwrap(); @@ -460,7 +461,23 @@ fn recreate_arguments(args: &[String]) -> Vec { arguments .into_iter() - .filter(|i| !column_page_option.is_match(i)) + .flat_map(|arg| { + if let Some(caps) = column_page_option.captures(&arg) { + let prefix = caps.get(1).unwrap().as_str(); + let remainder = caps.get(3).unwrap().as_str(); + + let mut split = vec![]; + if prefix == "-" + && !remainder.is_empty() + && !remainder.starts_with(|c: char| c.is_ascii_digit()) + { + split.push(format!("-{remainder}")); + } + split + } else { + vec![arg] + } + }) .collect() } @@ -814,7 +831,14 @@ fn build_options( let columns_to_print = merge_files_print.unwrap_or_else(|| column_mode_options.as_ref().map_or(1, |i| i.columns)); - let line_width = if join_lines { + let s_flag_active = matches.value_source(options::COLUMN_CHAR_SEPARATOR) + == Some(clap::parser::ValueSource::CommandLine); + let s_string_flag_active = matches.value_source(options::COLUMN_STRING_SEPARATOR) + == Some(clap::parser::ValueSource::CommandLine); + + let alignment_disabled = s_flag_active && !s_string_flag_active; + + let line_width = if join_lines || alignment_disabled { None } else if columns_to_print > 1 { Some( @@ -846,6 +870,7 @@ fn build_options( col_sep_for_printing, line_width, expand_tabs, + omit_pagination: matches.get_flag(options::OMIT_PAGINATION), }) } @@ -1115,7 +1140,11 @@ fn print_page( out.write_all(line_separator)?; } } - out.write_all(page_separator)?; + + if !options.omit_pagination { + out.write_all(page_separator)?; + } + out.flush()?; Ok(()) } @@ -1269,7 +1298,7 @@ fn write_columns( )?; } } - if not_found_break && feed_line_present { + if not_found_break && (feed_line_present || options.omit_pagination) { break; } out.write_all(line_separator)?; diff --git a/tests/by-util/test_pr.rs b/tests/by-util/test_pr.rs index 26403b6f464..7a363ff15ac 100644 --- a/tests/by-util/test_pr.rs +++ b/tests/by-util/test_pr.rs @@ -889,3 +889,48 @@ fn test_zero_columns_shortcut() { .fails_with_code(1) .stderr_contains("pr: invalid --column argument '0'"); } + +#[test] +fn test_combined_digit_flags() { + // -3Ts, should be parsed correctly as -3 columns, -T (no pagination), -s, (comma separated) + let input = "a\nb\nc\n"; + let expected = "a,b,c\n"; + new_ucmd!() + .args(&["-3Ts,"]) + .pipe_in(input) + .succeeds() + .stdout_only(expected); +} + +#[test] +fn test_plain_digit_arg_with_flags() { + // -3 -T -s, should be parsed identically + let input = "a\nb\nc\n"; + let expected = "a,b,c\n"; + new_ucmd!() + .args(&["-3", "-T", "-s,"]) + .pipe_in(input) + .succeeds() + .stdout_only(expected); +} + +#[test] +fn test_page_range_with_plus() { + // +2:3 should start on page 2 and end on page 3. + // Note: currently uutils uses 56-line content per page even with -T. + let mut input = String::new(); + for i in 1..=200 { + input.push_str(&format!("line {i}\n")); + } + + let mut expected = String::new(); + for i in 57..=168 { + expected.push_str(&format!("line {i}\n")); + } + + new_ucmd!() + .args(&["+2:3", "-T"]) + .pipe_in(input) + .succeeds() + .stdout_only(expected); +}