use super::diagnostics;
use super::{Action, App, Component, KeyEvent, Mode, Outcome, keymap};
impl App {
pub(super) fn effective_mode(&self) -> Mode {
if self.consent.is_some() {
return Mode::Browse;
}
if let Some(wizard) = &self.wizard {
return wizard.effective_mode();
}
if let Some(settings) = &self.settings {
return settings.effective_mode();
}
if let Some(help) = &self.help {
return help.effective_mode();
}
if let Some(refs) = &self.refs_popup {
return refs.effective_mode();
}
if self.command_line.is_some() {
return Mode::Insert;
}
if self.mode == Mode::History && self.browser.history_filtering() {
return Mode::Search;
}
if self.mode == Mode::Commit
&& self
.browser
.commit_ref()
.is_some_and(|view| view.filtering())
{
return Mode::Search;
}
if self.mode == Mode::Commit
&& self
.browser
.commit_ref()
.is_some_and(|view| view.searching())
{
return Mode::Find;
}
if let Some(view) = &self.search_view {
if self.mode == Mode::Leader {
return Mode::Leader;
}
return view.effective_mode();
}
match &self.popup {
Some(popup) => popup.effective_mode(),
None => self.mode,
}
}
pub fn handle_key(&mut self, key: KeyEvent) {
rootle_trace::in_operation(rootle_trace::operation_id(), || {
diagnostics::record_key(&key, self.effective_mode().chip());
let action = self.dispatch(key);
self.handle_action(action);
diagnostics::record_state(self, "post_key");
});
}
pub(super) fn dispatch(&mut self, key: KeyEvent) -> Action {
if let Some(consent) = &mut self.consent {
return consent.handle_key(key);
}
if let Some(wizard) = &mut self.wizard {
return wizard.handle_key(key);
}
if let Some(settings) = &mut self.settings {
return settings.handle_key(key);
}
if let Some(help) = &mut self.help {
return help.handle_key(key);
}
if let Some(refs) = &mut self.refs_popup {
return refs.handle_key(key);
}
if let Some(command_line) = &mut self.command_line {
return command_line.handle_key(key);
}
if let Some(view) = &mut self.search_view {
if self.mode == Mode::Leader {
return keymap::leader(key.code);
}
return view.handle_key(key);
}
if let Some(popup) = &mut self.popup {
return popup.handle_key(key);
}
match self.mode {
Mode::Browse => keymap::browsing(key.code),
Mode::Visual => keymap::visual(key.code),
Mode::Search => match self.browser.filter_input.handle_key(key) {
Outcome::Changed => Action::Noop, Outcome::Submitted => Action::CommitFilter,
Outcome::Cancelled => Action::ClearFilter,
Outcome::Noop => Action::Noop,
},
Mode::Find => match self.browser.find_input.handle_key(key) {
Outcome::Changed => Action::UpdateFind,
Outcome::Submitted => Action::CommitFind,
Outcome::Cancelled => Action::CancelFind,
Outcome::Noop => Action::Noop,
},
Mode::Leader => keymap::leader(key.code),
Mode::History => {
if self.browser.history_filtering() {
Action::HistoryFilterKey(key)
} else if self.browser.repository_history_active() {
keymap::repository_history(key.code)
} else {
keymap::history(key.code)
}
}
Mode::Preview => self.browser.preview_key(key),
Mode::Commit => self
.browser
.commit()
.map(|view| view.handle_key(key))
.unwrap_or(Action::Noop),
_ => Action::Noop,
}
}
pub fn handle_action(&mut self, action: Action) {
diagnostics::record_action(&action);
let left = self
.try_browse(action)
.and_then(|a| self.try_search(a))
.and_then(|a| self.try_lenses(a))
.and_then(|a| self.try_lifecycle(a));
debug_assert!(left.is_none(), "unrouted action: {left:?}");
let _ = left;
if self.mode == Mode::Search {
self.browser.apply_filter();
}
self.sync_highlight_theme();
self.maybe_load_blob();
if let Some(note) = self.provider.take_notice() {
if note.contains("keeps failing to restart") {
self.degraded = Some(note.clone());
}
self.status = Some(note);
}
diagnostics::record_state(self, "post_action");
}
}