migrate portfolio tab to new keybindings

This commit is contained in:
Emil Lerch 2026-05-15 11:29:59 -07:00
parent dda56e3c97
commit 9a132f89a5
Signed by: lobo
GPG key ID: A7B62D657EF764F8
3 changed files with 16 additions and 49 deletions

View file

@ -1243,26 +1243,6 @@ pub const App = struct {
return ctx.consumeAndRedraw();
}
// Escape: portfolio tab clears its account filter inline.
// Other tabs fall through to the global keymap (no global
// Esc binding) and then to the tab-local fallback dispatcher
// (e.g. history binds Esc to `compare_cancel`, projections
// binds Esc to `clear_as_of`). When portfolio migrates, its
// Esc handling moves into a tab-local action too.
if (key.codepoint == vaxis.Key.escape) {
if (self.active_tab == .portfolio and self.states.portfolio.account_filter != null) {
self.setAccountFilter(null);
self.states.portfolio.cursor = 0;
self.scroll_offset = 0;
tab_modules.portfolio.rebuildPortfolioRows(&self.states.portfolio, self);
self.setStatus("Filter cleared: showing all accounts");
return ctx.consumeAndRedraw();
}
// 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 {
// No global binding matched. Fall back to tab-local
// dispatch the active tab may bind this key in its
@ -1371,24 +1351,6 @@ pub const App = struct {
self.reloadPortfolioFile();
return ctx.consumeAndRedraw();
},
.sort_col_next => {
if (self.active_tab == .portfolio) {
tab_modules.portfolio.tab.handleAction(&self.states.portfolio, self, tab_modules.portfolio.Action.sort_col_next);
return ctx.consumeAndRedraw();
}
},
.sort_col_prev => {
if (self.active_tab == .portfolio) {
tab_modules.portfolio.tab.handleAction(&self.states.portfolio, self, tab_modules.portfolio.Action.sort_col_prev);
return ctx.consumeAndRedraw();
}
},
.account_filter => {
if (self.active_tab == .portfolio) {
tab_modules.portfolio.tab.handleAction(&self.states.portfolio, self, tab_modules.portfolio.Action.open_account_picker);
return ctx.consumeAndRedraw();
}
},
}
}

View file

@ -27,9 +27,6 @@ pub const Action = enum {
symbol_input,
help,
reload_portfolio,
sort_col_next,
sort_col_prev,
account_filter,
};
pub const KeyCombo = struct {
@ -147,9 +144,6 @@ pub const global_default_bindings = [_]Binding{
.{ .action = .symbol_input, .key = .{ .codepoint = '/' } },
.{ .action = .help, .key = .{ .codepoint = '?' } },
.{ .action = .reload_portfolio, .key = .{ .codepoint = 'R' } },
.{ .action = .sort_col_next, .key = .{ .codepoint = '>' } },
.{ .action = .sort_col_prev, .key = .{ .codepoint = '<' } },
.{ .action = .account_filter, .key = .{ .codepoint = 'a' } },
};
pub fn defaults() KeyMap {

View file

@ -48,6 +48,9 @@ pub const Action = enum {
/// Open the account picker modal (mode = .account_picker).
/// No-op if no portfolio is loaded.
open_account_picker,
/// Clear the active account filter (return to "all accounts").
/// No-op when no filter is active. Bound to Esc.
clear_account_filter,
/// Select the cursor row's symbol as the currently-active
/// symbol for the per-symbol tabs (quote/perf/options/etc.).
select_symbol,
@ -127,14 +130,12 @@ pub const tab = struct {
pub const label: []const u8 = "Portfolio";
pub const default_bindings: []const framework.TabBinding(Action) = &.{
// These are dead until scoped keymaps land the global
// keymap matches first. Declared per-tab so the help
// overlay and future scoped-dispatch can find them.
.{ .action = .expand_collapse, .key = .{ .codepoint = vaxis.Key.enter } },
.{ .action = .sort_col_next, .key = .{ .codepoint = 'S' } },
.{ .action = .sort_col_prev, .key = .{ .codepoint = ';' } },
.{ .action = .sort_col_next, .key = .{ .codepoint = '>' } },
.{ .action = .sort_col_prev, .key = .{ .codepoint = '<' } },
.{ .action = .sort_reverse, .key = .{ .codepoint = 'o' } },
.{ .action = .open_account_picker, .key = .{ .codepoint = 'a' } },
.{ .action = .clear_account_filter, .key = .{ .codepoint = vaxis.Key.escape } },
.{ .action = .select_symbol, .key = .{ .codepoint = 's' } },
.{ .action = .select_symbol, .key = .{ .codepoint = vaxis.Key.space } },
};
@ -145,6 +146,7 @@ pub const tab = struct {
.sort_col_prev = "Sort: previous column",
.sort_reverse = "Sort: reverse direction",
.open_account_picker = "Filter by account",
.clear_account_filter = "Clear account filter",
.select_symbol = "Select symbol",
});
@ -222,6 +224,15 @@ pub const tab = struct {
}
}
},
.clear_account_filter => {
// No-op when no filter is active.
if (state.account_filter == null) return;
app.setAccountFilter(null);
state.cursor = 0;
app.scroll_offset = 0;
rebuildPortfolioRows(state, app);
app.setStatus("Filter cleared: showing all accounts");
},
.select_symbol => {
if (state.rows.items.len == 0) return;
if (state.cursor >= state.rows.items.len) return;