From b0dd16f813ecc21cad0e00fb9389c91fd48fa30b Mon Sep 17 00:00:00 2001 From: Miguel Mota Date: Sun, 29 Aug 2021 03:22:14 -0700 Subject: [PATCH] Unbind forward slash keybinding when not in table view. #150 #149 --- cointop/active_view.go | 12 ++ cointop/cointop.go | 2 +- cointop/keybindings.go | 350 ++++++++++++++++++++++------------------- pkg/eval/eval.go | 10 +- 4 files changed, 209 insertions(+), 165 deletions(-) diff --git a/cointop/active_view.go b/cointop/active_view.go index 778e19b..eee0727 100644 --- a/cointop/active_view.go +++ b/cointop/active_view.go @@ -10,5 +10,17 @@ func (ct *Cointop) SetActiveView(v string) error { } else if v == ct.Views.Table.Name() { ct.g.SetViewOnTop(ct.Views.Statusbar.Name()) } + + // TODO: better way to map/unmap shortcut key actions based on active view + if v == ct.Views.Table.Name() { + if err := ct.SetKeybindingAction("/", "open_search"); err != nil { + return err + } + } else { + // deletes binding to allow using "/" key on input fields + if err := ct.DeleteKeybinding("/"); err != nil { + return err + } + } return nil } diff --git a/cointop/cointop.go b/cointop/cointop.go index 17a9843..ee97652 100644 --- a/cointop/cointop.go +++ b/cointop/cointop.go @@ -486,7 +486,7 @@ func (ct *Cointop) Run() error { ui.SetMouse(true) ui.SetHighlight(true) ui.SetManagerFunc(ct.layout) - if err := ct.Keybindings(ct.g); err != nil { + if err := ct.SetKeybindings(); err != nil { return fmt.Errorf("keybindings: %v", err) } diff --git a/cointop/keybindings.go b/cointop/keybindings.go index a6c544d..8005338 100644 --- a/cointop/keybindings.go +++ b/cointop/keybindings.go @@ -167,166 +167,174 @@ func (ct *Cointop) ParseKeys(s string) (interface{}, gocui.Modifier) { return key, mod } -// Keybindings sets keyboard shortcut key bindings -func (ct *Cointop) Keybindings(g *gocui.Gui) error { +// SetKeybindingAction maps a shortcut key to an action +func (ct *Cointop) SetKeybindingAction(shortcutKey string, action string) error { + if shortcutKey == "" { + return nil + } + action = strings.TrimSpace(strings.ToLower(action)) + var fn func(g *gocui.Gui, v *gocui.View) error + key, mod := ct.ParseKeys(shortcutKey) + view := "table" + switch action { + case "move_up": + fn = ct.Keyfn(ct.CursorUp) + case "move_down": + fn = ct.Keyfn(ct.CursorDown) + case "previous_page": + fn = ct.handleHkey(key) + case "next_page": + fn = ct.Keyfn(ct.NextPage) + case "page_down": + fn = ct.Keyfn(ct.PageDown) + case "page_up": + fn = ct.Keyfn(ct.PageUp) + case "sort_column_symbol": + fn = ct.Sortfn("symbol", false) + case "move_to_page_first_row": + fn = ct.Keyfn(ct.NavigateFirstLine) + case "move_to_page_last_row": + fn = ct.Keyfn(ct.NavigateLastLine) + case "open_link": + fn = ct.Keyfn(ct.OpenLink) + case "refresh": + fn = ct.Keyfn(ct.Refresh) + case "sort_column_asc": + fn = ct.Keyfn(ct.SortAsc) + case "sort_column_desc": + fn = ct.Keyfn(ct.SortDesc) + case "sort_left_column": + fn = ct.Keyfn(ct.SortPrevCol) + case "sort_right_column": + fn = ct.Keyfn(ct.SortNextCol) + case "help", "toggle_show_help": + fn = ct.Keyfn(ct.ToggleHelp) + view = "" + case "show_help": + fn = ct.Keyfn(ct.ShowHelp) + view = "" + case "hide_help": + fn = ct.Keyfn(ct.HideHelp) + view = "help" + case "first_page": + fn = ct.Keyfn(ct.FirstPage) + case "sort_column_1h_change": + fn = ct.Sortfn("1h_change", true) + case "sort_column_24h_change": + fn = ct.Sortfn("24h_change", true) + case "sort_column_7d_change": + fn = ct.Sortfn("7d_change", true) + case "sort_column_30d_change": + fn = ct.Sortfn("30d_change", true) + case "sort_column_1y_change": + fn = ct.Sortfn("1y_change", true) + case "sort_column_available_supply": + fn = ct.Sortfn("available_supply", true) + case "toggle_row_chart": + fn = ct.Keyfn(ct.ToggleCoinChart) + case "move_to_page_visible_first_row": + fn = ct.Keyfn(ct.NavigatePageFirstLine) + case "move_to_page_visible_last_row": + fn = ct.Keyfn(ct.navigatePageLastLine) + case "sort_column_market_cap": + fn = ct.Sortfn("market_cap", true) + case "move_to_page_visible_middle_row": + fn = ct.Keyfn(ct.NavigatePageMiddleLine) + case "scroll_left": + fn = ct.Keyfn(ct.TableScrollLeft) + case "scroll_right": + fn = ct.Keyfn(ct.TableScrollRight) + case "sort_column_name": + fn = ct.Sortfn("name", false) + case "sort_column_price": + fn = ct.Sortfn("price", true) + case "sort_column_rank": + fn = ct.Sortfn("rank", false) + case "sort_column_total_supply": + fn = ct.Sortfn("total_supply", true) + case "sort_column_last_updated": + fn = ct.Sortfn("last_updated", true) + case "sort_column_24h_volume": + fn = ct.Sortfn("24h_volume", true) + case "sort_column_balance": + fn = ct.Sortfn("balance", true) + case "sort_column_holdings": + fn = ct.Sortfn("holdings", true) + case "sort_column_percent_holdings": + fn = ct.Sortfn("percent_holdings", true) + case "last_page": + fn = ct.Keyfn(ct.LastPage) + case "open_search": + fn = ct.Keyfn(ct.openSearch) + view = "" + case "toggle_price_alerts": + fn = ct.Keyfn(ct.TogglePriceAlerts) + case "toggle_favorite": + fn = ct.Keyfn(ct.ToggleFavorite) + case "toggle_favorites": + fn = ct.Keyfn(ct.ToggleFavorites) + case "toggle_show_favorites": + fn = ct.Keyfn(ct.ToggleShowFavorites) + case "save": + fn = ct.Keyfn(ct.Save) + case "quit": + fn = ct.Keyfn(ct.Quit) + view = "" + case "quit_view": + fn = ct.Keyfn(ct.QuitView) + case "next_chart_range": + fn = ct.Keyfn(ct.NextChartRange) + case "previous_chart_range": + fn = ct.Keyfn(ct.PrevChartRange) + case "first_chart_range": + fn = ct.Keyfn(ct.FirstChartRange) + case "last_chart_range": + fn = ct.Keyfn(ct.LastChartRange) + case "toggle_show_currency_convert_menu": + fn = ct.Keyfn(ct.ToggleConvertMenu) + case "show_currency_convert_menu": + fn = ct.Keyfn(ct.ShowConvertMenu) + case "hide_currency_convert_menu": + fn = ct.Keyfn(ct.HideConvertMenu) + view = "convertmenu" + case "toggle_portfolio": + fn = ct.Keyfn(ct.TogglePortfolio) + case "toggle_show_portfolio": + fn = ct.Keyfn(ct.ToggleShowPortfolio) + case "show_portfolio_edit_menu": + fn = ct.Keyfn(ct.TogglePortfolioUpdateMenu) + case "show_price_alert_edit_menu": + fn = ct.Keyfn(ct.ShowPriceAlertsUpdateMenu) + case "show_price_alert_add_menu": + fn = ct.Keyfn(ct.ShowPriceAlertsAddMenu) + case "toggle_table_fullscreen": + fn = ct.Keyfn(ct.ToggleTableFullscreen) + view = "" + case "toggle_chart_fullscreen": + fn = ct.Keyfn(ct.ToggleChartFullscreen) + view = "" + case "enlarge_chart": + fn = ct.Keyfn(ct.EnlargeChart) + case "shorten_chart": + fn = ct.Keyfn(ct.ShortenChart) + case "move_down_or_next_page": + fn = ct.Keyfn(ct.CursorDownOrNextPage) + case "move_up_or_previous_page": + fn = ct.Keyfn(ct.CursorUpOrPreviousPage) + default: + fn = ct.Keyfn(ct.Noop) + } + + ct.SetKeybindingMod(key, mod, fn, view) + return nil +} + +// SetKeybindings sets keyboard shortcut key bindings +func (ct *Cointop) SetKeybindings() error { for k, v := range ct.State.shortcutKeys { - if k == "" { - continue - } - v = strings.TrimSpace(strings.ToLower(v)) - var fn func(g *gocui.Gui, v *gocui.View) error - key, mod := ct.ParseKeys(k) - view := "table" - switch v { - case "move_up": - fn = ct.Keyfn(ct.CursorUp) - case "move_down": - fn = ct.Keyfn(ct.CursorDown) - case "previous_page": - fn = ct.handleHkey(key) - case "next_page": - fn = ct.Keyfn(ct.NextPage) - case "page_down": - fn = ct.Keyfn(ct.PageDown) - case "page_up": - fn = ct.Keyfn(ct.PageUp) - case "sort_column_symbol": - fn = ct.Sortfn("symbol", false) - case "move_to_page_first_row": - fn = ct.Keyfn(ct.NavigateFirstLine) - case "move_to_page_last_row": - fn = ct.Keyfn(ct.NavigateLastLine) - case "open_link": - fn = ct.Keyfn(ct.OpenLink) - case "refresh": - fn = ct.Keyfn(ct.Refresh) - case "sort_column_asc": - fn = ct.Keyfn(ct.SortAsc) - case "sort_column_desc": - fn = ct.Keyfn(ct.SortDesc) - case "sort_left_column": - fn = ct.Keyfn(ct.SortPrevCol) - case "sort_right_column": - fn = ct.Keyfn(ct.SortNextCol) - case "help", "toggle_show_help": - fn = ct.Keyfn(ct.ToggleHelp) - view = "" - case "show_help": - fn = ct.Keyfn(ct.ShowHelp) - view = "" - case "hide_help": - fn = ct.Keyfn(ct.HideHelp) - view = "help" - case "first_page": - fn = ct.Keyfn(ct.FirstPage) - case "sort_column_1h_change": - fn = ct.Sortfn("1h_change", true) - case "sort_column_24h_change": - fn = ct.Sortfn("24h_change", true) - case "sort_column_7d_change": - fn = ct.Sortfn("7d_change", true) - case "sort_column_30d_change": - fn = ct.Sortfn("30d_change", true) - case "sort_column_1y_change": - fn = ct.Sortfn("1y_change", true) - case "sort_column_available_supply": - fn = ct.Sortfn("available_supply", true) - case "toggle_row_chart": - fn = ct.Keyfn(ct.ToggleCoinChart) - case "move_to_page_visible_first_row": - fn = ct.Keyfn(ct.NavigatePageFirstLine) - case "move_to_page_visible_last_row": - fn = ct.Keyfn(ct.navigatePageLastLine) - case "sort_column_market_cap": - fn = ct.Sortfn("market_cap", true) - case "move_to_page_visible_middle_row": - fn = ct.Keyfn(ct.NavigatePageMiddleLine) - case "scroll_left": - fn = ct.Keyfn(ct.TableScrollLeft) - case "scroll_right": - fn = ct.Keyfn(ct.TableScrollRight) - case "sort_column_name": - fn = ct.Sortfn("name", false) - case "sort_column_price": - fn = ct.Sortfn("price", true) - case "sort_column_rank": - fn = ct.Sortfn("rank", false) - case "sort_column_total_supply": - fn = ct.Sortfn("total_supply", true) - case "sort_column_last_updated": - fn = ct.Sortfn("last_updated", true) - case "sort_column_24h_volume": - fn = ct.Sortfn("24h_volume", true) - case "sort_column_balance": - fn = ct.Sortfn("balance", true) - case "sort_column_holdings": - fn = ct.Sortfn("holdings", true) - case "sort_column_percent_holdings": - fn = ct.Sortfn("percent_holdings", true) - case "last_page": - fn = ct.Keyfn(ct.LastPage) - case "open_search": - fn = ct.Keyfn(ct.openSearch) - view = "" - case "toggle_price_alerts": - fn = ct.Keyfn(ct.TogglePriceAlerts) - case "toggle_favorite": - fn = ct.Keyfn(ct.ToggleFavorite) - case "toggle_favorites": - fn = ct.Keyfn(ct.ToggleFavorites) - case "toggle_show_favorites": - fn = ct.Keyfn(ct.ToggleShowFavorites) - case "save": - fn = ct.Keyfn(ct.Save) - case "quit": - fn = ct.Keyfn(ct.Quit) - view = "" - case "quit_view": - fn = ct.Keyfn(ct.QuitView) - case "next_chart_range": - fn = ct.Keyfn(ct.NextChartRange) - case "previous_chart_range": - fn = ct.Keyfn(ct.PrevChartRange) - case "first_chart_range": - fn = ct.Keyfn(ct.FirstChartRange) - case "last_chart_range": - fn = ct.Keyfn(ct.LastChartRange) - case "toggle_show_currency_convert_menu": - fn = ct.Keyfn(ct.ToggleConvertMenu) - case "show_currency_convert_menu": - fn = ct.Keyfn(ct.ShowConvertMenu) - case "hide_currency_convert_menu": - fn = ct.Keyfn(ct.HideConvertMenu) - view = "convertmenu" - case "toggle_portfolio": - fn = ct.Keyfn(ct.TogglePortfolio) - case "toggle_show_portfolio": - fn = ct.Keyfn(ct.ToggleShowPortfolio) - case "show_portfolio_edit_menu": - fn = ct.Keyfn(ct.TogglePortfolioUpdateMenu) - case "show_price_alert_edit_menu": - fn = ct.Keyfn(ct.ShowPriceAlertsUpdateMenu) - case "show_price_alert_add_menu": - fn = ct.Keyfn(ct.ShowPriceAlertsAddMenu) - case "toggle_table_fullscreen": - fn = ct.Keyfn(ct.ToggleTableFullscreen) - view = "" - case "toggle_chart_fullscreen": - fn = ct.Keyfn(ct.ToggleChartFullscreen) - view = "" - case "enlarge_chart": - fn = ct.Keyfn(ct.EnlargeChart) - case "shorten_chart": - fn = ct.Keyfn(ct.ShortenChart) - case "move_down_or_next_page": - fn = ct.Keyfn(ct.CursorDownOrNextPage) - case "move_up_or_previous_page": - fn = ct.Keyfn(ct.CursorUpOrPreviousPage) - default: - fn = ct.Keyfn(ct.Noop) + if err := ct.SetKeybindingAction(k, v); err != nil { + return err } - - ct.SetKeybindingMod(key, mod, fn, view) } // keys to force quit @@ -352,6 +360,9 @@ func (ct *Cointop) Keybindings(g *gocui.Gui) error { // keys to update portfolio holdings ct.SetKeybindingMod(gocui.KeyEnter, gocui.ModNone, ct.Keyfn(ct.EnterKeyPressHandler), ct.Views.Input.Name()) + key, mod := ct.ParseKeys("/") + ct.DeleteKeybindingMod(key, mod, "") + // mouse events ct.SetKeybindingMod(gocui.MouseRelease, gocui.ModNone, ct.Keyfn(ct.MouseRelease), "") ct.SetKeybindingMod(gocui.MouseLeft, gocui.ModNone, ct.Keyfn(ct.MouseLeftClick), "") @@ -382,10 +393,31 @@ func (ct *Cointop) SetKeybindingMod(key interface{}, mod gocui.Modifier, callbac return err } +// DeleteKeybinding ... +func (ct *Cointop) DeleteKeybinding(shortcutKey string) error { + key, mod := ct.ParseKeys(shortcutKey) + return ct.DeleteKeybindingMod(key, mod, "") +} + +// DeleteKeybindingMod ... +func (ct *Cointop) DeleteKeybindingMod(key interface{}, mod gocui.Modifier, view string) error { + var err error + switch t := key.(type) { + case gocui.Key: + err = ct.g.DeleteKeybinding(view, t, mod) + case rune: + err = ct.g.DeleteKeybinding(view, t, mod) + } + return err +} + // Keyfn returns the keybinding function as a wrapped gocui view function func (ct *Cointop) Keyfn(fn func() error) func(g *gocui.Gui, v *gocui.View) error { return func(g *gocui.Gui, v *gocui.View) error { - return fn() + if fn != nil { + return fn() + } + return nil } } diff --git a/pkg/eval/eval.go b/pkg/eval/eval.go index 3e51108..d7ecf6d 100644 --- a/pkg/eval/eval.go +++ b/pkg/eval/eval.go @@ -7,13 +7,13 @@ import ( "github.com/Knetic/govaluate" ) -// EvaluateExpression ... -func EvaluateExpressionToFloat64(expressionInput string) (float64, error) { - expressionInput = strings.TrimSpace(expressionInput) // remove trailing \0s - if expressionInput == "" { +// EvaluateExpression evaulates a simple math expression string to a float64 +func EvaluateExpressionToFloat64(input string) (float64, error) { + input = strings.TrimSpace(input) // remove trailing \0s + if input == "" { return 0, nil } - expression, err := govaluate.NewEvaluableExpression(expressionInput) + expression, err := govaluate.NewEvaluableExpression(input) if err != nil { return 0, err }