From a3be935a29e7d11f6f66567e201c753eea9daba8 Mon Sep 17 00:00:00 2001 From: Emmanuel BERNAT Date: Sun, 22 Sep 2024 19:16:06 +0200 Subject: [PATCH] =?UTF-8?q?Traitement=20de=20l'option=20-v=20(show-non-pri?= =?UTF-8?q?nting)=20de=20la=20m=C3=AAme=20fa=C3=A7on=20que=20la=20commande?= =?UTF-8?q?=20GNU=20cat.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 73 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 15 deletions(-) diff --git a/src/main.rs b/src/main.rs index 48e2141..268832d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -58,19 +58,17 @@ fn main() { args.show_tabs = args.show_tabs || args.show_all || args.show_all_no_ends; args.number_nonblank = args.number_nonblank && !args.number; - //args.files = vec!(String::from("fichier1")); - let line_ends = if args.show_ends { "$" } else { "" }; let mut line_number = 0; let mut line_prefix: String; let mut last_was_blank = false; for file_path in args.files { - let f = File::open(file_path).unwrap(); - let mut reader = BufReader::new(f); + let f = File::open(file_path).unwrap(); // File : structure pour accéder à un fichier + let mut reader = BufReader::new(f); // BufRead : structure pour faire des lectures bufferisées loop { let mut line = String::new(); - if let Ok(len) = reader.read_line(&mut line) { + if let Ok(len) = reader.read_line(&mut line) { // read_line retourne une longueur nulle à la fin du fichier if len==0 { break; } @@ -80,7 +78,7 @@ fn main() { if args.number || (args.number_nonblank && !line_is_blank) { line_number += 1; - line_prefix = format!("{:>6} ", line_number); + line_prefix = format!("{:>6} ", line_number); // format! : macro de formatage (à la printf) if line_prefix.len()<8 { line_prefix.push(' '); } @@ -89,18 +87,63 @@ fn main() { } let mut line_to_display = String::from(""); - for c in line.to_string().chars() { - match c as u8 { - 9 => if args.show_tabs { line_to_display.push(c) } else { line_to_display.push_str("^I") } - 10 => {}, - 0 ..= 127 => line_to_display.push(c), - 128 ..= 255 => if args.show_nonprinting { line_to_display.push_str("M^"); line_to_display.push((c as u8 - 128) as char) } else { line_to_display.push(c) }, - _ => {} - }; + + for c in line.chars() { + if c.len_utf8() == 1 { + // Si le caractère est convertible en ASCII + let ascii_ch = c as u8; + if ascii_ch>=32 { + line_to_display.push(c) + } else if ascii_ch==9 && !args.show_tabs { + line_to_display.push(c) + } else if ascii_ch==10 { + line_to_display.push(c) + } else if ascii_ch==13 { + line_to_display.push_str("^M") + } else if ascii_ch!=13 && args.show_nonprinting { + line_to_display.push_str("^"); + line_to_display.push((ascii_ch + 64) as char) + } + } else { + // On est sur un caractère UNICODE + // Conversion des caractères non imprimables selon https://github.com/coreutils/coreutils/blob/5cecd703e57b2e1301767d82cbe5bb01cae88472/src/cat.c#L412 + if args.show_nonprinting { + let mut caracts_ut8 = [0; 4]; + let _result = c.encode_utf8(&mut caracts_ut8); + + for sub in caracts_ut8 { + if sub>=32 { + if sub < 127 { + line_to_display.push(char::from_u32(sub as u32).unwrap()) + } else if sub == 127 { + line_to_display.push_str("^?") + } else { + line_to_display.push_str("M-"); + if sub >= 128 + 32 { + if sub < 128 + 127 { + line_to_display.push(char::from_u32(sub as u32 - 128).unwrap()); + } else { + line_to_display.push_str("^?") + } + } else { + line_to_display.push('^'); + line_to_display.push(char::from_u32(sub as u32 - 128 + 64).unwrap()); + } + } + } else { + if sub==0x9 && !args.show_tabs { + line_to_display.push(char::from_u32(sub as u32).unwrap()) + } + } + } + } else { + line_to_display.push(c) + } + } } if !skip_line { - println!("{}{}{}", line_prefix, line_to_display, line_ends); + print!("{}{}{}", line_prefix, line_to_display, line_ends); } last_was_blank = line_is_blank;