excel-cli 0.4.2

A lightweight terminal-based Excel viewer with Vim-like navigation for viewing, editing, and exporting Excel data to JSON format.
Documentation
use crate::app::AppState;
use crate::app::InputMode;

impl AppState<'_> {
    pub fn show_help(&mut self) {
        self.help_scroll = 0;

        self.help_text = "FILE OPERATIONS:\n\
             :w          - Save file\n\
             :wq, :x     - Save and quit\n\
             :q          - Quit (will warn if unsaved changes)\n\
             :q!         - Force quit without saving\n\n\
             NAVIGATION:\n\
             :[cell]     - Jump to cell (e.g., :B10)\n\
             hjkl        - Move cursor (left, down, up, right)\n\
             0           - Jump to first column\n\
             ^           - Jump to first non-empty column\n\
             $           - Jump to last column\n\
             gg          - Jump to first row\n\
             G           - Jump to last row\n\
             Ctrl+arrows - Jump to next non-empty cell\n\
             [           - Switch to previous sheet\n\
             ]           - Switch to next sheet\n\
             :sheet [name/number] - Switch to sheet by name or index\n\n\
             EDITING:\n\
             Enter       - Edit current cell\n\
             :y          - Copy current cell\n\
             :d          - Cut current cell\n\
             :put, :pu   - Paste to current cell\n\
             u           - Undo last operation\n\
             Ctrl+r      - Redo last undone operation\n\n\
             SEARCH:\n\
             /           - Search forward\n\
             ?           - Search backward\n\
             n           - Jump to next search result\n\
             N           - Jump to previous search result\n\
             :nohlsearch, :noh - Disable search highlighting\n\n\
             COLUMN OPERATIONS:\n\
             :cw fit     - Adjust width of current column to fit its content\n\
             :cw fit all - Adjust width of all columns to fit their content\n\
             :cw min     - Set current column width to minimum (5 characters)\n\
             :cw min all - Set all columns width to minimum\n\
             :cw [number] - Set current column width to specific number of characters\n\
             :dc         - Delete current column\n\
             :dc [col]   - Delete specific column (e.g., :dc A or :dc 1)\n\
             :dc [start] [end] - Delete columns from start to end (e.g., :dc A C)\n\n\
             ROW OPERATIONS:\n\
             :dr         - Delete current row\n\
             :dr [row]   - Delete specific row\n\
             :dr [start] [end] - Delete rows from start to end\n\n\
             EXPORT:\n\
             :ej [h|v] [rows]  - Export current sheet to JSON\n\
             :eja [h|v] [rows] - Export all sheets to a single JSON file\n\
                                h=horizontal (default), v=vertical\n\
                                [rows]=number of header rows (default: 1)\n\n\
             SHEET OPERATIONS:\n\
             :addsheet [name] - Add a new sheet after the current sheet\n\
             :delsheet   - Delete the current sheet\n\n\
             UI ADJUSTMENTS:\n\
             +/=         - Increase info panel height\n\
             -           - Decrease info panel height\n\n\
             EDITING MODE:\n\
             Esc         - Exit Vim mode and save changes\n\
             i           - Enter Insert mode\n\
             v           - Enter Visual mode\n\
             y           - Yank (copy) text in Visual mode or with operator\n\
             d           - Delete text in Visual mode or with operator\n\
             c           - Change text in Visual mode or with operator\n\
             p           - Paste yanked or deleted text\n\
             u           - Undo last change\n\
             Ctrl+r      - Redo last undone change\n\
             h,j,k,l     - Move cursor left, down, up, right\n\
             w           - Move to next word\n\
             b           - Move to beginning of word\n\
             e           - Move to end of word\n\
             $           - Move to end of line\n\
             ^           - Move to first non-blank character of line\n\
             gg          - Move to first line\n\
             G           - Move to last line\n\
             x           - Delete character under cursor\n\
             D           - Delete to end of line\n\
             C           - Change to end of line\n\
             o           - Open new line below and enter Insert mode\n\
             O           - Open new line above and enter Insert mode\n\
             A           - Append at end of line\n\
             I           - Insert at beginning of line"
            .to_string();

        self.input_mode = InputMode::Help;
    }

    pub fn save_and_exit(&mut self) {
        if !self.workbook.is_modified() {
            self.add_notification("No changes to save".to_string());
            self.should_quit = true;
            return;
        }

        match self.workbook.save() {
            Ok(_) => {
                self.undo_history.clear();
                self.add_notification("File saved".to_string());
                self.should_quit = true;
            }
            Err(e) => {
                self.add_notification(format!("Save failed: {e}"));
                self.input_mode = InputMode::Normal;
            }
        }
    }

    pub fn save(&mut self) -> Result<(), anyhow::Error> {
        if !self.workbook.is_modified() {
            self.add_notification("No changes to save".to_string());
            return Ok(());
        }

        match self.workbook.save() {
            Ok(_) => {
                self.undo_history.clear();
                self.add_notification("File saved".to_string());
            }
            Err(e) => {
                self.add_notification(format!("Save failed: {e}"));
            }
        }
        Ok(())
    }

    pub fn exit_without_saving(&mut self) {
        self.should_quit = true;
    }
}