Add output format options for holdings command

pull/61/head
Miguel Mota 4 years ago
parent 832284dc26
commit fd87bb6dda

@ -275,6 +275,12 @@ Just run the `cointop` command to get started:
$ cointop
```
To see all the available commands and options run `help` flag:
```bash
$ cointop --help
```
### Navigation
- Easiest way to navigate up and down is using the arrow keys <kbd></kbd> and <kbd></kbd>, respectively

@ -15,6 +15,7 @@ func HoldingsCmd() *cobra.Command {
var config string
var sortBy string
var sortDesc bool
var format string = "table"
var humanReadable bool
holdingsCmd := &cobra.Command{
@ -37,6 +38,7 @@ func HoldingsCmd() *cobra.Command {
if total {
return ct.PrintTotalHoldings(&cointop.TablePrintOptions{
HumanReadable: humanReadable,
Format: format,
})
}
@ -44,6 +46,7 @@ func HoldingsCmd() *cobra.Command {
SortBy: sortBy,
SortDesc: sortDesc,
HumanReadable: humanReadable,
Format: format,
})
},
}
@ -55,6 +58,7 @@ func HoldingsCmd() *cobra.Command {
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", "f", format, `Ouput format. Options are "table", "csv", "json"`)
return holdingsCmd
}

@ -9,7 +9,7 @@ import (
func TestCmd() *cobra.Command {
testCmd := &cobra.Command{
Use: "test",
Short: "Runs tests",
Short: "Runs tests for Homebrew",
Long: `The test command runs tests for Homebrew`,
Run: func(cmd *cobra.Command, args []string) {
doTest()

@ -1,6 +1,8 @@
package cointop
import (
"encoding/csv"
"encoding/json"
"fmt"
"math"
"os"
@ -320,9 +322,17 @@ type TablePrintOptions struct {
SortBy string
SortDesc bool
HumanReadable bool
Format string
}
// portfolioColumns is list of column keys for portfolio
// outputFormats is list of valid output formats
var outputFormats = map[string]bool{
"table": true,
"csv": true,
"json": true,
}
// portfolioColumns is list of valid column keys for portfolio
var portfolioColumns = map[string]bool{
"name": true,
"symbol": true,
@ -335,34 +345,46 @@ var portfolioColumns = map[string]bool{
// PrintHoldingsTable prints the holdings in an ASCII table
func (ct *Cointop) PrintHoldingsTable(options *TablePrintOptions) error {
ct.debuglog("printHoldingsTable()")
ct.RefreshPortfolioCoins()
if options == nil {
options = &TablePrintOptions{}
}
ct.RefreshPortfolioCoins()
sortBy := options.SortBy
sortDesc := options.SortDesc
format := options.Format
humanReadable := options.HumanReadable
holdings := ct.GetPortfolioSlice()
if options.SortBy != "" {
if _, ok := portfolioColumns[options.SortBy]; !ok {
return fmt.Errorf("The option %q is not a valid column name", options.SortBy)
if format == "" {
format = "table"
}
if sortBy != "" {
if _, ok := portfolioColumns[sortBy]; !ok {
return fmt.Errorf("The option %q is not a valid column name", sortBy)
}
ct.Sort(options.SortBy, options.SortDesc, holdings, true)
ct.Sort(sortBy, sortDesc, holdings, true)
}
if _, ok := outputFormats[format]; !ok {
return fmt.Errorf("The option %q is not a valid format type", format)
}
total := ct.GetPortfolioTotal()
data := make([][]string, len(holdings))
records := make([][]string, len(holdings))
symbol := ct.CurrencySymbol()
for _, entry := range holdings {
for i, entry := range holdings {
percentHoldings := (entry.Balance / total) * 1e2
if math.IsNaN(percentHoldings) {
percentHoldings = 0
}
if options.HumanReadable {
data = append(data, []string{
if humanReadable {
records[i] = []string{
entry.Name,
entry.Symbol,
fmt.Sprintf("%s%s", symbol, humanize.Commaf(entry.Price)),
@ -370,9 +392,9 @@ func (ct *Cointop) PrintHoldingsTable(options *TablePrintOptions) error {
fmt.Sprintf("%s%s", symbol, humanize.Commaf(entry.Balance)),
fmt.Sprintf("%.2f%%", entry.PercentChange24H),
fmt.Sprintf("%.2f%%", percentHoldings),
})
}
} else {
data = append(data, []string{
records[i] = []string{
entry.Name,
entry.Symbol,
strconv.FormatFloat(entry.Price, 'f', -1, 64),
@ -380,14 +402,53 @@ func (ct *Cointop) PrintHoldingsTable(options *TablePrintOptions) error {
strconv.FormatFloat(entry.Balance, 'f', -1, 64),
fmt.Sprintf("%.2f", entry.PercentChange24H),
fmt.Sprintf("%.2f", percentHoldings),
})
}
}
}
alignment := []int{-1, -1, 1, 1, 1, 1, 1}
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
}
for _, record := range records {
if err := csvWriter.Write(record); err != nil {
return err
}
}
csvWriter.Flush()
if err := csvWriter.Error(); err != nil {
return err
}
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
}
list[i] = obj
}
output, err := json.Marshal(list)
if err != nil {
return err
}
fmt.Println(string(output))
return nil
}
alignment := []int{-1, -1, 1, 1, 1, 1, 1}
table := asciitable.NewAsciiTable(&asciitable.Input{
Data: data,
Data: records,
Headers: headers,
Alignment: alignment,
})
@ -404,15 +465,46 @@ func (ct *Cointop) PrintTotalHoldings(options *TablePrintOptions) error {
}
ct.RefreshPortfolioCoins()
humanReadable := options.HumanReadable
total := ct.GetPortfolioTotal()
symbol := ct.CurrencySymbol()
format := options.Format
if options.HumanReadable {
fmt.Fprintf(os.Stdout, "%s%s\n", symbol, humanize.Commaf(total))
} else {
fmt.Fprintf(os.Stdout, "%s\n", strconv.FormatFloat(total, 'f', -1, 64))
value := strconv.FormatFloat(total, 'f', -1, 64)
if humanReadable {
value = fmt.Sprintf("%s%s", symbol, humanize.Commaf(total))
}
if format == "csv" {
csvWriter := csv.NewWriter(os.Stdout)
if err := csvWriter.Write([]string{"total"}); err != nil {
return err
}
if err := csvWriter.Write([]string{value}); err != nil {
return err
}
csvWriter.Flush()
if err := csvWriter.Error(); err != nil {
return err
}
return nil
} else if format == "json" {
obj := map[string]string{"total": value}
output, err := json.Marshal(obj)
if err != nil {
return err
}
fmt.Println(string(output))
return nil
}
fmt.Println(value)
return nil
}

Loading…
Cancel
Save