use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; use std::process::Command; use std::time::{SystemTime, UNIX_EPOCH}; pub type BufferID = usize; #[derive(Debug)] pub enum BufferState { Modified, Unmodified, } #[derive(Debug)] pub struct Buffer { pub content: String, pub name: String, pub state: BufferState, pub read_only: bool, pub ephemeral: bool, } impl Buffer { pub fn new(name: String, content: String) -> Self { Self { name, content, state: BufferState::Unmodified, read_only: false, ephemeral: false, } } pub fn max_pos(&self) -> usize { self.content.len() } pub fn valid_pos(&self, pos: usize) -> bool { pos <= self.max_pos() } fn generate_shell_name(command: &str) -> String { let mut hasher = DefaultHasher::new(); command.hash(&mut hasher); let command_hash = hasher.finish(); let timestamp = match SystemTime::now().duration_since(UNIX_EPOCH) { Ok(x) => x.as_secs(), Err(_) => 0, }; format!("shell_{:x}_{}", command_hash, timestamp) } pub fn from_shell_command(command: &str) -> Self { let name = Self::generate_shell_name(command); let output = Command::new("sh").arg("-c").arg(command).output(); let content = match output { Ok(output) => match String::from_utf8(output.stdout) { Ok(s) => s, Err(e) => format!("UTF-8 decode error: {}", e), }, Err(e) => format!("Command failed: {}", e), }; Self { name, content, read_only: true, state: BufferState::Unmodified, ephemeral: true, } } }