migrate history tab to new keybindings
This commit is contained in:
parent
18d3031456
commit
b9f4c42b42
3 changed files with 71 additions and 187 deletions
80
src/tui.zig
80
src/tui.zig
|
|
@ -1243,19 +1243,12 @@ pub const App = struct {
|
||||||
return ctx.consumeAndRedraw();
|
return ctx.consumeAndRedraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
// History-tab compare intercept.
|
// Escape: portfolio tab clears its account filter; projections
|
||||||
//
|
// tab clears its as-of date. Other tabs fall through to the
|
||||||
// `s` / space / `c` / escape have existing global bindings
|
// global keymap (no global Esc binding) and then to the
|
||||||
// (select_symbol, collapse_all_calls, plus the account-filter
|
// tab-local fallback dispatcher (e.g. history binds Esc to
|
||||||
// escape handler below) that would otherwise handle (or
|
// `compare_cancel`). When portfolio/projections migrate,
|
||||||
// silently consume) these keys. This intercept runs first when
|
// their Esc handling moves into tab-local actions too.
|
||||||
// the user is in the history tab so compare behavior wins.
|
|
||||||
if (self.active_tab == .history) {
|
|
||||||
if (tab_modules.history.handleCompareKey(&self.states.history, self, ctx, key)) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Escape: clear account filter on portfolio tab, clear as-of
|
|
||||||
// on projections tab, no-op otherwise.
|
|
||||||
if (key.codepoint == vaxis.Key.escape) {
|
if (key.codepoint == vaxis.Key.escape) {
|
||||||
if (self.active_tab == .portfolio and self.states.portfolio.account_filter != null) {
|
if (self.active_tab == .portfolio and self.states.portfolio.account_filter != null) {
|
||||||
self.setAccountFilter(null);
|
self.setAccountFilter(null);
|
||||||
|
|
@ -1273,7 +1266,9 @@ pub const App = struct {
|
||||||
self.setStatus("As-of cleared — showing live");
|
self.setStatus("As-of cleared — showing live");
|
||||||
return ctx.consumeAndRedraw();
|
return ctx.consumeAndRedraw();
|
||||||
}
|
}
|
||||||
return;
|
// Fall through — no tab-specific handler. Esc isn't
|
||||||
|
// globally bound, so matchAction returns null and the
|
||||||
|
// tab-local fallback gets a chance.
|
||||||
}
|
}
|
||||||
|
|
||||||
const action = self.keymap.matchAction(key) orelse {
|
const action = self.keymap.matchAction(key) orelse {
|
||||||
|
|
@ -1294,13 +1289,6 @@ pub const App = struct {
|
||||||
self.input_len = 0;
|
self.input_len = 0;
|
||||||
return ctx.consumeAndRedraw();
|
return ctx.consumeAndRedraw();
|
||||||
},
|
},
|
||||||
.select_symbol => {
|
|
||||||
// 's' selects the current portfolio row's symbol as the active symbol
|
|
||||||
if (self.active_tab == .portfolio) {
|
|
||||||
tab_modules.portfolio.tab.handleAction(&self.states.portfolio, self, tab_modules.portfolio.Action.select_symbol);
|
|
||||||
return ctx.consumeAndRedraw();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.refresh => {
|
.refresh => {
|
||||||
self.refreshCurrentTab();
|
self.refreshCurrentTab();
|
||||||
return ctx.consumeAndRedraw();
|
return ctx.consumeAndRedraw();
|
||||||
|
|
@ -1391,12 +1379,6 @@ pub const App = struct {
|
||||||
self.reloadPortfolioFile();
|
self.reloadPortfolioFile();
|
||||||
return ctx.consumeAndRedraw();
|
return ctx.consumeAndRedraw();
|
||||||
},
|
},
|
||||||
.collapse_all_calls => {
|
|
||||||
if (self.active_tab == .options) {
|
|
||||||
tab_modules.options.tab.handleAction(&self.states.options, self, tab_modules.options.Action.collapse_all_calls);
|
|
||||||
return ctx.consumeAndRedraw();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.collapse_all_puts => {
|
.collapse_all_puts => {
|
||||||
if (self.active_tab == .options) {
|
if (self.active_tab == .options) {
|
||||||
tab_modules.options.tab.handleAction(&self.states.options, self, tab_modules.options.Action.collapse_all_puts);
|
tab_modules.options.tab.handleAction(&self.states.options, self, tab_modules.options.Action.collapse_all_puts);
|
||||||
|
|
@ -1414,18 +1396,6 @@ pub const App = struct {
|
||||||
return ctx.consumeAndRedraw();
|
return ctx.consumeAndRedraw();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.history_metric_next => {
|
|
||||||
if (self.active_tab == .history) {
|
|
||||||
tab_modules.history.tab.handleAction(&self.states.history, self, tab_modules.history.Action.metric_next);
|
|
||||||
return ctx.consumeAndRedraw();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.history_resolution_next => {
|
|
||||||
if (self.active_tab == .history) {
|
|
||||||
tab_modules.history.tab.handleAction(&self.states.history, self, tab_modules.history.Action.resolution_next);
|
|
||||||
return ctx.consumeAndRedraw();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.sort_col_next => {
|
.sort_col_next => {
|
||||||
if (self.active_tab == .portfolio) {
|
if (self.active_tab == .portfolio) {
|
||||||
tab_modules.portfolio.tab.handleAction(&self.states.portfolio, self, tab_modules.portfolio.Action.sort_col_next);
|
tab_modules.portfolio.tab.handleAction(&self.states.portfolio, self, tab_modules.portfolio.Action.sort_col_next);
|
||||||
|
|
@ -1484,38 +1454,6 @@ pub const App = struct {
|
||||||
return ctx.consumeAndRedraw();
|
return ctx.consumeAndRedraw();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// History-tab compare actions are normally intercepted in
|
|
||||||
// `handleCompareKey` before `matchAction` runs (because the
|
|
||||||
// default 's'/'c'/space/escape key bindings belong to other
|
|
||||||
// actions). These cases exist so the switch is exhaustive
|
|
||||||
// and so future user-supplied keybindings targeting these
|
|
||||||
// action names work correctly.
|
|
||||||
.compare_select => {
|
|
||||||
if (self.active_tab == .history) {
|
|
||||||
const hs = &self.states.history;
|
|
||||||
if (hs.compare_view == null and hs.table_row_count > 0) {
|
|
||||||
tab_modules.history.toggleSelectionAt(hs, self, hs.cursor);
|
|
||||||
return ctx.consumeAndRedraw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.compare_commit => {
|
|
||||||
if (self.active_tab == .history) {
|
|
||||||
const hs = &self.states.history;
|
|
||||||
if (hs.compare_view != null) {
|
|
||||||
tab_modules.history.clearCompareState(hs, self);
|
|
||||||
} else {
|
|
||||||
tab_modules.history.commitCompareExternal(hs, self);
|
|
||||||
}
|
|
||||||
return ctx.consumeAndRedraw();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.compare_cancel => {
|
|
||||||
if (self.active_tab == .history) {
|
|
||||||
tab_modules.history.clearCompareState(&self.states.history, self);
|
|
||||||
return ctx.consumeAndRedraw();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,11 +28,7 @@
|
||||||
//! `src/history.zig` (snapshot IO). Compare composition is delegated
|
//! `src/history.zig` (snapshot IO). Compare composition is delegated
|
||||||
//! to `src/compare.zig`; compare rendering to `src/views/compare.zig`.
|
//! to `src/compare.zig`; compare rendering to `src/views/compare.zig`.
|
||||||
//!
|
//!
|
||||||
//! Keybinds:
|
//! Keybinds: see the `Action` enum + `default_bindings` below.
|
||||||
//! - `m` cycles chart metric (`history_metric_next`)
|
|
||||||
//! - `t` cycles resolution (`history_resolution_next`)
|
|
||||||
//! - `s` / space / `c` / Esc — compare (intercepted in `tui.zig`
|
|
||||||
//! before matchAction, see `handleCompareKey` below)
|
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const vaxis = @import("vaxis");
|
const vaxis = @import("vaxis");
|
||||||
|
|
@ -60,13 +56,20 @@ const StyledLine = tui.StyledLine;
|
||||||
// (only meaningful for non-daily, non-live
|
// (only meaningful for non-daily, non-live
|
||||||
// rows with finer-tier breakdown).
|
// rows with finer-tier breakdown).
|
||||||
//
|
//
|
||||||
// `s` / space / `c` / Esc are ALSO history-local (compare-mode
|
// History tab keybinds:
|
||||||
// selection toggle, commit, and cancel) but are still routed via
|
// - `m` : cycle the focused metric (liquid →
|
||||||
// the legacy global `keybinds.Action.compare_*` variants and the
|
// illiquid → net_worth).
|
||||||
// pre-dispatch `handleCompareKey` intercept in tui.zig. Those are
|
// - `t` : cycle the resolution (cascading →
|
||||||
// the next layer of the migration (scoped keymaps, TODO step 3) —
|
// daily → weekly → monthly → cascading).
|
||||||
// once scoped keymaps land, both the global variants and the
|
// - Enter : expand/collapse the bucket at the cursor
|
||||||
// intercept disappear and these become per-tab actions.
|
// (only meaningful for non-daily, non-live
|
||||||
|
// rows with finer-tier breakdown).
|
||||||
|
// - `s` / space : toggle inclusion of the cursor row in
|
||||||
|
// the compare-selection set (0, 1, or 2).
|
||||||
|
// - `c` : commit compare (requires 2 rows
|
||||||
|
// selected) or exit an active compare view.
|
||||||
|
// - Esc : cancel compare view or clear pending
|
||||||
|
// selections.
|
||||||
|
|
||||||
pub const Action = enum {
|
pub const Action = enum {
|
||||||
/// Toggle expansion of the bucket at the cursor. No-op for
|
/// Toggle expansion of the bucket at the cursor. No-op for
|
||||||
|
|
@ -76,6 +79,15 @@ pub const Action = enum {
|
||||||
metric_next,
|
metric_next,
|
||||||
/// Cycle the resolution: cascading → daily → weekly → monthly → cascading.
|
/// Cycle the resolution: cascading → daily → weekly → monthly → cascading.
|
||||||
resolution_next,
|
resolution_next,
|
||||||
|
/// Toggle inclusion of the cursor row in the compare selection set.
|
||||||
|
/// Disabled while a compare view is up. Bound to `s` and space.
|
||||||
|
compare_select,
|
||||||
|
/// Run compare if exactly 2 rows are selected (otherwise status
|
||||||
|
/// hint), or exit an active compare view. Bound to `c`.
|
||||||
|
compare_commit,
|
||||||
|
/// Cancel compare: drop active compare view if up, else clear
|
||||||
|
/// pending selections. No-op when nothing is active. Bound to Esc.
|
||||||
|
compare_cancel,
|
||||||
};
|
};
|
||||||
|
|
||||||
// ── Tab-private state ─────────────────────────────────────────
|
// ── Tab-private state ─────────────────────────────────────────
|
||||||
|
|
@ -156,12 +168,19 @@ pub const tab = struct {
|
||||||
.{ .action = .expand_collapse, .key = .{ .codepoint = vaxis.Key.enter } },
|
.{ .action = .expand_collapse, .key = .{ .codepoint = vaxis.Key.enter } },
|
||||||
.{ .action = .metric_next, .key = .{ .codepoint = 'm' } },
|
.{ .action = .metric_next, .key = .{ .codepoint = 'm' } },
|
||||||
.{ .action = .resolution_next, .key = .{ .codepoint = 't' } },
|
.{ .action = .resolution_next, .key = .{ .codepoint = 't' } },
|
||||||
|
.{ .action = .compare_select, .key = .{ .codepoint = 's' } },
|
||||||
|
.{ .action = .compare_select, .key = .{ .codepoint = vaxis.Key.space } },
|
||||||
|
.{ .action = .compare_commit, .key = .{ .codepoint = 'c' } },
|
||||||
|
.{ .action = .compare_cancel, .key = .{ .codepoint = vaxis.Key.escape } },
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const action_labels = std.enums.EnumArray(Action, []const u8).init(.{
|
pub const action_labels = std.enums.EnumArray(Action, []const u8).init(.{
|
||||||
.expand_collapse = "Expand/collapse bucket",
|
.expand_collapse = "Expand/collapse bucket",
|
||||||
.metric_next = "Cycle metric",
|
.metric_next = "Cycle metric",
|
||||||
.resolution_next = "Cycle resolution",
|
.resolution_next = "Cycle resolution",
|
||||||
|
.compare_select = "Toggle compare selection",
|
||||||
|
.compare_commit = "Compare selected rows",
|
||||||
|
.compare_cancel = "Cancel compare",
|
||||||
});
|
});
|
||||||
|
|
||||||
pub const status_hints: []const Action = &.{
|
pub const status_hints: []const Action = &.{
|
||||||
|
|
@ -201,6 +220,37 @@ pub const tab = struct {
|
||||||
.expand_collapse => _ = toggleTierAtCursor(state, app),
|
.expand_collapse => _ = toggleTierAtCursor(state, app),
|
||||||
.metric_next => cycleMetric(state),
|
.metric_next => cycleMetric(state),
|
||||||
.resolution_next => cycleResolution(state),
|
.resolution_next => cycleResolution(state),
|
||||||
|
.compare_select => {
|
||||||
|
// Disabled while a compare view is up — Esc to return first.
|
||||||
|
if (state.compare_view != null) return;
|
||||||
|
if (state.table_row_count == 0) return;
|
||||||
|
toggleSelection(state, app, state.cursor);
|
||||||
|
},
|
||||||
|
.compare_commit => {
|
||||||
|
// If a compare view is up, treat `c` as toggle-off
|
||||||
|
// (mirrors Esc semantics on this tab).
|
||||||
|
if (state.compare_view != null) {
|
||||||
|
clearCompareView(state, app);
|
||||||
|
clearSelections(state);
|
||||||
|
app.setStatus("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
commitCompare(state, app);
|
||||||
|
},
|
||||||
|
.compare_cancel => {
|
||||||
|
// Esc semantics: drop active compare view if up,
|
||||||
|
// else clear pending selections, else no-op.
|
||||||
|
if (state.compare_view != null) {
|
||||||
|
clearCompareView(state, app);
|
||||||
|
clearSelections(state);
|
||||||
|
app.setStatus("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (selectionCount(state) > 0) {
|
||||||
|
clearSelections(state);
|
||||||
|
app.setStatus("");
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -447,26 +497,6 @@ fn setSelectionStatus(state: *const State, app: *App) void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Public entry for the `compare_select` action dispatched via
|
|
||||||
/// matchAction. Internally delegates to the same toggle function the
|
|
||||||
/// intercept uses.
|
|
||||||
pub fn toggleSelectionAt(state: *State, app: *App, idx: usize) void {
|
|
||||||
toggleSelection(state, app, idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Public entry for the `compare_commit` action.
|
|
||||||
pub fn commitCompareExternal(state: *State, app: *App) void {
|
|
||||||
commitCompare(state, app);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Public entry for the `compare_cancel` action or internal Esc path:
|
|
||||||
/// clear selections and any active compare view.
|
|
||||||
pub fn clearCompareState(state: *State, app: *App) void {
|
|
||||||
clearCompareView(state, app);
|
|
||||||
clearSelections(state);
|
|
||||||
app.setStatus("");
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Compare commit ───────────────────────────────────────────
|
// ── Compare commit ───────────────────────────────────────────
|
||||||
|
|
||||||
/// Attempt to run compare. Called when the user presses `c`.
|
/// Attempt to run compare. Called when the user presses `c`.
|
||||||
|
|
@ -663,63 +693,6 @@ fn aggregateFromSummary(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Compare key handler (intercepted from tui.zig) ───────────
|
|
||||||
|
|
||||||
/// Intercepted before `matchAction` runs when the active tab is
|
|
||||||
/// history. Returns true if the key was consumed.
|
|
||||||
///
|
|
||||||
/// TODO(scoped-keymaps): once scoped keymaps land (TODO step 3),
|
|
||||||
/// this intercept goes away — `s`/space/`c`/Esc become
|
|
||||||
/// per-tab keybinds bound to local Action variants in
|
|
||||||
/// `default_bindings`, and the global keymap stops binding them.
|
|
||||||
/// The pre-dispatch interception in `tui.zig` (the call to
|
|
||||||
/// `handleCompareKey`) gets deleted alongside.
|
|
||||||
pub fn handleCompareKey(state: *State, app: *App, ctx: *vaxis.vxfw.EventContext, key: vaxis.Key) bool {
|
|
||||||
// Escape: exit compare view, or clear selections.
|
|
||||||
if (key.codepoint == vaxis.Key.escape) {
|
|
||||||
if (state.compare_view != null) {
|
|
||||||
clearCompareView(state, app);
|
|
||||||
clearSelections(state);
|
|
||||||
app.setStatus("");
|
|
||||||
ctx.consumeAndRedraw();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (selectionCount(state) > 0) {
|
|
||||||
clearSelections(state);
|
|
||||||
app.setStatus("");
|
|
||||||
ctx.consumeAndRedraw();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 's' or space: toggle selection on the cursor row.
|
|
||||||
if (key.matches('s', .{}) or key.matches(vaxis.Key.space, .{})) {
|
|
||||||
// Disabled while the compare view is up — Esc to return first.
|
|
||||||
if (state.compare_view != null) return false;
|
|
||||||
if (state.table_row_count == 0) return false;
|
|
||||||
toggleSelection(state, app, state.cursor);
|
|
||||||
ctx.consumeAndRedraw();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 'c': commit compare, or exit compare view if already active.
|
|
||||||
if (key.matches('c', .{})) {
|
|
||||||
if (state.compare_view != null) {
|
|
||||||
clearCompareView(state, app);
|
|
||||||
clearSelections(state);
|
|
||||||
app.setStatus("");
|
|
||||||
ctx.consumeAndRedraw();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
commitCompare(state, app);
|
|
||||||
ctx.consumeAndRedraw();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Table row model ──────────────────────────────────────────
|
// ── Table row model ──────────────────────────────────────────
|
||||||
|
|
||||||
/// One row in the rendered recent-snapshots table.
|
/// One row in the rendered recent-snapshots table.
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,9 @@ pub const Action = enum {
|
||||||
select_next,
|
select_next,
|
||||||
select_prev,
|
select_prev,
|
||||||
expand_collapse,
|
expand_collapse,
|
||||||
select_symbol,
|
|
||||||
symbol_input,
|
symbol_input,
|
||||||
help,
|
help,
|
||||||
reload_portfolio,
|
reload_portfolio,
|
||||||
collapse_all_calls,
|
|
||||||
collapse_all_puts,
|
collapse_all_puts,
|
||||||
options_filter_1,
|
options_filter_1,
|
||||||
options_filter_2,
|
options_filter_2,
|
||||||
|
|
@ -39,17 +37,6 @@ pub const Action = enum {
|
||||||
options_filter_7,
|
options_filter_7,
|
||||||
options_filter_8,
|
options_filter_8,
|
||||||
options_filter_9,
|
options_filter_9,
|
||||||
history_metric_next,
|
|
||||||
history_resolution_next,
|
|
||||||
/// History tab: toggle inclusion of the row under the cursor in the
|
|
||||||
/// compare-selection set (0, 1, or 2 rows). Defaults: 's' and space.
|
|
||||||
compare_select,
|
|
||||||
/// History tab: run compare if exactly 2 rows are selected; otherwise
|
|
||||||
/// status-bar hint. Default: 'c'.
|
|
||||||
compare_commit,
|
|
||||||
/// History tab: clear the current compare view (return to timeline)
|
|
||||||
/// or clear pending selections. Default: escape.
|
|
||||||
compare_cancel,
|
|
||||||
sort_col_next,
|
sort_col_next,
|
||||||
sort_col_prev,
|
sort_col_prev,
|
||||||
sort_reverse,
|
sort_reverse,
|
||||||
|
|
@ -179,12 +166,9 @@ pub const global_default_bindings = [_]Binding{
|
||||||
.{ .action = .select_prev, .key = .{ .codepoint = 'k' } },
|
.{ .action = .select_prev, .key = .{ .codepoint = 'k' } },
|
||||||
.{ .action = .select_prev, .key = .{ .codepoint = vaxis.Key.up } },
|
.{ .action = .select_prev, .key = .{ .codepoint = vaxis.Key.up } },
|
||||||
.{ .action = .expand_collapse, .key = .{ .codepoint = vaxis.Key.enter } },
|
.{ .action = .expand_collapse, .key = .{ .codepoint = vaxis.Key.enter } },
|
||||||
.{ .action = .select_symbol, .key = .{ .codepoint = 's' } },
|
|
||||||
.{ .action = .select_symbol, .key = .{ .codepoint = vaxis.Key.space } },
|
|
||||||
.{ .action = .symbol_input, .key = .{ .codepoint = '/' } },
|
.{ .action = .symbol_input, .key = .{ .codepoint = '/' } },
|
||||||
.{ .action = .help, .key = .{ .codepoint = '?' } },
|
.{ .action = .help, .key = .{ .codepoint = '?' } },
|
||||||
.{ .action = .reload_portfolio, .key = .{ .codepoint = 'R' } },
|
.{ .action = .reload_portfolio, .key = .{ .codepoint = 'R' } },
|
||||||
.{ .action = .collapse_all_calls, .key = .{ .codepoint = 'c' } },
|
|
||||||
.{ .action = .collapse_all_puts, .key = .{ .codepoint = 'p' } },
|
.{ .action = .collapse_all_puts, .key = .{ .codepoint = 'p' } },
|
||||||
.{ .action = .options_filter_1, .key = .{ .codepoint = '1', .mods = .{ .ctrl = true } } },
|
.{ .action = .options_filter_1, .key = .{ .codepoint = '1', .mods = .{ .ctrl = true } } },
|
||||||
.{ .action = .options_filter_2, .key = .{ .codepoint = '2', .mods = .{ .ctrl = true } } },
|
.{ .action = .options_filter_2, .key = .{ .codepoint = '2', .mods = .{ .ctrl = true } } },
|
||||||
|
|
@ -195,17 +179,6 @@ pub const global_default_bindings = [_]Binding{
|
||||||
.{ .action = .options_filter_7, .key = .{ .codepoint = '7', .mods = .{ .ctrl = true } } },
|
.{ .action = .options_filter_7, .key = .{ .codepoint = '7', .mods = .{ .ctrl = true } } },
|
||||||
.{ .action = .options_filter_8, .key = .{ .codepoint = '8', .mods = .{ .ctrl = true } } },
|
.{ .action = .options_filter_8, .key = .{ .codepoint = '8', .mods = .{ .ctrl = true } } },
|
||||||
.{ .action = .options_filter_9, .key = .{ .codepoint = '9', .mods = .{ .ctrl = true } } },
|
.{ .action = .options_filter_9, .key = .{ .codepoint = '9', .mods = .{ .ctrl = true } } },
|
||||||
.{ .action = .history_metric_next, .key = .{ .codepoint = 'm' } },
|
|
||||||
.{ .action = .history_resolution_next, .key = .{ .codepoint = 't' } },
|
|
||||||
// Compare bindings live AFTER the existing `s`/`c`/space bindings
|
|
||||||
// so `matchAction` (first-match-wins) returns the original action
|
|
||||||
// in non-history tabs. The history-tab intercept in `tui.zig`
|
|
||||||
// routes these keys directly to `handleCompareKey` before
|
|
||||||
// `matchAction` is consulted.
|
|
||||||
.{ .action = .compare_select, .key = .{ .codepoint = 's' } },
|
|
||||||
.{ .action = .compare_select, .key = .{ .codepoint = vaxis.Key.space } },
|
|
||||||
.{ .action = .compare_commit, .key = .{ .codepoint = 'c' } },
|
|
||||||
.{ .action = .compare_cancel, .key = .{ .codepoint = vaxis.Key.escape } },
|
|
||||||
.{ .action = .sort_col_next, .key = .{ .codepoint = '>' } },
|
.{ .action = .sort_col_next, .key = .{ .codepoint = '>' } },
|
||||||
.{ .action = .sort_col_prev, .key = .{ .codepoint = '<' } },
|
.{ .action = .sort_col_prev, .key = .{ .codepoint = '<' } },
|
||||||
.{ .action = .sort_reverse, .key = .{ .codepoint = 'o' } },
|
.{ .action = .sort_reverse, .key = .{ .codepoint = 'o' } },
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue