use crate::app_state_container::SelectionMode;
use crate::buffer::AppMode;
use anyhow::Result;
#[derive(Debug, Clone, PartialEq)]
pub enum CursorPosition {
Current,
End,
AfterClause(SqlClause),
}
#[derive(Debug, Clone, PartialEq)]
pub enum SqlClause {
Select,
From,
Where,
OrderBy,
GroupBy,
Having,
Limit,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Action {
Navigate(NavigateAction),
SwitchMode(AppMode),
SwitchModeWithCursor(AppMode, CursorPosition),
ToggleSelectionMode,
ExitCurrentMode,
InsertChar(char),
Backspace,
Delete,
ClearLine,
Undo,
Redo,
MoveCursorLeft,
MoveCursorRight,
MoveCursorHome,
MoveCursorEnd,
MoveCursorWordLeft,
MoveCursorWordRight,
JumpToPrevToken,
JumpToNextToken,
DeleteWordBackward,
DeleteWordForward,
DeleteToLineStart,
DeleteToLineEnd,
Yank(YankTarget),
Paste,
ToggleColumnPin,
HideColumn,
UnhideAllColumns,
HideEmptyColumns,
MoveColumnLeft,
MoveColumnRight,
ClearAllPins,
NextColumn,
PreviousColumn,
ToggleCompactMode,
ToggleRowNumbers,
Sort(Option<usize>), StartFilter,
StartFuzzyFilter,
ApplyFilter(String),
ClearFilter,
ExportToCsv,
ExportToJson,
StartSearch,
StartColumnSearch,
NextMatch,
PreviousMatch,
NextSearchMatch, PreviousSearchMatch,
ExecuteQuery,
LoadFromHistory(usize),
StartHistorySearch,
PreviousHistoryCommand, NextHistoryCommand,
RefreshView,
ShowHelp,
ShowDebugInfo,
ShowPrettyQuery,
StartJumpToRow,
NavigateToViewportTop,
NavigateToViewportMiddle,
NavigateToViewportBottom,
ToggleCursorLock,
ToggleViewportLock,
ToggleCaseInsensitive,
ToggleKeyIndicator,
ShowColumnStatistics, CycleColumnPacking,
KillLine, KillLineBackward, ExpandAsterisk, ExpandAsteriskVisible,
Quit,
ForceQuit,
}
#[derive(Debug, Clone, PartialEq)]
pub enum NavigateAction {
Up(usize),
Down(usize),
Left(usize),
Right(usize),
PageUp,
PageDown,
Home,
End,
FirstColumn,
LastColumn,
JumpToRow(usize),
JumpToColumn(usize),
}
#[derive(Debug, Clone, PartialEq)]
pub enum YankTarget {
Cell,
Row,
Column,
All,
Query,
}
#[derive(Debug, Clone)]
pub struct ActionContext {
pub mode: AppMode,
pub selection_mode: SelectionMode,
pub has_results: bool,
pub has_filter: bool,
pub has_search: bool,
pub row_count: usize,
pub column_count: usize,
pub current_row: usize,
pub current_column: usize,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ActionResult {
Handled,
NotHandled,
Exit,
SwitchMode(AppMode),
Error(String),
}
pub trait ActionHandler {
fn can_handle(&self, action: &Action, context: &ActionContext) -> bool;
fn handle(&mut self, action: Action, context: &ActionContext) -> Result<ActionResult>;
}
#[must_use]
pub fn can_perform_action(action: &Action, context: &ActionContext) -> bool {
match action {
Action::Navigate(_) => context.mode == AppMode::Results && context.has_results,
Action::ToggleSelectionMode => context.mode == AppMode::Results,
Action::ExitCurrentMode => context.mode != AppMode::Command,
Action::Yank(_) => context.has_results,
Action::StartFilter | Action::StartFuzzyFilter => {
context.mode == AppMode::Results || context.mode == AppMode::Command
}
Action::ClearFilter => context.has_filter,
Action::NextMatch | Action::PreviousMatch => context.has_search,
_ => true,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_navigation_action_creation() {
let action = Action::Navigate(NavigateAction::Down(5));
assert_eq!(action, Action::Navigate(NavigateAction::Down(5)));
}
#[test]
fn test_action_context() {
let context = ActionContext {
mode: AppMode::Results,
selection_mode: SelectionMode::Row,
has_results: true,
has_filter: false,
has_search: false,
row_count: 100,
column_count: 10,
current_row: 0,
current_column: 0,
};
assert!(can_perform_action(
&Action::Navigate(NavigateAction::Down(1)),
&context
));
assert!(!can_perform_action(&Action::ClearFilter, &context));
}
}