use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; use std::path::PathBuf; pub fn compute_content_hash(content: &str) -> u64 { let mut hasher = DefaultHasher::new(); content.hash(&mut hasher); let hash = hasher.finish(); hash } #[derive(Clone)] pub struct Tab { pub content: String, pub original_content_hash: u64, pub file_path: Option, pub is_modified: bool, pub title: String, } impl Tab { pub fn new_empty(tab_number: usize) -> Self { let content = String::new(); let hash = compute_content_hash(&content); Self { original_content_hash: hash, content, file_path: None, is_modified: false, title: format!("new_{tab_number}"), } } pub fn new_with_file(content: String, file_path: PathBuf) -> Self { let title = file_path .file_name() .and_then(|n| n.to_str()) .unwrap_or("UNKNOWN") .to_string(); let hash = compute_content_hash(&content); Self { original_content_hash: hash, content, file_path: Some(file_path), is_modified: false, title, } } pub fn get_display_title(&self) -> String { let modified_indicator = if self.is_modified { "*" } else { "" }; format!("{}{}", self.title, modified_indicator) } pub fn update_modified_state(&mut self) { if self.title.starts_with("new_") { self.is_modified = !self.content.is_empty(); } else { let current_hash = compute_content_hash(&self.content); self.is_modified = current_hash != self.original_content_hash; } } pub fn mark_as_saved(&mut self) { self.original_content_hash = compute_content_hash(&self.content); self.is_modified = false; } }