use crate::*; /// Browses for phrase to import/export #[derive(Debug, Clone)] pub struct FileBrowser { pub cwd: PathBuf, pub dirs: Vec<(OsString, String)>, pub files: Vec<(OsString, String)>, pub filter: String, pub index: usize, pub scroll: usize, pub size: Measure } /// Commands supported by [FileBrowser] #[derive(Debug, Clone, PartialEq)] pub enum FileBrowserCommand { Begin, Cancel, Confirm, Select(usize), Chdir(PathBuf), Filter(String), } render!(Tui: (self: FileBrowser) => /*Stack::down(|add|{ let mut i = 0; for (_, name) in self.dirs.iter() { if i >= self.scroll { add(&Tui::bold(i == self.index, name.as_str()))?; } i += 1; } for (_, name) in self.files.iter() { if i >= self.scroll { add(&Tui::bold(i == self.index, name.as_str()))?; } i += 1; } add(&format!("{}/{i}", self.index))?; Ok(()) })*/"todo"); impl FileBrowser { pub fn new (cwd: Option) -> Usually { let cwd = if let Some(cwd) = cwd { cwd } else { std::env::current_dir()? }; let mut dirs = vec![]; let mut files = vec![]; for entry in std::fs::read_dir(&cwd)? { let entry = entry?; let name = entry.file_name(); let decoded = name.clone().into_string().unwrap_or_else(|_|"".to_string()); let meta = entry.metadata()?; if meta.is_dir() { dirs.push((name, format!("📁 {decoded}"))); } else if meta.is_file() { files.push((name, format!("📄 {decoded}"))); } } Ok(Self { cwd, dirs, files, filter: "".to_string(), index: 0, scroll: 0, size: Measure::new(), }) } pub fn len (&self) -> usize { self.dirs.len() + self.files.len() } pub fn is_dir (&self) -> bool { self.index < self.dirs.len() } pub fn is_file (&self) -> bool { self.index >= self.dirs.len() } pub fn path (&self) -> PathBuf { self.cwd.join(if self.is_dir() { &self.dirs[self.index].0 } else if self.is_file() { &self.files[self.index - self.dirs.len()].0 } else { unreachable!() }) } pub fn chdir (&self) -> Usually { Self::new(Some(self.path())) } }