diff --git a/src/uu/ptx/src/ptx.rs b/src/uu/ptx/src/ptx.rs index 111d74d39..a0fe9a5e8 100644 --- a/src/uu/ptx/src/ptx.rs +++ b/src/uu/ptx/src/ptx.rs @@ -224,7 +224,7 @@ fn get_config(matches: &clap::ArgMatches) -> UResult { } config.auto_ref = matches.get_flag(options::AUTO_REFERENCE); config.input_ref = matches.get_flag(options::REFERENCES); - config.right_ref &= matches.get_flag(options::RIGHT_SIDE_REFS); + config.right_ref = matches.get_flag(options::RIGHT_SIDE_REFS); config.ignore_case = matches.get_flag(options::IGNORE_CASE); if matches.contains_id(options::MACRO_NAME) { config.macro_name = matches @@ -661,7 +661,7 @@ fn prepare_line_chunks( } fn write_traditional_output( - config: &Config, + config: &mut Config, file_map: &FileMap, words: &BTreeSet, output_filename: &OsStr, @@ -677,6 +677,15 @@ fn write_traditional_output( let context_reg = Regex::new(&config.context_regex).unwrap(); + if !config.right_ref { + let max_ref_len = if config.auto_ref { + get_auto_max_reference_len(words) + } else { + 0 + }; + config.line_width -= max_ref_len; + } + for word_ref in words { let file_map_value: &FileContent = file_map .get(&word_ref.filename) @@ -722,6 +731,31 @@ fn write_traditional_output( Ok(()) } +fn get_auto_max_reference_len(words: &BTreeSet) -> usize { + //Get the maximum length of the reference field + let line_num = words + .iter() + .map(|w| { + if w.local_line_nr == 0 { + 1 + } else { + (w.local_line_nr as f64).log10() as usize + 1 + } + }) + .max() + .unwrap_or(0); + + let filename_len = words + .iter() + .filter(|w| w.filename != "-") + .map(|w| w.filename.maybe_quote().to_string().len()) + .max() + .unwrap_or(0); + + // +1 for the colon + line_num + filename_len + 1 +} + mod options { pub mod format { pub static ROFF: &str = "roff"; @@ -749,7 +783,7 @@ mod options { #[uucore::main] pub fn uumain(args: impl uucore::Args) -> UResult<()> { let matches = uucore::clap_localization::handle_clap_result(uu_app(), args)?; - let config = get_config(&matches)?; + let mut config = get_config(&matches)?; let input_files; let output_file: OsString; @@ -783,7 +817,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let word_filter = WordFilter::new(&matches, &config)?; let file_map = read_input(&input_files).map_err_context(String::new)?; let word_set = create_word_set(&config, &word_filter, &file_map); - write_traditional_output(&config, &file_map, &word_set, &output_file) + write_traditional_output(&mut config, &file_map, &word_set, &output_file) } pub fn uu_app() -> Command { diff --git a/tests/by-util/test_ptx.rs b/tests/by-util/test_ptx.rs index 917cd047a..3ff36a1c6 100644 --- a/tests/by-util/test_ptx.rs +++ b/tests/by-util/test_ptx.rs @@ -57,6 +57,30 @@ fn test_truncation_no_extra_space_in_after() { .stdout_contains(".xx \"\" \"Rust\" \"is/\" \"\""); } +#[test] +fn gnu_ext_disabled_reference_calculation() { + let input = "Hello World Rust is good language"; + let expected_output = concat!( + r#".xx "language" "" "Hello World Rust is good" "" ":1""#, + "\n", + r#".xx "" "Hello World" "Rust is good language" "" ":1""#, + "\n", + r#".xx "" "Hello" "World Rust is good language" "" ":1""#, + "\n", + r#".xx "" "Hello World Rust is" "good language" "" ":1""#, + "\n", + r#".xx "" "Hello World Rust" "is good language" "" ":1""#, + "\n", + r#".xx "" "Hello World Rust is good" "language" "" ":1""#, + "\n", + ); + new_ucmd!() + .args(&["-G", "-A"]) + .pipe_in(input) + .succeeds() + .stdout_only(expected_output); +} + #[test] fn gnu_ext_disabled_rightward_no_ref() { new_ucmd!()