use crate::app::state::AppMode;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct KeyBindingInfo {
pub key: &'static str,
pub description: &'static str,
pub group: &'static str,
pub extended_description: Option<&'static str>,
}
impl KeyBindingInfo {
pub const fn new(
key: &'static str,
description: &'static str,
group: &'static str,
extended_description: Option<&'static str>,
) -> Self {
Self {
key,
description,
group,
extended_description,
}
}
}
pub fn get_help_for_mode(mode: AppMode) -> Vec<KeyBindingInfo> {
match mode {
AppMode::Normal => vec![
KeyBindingInfo::new("↑/↓", "Navigate transactions", "Navigation", None),
KeyBindingInfo::new("PgUp/PgDn", "Scroll page up/down", "Navigation", None),
KeyBindingInfo::new("Ctrl+Up/Down", "Jump to First/Last", "Navigation", None),
KeyBindingInfo::new(
"a",
"Add new transaction",
"Actions",
Some(
"Opens the 'Add Transaction' form where you can input details like date, amount, category, etc.",
),
),
KeyBindingInfo::new(
"e",
"Edit selected transaction",
"Actions",
Some("Opens the edit mode for the currently selected transaction."),
),
KeyBindingInfo::new(
"d",
"Delete selected transaction",
"Actions",
Some("Prompts for confirmation to delete the selected transaction."),
),
KeyBindingInfo::new(
"Ctrl+C",
"Copy selected transaction",
"Actions",
Some(
"Creates a duplicate of the selected transaction with today's date, keeping the same description, category, subcategory, amount, and type.",
),
),
KeyBindingInfo::new(
"r",
"Manage recurring transactions",
"Actions",
Some("Opens the recurring transactions manager."),
),
KeyBindingInfo::new(
"f",
"Filter transactions",
"Actions",
Some("Enables simple filtering mode. Type to filter by any field."),
),
KeyBindingInfo::new(
"Ctrl+F",
"Advanced Filter",
"Actions",
Some(
"Opens the advanced filter form directly, for filtering by date range, category, type, amount, and more.",
),
),
KeyBindingInfo::new(
"s",
"Monthly Summary",
"Actions",
Some("View a monthly breakdown of income vs expenses."),
),
KeyBindingInfo::new(
"c",
"Category Summary",
"Actions",
Some("View expenses broken down by category and subcategory."),
),
KeyBindingInfo::new(
"b",
"Budget View",
"Actions",
Some(
"View monthly budget progress and budgeted category spending for the selected month.",
),
),
KeyBindingInfo::new(
"o",
"Settings",
"Actions",
Some(
"Open application settings: database location, category management, CSV import/export, budget and display preferences.",
),
),
KeyBindingInfo::new("1/F1", "Sort by Date", "Sorting", None),
KeyBindingInfo::new("2/F2", "Sort by Description", "Sorting", None),
KeyBindingInfo::new("3/F3", "Sort by Category", "Sorting", None),
KeyBindingInfo::new("4/F4", "Sort by Subcategory", "Sorting", None),
KeyBindingInfo::new("5/F5", "Sort by Type", "Sorting", None),
KeyBindingInfo::new("6/F6", "Sort by Amount", "Sorting", None),
KeyBindingInfo::new(
"q/Esc",
"Quit / Clear Filters",
"System",
Some("If filters are active, clears them. Otherwise, quits the application."),
),
KeyBindingInfo::new(
"Ctrl+H",
"Show Keybindings Help",
"System",
Some("Shows this help menu."),
),
],
AppMode::Adding | AppMode::Editing => vec![
KeyBindingInfo::new("Tab/↑/↓", "Navigate fields", "Navigation", None),
KeyBindingInfo::new(
"Date Field",
"Transaction Date (YYYY-MM-DD)",
"Fields",
Some(
"Enter the date of the transaction (YYYY-MM-DD). Use Arrow keys to adjust day by day. Hold Shift + Arrow keys to jump by month. Accurate dating helps with monthly filtering.",
),
),
KeyBindingInfo::new(
"Amount Field",
"Transaction Amount",
"Fields",
Some(
"Numerical value of the transaction. Positive numbers are standard. The 'Type' field determines if it's income or expense. For expenses, enter the positive cost.",
),
),
KeyBindingInfo::new(
"Category",
"Main Category",
"Fields",
Some(
"Primary classification (e.g., 'Food', 'Housing'). Press Enter to open a selection list of categories from the current catalog.",
),
),
KeyBindingInfo::new(
"Subcategory",
"Sub Category",
"Fields",
Some(
"More specific classification (e.g., 'Groceries', 'Rent'). Useful for detailed breakdown in the Category Summary view.",
),
),
KeyBindingInfo::new(
"Type",
"Expense / Income",
"Fields",
Some(
"Classifies the transaction as 'Expense' or 'Income'. This affects how totals are calculated in summaries. Use Left/Right arrows to toggle.",
),
),
KeyBindingInfo::new(
"Description",
"Notes / Details",
"Fields",
Some(
"Optional details about the transaction. Add context that doesn't fit in categories.",
),
),
KeyBindingInfo::new(
"←/→",
"Toggle type / Adjust date / Move cursor",
"Input",
Some(
"On the Type field toggles Income/Expense; on the Date field moves the date by one day; on text fields moves the cursor.",
),
),
KeyBindingInfo::new(
"Shift+←/→",
"Jump month (Date field)",
"Input",
Some("In date fields, moves date by one month instead of one day."),
),
KeyBindingInfo::new(
"+/-",
"Adjust date",
"Input",
Some(
"On the Date field, '+' or '=' moves the date forward a day and '-' moves it back.",
),
),
KeyBindingInfo::new(
"Enter",
"Save / Toggle type / Open selection",
"Actions",
Some(
"On the Type field toggles Income/Expense; on Category/Subcategory opens a selection list; on any other field saves the transaction.",
),
),
KeyBindingInfo::new("Esc", "Cancel", "Actions", None),
KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
],
AppMode::ConfirmDelete => vec![
KeyBindingInfo::new("y", "Confirm deletion", "Actions", None),
KeyBindingInfo::new("n/Esc", "Cancel deletion", "Actions", None),
KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
],
AppMode::Filtering => vec![
KeyBindingInfo::new("Any Char", "Type filter text", "Input", None),
KeyBindingInfo::new("Bksp/Del", "Delete character", "Input", None),
KeyBindingInfo::new("←/→", "Move cursor", "Navigation", None),
KeyBindingInfo::new(
"Ctrl+F",
"Switch to Advanced Filter",
"Actions",
Some("Switch to advanced filtering mode for more specific criteria."),
),
KeyBindingInfo::new("Ctrl+R", "Clear filter", "Actions", None),
KeyBindingInfo::new("Enter", "Apply filter", "Actions", None),
KeyBindingInfo::new("Esc", "Clear filter", "Actions", None),
KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
],
AppMode::AdvancedFiltering => vec![
KeyBindingInfo::new("Tab/↑/↓", "Navigate fields", "Navigation", None),
KeyBindingInfo::new(
"Start Date",
"Filter From Date",
"Fields",
Some("Include transactions on or after this date."),
),
KeyBindingInfo::new(
"End Date",
"Filter To Date",
"Fields",
Some("Include transactions on or before this date."),
),
KeyBindingInfo::new(
"Min Amount",
"Minimum Amount",
"Fields",
Some("Filter transactions with amount greater than or equal to this."),
),
KeyBindingInfo::new(
"Max Amount",
"Maximum Amount",
"Fields",
Some("Filter transactions with amount less than or equal to this."),
),
KeyBindingInfo::new(
"Category",
"Filter Category",
"Fields",
Some("Filter by specific category."),
),
KeyBindingInfo::new(
"Subcategory",
"Filter Subcategory",
"Fields",
Some("Filter by specific subcategory."),
),
KeyBindingInfo::new(
"Type",
"Filter Type",
"Fields",
Some("Filter by Expense or Income."),
),
KeyBindingInfo::new(
"Desc",
"Filter Description",
"Fields",
Some("Filter by text in description."),
),
KeyBindingInfo::new(
"←/→",
"Adjust date / Toggle type / Move cursor",
"Input",
Some(
"On the Start/End Date fields adjusts by a day; on the Type field toggles Expense/Income; on text fields moves the cursor.",
),
),
KeyBindingInfo::new("Shift+←/→", "Jump month (date fields)", "Input", None),
KeyBindingInfo::new("Ctrl+R", "Clear all filters", "Actions", None),
KeyBindingInfo::new(
"Enter",
"Save & Apply / Open selection",
"Actions",
Some(
"On the Category/Subcategory fields opens a selection list; on any other field saves and applies the filters.",
),
),
KeyBindingInfo::new("Esc", "Cancel / Back to Normal Mode", "Actions", None),
KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
],
AppMode::Summary => vec![
KeyBindingInfo::new("↑/↓", "Change Month", "Navigation", None),
KeyBindingInfo::new("←/→ / [/] / PgUp/PgDn", "Change Year", "Navigation", None),
KeyBindingInfo::new(
"m",
"Toggle Multi-Month View",
"View",
Some("Switch between single month view and multi-month view."),
),
KeyBindingInfo::new(
"c",
"Toggle Cumulative View",
"View",
Some("Toggle cumulative (running total) view."),
),
KeyBindingInfo::new("q/Esc", "Back to Transactions", "Actions", None),
KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
],
AppMode::CategorySummary => vec![
KeyBindingInfo::new("↑/↓", "Select Category/Subcategory", "Navigation", None),
KeyBindingInfo::new("←/→ / [/]", "Change Year", "Navigation", None),
KeyBindingInfo::new("PgUp/PgDn", "Jump Selected Month", "Navigation", None),
KeyBindingInfo::new("Enter", "Expand/Collapse Category", "Actions", None),
KeyBindingInfo::new("q/Esc", "Back to Transactions", "Actions", None),
KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
],
AppMode::Budget => vec![
KeyBindingInfo::new("↑/↓", "Select Budget Row", "Navigation", None),
KeyBindingInfo::new("←/→", "Change Month", "Navigation", None),
KeyBindingInfo::new("Shift+←/→", "Change Year", "Navigation", None),
KeyBindingInfo::new(
"c",
"Manage Categories",
"Actions",
Some(
"Open the category catalog to add or edit category target budgets without leaving the budget view. Esc returns here.",
),
),
KeyBindingInfo::new("q/Esc", "Back to Transactions", "Actions", None),
KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
],
AppMode::Settings => vec![
KeyBindingInfo::new("Tab/↑/↓", "Navigate settings", "Navigation", None),
KeyBindingInfo::new(
"Database Path",
"SQLite Database Location",
"Fields",
Some(
"Path to the SQLite database that stores your transactions and category catalog. Point this at a new file to create a fresh database, or an existing file to load different data. Tip: place it in iCloud Drive, Google Drive, or Dropbox to sync across devices.",
),
),
KeyBindingInfo::new(
"Manage Categories",
"Open Category Catalog",
"Fields",
Some("Select this action and press Enter to open the category catalog manager."),
),
KeyBindingInfo::new(
"Import Transactions",
"Import from CSV",
"Fields",
Some(
"Press Enter to open a path prompt and import a CSV. New rows are added and exact duplicates are skipped; recurring occurrences are regenerated automatically.",
),
),
KeyBindingInfo::new(
"Export Transactions",
"Export to CSV",
"Fields",
Some(
"Press Enter to open a path prompt and export all transactions to a CSV file you can back up or share.",
),
),
KeyBindingInfo::new(
"Target Budget",
"Monthly Budget Goal",
"Fields",
Some("Set a target monthly budget amount for reference in summaries."),
),
KeyBindingInfo::new(
"Hourly Rate",
"Hourly Earning Rate",
"Fields",
Some(
"Optional. Enter your hourly rate to enable viewing transaction amounts as equivalent hours worked.",
),
),
KeyBindingInfo::new(
"Show Hours",
"Toggle Hours View",
"Fields",
Some(
"Enable to display transaction amounts in equivalent hours based on your hourly rate.",
),
),
KeyBindingInfo::new(
"Fuzzy Search",
"Toggle Fuzzy Search",
"Fields",
Some(
"Toggle to enable fuzzy searching for categories/subcategories. When enabled, selecting 'Category' opens a search bar to filter both category and subcategory at once.",
),
),
KeyBindingInfo::new(
"Hide Help Bar",
"Toggle Help Bar",
"Fields",
Some(
"Toggle to hide the bottom help bar for a cleaner interface. Ctrl+H will still work. NOT RECOMMENDED unless you know the keybindings well.",
),
),
KeyBindingInfo::new(
"←/→",
"Toggle Options / Move cursor",
"Navigation",
Some(
"On toggle settings changes the value (e.g. Yes/No); on path/number fields moves the text cursor.",
),
),
KeyBindingInfo::new(
"Ctrl+D",
"Reset Database Path",
"Actions",
Some(
"On the Database Path field, resets it to the default location for the current data directory.",
),
),
KeyBindingInfo::new("Ctrl+U", "Clear Field", "Actions", None),
KeyBindingInfo::new(
"Enter",
"Save Settings / Activate Action",
"Actions",
Some(
"On editable fields saves your settings; on action rows (Manage Categories, Import, Export) opens that action.",
),
),
KeyBindingInfo::new("Esc", "Cancel / Back", "Actions", None),
KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
],
AppMode::CategoryCatalog => vec![
KeyBindingInfo::new("↑/↓", "Navigate categories", "Navigation", None),
KeyBindingInfo::new("PgUp/PgDn", "Scroll page up/down", "Navigation", None),
KeyBindingInfo::new("Ctrl+Up/Down", "Jump to First/Last", "Navigation", None),
KeyBindingInfo::new(
"f",
"Filter categories",
"Actions",
Some(
"Opens a filter bar. Type to narrow the catalog by type, category, subcategory, or tag as you type.",
),
),
KeyBindingInfo::new("a", "Add category", "Actions", None),
KeyBindingInfo::new("e/Enter", "Edit selected category", "Actions", None),
KeyBindingInfo::new("d", "Delete selected category", "Actions", None),
KeyBindingInfo::new(
"q/Esc",
"Back to Previous View / Clear Filter",
"Actions",
Some("If a filter is active, clears it. Otherwise, returns to the previous view."),
),
KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
],
AppMode::CategoryCatalogFilter => vec![
KeyBindingInfo::new("Any Char", "Type filter text", "Input", None),
KeyBindingInfo::new("Bksp/Del", "Delete character", "Input", None),
KeyBindingInfo::new("←/→", "Move cursor", "Navigation", None),
KeyBindingInfo::new(
"↑/↓",
"Navigate categories",
"Navigation",
Some("Move through the filtered list without leaving the filter bar."),
),
KeyBindingInfo::new("Ctrl+R", "Clear filter", "Actions", None),
KeyBindingInfo::new("Enter", "Apply filter", "Actions", None),
KeyBindingInfo::new("Esc", "Clear filter", "Actions", None),
KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
],
AppMode::CategoryEditor => vec![
KeyBindingInfo::new("Tab/↑/↓", "Navigate fields", "Navigation", None),
KeyBindingInfo::new("←/→", "Toggle type / move cursor", "Navigation", None),
KeyBindingInfo::new("Enter", "Toggle type or save", "Actions", None),
KeyBindingInfo::new("Esc", "Cancel editor", "Actions", None),
KeyBindingInfo::new(
"Target Budget",
"Expense-only category budget goal",
"Fields",
Some(
"Optional for expense categories only. Income categories do not use per-category target budgets in the budget view.",
),
),
KeyBindingInfo::new(
"Tag",
"Optional label",
"Fields",
Some("Optional. Store an extra short label for the category row."),
),
KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
],
AppMode::ConfirmCategoryDelete => vec![
KeyBindingInfo::new("y", "Confirm delete", "Actions", None),
KeyBindingInfo::new("n/Esc", "Cancel delete", "Actions", None),
KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
],
AppMode::RecurringSettings => vec![
KeyBindingInfo::new("Tab/↑/↓", "Navigate fields", "Navigation", None),
KeyBindingInfo::new(
"Active",
"Enable/Disable",
"Fields",
Some("Toggle if this transaction will be recurring."),
),
KeyBindingInfo::new(
"Frequency",
"Recurrence Interval",
"Fields",
Some(
"Determines the interval for the transaction. Options include 'Daily', 'Weekly', 'Bi-Weekly', 'Semi-Monthly' (15th and last day), 'Semi-Monthly (Weekday Adjusted)' (15th and last day, moved earlier to the nearest weekday when either falls on a weekend), 'Monthly', 'Quarterly', and 'Yearly'. The app will automatically generate these transactions up to the current date when you open it.",
),
),
KeyBindingInfo::new(
"End Date",
"Stop Date",
"Fields",
Some(
"Optional. If set, the recurring transaction will stop being generated after this date. Leave empty for indefinite recurrence.",
),
),
KeyBindingInfo::new(
"←/→",
"Toggle active / Adjust end date",
"Input",
Some(
"On the Active field toggles recurrence on/off; on the End Date field moves the date by one day.",
),
),
KeyBindingInfo::new("Shift+←/→", "Jump month (End Date)", "Input", None),
KeyBindingInfo::new(
"Enter",
"Select frequency / Save",
"Actions",
Some(
"On the Frequency field opens the frequency picker; on any other field saves the recurring settings.",
),
),
KeyBindingInfo::new("Esc", "Cancel", "Actions", None),
KeyBindingInfo::new(
"Tip!",
"Your recurring transaction changes",
"Info",
Some(
"The recurring transactions generate from the initial transaction up to the current date. If a recurring transaction needs to be changed, set an end date and then create a new transaction with the updated details. That can then be set as recurring again to continue.",
),
),
KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
],
AppMode::SelectingCategory
| AppMode::SelectingSubcategory
| AppMode::SelectingFilterCategory
| AppMode::SelectingFilterSubcategory
| AppMode::SelectingRecurrenceFrequency => vec![
KeyBindingInfo::new("↑/↓", "Navigate options", "Navigation", None),
KeyBindingInfo::new("Enter", "Confirm Selection", "Actions", None),
KeyBindingInfo::new("Esc", "Cancel Selection", "Actions", None),
KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
],
AppMode::FuzzyFinding => vec![
KeyBindingInfo::new(
"Any Char",
"Type to search",
"Input",
Some("Type to filter the list of categories and subcategories."),
),
KeyBindingInfo::new("↑/↓", "Navigate results", "Navigation", None),
KeyBindingInfo::new(
"Enter",
"Select Category",
"Actions",
Some("Confirm selection. Auto-fills both Category and Subcategory fields."),
),
KeyBindingInfo::new("Esc", "Cancel", "Actions", None),
KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
],
AppMode::ImportTransactions | AppMode::ExportTransactions => vec![
KeyBindingInfo::new(
"Any Char",
"Type the file path",
"Input",
Some("Type or paste an absolute path to the CSV file."),
),
KeyBindingInfo::new("←/→", "Move cursor", "Navigation", None),
KeyBindingInfo::new("Ctrl+U", "Clear path", "Actions", None),
KeyBindingInfo::new("Ctrl+D", "Reset to default location", "Actions", None),
KeyBindingInfo::new("Enter", "Confirm import/export", "Actions", None),
KeyBindingInfo::new("Esc", "Cancel / back to Settings", "Actions", None),
KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
],
_ => vec![
KeyBindingInfo::new("Ctrl+H", "Close Help", "System", None),
KeyBindingInfo::new("Esc", "Close Help", "System", None),
],
}
}