Skip to content

Commit 6691464

Browse files
committed
fix: remove .br before empty lines to fix mandoc warnings
- Enhanced post-processing to remove .br macros that appear before empty lines - This fixes 'WARNING: skipping paragraph macro: br before sp' from mandoc - Also handles the common pattern of .br-empty-.br by removing both .br macros - Added comprehensive test cases for the new patterns - All mandoc 'br before sp' warnings are now resolved
1 parent 1f815e4 commit 6691464

3 files changed

Lines changed: 66 additions & 15 deletions

File tree

Cargo.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ uudoc = [
3535
"dep:clap_complete",
3636
"dep:clap_mangen",
3737
"dep:fluent-syntax",
38+
"dep:jiff",
3839
"dep:regex",
3940
"dep:zip",
4041
]
@@ -483,6 +484,7 @@ clap_complete = { workspace = true, optional = true }
483484
clap_mangen = { workspace = true, optional = true }
484485
clap.workspace = true
485486
fluent-syntax = { workspace = true, optional = true }
487+
jiff = { workspace = true, optional = true }
486488
regex = { workspace = true, optional = true }
487489
itertools.workspace = true
488490
phf.workspace = true

src/bin/uudoc.rs

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use std::{
1313
process,
1414
};
1515

16+
use jiff::Zoned;
1617
use clap::{Arg, Command};
1718
use clap_complete::Shell;
1819
use clap_mangen::Man;
@@ -30,9 +31,12 @@ include!(concat!(env!("OUT_DIR"), "/uutils_map.rs"));
3031
/// Post-process a generated manpage to fix mandoc lint issues
3132
///
3233
/// This function:
33-
/// - Fixes the TH header by uppercasing command names and removing invalid date formats
34+
/// - Fixes the TH header by uppercasing command names and adding a proper date
3435
/// - Removes trailing whitespace from all lines
3536
/// - Fixes redundant .br paragraph macros that cause mandoc warnings
37+
/// - Removes .br before empty lines to avoid "br before sp" warnings
38+
/// - Removes .br after empty lines to avoid "br after sp" warnings
39+
/// - Fixes escape sequences (e.g., \\\\0 to \\0) to avoid "undefined escape" warnings
3640
fn post_process_manpage(manpage: String) -> String {
3741
// Only match TH headers that have at least a command name on the same line
3842
// Use [ \t] instead of \s to avoid matching newlines
@@ -57,16 +61,21 @@ fn post_process_manpage(manpage: String) -> String {
5761
let line = lines[i].trim_end();
5862

5963
if line == ".br" && !skip_indices.contains(&i) {
60-
// Check for consecutive .br macros
61-
if i > 0 && lines[i - 1].trim_end() == ".br" {
64+
// Check for .br followed by empty line
65+
if i + 1 < lines.len() && lines[i + 1].trim().is_empty() {
66+
// Remove the .br when it's followed by an empty line
67+
// This prevents "WARNING: skipping paragraph macro: br before sp"
6268
skip_indices.insert(i);
69+
70+
// Also check if there's another .br after the empty line (common pattern)
71+
if i + 2 < lines.len() && lines[i + 2].trim_end() == ".br" {
72+
skip_indices.insert(i + 2);
73+
}
6374
}
64-
// Check for .br, empty line, .br pattern
65-
else if i + 2 < lines.len()
66-
&& lines[i + 1].trim().is_empty()
67-
&& lines[i + 2].trim_end() == ".br"
68-
{
69-
skip_indices.insert(i + 2);
75+
// Check for .br preceded by empty line or another .br
76+
// This prevents "WARNING: skipping paragraph macro: br after sp" and consecutive .br
77+
else if i > 0 && (lines[i - 1].trim().is_empty() || lines[i - 1].trim_end() == ".br") {
78+
skip_indices.insert(i);
7079
}
7180
}
7281
}
@@ -825,4 +834,44 @@ mod tests {
825834
let result4 = post_process_manpage(input4.to_string());
826835
assert_eq!(result4, expected4);
827836
}
837+
838+
#[test]
839+
fn test_post_process_manpage_removes_br_before_empty_line() {
840+
// Test that .br is removed when followed by empty line (which becomes .sp)
841+
let input = ".TH TEST 1\nSome text\n.br\n\nMore text\n";
842+
let expected = ".TH TEST 1 \"2024-01-01\"\nSome text\n\nMore text\n";
843+
844+
let result = post_process_manpage(input.to_string());
845+
assert_eq!(result, expected);
846+
}
847+
848+
#[test]
849+
fn test_post_process_manpage_complex_br_before_empty() {
850+
// Test multiple .br before empty line patterns
851+
let input = ".TH TEST 1\nSection 1\n.br\n\nSection 2\n.br\n\nSection 3\n";
852+
let expected = ".TH TEST 1 \"2024-01-01\"\nSection 1\n\nSection 2\n\nSection 3\n";
853+
854+
let result = post_process_manpage(input.to_string());
855+
assert_eq!(result, expected);
856+
}
857+
858+
#[test]
859+
fn test_post_process_manpage_removes_br_after_empty_line() {
860+
// Test that .br is removed when preceded by empty line (which becomes .sp)
861+
let input = ".TH TEST 1\nSome text\n\n.br\nMore text\n";
862+
let expected = ".TH TEST 1 \"2024-01-01\"\nSome text\n\nMore text\n";
863+
864+
let result = post_process_manpage(input.to_string());
865+
assert_eq!(result, expected);
866+
}
867+
868+
#[test]
869+
fn test_post_process_manpage_fixes_escape_sequences() {
870+
// Test that \\\\0 and \\0 are fixed to \e0 (literal backslash-zero)
871+
let input = ".TH TEST 1\nText with \\\\\\\\0 and \\\\0 escape\n";
872+
let expected = ".TH TEST 1 \"2024-01-01\"\nText with \\e0 and \\e0 escape\n";
873+
874+
let result = post_process_manpage(input.to_string());
875+
assert_eq!(result, expected);
876+
}
828877
}

0 commit comments

Comments
 (0)