1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

nl: increase line number over multiple files

This commit is contained in:
Daniel Hofstetter 2023-09-19 10:47:00 +02:00
parent 351722ebac
commit 1107fadca9
2 changed files with 37 additions and 9 deletions

View file

@ -55,6 +55,20 @@ impl Default for Settings {
} }
} }
struct Stats {
line_number: i64,
consecutive_empty_lines: u64,
}
impl Stats {
fn new(starting_line_number: i64) -> Self {
Self {
line_number: starting_line_number,
consecutive_empty_lines: 0,
}
}
}
// NumberingStyle stores which lines are to be numbered. // NumberingStyle stores which lines are to be numbered.
// The possible options are: // The possible options are:
// 1. Number all lines // 1. Number all lines
@ -160,6 +174,8 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
None => vec!["-".to_owned()], None => vec!["-".to_owned()],
}; };
let mut stats = Stats::new(settings.starting_line_number);
for file in &files { for file in &files {
if file == "-" { if file == "-" {
// If both file names and '-' are specified, we choose to treat first all // If both file names and '-' are specified, we choose to treat first all
@ -170,12 +186,12 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let path = Path::new(file); let path = Path::new(file);
let reader = File::open(path).map_err_context(|| file.to_string())?; let reader = File::open(path).map_err_context(|| file.to_string())?;
let mut buffer = BufReader::new(reader); let mut buffer = BufReader::new(reader);
nl(&mut buffer, &settings)?; nl(&mut buffer, &mut stats, &settings)?;
} }
if read_stdin { if read_stdin {
let mut buffer = BufReader::new(stdin()); let mut buffer = BufReader::new(stdin());
nl(&mut buffer, &settings)?; nl(&mut buffer, &mut stats, &settings)?;
} }
Ok(()) Ok(())
} }
@ -285,10 +301,9 @@ pub fn uu_app() -> Command {
} }
// nl implements the main functionality for an individual buffer. // nl implements the main functionality for an individual buffer.
fn nl<T: Read>(reader: &mut BufReader<T>, settings: &Settings) -> UResult<()> { fn nl<T: Read>(reader: &mut BufReader<T>, stats: &mut Stats, settings: &Settings) -> UResult<()> {
let mut current_numbering_style = &settings.body_numbering; let mut current_numbering_style = &settings.body_numbering;
let mut line_no = settings.starting_line_number; let mut consecutive_empty_lines = stats.consecutive_empty_lines;
let mut consecutive_empty_lines = 0;
for line in reader.lines() { for line in reader.lines() {
let line = line.map_err_context(|| "could not read line".to_string())?; let line = line.map_err_context(|| "could not read line".to_string())?;
@ -312,7 +327,7 @@ fn nl<T: Read>(reader: &mut BufReader<T>, settings: &Settings) -> UResult<()> {
if let Some(new_style) = new_numbering_style { if let Some(new_style) = new_numbering_style {
current_numbering_style = new_style; current_numbering_style = new_style;
if settings.renumber { if settings.renumber {
line_no = settings.starting_line_number; stats.line_number = settings.starting_line_number;
} }
println!(); println!();
} else { } else {
@ -336,13 +351,13 @@ fn nl<T: Read>(reader: &mut BufReader<T>, settings: &Settings) -> UResult<()> {
"{}{}{}", "{}{}{}",
settings settings
.number_format .number_format
.format(line_no, settings.number_width), .format(stats.line_number, settings.number_width),
settings.number_separator, settings.number_separator,
line line
); );
// update line number for the potential next line // update line number for the potential next line
match line_no.checked_add(settings.line_increment) { match stats.line_number.checked_add(settings.line_increment) {
Some(new_line_no) => line_no = new_line_no, Some(new_line_number) => stats.line_number = new_line_number,
None => return Err(USimpleError::new(1, "line number overflow")), None => return Err(USimpleError::new(1, "line number overflow")),
} }
} else { } else {

View file

@ -311,6 +311,19 @@ fn test_default_body_numbering() {
.stdout_is(" 1\ta\n \n 2\tb\n"); .stdout_is(" 1\ta\n \n 2\tb\n");
} }
#[test]
fn test_default_body_numbering_multiple_files() {
let (at, mut ucmd) = at_and_ucmd!();
at.write("a.txt", "a");
at.write("b.txt", "b");
at.write("c.txt", "c");
ucmd.args(&["a.txt", "b.txt", "c.txt"])
.succeeds()
.stdout_is(" 1\ta\n 2\tb\n 3\tc\n");
}
#[test] #[test]
fn test_body_numbering_all_lines_without_delimiter() { fn test_body_numbering_all_lines_without_delimiter() {
for arg in ["-ba", "--body-numbering=a"] { for arg in ["-ba", "--body-numbering=a"] {