use crate::*; use std::path::PathBuf; use std::ffi::OsString; #[derive(Clone, Debug)] pub enum BrowseTarget { SaveProject, LoadProject, ImportSample(Arc>>), ExportSample(Arc>>), ImportClip(Arc>>), ExportClip(Arc>>), } impl PartialEq for BrowseTarget { fn eq (&self, other: &Self) -> bool { match self { Self::ImportSample(_) => false, Self::ExportSample(_) => false, Self::ImportClip(_) => false, Self::ExportClip(_) => false, t => matches!(other, t) } } } /// Browses for phrase to import/export #[derive(Debug, Clone, Default, PartialEq)] pub struct Browse { 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, } impl Browse { 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())) } } impl Browse { fn _todo_stub_path_buf (&self) -> PathBuf { todo!() } fn _todo_stub_usize (&self) -> usize { todo!() } fn _todo_stub_arc_str (&self) -> Arc { todo!() } } def_command!(BrowseCommand: |browse: Browse| { SetVisible => Ok(None), SetPath { address: PathBuf } => Ok(None), SetSearch { filter: Arc } => Ok(None), SetCursor { cursor: usize } => Ok(None), }); impl HasContent for Browse { fn content (&self) -> impl Content { Map::south(1, ||EntriesIterator { offset: 0, index: 0, length: self.dirs.len() + self.files.len(), browser: self, }, |entry, _index|Fill::X(Align::w(entry))) } } struct EntriesIterator<'a> { browser: &'a Browse, offset: usize, length: usize, index: usize, } impl<'a> Iterator for EntriesIterator<'a> { type Item = Modify<&'a str>; fn next (&mut self) -> Option { let dirs = self.browser.dirs.len(); let files = self.browser.files.len(); let index = self.index; if self.index < dirs { self.index += 1; Some(Tui::bold(true, self.browser.dirs[index].1.as_str())) } else if self.index < dirs + files { self.index += 1; Some(Tui::bold(false, self.browser.files[index - dirs].1.as_str())) } else { None } } } // Commands supported by [Browse] //#[derive(Debug, Clone, PartialEq)] //pub enum BrowseCommand { //Begin, //Cancel, //Confirm, //Select(usize), //Chdir(PathBuf), //Filter(Arc), //} //fn begin (browse: &mut Browse) => { //unreachable!(); //} //fn cancel (browse: &mut Browse) => { //todo!() ////browse.mode = None; ////Ok(None) //} //fn confirm (browse: &mut Browse) => { //todo!() ////Ok(match browse.mode { ////Some(PoolMode::Import(index, ref mut browse)) => { ////if browse.is_file() { ////let path = browse.path(); ////browse.mode = None; ////let _undo = PoolClipCommand::import(browse, index, path)?; ////None ////} else if browse.is_dir() { ////browse.mode = Some(PoolMode::Import(index, browse.chdir()?)); ////None ////} else { ////None ////} ////}, ////Some(PoolMode::Export(index, ref mut browse)) => { ////todo!() ////}, ////_ => unreachable!(), ////}) //} //fn select (browse: &mut Browse, index: usize) => { //todo!() ////Ok(match browse.mode { ////Some(PoolMode::Import(index, ref mut browse)) => { ////browse.index = index; ////None ////}, ////Some(PoolMode::Export(index, ref mut browse)) => { ////browse.index = index; ////None ////}, ////_ => unreachable!(), ////}) //} //fn chdir (browse: &mut Browse, dir: PathBuf) => { //todo!() ////Ok(match browse.mode { ////Some(PoolMode::Import(index, ref mut browse)) => { ////browse.mode = Some(PoolMode::Import(index, Browse::new(Some(dir))?)); ////None ////}, ////Some(PoolMode::Export(index, ref mut browse)) => { ////browse.mode = Some(PoolMode::Export(index, Browse::new(Some(dir))?)); ////None ////}, ////_ => unreachable!(), ////}) //} //fn filter (browse: &mut Browse, filter: Arc) => { //todo!() //}