use std::fmt::Display;
use crossterm::event::{KeyCode, KeyModifiers};
use strum::IntoEnumIterator;
use strum_macros::{EnumIter, IntoStaticStr};
use crate::{
handler::message::Message,
misc::{config::config, type_ext::UnwrapOrEnqueueError},
tui::{component::Component, icons, pickers::search_picker::SearchPicker},
};
#[derive(Debug)]
pub struct CommandPalette {
picker: SearchPicker<Command>,
}
impl Default for CommandPalette {
fn default() -> Self {
Self {
picker: SearchPicker::new(Command::all()),
}
}
}
impl Component for CommandPalette {
fn render(
&mut self,
area: ratatui::prelude::Rect,
buf: &mut ratatui::prelude::Buffer,
focus_state: crate::tui::component::FocusState,
) {
self.picker.render(area, buf, focus_state);
}
fn handle(&mut self, event: crossterm::event::KeyEvent) -> bool {
if self.picker.handle(event) {
match self.picker.text() {
"s " => {
Message::AppDismissOverlay.enqueue();
Message::PaneShowInlineSelect.enqueue();
}
"o " => {
Message::AppDismissOverlay.enqueue();
Message::PaneShowInlineOrder.enqueue();
}
"f " => {
Message::AppDismissOverlay.enqueue();
Message::PaneShowInlineFilter.enqueue();
}
"q " => {
Message::AppDismissOverlay.enqueue();
Message::AppShowSqlQuery.enqueue();
}
_ => (),
}
true
} else {
match (event.code, event.modifiers) {
(KeyCode::Enter, KeyModifiers::NONE) => {
Message::AppDismissOverlay.enqueue();
if let Some(item) = self.picker.selected_item() {
match item {
Command::About => Message::AppShowAbout.enqueue(),
Command::Cast => Message::PaneShowColumnCaster.enqueue(),
Command::Info => Message::PaneShowTableInfo.enqueue(),
Command::Export => Message::PaneShowExporter.enqueue(),
Command::Filter => Message::PaneShowInlineFilter.enqueue(),
Command::Histogram => Message::PaneShowHistogramBuilder.enqueue(),
Command::Import => Message::AppShowImporter.enqueue(),
Command::Order => Message::PaneShowInlineOrder.enqueue(),
Command::Query => Message::AppShowSqlQuery.enqueue(),
Command::Quit => Message::Quit.enqueue(),
Command::Register => Message::PaneShowTableRegisterer.enqueue(),
Command::ScatterPlot => Message::PaneShowScatterPlotBuilder.enqueue(),
Command::Schema => Message::AppShowSchema.enqueue(),
Command::Select => Message::PaneShowInlineSelect.enqueue(),
Command::Sort => Message::PaneShowInlineOrder.enqueue(),
Command::ThemeSelector => Message::AppShowThemeSelector.enqueue(),
Command::ToggleBorders => {
config().toggle_show_table_borders();
config().store().unwrap_or_enqueue_error();
}
Command::ToggleRowNumbers => {
config().toggle_show_table_row_numbers();
config().store().unwrap_or_enqueue_error();
}
Command::ToggleNerdFont => {
config().toggle_use_nerd_font();
config().store().unwrap_or_enqueue_error();
}
Command::FloatingPointPrecision => {
Message::AppShowFpPrecisionPicker.enqueue()
}
Command::FuzzySearch => Message::PaneShowFuzzySearch.enqueue(),
Command::Search => Message::PaneShowSearch.enqueue(),
Command::Edit => Message::PaneEditInExternalEditor.enqueue(),
Command::ReloadConfig => Message::AppReloadConfig.enqueue(),
}
}
true
}
(KeyCode::Esc, KeyModifiers::NONE) => {
Message::AppDismissOverlay.enqueue();
true
}
_ => false,
}
}
}
}
#[derive(Debug, Clone, Copy, EnumIter, IntoStaticStr)]
enum Command {
About,
Cast,
Edit,
Export,
Filter,
FloatingPointPrecision,
FuzzySearch,
Histogram,
Import,
Info,
Order,
Query,
Quit,
Register,
ReloadConfig,
ScatterPlot,
Search,
Schema,
Select,
Sort,
ThemeSelector,
ToggleBorders,
ToggleNerdFont,
ToggleRowNumbers,
}
impl Command {
fn all() -> Vec<Command> {
Command::iter().collect()
}
}
impl Command {
fn icon(&self) -> icons::Icon {
match self {
Command::About => icons::INFO,
Command::Cast => icons::CAST,
Command::Edit => icons::PENCIL,
Command::Export => icons::EXPORT,
Command::Filter => icons::FILTER,
Command::FloatingPointPrecision => icons::PRECISION,
Command::FuzzySearch => icons::FUZZY_SEARCH,
Command::Histogram => icons::CHART,
Command::Import => icons::IMPORT,
Command::Info => icons::INFO,
Command::Order | Command::Sort => icons::SORT,
Command::Query => icons::DATABASE,
Command::Quit => icons::POWER,
Command::Register => icons::TAG,
Command::ReloadConfig => icons::REFRESH,
Command::ScatterPlot => icons::SCATTER,
Command::Schema => icons::SCHEMA,
Command::Search => icons::SEARCH,
Command::Select => icons::COLUMN,
Command::ThemeSelector => icons::PALETTE,
Command::ToggleBorders => icons::BORDERS,
Command::ToggleNerdFont => icons::FONT,
Command::ToggleRowNumbers => icons::ROW_NUMBERS,
}
}
}
impl Display for Command {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.icon().item(Into::<&str>::into(self)))
}
}