tabiew 0.15.1

A lightweight TUI application to view and query tabular data files, such as CSV, TSV, and parquet.
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)))
    }
}