mirror of
https://github.com/miguelmota/cointop
synced 2024-11-05 00:00:14 +00:00
Add column filter option to holdings command
This commit is contained in:
parent
6e3b9d41f1
commit
3c97b58e09
@ -12,12 +12,14 @@ func HoldingsCmd() *cobra.Command {
|
||||
var help bool
|
||||
var total bool
|
||||
var noCache bool
|
||||
var noHeader bool
|
||||
var config string
|
||||
var sortBy string
|
||||
var sortDesc bool
|
||||
var format string = "table"
|
||||
var humanReadable bool
|
||||
var filter []string
|
||||
var cols []string
|
||||
var convert string
|
||||
|
||||
holdingsCmd := &cobra.Command{
|
||||
@ -52,7 +54,9 @@ func HoldingsCmd() *cobra.Command {
|
||||
HumanReadable: humanReadable,
|
||||
Format: format,
|
||||
Filter: filter,
|
||||
Cols: cols,
|
||||
Convert: convert,
|
||||
NoHeader: noHeader,
|
||||
})
|
||||
},
|
||||
}
|
||||
@ -61,11 +65,13 @@ func HoldingsCmd() *cobra.Command {
|
||||
holdingsCmd.Flags().BoolVarP(&total, "total", "t", total, "Show total only")
|
||||
holdingsCmd.Flags().BoolVarP(&noCache, "no-cache", "", noCache, "No cache")
|
||||
holdingsCmd.Flags().BoolVarP(&humanReadable, "human", "h", humanReadable, "Human readable output")
|
||||
holdingsCmd.Flags().BoolVarP(&noHeader, "no-header", "", noHeader, "Don't display header columns")
|
||||
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().BoolVarP(&sortDesc, "sort-desc", "d", sortDesc, "Sort in descending order")
|
||||
holdingsCmd.Flags().StringVarP(&format, "format", "", format, `Ouput format. Options are "table", "csv", "json"`)
|
||||
holdingsCmd.Flags().StringSliceVarP(&filter, "filter", "", filter, `Filter portfolio entries by coin name or symbol, comma separated. Example: "btc,eth,doge"`)
|
||||
holdingsCmd.Flags().StringSliceVarP(&filter, "filter", "", filter, `Filter portfolio entries by coin name or symbol, comma separated without spaces. Example: "btc,eth,doge"`)
|
||||
holdingsCmd.Flags().StringSliceVarP(&cols, "cols", "", cols, `Filter portfolio columns, comma separated without spaces. Example: "symbol,holdings,balance"`)
|
||||
holdingsCmd.Flags().StringVarP(&convert, "convert", "f", convert, "The currency to convert to")
|
||||
|
||||
return holdingsCmd
|
||||
|
@ -591,7 +591,9 @@ type TablePrintOptions struct {
|
||||
HumanReadable bool
|
||||
Format string
|
||||
Filter []string
|
||||
Cols []string
|
||||
Convert string
|
||||
NoHeader bool
|
||||
}
|
||||
|
||||
// outputFormats is list of valid output formats
|
||||
@ -628,8 +630,10 @@ func (ct *Cointop) PrintHoldingsTable(options *TablePrintOptions) error {
|
||||
sortDesc := options.SortDesc
|
||||
format := options.Format
|
||||
humanReadable := options.HumanReadable
|
||||
filter := options.Filter
|
||||
filterCoins := options.Filter
|
||||
filterCols := options.Cols
|
||||
holdings := ct.GetPortfolioSlice()
|
||||
noHeader := options.NoHeader
|
||||
|
||||
if format == "" {
|
||||
format = "table"
|
||||
@ -651,10 +655,41 @@ func (ct *Cointop) PrintHoldingsTable(options *TablePrintOptions) error {
|
||||
records := make([][]string, len(holdings))
|
||||
symbol := ct.CurrencySymbol()
|
||||
|
||||
headers := []string{"name", "symbol", "price", "holdings", "balance", "24h%", "%holdings"}
|
||||
if len(filterCols) > 0 {
|
||||
for _, col := range filterCols {
|
||||
valid := false
|
||||
for _, h := range headers {
|
||||
if col == h {
|
||||
valid = true
|
||||
break
|
||||
}
|
||||
}
|
||||
switch col {
|
||||
case "amount":
|
||||
return fmt.Errorf("did you mean %q?", "balance")
|
||||
case "24H":
|
||||
fallthrough
|
||||
case "24H%":
|
||||
fallthrough
|
||||
case "24h":
|
||||
fallthrough
|
||||
case "24h_change":
|
||||
return fmt.Errorf("did you mean %q?", "24h%")
|
||||
case "percent_holdings":
|
||||
return fmt.Errorf("did you mean %q?", "%holdings")
|
||||
}
|
||||
if !valid {
|
||||
return fmt.Errorf("unsupported column value %q", col)
|
||||
}
|
||||
}
|
||||
headers = filterCols
|
||||
}
|
||||
|
||||
for i, entry := range holdings {
|
||||
if len(filter) > 0 {
|
||||
if len(filterCoins) > 0 {
|
||||
found := false
|
||||
for _, item := range filter {
|
||||
for _, item := range filterCoins {
|
||||
item = strings.ToLower(strings.TrimSpace(item))
|
||||
if strings.ToLower(entry.Symbol) == item || strings.ToLower(entry.Name) == item {
|
||||
found = true
|
||||
@ -671,35 +706,54 @@ func (ct *Cointop) PrintHoldingsTable(options *TablePrintOptions) error {
|
||||
percentHoldings = 0
|
||||
}
|
||||
|
||||
if humanReadable {
|
||||
records[i] = []string{
|
||||
entry.Name,
|
||||
entry.Symbol,
|
||||
fmt.Sprintf("%s%s", symbol, humanize.Commaf(entry.Price)),
|
||||
humanize.Commaf(entry.Holdings),
|
||||
fmt.Sprintf("%s%s", symbol, humanize.Commaf(entry.Balance)),
|
||||
fmt.Sprintf("%.2f%%", entry.PercentChange24H),
|
||||
fmt.Sprintf("%.2f%%", percentHoldings),
|
||||
}
|
||||
} else {
|
||||
records[i] = []string{
|
||||
entry.Name,
|
||||
entry.Symbol,
|
||||
strconv.FormatFloat(entry.Price, 'f', -1, 64),
|
||||
strconv.FormatFloat(entry.Holdings, 'f', -1, 64),
|
||||
strconv.FormatFloat(entry.Balance, 'f', -1, 64),
|
||||
fmt.Sprintf("%.2f", entry.PercentChange24H),
|
||||
fmt.Sprintf("%.2f", percentHoldings),
|
||||
item := make([]string, len(headers))
|
||||
for i, header := range headers {
|
||||
switch header {
|
||||
case "name":
|
||||
item[i] = entry.Name
|
||||
case "symbol":
|
||||
item[i] = entry.Symbol
|
||||
case "price":
|
||||
if humanReadable {
|
||||
item[i] = fmt.Sprintf("%s%s", symbol, humanize.Commaf(entry.Price))
|
||||
} else {
|
||||
item[i] = strconv.FormatFloat(entry.Price, 'f', -1, 64)
|
||||
}
|
||||
case "holdings":
|
||||
if humanReadable {
|
||||
item[i] = humanize.Commaf(entry.Holdings)
|
||||
} else {
|
||||
item[i] = strconv.FormatFloat(entry.Holdings, 'f', -1, 64)
|
||||
}
|
||||
case "balance":
|
||||
if humanReadable {
|
||||
item[i] = fmt.Sprintf("%s%s", symbol, humanize.Commaf(entry.Balance))
|
||||
} else {
|
||||
item[i] = strconv.FormatFloat(entry.Balance, 'f', -1, 64)
|
||||
}
|
||||
case "24h%":
|
||||
if humanReadable {
|
||||
item[i] = fmt.Sprintf("%.2f%%", entry.PercentChange24H)
|
||||
} else {
|
||||
item[i] = fmt.Sprintf("%.2f", entry.PercentChange24H)
|
||||
}
|
||||
case "%holdings":
|
||||
if humanReadable {
|
||||
item[i] = fmt.Sprintf("%.2f%%", percentHoldings)
|
||||
} else {
|
||||
item[i] = fmt.Sprintf("%.2f", percentHoldings)
|
||||
}
|
||||
}
|
||||
}
|
||||
records[i] = item
|
||||
}
|
||||
|
||||
headers := []string{"name", "symbol", "price", "holdings", "balance", "24h%", "%holdings"}
|
||||
|
||||
if format == "csv" {
|
||||
csvWriter := csv.NewWriter(os.Stdout)
|
||||
if err := csvWriter.Write(headers); err != nil {
|
||||
return err
|
||||
if !noHeader {
|
||||
if err := csvWriter.Write(headers); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, record := range records {
|
||||
@ -715,19 +769,28 @@ func (ct *Cointop) PrintHoldingsTable(options *TablePrintOptions) error {
|
||||
|
||||
return nil
|
||||
} else if format == "json" {
|
||||
list := make([]map[string]string, len(records))
|
||||
for i, record := range records {
|
||||
obj := make(map[string]string, len(record))
|
||||
for j, column := range record {
|
||||
obj[headers[j]] = column
|
||||
var output []byte
|
||||
var err error
|
||||
if noHeader {
|
||||
output, err = json.Marshal(records)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
list := make([]map[string]string, len(records))
|
||||
for i, record := range records {
|
||||
obj := make(map[string]string, len(record))
|
||||
for j, column := range record {
|
||||
obj[headers[j]] = column
|
||||
}
|
||||
|
||||
list[i] = obj
|
||||
}
|
||||
|
||||
list[i] = obj
|
||||
}
|
||||
|
||||
output, err := json.Marshal(list)
|
||||
if err != nil {
|
||||
return err
|
||||
output, err = json.Marshal(list)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println(string(output))
|
||||
@ -735,9 +798,13 @@ func (ct *Cointop) PrintHoldingsTable(options *TablePrintOptions) error {
|
||||
}
|
||||
|
||||
alignment := []int{-1, -1, 1, 1, 1, 1, 1}
|
||||
var tableHeaders []string
|
||||
if !noHeader {
|
||||
tableHeaders = headers
|
||||
}
|
||||
table := asciitable.NewAsciiTable(&asciitable.Input{
|
||||
Data: records,
|
||||
Headers: headers,
|
||||
Headers: tableHeaders,
|
||||
Alignment: alignment,
|
||||
})
|
||||
|
||||
|
@ -87,6 +87,19 @@ Ethereum ETH 394.48 100 39448 -0.18
|
||||
|
||||
```bash
|
||||
$ cointop holdings --cols symbol,holdings,balance
|
||||
symbol holdings balance
|
||||
BTC 10 118331.6
|
||||
ETH 100 39490
|
||||
DOGE 500000 1779.3
|
||||
```
|
||||
|
||||
### Output without headers
|
||||
|
||||
```bash
|
||||
$ cointop holdings --no-header
|
||||
Bitcoin BTC $11,833.16 10 $118,331.6 -1.02% 74.14%
|
||||
Ethereum ETH $394.9 100 $39,490 0.02% 24.74%
|
||||
Dogecoin DOGE $0.00355861 500,000 $1,779.3 1.46% 1.11%
|
||||
```
|
||||
|
||||
### Convert to a different fiat currency
|
||||
@ -97,6 +110,13 @@ $ cointop holdings -h --convert eur
|
||||
Ethereum ETH €278.49 100 €27,849 -15.87% 100.00%
|
||||
```
|
||||
|
||||
### Total portfolio value
|
||||
|
||||
```bash
|
||||
$ cointop holdings --total
|
||||
3671.32
|
||||
```
|
||||
|
||||
### Combining flags
|
||||
|
||||
```bash
|
||||
|
Loading…
Reference in New Issue
Block a user