use crate::enums::Address; use std::fs::File; use std::io; use std::io::Write; pub struct Buffer { has_changed: bool, buffer: Vec>, // vraie adresse dans le vecteur, l'utilisateur se trouve à current_line + // 1 pour lui. current_line: usize, file_name: String, } impl Buffer { pub fn new(file_name: &str, buffer: Vec>) -> Self { let tmp = buffer.len().saturating_sub(1); Self { has_changed: false, buffer, current_line: tmp, file_name: String::from(file_name), } } pub fn is_modified(&self) -> bool { self.has_changed } // Return the actual line of the buffer pub fn line(&self) -> usize { self.current_line } // change la ligne actuelle pub fn change_line(&mut self, new: usize) { // TODO check si > len self.current_line = new; } pub fn save(&mut self, range: Address) { let len = self.buffer.len(); let curr = self.current_line; match range { Address::Actual => self.save_range(curr, curr.saturating_add(1)), Address::Empty | Address::All => self.save_range(0, len), Address::Last => self.save_range(len.saturating_sub(1), len), Address::Line(l) => self.save_range(l.saturating_sub(1), l), Address::FromStartTo(l) => self.save_range(0, l), Address::FromToEnd(l) => self.save_range(l.saturating_sub(1), len), Address::FromTo(a, b) => self.save_range(a.saturating_sub(1), b), Address::FromActTo(l) => self.save_range(curr, l), Address::FromActToEnd => self.save_range(curr, len), _ => (), } } fn save_range(&mut self, start: usize, end: usize) { if let Ok(mut file) = File::create(&self.file_name) { let mut tmp = String::new(); for line in self.buffer[start..end].iter().flatten() { tmp.push_str(line); tmp.push('\n'); } if let Err(e) = file.write(tmp.as_bytes()) { panic!("{}", e); } self.has_changed = false; } } pub fn delete(&mut self, addr:Address) { self.has_changed = true; let curr = self.current_line; let last_line = self.buffer.len(); match addr { Address::Actual | Address::Empty => self.delete_lines(curr, curr.saturating_add(1)), Address::Line(l) => self.delete_lines(l.saturating_sub(1), l), Address::Last => self.delete_lines(last_line.saturating_sub(1), last_line), Address::All => self.delete_lines(0, last_line), Address::FromTo(a, b) => self.delete_lines(a.saturating_sub(1), b), Address::FromStartTo(a) => self.delete_lines(0, a), Address::FromToEnd(a) => self.delete_lines(a.saturating_sub(1), last_line), Address::FromActTo(a) => self.delete_lines(curr, a), Address::FromActToEnd => self.delete_lines(curr, last_line), Address::Null => println!("nul !"), } } fn delete_lines(&mut self, start: usize, end: usize) { for i in start..end { self.buffer.remove(start); } } pub fn append(&mut self, addr:Address, lines: Vec) { self.has_changed = true; match addr { Address::Actual | Address::Empty => self.insert_buffer(self.current_line + 1, lines), Address::Line(l) => self.insert_buffer(l, lines), Address::Last => self.insert_buffer(self.buffer.len(), lines), _ => (), } } pub fn insert(&mut self, addr: Address, lines: Vec) { self.has_changed = true; match addr { Address::Actual | Address::Empty => self.insert_buffer(self.current_line, lines), Address::Line(l) => self.insert_buffer(l.saturating_sub(1), lines), Address::Last => self.insert_buffer(self.buffer.len().saturating_sub(1), lines), _ => (), } } fn insert_buffer(&mut self, line: usize, lines: Vec) { for (i, l) in lines.iter().enumerate() { self.buffer.insert(i + line, Ok(l.to_string())); self.current_line = i + line; } } pub fn print(&mut self, addr: Address, print_numbers: bool) { let last_line = self.buffer.len(); match addr { Address::Actual | Address::Empty => { self.print_line(self.current_line, print_numbers); } Address::Line(l) => self.print_line(l.saturating_sub(1), print_numbers), Address::Last => self.print_line(last_line, print_numbers), Address::All => self.print_range(0, last_line, print_numbers), Address::FromTo(a, b) => self.print_range(a.saturating_sub(1), b, print_numbers), Address::FromStartTo(a) => self.print_range(0, a, print_numbers), Address::FromToEnd(a) => { self.print_range(a.saturating_sub(1), last_line, print_numbers) } Address::FromActTo(a) => self.print_range(self.current_line, a, print_numbers), Address::FromActToEnd => self.print_range(self.current_line, last_line, print_numbers), Address::Null => println!("nul !"), } } // affiche une ligne fn print_line(&mut self, nb: usize, print_numbers: bool) { if nb >= self.buffer.len() { println!("?"); } else if let Ok(line) = &self.buffer[nb] { self.current_line = nb; if print_numbers { println!("{}\t{}", nb + 1, line); } else { println!("{}", line); } } else { println!("?"); } } // affiche plusieurs lignes fn print_range(&mut self, first: usize, last: usize, print_numbers: bool) { let len = self.buffer.len(); // anti idiot, vraiment utile vu que les adresses gères déjà ça ? if len > 0 && (first <= len && last <= len && first <= last) { for i in first..last { self.print_line(i, print_numbers); } } else { println!("?"); } } }