Skip to content

Commit 9d87a2e

Browse files
committed
pr: fix header formatting for custom date formats starting with '+'
Should fix tests/misc/time-style.sh
1 parent d432131 commit 9d87a2e

File tree

2 files changed

+90
-6
lines changed

2 files changed

+90
-6
lines changed

src/uu/pr/src/pr.rs

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,12 +1151,52 @@ fn get_formatted_line_number(opts: &OutputOptions, line_number: usize, index: us
11511151
/// using `NO_HEADER_TRAILER_OPTION` option.
11521152
fn header_content(options: &OutputOptions, page: usize) -> Vec<String> {
11531153
if options.display_header_and_trailer {
1154-
let first_line = format!(
1155-
"{} {} {} {page}",
1156-
options.last_modified_time,
1157-
options.header,
1158-
translate!("pr-page")
1159-
);
1154+
// The header should be formatted with proper spacing:
1155+
// - Date/time on the left
1156+
// - Filename centered
1157+
// - "Page X" on the right
1158+
let date_part = &options.last_modified_time;
1159+
let filename = &options.header;
1160+
let page_part = format!("{} {page}", translate!("pr-page"));
1161+
1162+
// Use the line width if available, otherwise use default of 72
1163+
let total_width = options.line_width.unwrap_or(DEFAULT_COLUMN_WIDTH);
1164+
1165+
// GNU pr uses a specific layout:
1166+
// Date takes up the left part, filename is centered, page is right-aligned
1167+
let date_len = date_part.chars().count();
1168+
let filename_len = filename.chars().count();
1169+
let page_len = page_part.chars().count();
1170+
1171+
let first_line = if date_len + filename_len + page_len + 2 < total_width {
1172+
// Check if we're using a custom date format that needs centered alignment
1173+
// This preserves backward compatibility while fixing the GNU time-style test
1174+
let needs_centering = date_part.starts_with('+');
1175+
1176+
if needs_centering {
1177+
// GNU pr uses centered layout for headers with custom date formats
1178+
// The filename should be centered between the date and page parts
1179+
let space_for_filename = total_width - date_len - page_len;
1180+
let padding_before_filename = (space_for_filename - filename_len) / 2;
1181+
let padding_after_filename =
1182+
space_for_filename - filename_len - padding_before_filename;
1183+
1184+
format!(
1185+
"{date_part}{:width1$}{filename}{:width2$}{page_part}",
1186+
"",
1187+
"",
1188+
width1 = padding_before_filename,
1189+
width2 = padding_after_filename
1190+
)
1191+
} else {
1192+
// For standard date formats, use simple spacing for backward compatibility
1193+
format!("{date_part} {filename} {page_part}")
1194+
}
1195+
} else {
1196+
// If content is too long, just use single spaces
1197+
format!("{date_part} {filename} {page_part}")
1198+
};
1199+
11601200
vec![
11611201
String::new(),
11621202
String::new(),

tests/by-util/test_pr.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,50 @@ fn test_value_for_number_lines() {
558558
new_ucmd!().args(&["-n", "foo5.txt", "test.log"]).fails();
559559
}
560560

561+
#[test]
562+
fn test_header_formatting_with_custom_date_format() {
563+
// This test verifies that the header is properly formatted with:
564+
// - Date/time on the left
565+
// - Filename centered
566+
// - "Page X" on the right
567+
// This matches GNU pr behavior for the time-style test
568+
569+
let test_file_path = "test_one_page.log";
570+
let mut scenario = new_ucmd!();
571+
572+
// Set a specific date format like in the GNU test
573+
let output = scenario
574+
.args(&["-D", "+%Y-%m-%d %H:%M:%S %z (%Z)", test_file_path])
575+
.succeeds()
576+
.stdout_move_str();
577+
578+
// Extract the header line (3rd line of output)
579+
let lines: Vec<&str> = output.lines().collect();
580+
assert!(
581+
lines.len() >= 5,
582+
"Output should have at least 5 lines for header"
583+
);
584+
585+
let header_line = lines[2];
586+
587+
// The header should be 72 characters wide (default page width)
588+
assert_eq!(header_line.chars().count(), 72);
589+
590+
// Check that it contains the expected parts
591+
assert!(header_line.contains(test_file_path));
592+
assert!(header_line.contains("Page 1"));
593+
594+
// Verify the filename is roughly centered
595+
let filename_pos = header_line.find(test_file_path).unwrap();
596+
let page_pos = header_line.find("Page 1").unwrap();
597+
598+
// Filename should be somewhere in the middle third of the line
599+
assert!(filename_pos > 24 && filename_pos < 48);
600+
601+
// Page should be right-aligned (near the end)
602+
assert!(page_pos >= 60);
603+
}
604+
561605
#[test]
562606
fn test_help() {
563607
new_ucmd!().arg("--help").succeeds();

0 commit comments

Comments
 (0)