Implement `WhichKey` popup to show available command completions.
- Added `format_key_label` to convert `KeyCode` to human-readable strings.
- Added `binding_hints` to `Keymap` to extract available commands for a
given prefix.
- Added `src/ui/which_key.rs` for the widget implementation.
- Updated `src/ui/mod.rs` to export the new module.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
Implement help page navigation with `help-page-next` and `help-page-prev`
commands.
- Added `HelpPageNextCmd` and `HelpPagePrevCmd` to `src/command/cmd.rs` .
- Registered help navigation commands in `CmdRegistry` .
- Updated `HelpCmd` to initialize the help page.
- Added unit tests for help navigation in `src/ui/app.rs` .
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
Add footer_height method to PanelContent trait with default 0. Implement
footer_height in FormulaContent to return 1 when in FormulaEdit mode.
Update Panel::render to subtract footer height from item height. This
enables optional footers in panels.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (bartowski/nvidia_Nemotron-Cascade-2-30B-A3B-GGUF)
Refactor AppMode to use MinibufferConfig for all text-entry modes. Update
command implementations to use new mode constructors. Introduce
PanelContent trait and replace panel structs with content types. Adjust
rendering to use Panel::new and minibuffer configuration. Update imports
and add MinibufferConfig struct. No functional changes; all behavior
preserved.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (bartowski/nvidia_Nemotron-Cascade-2-30B-A3B-GGUF)
Add a `changes_mode` method to the `Effect` trait with a default implementation
returning `false` . Implement this method for the `ChangeMode` effect to return
`true` . Update the command execution logic to use `e.changes_mode()` instead of
string matching on formatted output. Adjust the corresponding test to assert the
presence of a mode‑changing effect directly via the new method, removing the
temporary debug string.
This change introduces a clear, typed way to detect mode‑changing effects,
improving readability and reducing reliance on string inspection.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (bartowski/nvidia_Nemotron-Cascade-2-30B-A3B-GGUF)
Expose CmdRegistry via KeymapSet registry method.
Update Z keybinding to use SaveAndQuit command.
Pass registry to App's CmdContext construction.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (bartowski/nvidia_Nemotron-Cascade-2-30B-A3B-GGUF)
Update UI components and effects to ensure layout is rebuilt when necessary.
- Rebuild layout in `EnterEditAtCursor` effect
- Use `Rc` for sharing records in `StartDrill` effect
- Improve formatting in `SetDrillPendingEdit` effect
- Update test case in `App` to use multi-line method calls
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
Clean up formatting and code style across the project.
- Remove unnecessary whitespace and empty lines in `src/model/cell.rs` ,
`src/model/types.rs` , and `src/draw.rs` .
- Reformat long lines and function calls in `src/command/cmd.rs` ,
`src/ui/grid.rs` , and `src/ui/tile_bar.rs` for better readability.
- Consolidate imports and simplify expressions in `src/command/keymap.rs` and
`src/ui/app.rs` .
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
Update TileBar to use UnicodeWidthStr for accurate text width calculation and
improve axis display.
- Use `unicode_width::UnicodeWidthStr` for calculating label and hint widths
- Move `axis_display` to a static method on `TileBar`
- Update axis symbols for better visual clarity (e.g., '|', '-', '=', '.')
- Clear the tile bar area before rendering to prevent stale characters
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
Refactor GridWidget and other UI components to use the pre-computed layout from
App instead of re-creating it on every render. This improves performance and
ensures consistency.
- Update GridWidget to take a reference to GridLayout
- Update GridWidget::new and render to use the provided layout
- Update App::cmd_context and other call sites to pass the layout
- Update tests to provide the layout to GridWidget
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
Refactor App and DrillState to use Rc for sharing records, and introduce
rebuild_layout() to manage GridLayout lifecycle. This ensures the layout is
consistently updated when the model or drill state changes.
- Use Rc<Vec<(CellKey, CellValue)>> for DrillState.records to allow cheap
cloning
- Add layout field to App
- Implement rebuild_layout() in App to refresh the GridLayout
- Update App::new and App::cmd_context to use the new layout management
- Ensure layout is rebuilt after applying effects and handling key events
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
Adds a `mode()` method to the `Panel` enum to map panels to their
corresponding `AppMode`. Simplifies `TogglePanelAndFocus` in `cmd.rs`
to use this method instead of a manual match block.
Also adds regression tests in `app.rs` to verify that viewport
scrolling now correctly handles small terminal heights.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-31B-it-GGUF:UD-Q5_K_XL)
Unifies cell text retrieval and formatting across pivot and records modes.
Introduces `GridLayout::display_text` to centralize how cell content is
resolved, reducing duplication in `GridWidget` and `export_csv`.
Moves formatting logic from `src/ui/grid.rs` to a new dedicated `src/format.rs`
module to improve reusability.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-31B-it-GGUF:UD-Q5_K_XL)
Clean up UI panel titles by removing redundant keyboard hints that are
already present in the app's status bar or are no longer needed.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-31B-it-GGUF:UD-Q5_K_XL)
Improve grid viewport calculations by using actual column widths instead of
rough estimates. This ensures that the viewport scrolls correctly when the
cursor moves past the visible area.
- Move column width and visible column calculations to public functions in
`src/ui/grid.rs`.
- Update `App::cmd_context` to use these precise calculations for `visible_cols`
.
- Add a regression test to verify that `col_offset` scrolls when cursor moves
past visible columns.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-31B-it-GGUF:UD-Q5_K_XL)
Add new navigation and editing capabilities to improve data entry and
browsing efficiency.
- Implement `PageScroll` command for PageUp/PageDown navigation.
- Implement `OpenRecordRow` command (Vim-style 'o') to add a row and enter edit
mode.
- Implement `CommitAndAdvanceRight` command for Excel-style Tab navigation.
- Add keybindings for Home, End, PageUp, PageDown, and Tab.
- Update UI hints to reflect new Tab functionality.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-31B-it-GGUF:UD-Q5_K_XL)
Refactor records mode to use synthetic CellKeys (_Index, _Dim) for all columns,
allowing uniform handling of display values and edits across both pivot and
records modes.
- Introduce `synthetic_record_info` to extract metadata from synthetic keys.
- Update `GridLayout::cell_key` to return synthetic keys in records mode.
- Add `GridLayout::resolve_display` to handle value resolution for synthetic
keys.
- Replace `records_col` and `records_value` in `CmdContext` with a unified
`display_value`.
- Update `EditOrDrill` and `AddRecordRow` to use synthetic key detection.
- Refactor `CommitCellEdit` to use a shared `commit_cell_value` helper.
BREAKING CHANGE: CmdContext fields `records_col` and `records_value` are replaced by
`display_value` .
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-31B-it-GGUF:UD-Q5_K_XL)
Update TogglePanelAndFocus and related components to use open/focused flags.
Changed TogglePanelAndFocus from currently_open to open+focused flags.
Parser accepts optional [open] [focused] arguments.
Interactive mode toggles between open+focus and closed/unfocused.
Keymap updates: F/C/V in panel modes close panels when focused.
Model initialization: Virtual categories _Index/_Dim default to None
axis, regular categories auto-assign Row/Column/Page.
App test context updated with visible_rows/visible_cols.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
Update grid widget with adaptive column/row widths and pruning support.
Replaced fixed ROW_HEADER_WIDTH (16) and COL_WIDTH (10) with adaptive
widths based on content. MIN_COL_WIDTH=5, MAX_COL_WIDTH=32. MIN_ROW_HEADER_W=4,
MAX_ROW_HEADER_W=24.
Column widths measured from header labels and cell content (pivot mode
measures formatted values, records mode measures raw values).
Row header widths measured from widest label at each level.
Added underlining for columns sharing ancestor groups with selected
column. Updated is_aggregated check to filter virtual categories.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
Update status bar hints for new features.
Normal mode hint: Added R:records P:prune, removed F/C/V:panels
CategoryPanel hint: Added d:delete
These hints reflect the new keybindings for records mode toggle,
prune empty toggle, and category deletion.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
Add EnterEditAtCursor effect to re-enter edit mode after commit.
Used by CommitCellEdit to continue data entry after advancing
cursor. Reads the cell value at the new cursor position and
starts editing mode with that value pre-filled.
Also adds TogglePruneEmpty, ToggleCatExpand, RemoveItem, and
RemoveCategory effects to effect.rs for the new commands.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
Add new commands for enhanced data entry and category management.
AddRecordRow: Adds a new record row in records mode with empty value.
TogglePruneEmpty: Toggles pruning of empty rows/columns in pivot mode.
ToggleRecordsMode: Switches between records and pivot layout.
DeleteCategoryAtCursor: Removes a category and all its cells.
ToggleCatExpand: Expands/collapses a category in the tree.
FilterToItem: Filters to show only items matching cursor position.
Model gains remove_category() and remove_item() to delete categories
and items along with all referencing cells and formulas.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
Add a tree-based category panel that supports expand/collapse of categories.
Introduces CatTreeEntry and build_cat_tree to render categories as
a collapsible tree. The category panel now displays categories with
expand indicators (▶/▼) and shows items under expanded categories.
CmdContext gains cat_tree_entry(), cat_at_cursor(), and cat_tree_len()
methods to work with the tree. App tracks expanded_cats in a HashSet.
Keymap updates: Enter in category panel now triggers filter-to-item.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
Fix column header and cell text truncation to prevent overflow
when text width equals column width. Changed truncate() calls to
use cw.saturating_sub(1) instead of cw, ensuring at least one
character of padding remains.
Affected areas:
- Column header labels (left-aligned)
- Column header labels (right-aligned)
- Cell values
- Total/summary rows
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
Introduce EditOrDrill command that intelligently handles
editing based on cell type. When cursor is on an aggregated
pivot cell (categories on Axis::None, no records mode), it
drills into the cell. Otherwise, it enters edit mode with
the current displayed value.
The 'i' and 'a' keys now trigger edit-or-drill instead of
enter-edit-mode. Aggregated cells are styled in italic to
signal that drilling is required for editing.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
Add a subtle dark-gray background color constant for row highlighting.
Apply the highlight background across the entire selected row area,
including gaps between columns and the margin after the last column.
Apply the highlight background to individual cells in the selected row,
using DarkGray for empty values and White for non-empty values.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
Implement dynamic column widths for the grid widget when in records mode.
In records mode, each column width is computed based on the widest
content (pending edit, record value, or header label), with a minimum
of 6 characters and maximum of 32. Pivot mode continues to use fixed
10-character column widths.
The rendering code has been updated to use the computed column widths
and x-offsets for all grid elements: headers, data cells, and totals.
Note that the total row is now only displayed in pivot mode, as it
is not meaningful in records mode.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
Introduce records-mode drill-down functionality that allows users to
edit individual records without immediately modifying the underlying model.
Key changes:
- Added DrillState struct to hold frozen records snapshot and pending edits
- New effects: StartDrill, ApplyAndClearDrill, SetDrillPendingEdit
- Extended CmdContext with records_col and records_value for records mode
- CommitCellEdit now stages edits in pending_edits when in records mode
- DrillIntoCell captures a snapshot before switching to drill view
- GridLayout supports frozen records for stable view during edits
- GridWidget renders with drill_state for pending edit display
In records mode, edits are staged and only applied to the model when
the user navigates away or commits. This prevents data loss and allows
batch editing of records.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
Implement records mode (long-format view) when drilling into aggregated cells.
Key changes:
- DrillIntoCell now creates views with _Index on Row and _Dim on Column
- GridLayout detects records mode and builds a records list instead of
cross-product row/col items
- Added records_display() to render individual cell values in records mode
- GridWidget and CSV export updated to handle records mode rendering
- category_names() now includes virtual categories (_Index, _Dim)
- Tests updated to reflect virtual categories counting toward limits
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
Add view navigation history with back/forward stacks (bound to < and >).
Introduce CategoryKind enum to distinguish regular categories from
virtual ones (_Index, _Dim) that are synthesized at query time.
Add DrillIntoCell command that creates a drill view showing raw data
for an aggregated cell, expanding categories on Axis::None into Row
and Column axes while filtering by the cell's fixed coordinates.
Virtual categories default to Axis::None and are automatically added
to all views when the model is initialized.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
Introduce a buffers HashMap to manage text input state across different
modes (command, edit, formula, category, export).
Changes:
- Added buffers field to GridWidget and updated constructor
- Updated draw_command_bar to use app.buffers instead of mode buffer
- Updated grid edit indicator to use buffers HashMap
- Added tests for command mode buffer behavior:
* command_mode_typing_appends_to_buffer
* command_mode_buffer_cleared_on_reentry
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
Remove the key_modifiers field from CmdContext struct and all its usages.
This simplifies the command context by removing unused modifier state.
The Cmd trait's execute method no longer receives key modifiers.
Changes:
- Removed KeyModifiers import from cmd.rs
- Removed key_modifiers field from CmdContext struct
- Removed file_path_set field from CmdContext (unused)
- Updated App::cmd_context to not populate key_modifiers
- Removed KeymapSet::registry() accessor
- Updated test code to match new struct layout
- Added documentation to Cmd::name() method
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
Refactor command system to pre-resolve cell key and grid dimensions
in CmdContext, eliminating repeated GridLayout construction.
Key changes:
- Add cell_key, row_count, col_count to CmdContext
- Replace generic CmdRegistry::register with
register/register_pure/register_nullary
- Cell commands (clear-cell, yank, paste) now take explicit CellKey
- Update keymap dispatch to use new interactive() method
- Special-case "search" buffer in SetBuffer effect
- Update tests to populate new context fields
This reduces code duplication and makes command execution more
efficient by computing layout once at context creation time.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
Refactor the keymap system to use string-based command names instead of
concrete command struct instantiations. This introduces a Binding enum that
can represent either a command lookup (name + args) or a prefix sub-keymap.
Key changes:
- Keymap now stores Binding enum instead of Arc<dyn Cmd>
- dispatch() accepts CmdRegistry to resolve commands at runtime
- Added bind_args() for commands with arguments
- KeymapSet now owns the command registry
- Removed PrefixKey struct, inlined its logic
- Updated all default keymap bindings to use string names
This enables more flexible command configuration and easier testing.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
Update headless command execution to use the new architecture:
- Removed CommandResult import (no longer needed)
- Headless mode now creates an App instance and uses cmd_context()
- Commands are parsed and executed via the registry, effects applied
through app.apply_effects() instead of command::dispatch()
- Made cmd_context() public so headless mode can access it
- Updated persistence save to use app.model instead of direct model
Tests updated to use ExecuteCommand instead of QuitCmd, with proper
buffer setup for command parsing.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
Add two new effects for headless model operations:
- LoadModel: Loads a model from a file path, replacing the current one
- ImportJsonHeadless: Imports JSON/CSV files via the analyzer, builds
a new model from detected fields, and replaces the current model
These effects enable headless mode to load and import data without
interactive prompts. ImportJsonHeadless handles both CSV and JSON
files, auto-detects array paths, and uses the existing import pipeline.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
Remove unused imports for legacy code that is no longer needed.
Delete execute_command function that handled :q, :w, :import
commands via direct AppMode matching.
Delete handle_wizard_key function and associated fallback logic
for modes not yet migrated to keymaps. These are now handled
by the new keymap-based approach.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
Add WizardKey effect to handle key bindings for navigating
wizard steps: Preview, SelectArrayPath, ReviewProposals,
ConfigureDates, DefineFormulas, and NameModel.
Add StartImportWizard effect to initialize the wizard by
reading and parsing a JSON file.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
Update handle_key to pass key code and modifiers to cmd_context.
Update keymap_set.dispatch to pass search_mode from App state.
Remove old-style panel handlers (handle_edit_key, handle_formula_edit_key,
handle_formula_panel_key, etc.) - approximately 500 lines.
Update handle_command_mode_key to use buffers map for command execution.
All other modes now handled via keymap dispatch.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
Add tile_cat_idx field to track selected tile category index.
Add buffers HashMap for named text buffers used in text-entry modes.
Update AppMode::TileSelect to remove nested cat_idx struct.
Update cmd_context to accept key and modifiers parameters.
Update cmd_context to populate new fields from App state.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
Add new fields to CmdContext for tracking search mode, panel cursors,
tile category index, named text buffers, and key information.
Add SetBuffer and SetTileCatIdx effects for managing application state.
Update TileBar to accept tile_cat_idx parameter for rendering.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
- Fixed transient keymap consumption logic: the transient keymap is now only
consumed when a match is found.
- Updated handle_key to retain transient keymap if no command matches, allowing
subsequent key presses to be processed by the main keymap set.
- Added issue noting the previous unintended consumption.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (gpt-oss:20b)
- Reformatted method calls in RemoveFormula and SetAxis for consistency.
- Minor formatting changes to improve readability.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (gpt-oss:20b)
- Updated imports to include Arc and removed KeyModifiers.
- Replaced pending_key with transient_keymap and keymap_set.
- Added KeymapSet for mode-specific keymaps.
- Removed legacy pending key logic and many helper methods.
- Updated tests to use new command execution pattern.
- Adjusted App struct and methods to align with new keymap system.
Co-Authored-By: fiddlerwoaroof/git-smart-commit (gpt-oss:20b)