use {
super::*,
crate::{
verb::{
Internal,
VerbStore,
},
},
};
pub struct StandardStatus {
tree_top_focus: String, tree_dir_focus: String,
tree_dir_cd: Option<String>, tree_file_open_stay: Option<String>,
tree_file_open_leave: Option<String>,
tree_unfiltered: String,
tree_filtered: String,
preview_unfiltered: String, preview_filtered: Option<String>,
preview_restorable_filter: Option<String>,
not_first_state: String, help: String,
no_verb: String,
}
impl StandardStatus {
pub fn new(verb_store: &VerbStore) -> Self {
let tree_top_focus = "*enter* to go up".to_string(); let tree_dir_focus = "*enter* to focus".to_string();
let tree_dir_cd = verb_store
.key_desc_of_internal_stype(Internal::open_leave, SelectionType::Directory)
.map(|k| format!("*{}* to cd", k));
let tree_file_open_stay = verb_store
.key_desc_of_internal_stype(Internal::open_stay, SelectionType::File)
.map(|k| format!("*{}* to open the file", k));
let tree_file_open_leave = verb_store
.key_desc_of_internal_stype(Internal::open_leave, SelectionType::File)
.map(|k| format!("*{}* to open and quit", k));
let tree_unfiltered = "a few letters to search".to_string();
let tree_filtered = "*esc* to clear the filter".to_string();
let preview_unfiltered = "a pattern to filter".to_string();
let preview_filtered = verb_store
.key_desc_of_internal(Internal::panel_right)
.map(|k| format!("*{}* to reveal the text", k));
let preview_restorable_filter = verb_store
.key_desc_of_internal(Internal::panel_left)
.map(|k| format!("*{}* to restore the filter", k));
let not_first_state = "*esc* to go back".to_string();
let help = "*?* for help".to_string();
let no_verb = "a space then a verb".to_string();
Self {
tree_top_focus,
tree_dir_focus,
tree_dir_cd,
tree_file_open_stay,
tree_file_open_leave,
tree_unfiltered,
tree_filtered,
preview_unfiltered,
preview_filtered,
preview_restorable_filter,
not_first_state,
help,
no_verb,
}
}
pub fn builder<'s>(
&'s self,
state_type: PanelStateType,
selection: Selection<'s>,
) -> StandardStatusBuilder<'s> {
StandardStatusBuilder::new(&self, state_type, selection)
}
}
#[derive(Default)]
struct StatusParts<'b> {
md_parts: Vec<&'b str>,
}
impl<'b> StatusParts<'b> {
fn add(&mut self, md: &'b str) {
self.md_parts.push(md);
}
fn addo(&mut self, md: &'b Option<String>) {
if let Some(md) = md {
self.md_parts.push(md);
}
}
fn len(&self) -> usize {
self.md_parts.len()
}
fn to_status(&self) -> Status {
let mut md = String::new();
for (i, p) in self.md_parts.iter().enumerate() {
md.push_str(if i == 0 {
"Hit "
} else if i == self.md_parts.len() - 1 {
", or "
} else {
", "
});
md.push_str(p);
}
Status::from_message(md)
}
}
pub struct StandardStatusBuilder<'s> {
ss: &'s StandardStatus,
state_type: PanelStateType,
selection: Selection<'s>,
pub has_previous_state: bool,
pub is_filtered: bool,
pub has_removed_pattern: bool,
pub on_tree_root: bool, }
impl<'s> StandardStatusBuilder<'s> {
fn new(
ss: &'s StandardStatus,
state_type: PanelStateType,
selection: Selection<'s>,
) -> Self {
Self {
ss,
state_type,
selection,
has_previous_state: true,
is_filtered: false,
has_removed_pattern: false,
on_tree_root: false,
}
}
pub fn status(self) -> Status {
let ss = &self.ss;
let mut parts = StatusParts::default();
if self.has_previous_state && !self.is_filtered {
parts.add(&ss.not_first_state);
}
match self.state_type {
PanelStateType::Tree => {
if self.on_tree_root {
if self.selection.path.file_name().is_some() { parts.add(&ss.tree_top_focus);
}
} else if self.selection.stype == SelectionType::Directory {
parts.add(&ss.tree_dir_focus);
parts.addo(&ss.tree_dir_cd);
} else if self.selection.stype == SelectionType::File {
parts.addo(&ss.tree_file_open_stay);
parts.addo(&ss.tree_file_open_leave);
}
if self.is_filtered {
parts.add(&ss.tree_filtered);
}
if parts.len() < 3 {
parts.add(&ss.help);
}
if parts.len() < 4 {
if self.on_tree_root && !self.is_filtered {
parts.add(&ss.tree_unfiltered);
} else {
parts.add(&ss.no_verb);
}
}
}
PanelStateType::Preview => {
if self.is_filtered {
parts.addo(&ss.preview_filtered);
} else if self.has_removed_pattern {
parts.addo(&ss.preview_restorable_filter);
} else {
parts.add(&ss.preview_unfiltered);
}
parts.add(&ss.no_verb);
}
PanelStateType::Help => {
if parts.len() < 4 {
parts.add(&ss.no_verb);
}
}
PanelStateType::Fs => {
warn!("TODO fs status");
}
PanelStateType::Stage => {
warn!("TODO stage status");
}
}
parts.to_status()
}
}