Keyboard Shortcuts

May 26, 2026 ยท View on GitHub

Thoth supports keyboard shortcuts for efficient navigation and operation. All shortcuts are customizable through the settings file.

Implementation Status

โœ… Fully Implemented - Working in current version ๐Ÿšง In Progress - Configured but needs additional work ๐Ÿ“‹ Planned - Defined for future implementation

Default Shortcuts

File Operations โœ…

ActionmacOSWindows/LinuxDescriptionStatus
Open FileโŒ˜OCtrl+OOpen a JSON or NDJSON fileโœ… Working
New WindowโŒ˜NCtrl+NOpen a new Thoth windowโœ… Working

Tab Operations โœ…

ActionmacOSWindows/LinuxDescriptionStatus
New TabโŒ˜TCtrl+TOpen a new empty tab (shows Welcome screen)โœ… Working
Close TabโŒ˜WCtrl+WClose the active tab; if the last tab is the welcome screen, exitโœ… Working
Next TabโŒ˜โŒฅโ†’Ctrl+Alt+โ†’Cycle to the next tab in the focused paneโœ… Working
Previous TabโŒ˜โŒฅโ†Ctrl+Alt+โ†Cycle to the previous tab in the focused paneโœ… Working
Switch to Tab 1โ€“9โŒ˜1โ€“โŒ˜9Ctrl+1โ€“Ctrl+9Jump directly to tab by position; โŒ˜9 always goes to the last tabโœ… Working

macOS note: โŒ˜โ‡ง[/โŒ˜โ‡ง] and Ctrl+Tab are intercepted by the OS before reaching the app (NSWindowTabbing and egui focus traversal respectively). โŒ˜โŒฅโ†’/โŒ˜โŒฅโ† are not affected.

UI Controls โœ…

ActionmacOSWindows/LinuxDescriptionStatus
SettingsโŒ˜,Ctrl+,Open/close settings panelโœ… Working
Toggle ThemeโŒ˜โ‡งTCtrl+Shift+TSwitch between dark/light themeโœ… Working
EscapeEscEscClose settings panelโœ… Working
ActionmacOSWindows/LinuxDescriptionStatus
Focus SearchโŒ˜FCtrl+FFocus the search inputโœ… Working
Next MatchโŒ˜GCtrl+GJump to next search match๐Ÿšง TODO
Previous MatchโŒ˜โ‡งGCtrl+Shift+GJump to previous search match๐Ÿšง TODO

Note: Search focus is fully working. Match navigation requires additional search result tracking.

Movement โœ…

ActionShortcutDescriptionStatus
Move Upโ†‘Move selection to previous itemโœ… Working
Move Downโ†“Move selection to next itemโœ… Working

Tree Operations โœ…

ActionShortcutDescriptionStatus
Expand Nodeโ†’Expand the selected nodeโœ… Working
Collapse Nodeโ†Collapse the selected nodeโœ… Working
Expand AllโŒ˜โ†’ / Ctrl+โ†’Expand all nodes in the treeโœ… Working
Collapse AllโŒ˜โ† / Ctrl+โ†Collapse all nodes in the treeโœ… Working

Clipboard Operations โœ…

ActionmacOSWindows/LinuxDescriptionStatus
Copy KeyโŒ˜CCtrl+CCopy the selected keyโœ… Working
Copy ValueโŒ˜โ‡งCCtrl+Shift+CCopy the selected valueโœ… Working
Copy ObjectโŒ˜โŒฅCCtrl+Alt+CCopy entire JSON object (formatted)โœ… Working
Copy PathโŒ˜โ‡งPCtrl+Shift+PCopy the JSON pathโœ… Working

Note: All clipboard operations also available via right-click context menu.

Summary

22 keyboard shortcuts are fully implemented and working:

  • 2 File Operations
  • 5 Tab Operations
  • 3 UI Controls
  • 1 Navigation (+ 2 planned)
  • 2 Movement
  • 4 Tree Operations
  • 4 Clipboard Operations

Customizing Shortcuts

Keyboard shortcuts can be customized by editing the settings file located at:

  • macOS/Linux: ~/.config/thoth/settings.toml
  • Windows: %APPDATA%\thoth\settings.toml

Configuration Format

Shortcuts are defined in the [shortcuts] section of the settings file:

