Add keybinding to toggle hide portfolio balances

pull/164/head v1.6.7
Miguel Mota 3 years ago
parent 5f76e89a0b
commit 1d29363185
No known key found for this signature in database
GPG Key ID: 67EC1161588A00F9

@ -22,6 +22,7 @@ func HoldingsCmd() *cobra.Command {
var filter []string var filter []string
var cols []string var cols []string
var convert string var convert string
var hideBalances bool
holdingsCmd := &cobra.Command{ holdingsCmd := &cobra.Command{
Use: "holdings", Use: "holdings",
@ -68,6 +69,7 @@ func HoldingsCmd() *cobra.Command {
Cols: cols, Cols: cols,
Convert: convert, Convert: convert,
NoHeader: noHeader, NoHeader: noHeader,
HideBalances: hideBalances,
}) })
}, },
} }
@ -78,6 +80,7 @@ func HoldingsCmd() *cobra.Command {
holdingsCmd.Flags().BoolVarP(&noCache, "no-cache", "", noCache, "No cache") holdingsCmd.Flags().BoolVarP(&noCache, "no-cache", "", noCache, "No cache")
holdingsCmd.Flags().BoolVarP(&humanReadable, "human", "h", humanReadable, "Human readable output") holdingsCmd.Flags().BoolVarP(&humanReadable, "human", "h", humanReadable, "Human readable output")
holdingsCmd.Flags().BoolVarP(&noHeader, "no-header", "", noHeader, "Don't display header columns") holdingsCmd.Flags().BoolVarP(&noHeader, "no-header", "", noHeader, "Don't display header columns")
holdingsCmd.Flags().BoolVarP(&hideBalances, "hide-balances", "", hideBalances, "Hide portfolio balances. Useful for when sharing screen or taking screenshotss")
holdingsCmd.Flags().StringVarP(&config, "config", "c", "", fmt.Sprintf("Config filepath. (default %s)", cointop.DefaultConfigFilepath)) holdingsCmd.Flags().StringVarP(&config, "config", "c", "", fmt.Sprintf("Config filepath. (default %s)", cointop.DefaultConfigFilepath))
holdingsCmd.Flags().StringVarP(&sortBy, "sort-by", "s", sortBy, `Sort by column. Options are "name", "symbol", "price", "holdings", "balance", "24h"`) holdingsCmd.Flags().StringVarP(&sortBy, "sort-by", "s", sortBy, `Sort by column. Options are "name", "symbol", "price", "holdings", "balance", "24h"`)
holdingsCmd.Flags().BoolVarP(&sortDesc, "sort-desc", "d", sortDesc, "Sort in descending order") holdingsCmd.Flags().BoolVarP(&sortDesc, "sort-desc", "d", sortDesc, "Sort in descending order")

@ -20,6 +20,7 @@ func RootCmd() *cobra.Command {
hideChart := getEnvBool("COINTOP_HIDE_CHART") hideChart := getEnvBool("COINTOP_HIDE_CHART")
hideTable := getEnvBool("COINTOP_HIDE_TABLE") hideTable := getEnvBool("COINTOP_HIDE_TABLE")
hideStatusbar := getEnvBool("COINTOP_HIDE_STATUSBAR") hideStatusbar := getEnvBool("COINTOP_HIDE_STATUSBAR")
hidePortfolioBalances := getEnvBool("COINTOP_HIDE_PORTFOLIO_BALANCES")
onlyTable := getEnvBool("COINTOP_ONLY_TABLE") onlyTable := getEnvBool("COINTOP_ONLY_TABLE")
onlyChart := getEnvBool("COINTOP_ONLY_CHART") onlyChart := getEnvBool("COINTOP_ONLY_CHART")
silent := getEnvBool("COINTOP_SILENT") silent := getEnvBool("COINTOP_SILENT")
@ -90,22 +91,23 @@ See git.io/cointop for more info.`,
} }
ct, err := cointop.NewCointop(&cointop.Config{ ct, err := cointop.NewCointop(&cointop.Config{
CacheDir: cacheDir, CacheDir: cacheDir,
ColorsDir: colorsDir, ColorsDir: colorsDir,
NoCache: noCache, NoCache: noCache,
ConfigFilepath: config, ConfigFilepath: config,
CoinMarketCapAPIKey: cmcAPIKey, CoinMarketCapAPIKey: cmcAPIKey,
APIChoice: apiChoice, APIChoice: apiChoice,
Colorscheme: colorscheme, Colorscheme: colorscheme,
HideMarketbar: hideMarketbar, HideMarketbar: hideMarketbar,
HideChart: hideChart, HideChart: hideChart,
HideTable: hideTable, HideTable: hideTable,
HideStatusbar: hideStatusbar, HideStatusbar: hideStatusbar,
OnlyTable: onlyTable, OnlyTable: onlyTable,
OnlyChart: onlyChart, OnlyChart: onlyChart,
RefreshRate: refreshRateP, RefreshRate: refreshRateP,
PerPage: perPage, PerPage: perPage,
MaxPages: maxPages, MaxPages: maxPages,
HidePortfolioBalances: hidePortfolioBalances,
}) })
if err != nil { if err != nil {
return err return err
@ -123,6 +125,7 @@ See git.io/cointop for more info.`,
rootCmd.Flags().BoolVarP(&hideChart, "hide-chart", "", hideChart, "Hide the chart view") rootCmd.Flags().BoolVarP(&hideChart, "hide-chart", "", hideChart, "Hide the chart view")
rootCmd.Flags().BoolVarP(&hideTable, "hide-table", "", hideTable, "Hide the table view") rootCmd.Flags().BoolVarP(&hideTable, "hide-table", "", hideTable, "Hide the table view")
rootCmd.Flags().BoolVarP(&hideStatusbar, "hide-statusbar", "", hideStatusbar, "Hide the bottom statusbar") rootCmd.Flags().BoolVarP(&hideStatusbar, "hide-statusbar", "", hideStatusbar, "Hide the bottom statusbar")
rootCmd.Flags().BoolVarP(&hidePortfolioBalances, "hide-portfolio-balances", "", hidePortfolioBalances, "Hide portfolio balances. Useful for when sharing screen or taking screenshots")
rootCmd.Flags().BoolVarP(&onlyTable, "only-table", "", onlyTable, "Show only the table. Hides the chart and top and bottom bars") rootCmd.Flags().BoolVarP(&onlyTable, "only-table", "", onlyTable, "Show only the table. Hides the chart and top and bottom bars")
rootCmd.Flags().BoolVarP(&onlyChart, "only-chart", "", onlyChart, "Show only the chart. Hides the table and top and bottom bars") rootCmd.Flags().BoolVarP(&onlyChart, "only-chart", "", onlyChart, "Show only the chart. Hides the table and top and bottom bars")
rootCmd.Flags().BoolVarP(&silent, "silent", "s", silent, "Silence log ouput") rootCmd.Flags().BoolVarP(&silent, "silent", "s", silent, "Silence log ouput")

@ -57,6 +57,7 @@ type State struct {
hideChart bool hideChart bool
hideTable bool hideTable bool
hideStatusbar bool hideStatusbar bool
hidePortfolioBalances bool
keepRowFocusOnSort bool keepRowFocusOnSort bool
lastSelectedRowIndex int lastSelectedRowIndex int
marketBarHeight int marketBarHeight int
@ -147,23 +148,24 @@ type PriceAlerts struct {
// Config config options // Config config options
type Config struct { type Config struct {
APIChoice string APIChoice string
CacheDir string CacheDir string
ColorsDir string ColorsDir string
Colorscheme string Colorscheme string
ConfigFilepath string ConfigFilepath string
CoinMarketCapAPIKey string CoinMarketCapAPIKey string
NoPrompts bool NoPrompts bool
HideMarketbar bool HideMarketbar bool
HideChart bool HideChart bool
HideTable bool HideTable bool
HideStatusbar bool HideStatusbar bool
NoCache bool HidePortfolioBalances bool
OnlyTable bool NoCache bool
OnlyChart bool OnlyTable bool
RefreshRate *uint OnlyChart bool
PerPage uint RefreshRate *uint
MaxPages uint PerPage uint
MaxPages uint
} }
// APIKeys is api keys structure // APIKeys is api keys structure
@ -251,6 +253,7 @@ func NewCointop(config *Config) (*Cointop, error) {
hideChart: config.HideChart, hideChart: config.HideChart,
hideTable: config.HideTable, hideTable: config.HideTable,
hideStatusbar: config.HideStatusbar, hideStatusbar: config.HideStatusbar,
hidePortfolioBalances: config.HidePortfolioBalances,
keepRowFocusOnSort: false, keepRowFocusOnSort: false,
marketBarHeight: 1, marketBarHeight: 1,
maxPages: int(maxPages), maxPages: int(maxPages),

@ -3,86 +3,87 @@ package cointop
// DefaultShortcuts is a map of the default shortcuts // DefaultShortcuts is a map of the default shortcuts
func DefaultShortcuts() map[string]string { func DefaultShortcuts() map[string]string {
return map[string]string{ return map[string]string{
"up": "move_up", "up": "move_up",
"down": "move_down", "down": "move_down",
"left": "previous_page", "left": "previous_page",
"right": "next_page", "right": "next_page",
"pagedown": "page_down", "pagedown": "page_down",
"pageup": "page_up", "pageup": "page_up",
"home": "move_to_page_first_row", "home": "move_to_page_first_row",
"end": "move_to_page_last_row", "end": "move_to_page_last_row",
"enter": "toggle_row_chart", "enter": "toggle_row_chart",
"esc": "quit_view", "esc": "quit_view",
"space": "toggle_favorite", "space": "toggle_favorite",
"tab": "move_down_or_next_page", "tab": "move_down_or_next_page",
"ctrl+c": "quit", "ctrl+c": "quit",
"ctrl+C": "quit", "ctrl+C": "quit",
"ctrl+d": "page_down", "ctrl+d": "page_down",
"ctrl+f": "open_search", "ctrl+f": "open_search",
"ctrl+n": "next_page", "ctrl+n": "next_page",
"ctrl+p": "previous_page", "ctrl+p": "previous_page",
"ctrl+r": "refresh", "ctrl+r": "refresh",
"ctrl+R": "refresh", "ctrl+R": "refresh",
"ctrl+s": "save", "ctrl+s": "save",
"ctrl+S": "save", "ctrl+S": "save",
"ctrl+u": "page_up", "ctrl+u": "page_up",
"ctrl+j": "enlarge_chart", "ctrl+j": "enlarge_chart",
"ctrl+k": "shorten_chart", "ctrl+k": "shorten_chart",
"|": "toggle_chart_fullscreen", "ctrl+space": "toggle_portfolio_balances",
"alt+up": "sort_column_asc", "|": "toggle_chart_fullscreen",
"alt+down": "sort_column_desc", "alt+up": "sort_column_asc",
"alt+left": "sort_left_column", "alt+down": "sort_column_desc",
"alt+right": "sort_right_column", "alt+left": "sort_left_column",
"F1": "help", "alt+right": "sort_right_column",
"F5": "refresh", "F1": "help",
"0": "first_page", "F5": "refresh",
"1": "sort_column_1h_change", "0": "first_page",
"2": "sort_column_24h_change", "1": "sort_column_1h_change",
"3": "sort_column_30d_change", "2": "sort_column_24h_change",
"7": "sort_column_7d_change", "3": "sort_column_30d_change",
"a": "sort_column_available_supply", "7": "sort_column_7d_change",
"b": "sort_column_balance", "a": "sort_column_available_supply",
"c": "show_currency_convert_menu", "b": "sort_column_balance",
"C": "show_currency_convert_menu", "c": "show_currency_convert_menu",
"e": "show_portfolio_edit_menu", "C": "show_currency_convert_menu",
"E": "show_portfolio_edit_menu", "e": "show_portfolio_edit_menu",
"A": "toggle_price_alerts", "E": "show_portfolio_edit_menu",
"f": "toggle_favorite", "A": "toggle_price_alerts",
"F": "toggle_show_favorites", "f": "toggle_favorite",
"g": "move_to_page_first_row", "F": "toggle_show_favorites",
"G": "move_to_page_last_row", "g": "move_to_page_first_row",
"h": "previous_page", "G": "move_to_page_last_row",
"H": "move_to_page_visible_first_row", "h": "previous_page",
"j": "move_down", "H": "move_to_page_visible_first_row",
"k": "move_up", "j": "move_down",
"l": "next_page", "k": "move_up",
"L": "move_to_page_visible_last_row", "l": "next_page",
"m": "sort_column_market_cap", "L": "move_to_page_visible_last_row",
"M": "move_to_page_visible_middle_row", "m": "sort_column_market_cap",
"n": "sort_column_name", "M": "move_to_page_visible_middle_row",
"o": "open_link", "n": "sort_column_name",
"O": "open_link", "o": "open_link",
"p": "sort_column_price", "O": "open_link",
"P": "toggle_portfolio", "p": "sort_column_price",
"r": "sort_column_rank", "P": "toggle_portfolio",
"s": "sort_column_symbol", "r": "sort_column_rank",
"t": "sort_column_total_supply", "s": "sort_column_symbol",
"u": "sort_column_last_updated", "t": "sort_column_total_supply",
"v": "sort_column_24h_volume", "u": "sort_column_last_updated",
"y": "sort_column_1y_change", "v": "sort_column_24h_volume",
"q": "quit_view", "y": "sort_column_1y_change",
"Q": "quit_view", "q": "quit_view",
"%": "sort_column_percent_holdings", "Q": "quit_view",
"$": "last_page", "%": "sort_column_percent_holdings",
"?": "help", "$": "last_page",
"/": "open_search", "?": "help",
"]": "next_chart_range", "/": "open_search",
"[": "previous_chart_range", "]": "next_chart_range",
"}": "last_chart_range", "[": "previous_chart_range",
"{": "first_chart_range", "}": "last_chart_range",
">": "scroll_right", "{": "first_chart_range",
"<": "scroll_left", ">": "scroll_right",
"+": "show_price_alert_add_menu", "<": "scroll_left",
"\\\\": "toggle_table_fullscreen", "+": "show_price_alert_add_menu",
"\\\\": "toggle_table_fullscreen",
} }
} }

@ -301,6 +301,8 @@ func (ct *Cointop) SetKeybindingAction(shortcutKey string, action string) error
fn = ct.Keyfn(ct.TogglePortfolio) fn = ct.Keyfn(ct.TogglePortfolio)
case "toggle_show_portfolio": case "toggle_show_portfolio":
fn = ct.Keyfn(ct.ToggleShowPortfolio) fn = ct.Keyfn(ct.ToggleShowPortfolio)
case "toggle_portfolio_balances":
fn = ct.Keyfn(ct.TogglePortfolioBalances)
case "show_portfolio_edit_menu": case "show_portfolio_edit_menu":
fn = ct.Keyfn(ct.TogglePortfolioUpdateMenu) fn = ct.Keyfn(ct.TogglePortfolioUpdateMenu)
case "show_price_alert_edit_menu": case "show_price_alert_edit_menu":

@ -42,6 +42,10 @@ func (ct *Cointop) UpdateMarketbar() error {
totalstr = humanize.Monetaryf(total, 2) totalstr = humanize.Monetaryf(total, 2)
} }
if ct.State.hidePortfolioBalances {
totalstr = HiddenBalanceChars
}
timeframe := ct.State.selectedChartRange timeframe := ct.State.selectedChartRange
chartname := ct.SelectedCoinName() chartname := ct.SelectedCoinName()
var charttitle string var charttitle string

@ -52,6 +52,9 @@ var DefaultPortfolioTableHeaders = []string{
"last_updated", "last_updated",
} }
// HiddenBalanceChars are the characters to show when hidding balances
var HiddenBalanceChars = "********"
// ValidPortfolioTableHeader returns the portfolio table headers // ValidPortfolioTableHeader returns the portfolio table headers
func (ct *Cointop) ValidPortfolioTableHeader(name string) bool { func (ct *Cointop) ValidPortfolioTableHeader(name string) bool {
for _, v := range SupportedPortfolioTableHeaders { for _, v := range SupportedPortfolioTableHeaders {
@ -154,6 +157,9 @@ func (ct *Cointop) GetPortfolioTable() *table.Table {
}) })
case "balance": case "balance":
text := humanize.Monetaryf(coin.Balance, 2) text := humanize.Monetaryf(coin.Balance, 2)
if ct.State.hidePortfolioBalances {
text = HiddenBalanceChars
}
ct.SetTableColumnWidthFromString(header, text) ct.SetTableColumnWidthFromString(header, text)
ct.SetTableColumnAlignLeft(header, false) ct.SetTableColumnAlignLeft(header, false)
colorBalance := ct.colorscheme.TableColumnPrice colorBalance := ct.colorscheme.TableColumnPrice
@ -634,6 +640,7 @@ type TablePrintOptions struct {
Convert string Convert string
NoHeader bool NoHeader bool
PercentChange24H bool PercentChange24H bool
HideBalances bool
} }
// outputFormats is list of valid output formats // outputFormats is list of valid output formats
@ -674,6 +681,7 @@ func (ct *Cointop) PrintHoldingsTable(options *TablePrintOptions) error {
filterCols := options.Cols filterCols := options.Cols
holdings := ct.GetPortfolioSlice() holdings := ct.GetPortfolioSlice()
noHeader := options.NoHeader noHeader := options.NoHeader
hideBalances := options.HideBalances
if format == "" { if format == "" {
format = "table" format = "table"
@ -771,6 +779,9 @@ func (ct *Cointop) PrintHoldingsTable(options *TablePrintOptions) error {
} else { } else {
item[i] = strconv.FormatFloat(entry.Balance, 'f', -1, 64) item[i] = strconv.FormatFloat(entry.Balance, 'f', -1, 64)
} }
if hideBalances {
item[i] = HiddenBalanceChars
}
case "24h%": case "24h%":
if humanReadable { if humanReadable {
item[i] = fmt.Sprintf("%s%%", humanize.Numericf(entry.PercentChange24H, 2)) item[i] = fmt.Sprintf("%s%%", humanize.Numericf(entry.PercentChange24H, 2))
@ -1034,3 +1045,14 @@ func (ct *Cointop) IsPortfolioVisible() bool {
func (ct *Cointop) PortfolioLen() int { func (ct *Cointop) PortfolioLen() int {
return len(ct.GetPortfolioSlice()) return len(ct.GetPortfolioSlice())
} }
// TogglePortfolioBalances toggles hide/show portfolio balances. Useful for keeping balances secret when sharing screen or taking screenshots.
func (ct *Cointop) TogglePortfolioBalances() error {
ct.State.hidePortfolioBalances = !ct.State.hidePortfolioBalances
ct.UpdateUI(func() error {
go ct.UpdateChart()
go ct.UpdateTable()
return nil
})
return nil
}

@ -183,6 +183,10 @@ draft: false
Your portfolio is autosaved after you edit holdings. You can also press <kbd>ctrl</kbd>+<kbd>s</kbd> to manually save your portfolio holdings to the config file. Your portfolio is autosaved after you edit holdings. You can also press <kbd>ctrl</kbd>+<kbd>s</kbd> to manually save your portfolio holdings to the config file.
## How do I hide my portfolio balances (private mode)?
You can run cointop with the `--hide-portfolio-balances` flag to toggle hide/show portfolio balances or use the keyboard shortcut <kbd>Ctrl</kbd>+<kbd>space</kbd> on the portfolio page.
## I'm getting question marks or weird symbols instead of the correct characters. ## I'm getting question marks or weird symbols instead of the correct characters.
Make sure that your terminal has the encoding set to UTF-8 and that your terminal font supports UTF-8. Make sure that your terminal has the encoding set to UTF-8 and that your terminal font supports UTF-8.

Loading…
Cancel
Save