use {
super::{
AppContext,
CmdResult,
},
crate::{
errors::ProgramError,
launchable::Launchable,
stage::Stage,
},
std::{
fs::OpenOptions,
io::Write,
path::Path,
},
};
pub type LineNumber = usize;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum SelectionType {
File,
Directory,
Any,
}
#[derive(Debug, Clone, Copy)]
pub struct Selection<'s> {
pub path: &'s Path,
pub line: LineNumber, pub stype: SelectionType,
pub is_exe: bool,
}
#[derive(Debug)]
pub enum SelInfo<'s> {
None,
One(Selection<'s>),
More(&'s Stage), }
impl SelectionType {
pub fn respects(self, constraint: Self) -> bool {
constraint == Self::Any || self == constraint
}
pub fn is_respected_by(self, sel_type: Option<Self>) -> bool {
match (self, sel_type) {
(Self::File, Some(Self::File)) => true,
(Self::Directory, Some(Self::Directory)) => true,
(Self::Any, _) => true,
_ => false,
}
}
pub fn from(path: &Path) -> Self {
if path.is_dir() {
Self::Directory
} else {
Self::File
}
}
}
impl Selection<'_> {
pub fn to_opener(
self,
con: &AppContext,
) -> Result<CmdResult, ProgramError> {
Ok(if self.is_exe {
let path = self.path.to_string_lossy().to_string();
if let Some(export_path) = &con.launch_args.cmd_export_path {
let f = OpenOptions::new().append(true).open(export_path)?;
writeln!(&f, "{}", path)?;
CmdResult::Quit
} else {
CmdResult::from(Launchable::program(
vec![path],
None, con,
)?)
}
} else {
CmdResult::from(Launchable::opener(self.path.to_path_buf()))
})
}
}
impl<'a> SelInfo<'a> {
pub fn count_paths(&self) -> usize {
match self {
SelInfo::None => 0,
SelInfo::One(_) => 1,
SelInfo::More(stage) => stage.len(),
}
}
pub fn common_stype(&self) -> Option<SelectionType> {
match self {
SelInfo::None => None,
SelInfo::One(sel) => Some(sel.stype),
SelInfo::More(stage) => {
let stype = SelectionType::from(&stage.paths()[0]);
for path in stage.paths().iter().skip(1) {
if stype != SelectionType::from(path) {
return None;
}
}
Some(stype)
}
}
}
pub fn one_sel(self) -> Option<Selection<'a>> {
match self {
SelInfo::One(sel) => Some(sel),
_ => None,
}
}
}