[shortcuts]
# File operations
open_file = { key = "O", ctrl = false, alt = false, shift = false, command = true }
new_window = { key = "N", ctrl = false, alt = false, shift = false, command = true }

# Tab operations
tab_close = { key = "W", ctrl = false, alt = false, shift = false, command = true }
tab_new = { key = "T", ctrl = false, alt = false, shift = false, command = true }
tab_cycle_next = { key = "ArrowRight", ctrl = false, alt = true, shift = false, command = true }
tab_cycle_prev = { key = "ArrowLeft", ctrl = false, alt = true, shift = false, command = true }

# UI controls
settings = { key = "Comma", ctrl = false, alt = false, shift = false, command = true }
toggle_theme = { key = "T", ctrl = false, alt = false, shift = true, command = true }
escape = { key = "Escape", ctrl = false, alt = false, shift = false, command = false }

# Navigation
focus_search = { key = "F", ctrl = false, alt = false, shift = false, command = true }
next_match = { key = "G", ctrl = false, alt = false, shift = false, command = true }
prev_match = { key = "G", ctrl = false, alt = false, shift = true, command = true }

# Movement
move_up = { key = "ArrowUp", ctrl = false, alt = false, shift = false, command = false }
move_down = { key = "ArrowDown", ctrl = false, alt = false, shift = false, command = false }

# Tree operations
expand_node = { key = "ArrowRight", ctrl = false, alt = false, shift = false, command = false }
collapse_node = { key = "ArrowLeft", ctrl = false, alt = false, shift = false, command = false }
expand_all = { key = "ArrowRight", ctrl = false, alt = false, shift = false, command = true }
collapse_all = { key = "ArrowLeft", ctrl = false, alt = false, shift = false, command = true }

# Clipboard operations
copy_key = { key = "C", ctrl = false, alt = false, shift = false, command = true }
copy_value = { key = "C", ctrl = false, alt = false, shift = true, command = true }
copy_object = { key = "C", ctrl = false, alt = true, shift = false, command = true }
copy_path = { key = "P", ctrl = false, alt = false, shift = true, command = true }

Modifier Keys

  • command: Primary modifier (โŒ˜ on macOS, Ctrl on Windows/Linux) - Use this for cross-platform shortcuts
  • ctrl: Control key (always Ctrl, even on macOS)
  • alt: Alt/Option key
  • shift: Shift key

Supported Key Names

Letters: A through Z

Numbers: 0 through 9

Special Keys:

  • Escape, Enter, Tab, Space, Backspace, Delete
  • ArrowLeft, ArrowRight, ArrowUp, ArrowDown
  • F1 through F12

Punctuation:

  • Comma (,), Period (.), Slash (/), Backslash ()
  • Semicolon (;), Quote ('), Backtick (`)
  • Minus (-), Equal (=)
  • BracketLeft ([), BracketRight (])

Example Customizations

Use Vim-style navigation

expand_node = { key = "L", ctrl = false, alt = false, shift = false, command = false }
collapse_node = { key = "H", ctrl = false, alt = false, shift = false, command = false }
move_up = { key = "K", ctrl = false, alt = false, shift = false, command = false }
move_down = { key = "J", ctrl = false, alt = false, shift = false, command = false }

Use F-keys for common actions

open_file = { key = "F1", ctrl = false, alt = false, shift = false, command = false }
settings = { key = "F2", ctrl = false, alt = false, shift = false, command = false }
toggle_theme = { key = "F3", ctrl = false, alt = false, shift = false, command = false }

Alternative search shortcuts

focus_search = { key = "S", ctrl = false, alt = false, shift = false, command = true }
next_match = { key = "N", ctrl = false, alt = false, shift = false, command = true }
prev_match = { key = "P", ctrl = false, alt = false, shift = false, command = true }

Implementation Details

Architecture

The keyboard shortcut system is built using native egui functionality with zero external dependencies:

  1. shortcuts.rs: Core shortcut types and configuration

    • Shortcut: Individual shortcut configuration with builder pattern
    • KeyboardShortcuts: Complete shortcut set
    • Cross-platform formatting and parsing
  2. app/shortcut_handler.rs: Shortcut detection and action mapping

    • ShortcutAction: Enum of all possible actions (17 total)
    • ShortcutHandler: Detects pressed shortcuts and returns actions
  3. components/file_viewer/viewer_trait.rs: Viewer operations

    • FileFormatViewer: Trait with 10 shortcut-related methods
    • Default implementations for all methods (no-op)
    • Enables shortcuts to work across all file formats
  4. settings.rs: Persistent configuration

    • Shortcuts are part of the main settings TOML file
    • Automatically loaded on startup
    • User-customizable

Trait-Based Design

All keyboard shortcut operations (tree, movement, clipboard) are defined in the FileFormatViewer trait:

pub trait FileFormatViewer {
    // Navigation & Tree Operations
    fn expand_selected(&mut self, selected: &Option<String>) -> bool;
    fn collapse_selected(&mut self, selected: &Option<String>) -> bool;
    fn expand_all(&mut self) -> bool;
    fn collapse_all(&mut self) -> bool;
    fn move_selection_up(&self, current: &Option<String>) -> Option<String>;
    fn move_selection_down(&self, current: &Option<String>) -> Option<String>;

    // Clipboard Operations
    fn copy_selected_key(&self, selected: &Option<String>) -> Option<String>;
    fn copy_selected_value(&self, ...) -> Option<String>;
    fn copy_selected_object(&self, ...) -> Option<String>;
    fn copy_selected_path(&self, selected: &Option<String>) -> Option<String>;
}

This design ensures that:

  • All file format viewers support the same shortcuts
  • New viewers automatically get shortcut support
  • Compile-time enforcement via trait bounds
  • Zero runtime overhead

Cross-Platform Support

The system uses egui::Modifiers::COMMAND which automatically maps to:

  • โŒ˜ (Command) on macOS
  • Ctrl on Windows and Linux

This ensures shortcuts feel native on each platform while using a single configuration.

Adding New Shortcuts

To add a new keyboard shortcut:

  1. Add the shortcut to KeyboardShortcuts in src/shortcuts.rs:
pub struct KeyboardShortcuts {
    // ... existing shortcuts ...
    pub my_new_shortcut: Shortcut,
}

impl Default for KeyboardShortcuts {
    fn default() -> Self {
        Self {
            // ... existing shortcuts ...
            my_new_shortcut: Shortcut::new("K").command(),
        }
    }
}
  1. Add the action to ShortcutAction in src/app/shortcut_handler.rs:
pub enum ShortcutAction {
    // ... existing actions ...
    MyNewAction,
}
  1. Add detection in ShortcutHandler::handle_shortcuts():
if ctx.input_mut(|i| i.consume_shortcut(&shortcuts.my_new_shortcut.to_keyboard_shortcut())) {
    actions.push(ShortcutAction::MyNewAction);
}
  1. Handle the action in ThothApp::handle_shortcut_actions():
ShortcutAction::MyNewAction => {
    // Your action implementation
}
  1. (Optional) If it's a viewer operation, add it to the FileFormatViewer trait with a default implementation, then implement it in specific viewers like JsonTreeViewer.

Tooltips

All toolbar buttons display their keyboard shortcuts in tooltips when hovering. This helps users discover available shortcuts naturally.

Technical Notes

  • Shortcuts are checked every frame in the order defined
  • Multiple shortcuts can be triggered in the same frame
  • consume_shortcut() prevents the shortcut from being processed twice
  • Tree, movement, and clipboard shortcuts are passed through the trait system
  • Escape key has special behavior: closes panels if open
  • Clipboard operations use ctx.copy_text() for cross-platform compatibility

Future Enhancements

Potential improvements for the shortcut system:

  1. Visual shortcut editor in settings panel
  2. Shortcut conflicts detection and warnings
  3. Shortcut recording - press keys to set shortcuts
  4. Per-action enable/disable flags
  5. Shortcut hints overlay (show all shortcuts on demand)
  6. Import/export shortcut configurations
  7. Preset configurations (VS Code-style, Vim-style, Emacs-style, etc.)
  8. Next/Previous match navigation for search results
  9. Home/End keys - jump to first/last item
  10. Page Up/Down - navigate by page
  • Architecture Overview - Details on the trait-based file viewer system
  • Issue #25 - Original keyboard shortcuts feature request
  • Issue #35 - Multi-format file support (benefits from shortcut architecture)