2
0
mirror of https://github.com/miguelmota/cointop synced 2024-11-05 00:00:14 +00:00

Merge branch 'afh-numeric-monetary-locale'

This commit is contained in:
Miguel Mota 2021-04-20 21:54:47 -07:00
commit 17fd13f150
No known key found for this signature in database
GPG Key ID: 67EC1161588A00F9
8 changed files with 78 additions and 74 deletions

View File

@ -120,7 +120,7 @@ func (ct *Cointop) GetCoinsTable() *table.Table {
Text: symbol,
})
case "price":
text := humanize.Commaf(coin.Price)
text := humanize.Monetaryf(coin.Price, 2)
ct.SetTableColumnWidthFromString(header, text)
ct.SetTableColumnAlignLeft(header, false)
rowCells = append(rowCells,
@ -132,7 +132,7 @@ func (ct *Cointop) GetCoinsTable() *table.Table {
Text: text,
})
case "24h_volume":
text := humanize.Commaf(coin.Volume24H)
text := humanize.Monetaryf(coin.Volume24H, 0)
ct.SetTableColumnWidthFromString(header, text)
ct.SetTableColumnAlignLeft(header, false)
rowCells = append(rowCells,
@ -151,7 +151,7 @@ func (ct *Cointop) GetCoinsTable() *table.Table {
if coin.PercentChange1H < 0 {
color1h = ct.colorscheme.TableColumnChangeDown
}
text := fmt.Sprintf("%.2f%%", coin.PercentChange1H)
text := fmt.Sprintf("%v%%", humanize.Numericf(coin.PercentChange1H, 2))
ct.SetTableColumnWidthFromString(header, text)
ct.SetTableColumnAlignLeft(header, false)
rowCells = append(rowCells,
@ -170,7 +170,7 @@ func (ct *Cointop) GetCoinsTable() *table.Table {
if coin.PercentChange24H < 0 {
color24h = ct.colorscheme.TableColumnChangeDown
}
text := fmt.Sprintf("%.2f%%", coin.PercentChange24H)
text := fmt.Sprintf("%v%%", humanize.Numericf(coin.PercentChange24H, 2))
ct.SetTableColumnWidthFromString(header, text)
ct.SetTableColumnAlignLeft(header, false)
rowCells = append(rowCells,
@ -189,7 +189,7 @@ func (ct *Cointop) GetCoinsTable() *table.Table {
if coin.PercentChange7D < 0 {
color7d = ct.colorscheme.TableColumnChangeDown
}
text := fmt.Sprintf("%.2f%%", coin.PercentChange7D)
text := fmt.Sprintf("%v%%", humanize.Numericf(coin.PercentChange7D, 2))
ct.SetTableColumnWidthFromString(header, text)
ct.SetTableColumnAlignLeft(header, false)
rowCells = append(rowCells,
@ -208,7 +208,7 @@ func (ct *Cointop) GetCoinsTable() *table.Table {
if coin.PercentChange30D < 0 {
color30d = ct.colorscheme.TableColumnChangeDown
}
text := fmt.Sprintf("%.2f%%", coin.PercentChange30D)
text := fmt.Sprintf("%v%%", humanize.Numericf(coin.PercentChange30D, 2))
ct.SetTableColumnWidthFromString(header, text)
ct.SetTableColumnAlignLeft(header, false)
rowCells = append(rowCells,
@ -220,7 +220,7 @@ func (ct *Cointop) GetCoinsTable() *table.Table {
Text: text,
})
case "market_cap":
text := humanize.Commaf(coin.MarketCap)
text := humanize.Monetaryf(coin.MarketCap, 0)
ct.SetTableColumnWidthFromString(header, text)
ct.SetTableColumnAlignLeft(header, false)
rowCells = append(rowCells,
@ -232,7 +232,7 @@ func (ct *Cointop) GetCoinsTable() *table.Table {
Text: text,
})
case "total_supply":
text := humanize.Commaf(coin.TotalSupply)
text := humanize.Numericf(coin.TotalSupply, 0)
ct.SetTableColumnWidthFromString(header, text)
ct.SetTableColumnAlignLeft(header, false)
rowCells = append(rowCells,
@ -244,7 +244,7 @@ func (ct *Cointop) GetCoinsTable() *table.Table {
Text: text,
})
case "available_supply":
text := humanize.Commaf(coin.AvailableSupply)
text := humanize.Numericf(coin.AvailableSupply, 0)
ct.SetTableColumnWidthFromString(header, text)
ct.SetTableColumnAlignLeft(header, false)
rowCells = append(rowCells,

View File

@ -35,10 +35,10 @@ func (ct *Cointop) UpdateMarketbar() error {
if ct.IsPortfolioVisible() {
ct.State.marketBarHeight = 1
total := ct.GetPortfolioTotal()
totalstr := humanize.Commaf(total)
totalstr := humanize.Monetaryf(total, 2)
if !(ct.State.currencyConversion == "BTC" || ct.State.currencyConversion == "ETH" || total < 1) {
total = math.Round(total*1e2) / 1e2
totalstr = humanize.Commaf2(total)
totalstr = humanize.Monetaryf(total, 2)
}
timeframe := ct.State.selectedChartRange
@ -149,9 +149,9 @@ func (ct *Cointop) UpdateMarketbar() error {
content = fmt.Sprintf(
"%sGlobal ▶ Market Cap: %s %s 24H Volume: %s %s BTC Dominance: %.2f%%",
chartInfo,
fmt.Sprintf("%s%s", ct.CurrencySymbol(), humanize.Commaf0(market.TotalMarketCapUSD)),
fmt.Sprintf("%s%s", ct.CurrencySymbol(), humanize.Monetaryf(market.TotalMarketCapUSD, 0)),
separator1,
fmt.Sprintf("%s%s", ct.CurrencySymbol(), humanize.Commaf0(market.Total24HVolumeUSD)),
fmt.Sprintf("%s%s", ct.CurrencySymbol(), humanize.Monetaryf(market.Total24HVolumeUSD, 0)),
separator2,
market.BitcoinPercentageOfMarketCap,
)

View File

@ -125,7 +125,7 @@ func (ct *Cointop) GetPortfolioTable() *table.Table {
Text: symbol,
})
case "price":
text := humanize.Commaf(coin.Price)
text := humanize.Monetaryf(coin.Price, 2)
symbolPadding := 1
ct.SetTableColumnWidth(header, utf8.RuneCountInString(text)+symbolPadding)
ct.SetTableColumnAlignLeft(header, false)
@ -150,7 +150,7 @@ func (ct *Cointop) GetPortfolioTable() *table.Table {
Text: text,
})
case "balance":
text := humanize.Commaf(coin.Balance)
text := humanize.Monetaryf(coin.Balance, 2)
ct.SetTableColumnWidthFromString(header, text)
ct.SetTableColumnAlignLeft(header, false)
colorBalance := ct.colorscheme.TableColumnPrice
@ -715,31 +715,31 @@ func (ct *Cointop) PrintHoldingsTable(options *TablePrintOptions) error {
item[i] = entry.Symbol
case "price":
if humanReadable {
item[i] = fmt.Sprintf("%s%s", symbol, humanize.Commaf(entry.Price))
item[i] = fmt.Sprintf("%s%s", symbol, humanize.Monetaryf(entry.Price, 2))
} else {
item[i] = strconv.FormatFloat(entry.Price, 'f', -1, 64)
}
case "holdings":
if humanReadable {
item[i] = humanize.Commaf(entry.Holdings)
item[i] = humanize.Monetaryf(entry.Holdings, 2)
} 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))
item[i] = fmt.Sprintf("%s%s", symbol, humanize.Monetaryf(entry.Balance, 2))
} else {
item[i] = strconv.FormatFloat(entry.Balance, 'f', -1, 64)
}
case "24h%":
if humanReadable {
item[i] = fmt.Sprintf("%.2f%%", entry.PercentChange24H)
item[i] = fmt.Sprintf("%s%%", humanize.Numericf(entry.PercentChange24H, 2))
} else {
item[i] = fmt.Sprintf("%.2f", entry.PercentChange24H)
}
case "%holdings":
if humanReadable {
item[i] = fmt.Sprintf("%.2f%%", percentHoldings)
item[i] = fmt.Sprintf("%s%%", humanize.Numericf(percentHoldings, 2))
} else {
item[i] = fmt.Sprintf("%.2f", percentHoldings)
}
@ -852,7 +852,7 @@ func (ct *Cointop) PrintTotalHoldings(options *TablePrintOptions) error {
value := strconv.FormatFloat(total, 'f', -1, 64)
if humanReadable {
value = fmt.Sprintf("%s%s", symbol, humanize.Commaf(total))
value = fmt.Sprintf("%s%s", symbol, humanize.Monetaryf(total, 2))
}
if format == "csv" {

View File

@ -69,7 +69,7 @@ func GetCoinPrices(config *PricesConfig) ([]string, error) {
}
symbol := CurrencySymbol(config.Currency)
value := fmt.Sprintf("%s%s", symbol, humanize.Commaf(price))
value := fmt.Sprintf("%s%s", symbol, humanize.Monetaryf(price, 2))
prices = append(prices, value)
}

View File

@ -96,7 +96,7 @@ func (ct *Cointop) GetPriceAlertsTable() *table.Table {
})
case "target_price":
targetPrice := fmt.Sprintf("%s %s", entry.Operator, humanize.Commaf(entry.TargetPrice))
targetPrice := fmt.Sprintf("%s %s", entry.Operator, humanize.Monetaryf(entry.TargetPrice, 2))
ct.SetTableColumnWidthFromString(header, targetPrice)
ct.SetTableColumnAlignLeft(header, false)
rowCells = append(rowCells, &table.RowCell{
@ -107,7 +107,7 @@ func (ct *Cointop) GetPriceAlertsTable() *table.Table {
Text: targetPrice,
})
case "price":
text := humanize.Commaf(coin.Price)
text := humanize.Monetaryf(coin.Price, 2)
ct.SetTableColumnWidthFromString(header, text)
ct.SetTableColumnAlignLeft(header, false)
rowCells = append(rowCells, &table.RowCell{
@ -187,7 +187,7 @@ func (ct *Cointop) CheckPriceAlert(alert *PriceAlert) error {
}
var msg string
title := "Cointop Alert"
priceStr := fmt.Sprintf("%s%s (%s%s)", ct.CurrencySymbol(), humanize.Commaf(alert.TargetPrice), ct.CurrencySymbol(), humanize.Commaf(coin.Price))
priceStr := fmt.Sprintf("%s%s (%s%s)", ct.CurrencySymbol(), humanize.Numericf(alert.TargetPrice, 2), ct.CurrencySymbol(), humanize.Monetaryf(coin.Price, 2))
if alert.Operator == ">" {
if coin.Price > alert.TargetPrice {
msg = fmt.Sprintf("%s price is greater than %v", alert.CoinName, priceStr)

View File

@ -1,7 +1,8 @@
package humanize
import (
"bytes"
"fmt"
"os"
"strconv"
"strings"
@ -9,47 +10,44 @@ import (
"golang.org/x/text/message"
)
// Commaf produces a string form of the given number in base 10 with
// commas after every three orders of magnitude.
// Numericf produces a string from of the given number with give fixed precision
// in base 10 with thousands separators after every three orders of magnitude
// using a thousands and decimal spearator according to LC_NUMERIC; defaulting "en".
//
// e.g. Commaf(834142.32) -> 834,142.32
func Commaf(v float64) string {
buf := &bytes.Buffer{}
if v < 0 {
buf.Write([]byte{'-'})
v = 0 - v
}
comma := []byte{','}
parts := strings.Split(strconv.FormatFloat(v, 'f', -1, 64), ".")
pos := 0
if len(parts[0])%3 != 0 {
pos += len(parts[0]) % 3
buf.WriteString(parts[0][:pos])
buf.Write(comma)
}
for ; pos < len(parts[0]); pos += 3 {
buf.WriteString(parts[0][pos : pos+3])
buf.Write(comma)
}
buf.Truncate(buf.Len() - 1)
if len(parts) > 1 {
buf.Write([]byte{'.'})
buf.WriteString(parts[1])
}
return buf.String()
// e.g. Numericf(834142.32, 2) -> "834,142.32"
func Numericf(value float64, precision int) string {
return f(value, precision, "LC_NUMERIC", true)
}
// Commaf2 ...
func Commaf2(v float64) string {
p := message.NewPrinter(language.English)
return p.Sprintf("%.2f", v)
// Monetaryf produces a string from of the given number give minimum precision
// in base 10 with thousands separators after every three orders of magnitude
// using thousands and decimal spearator according to LC_MONETARY; defaulting "en".
//
// e.g. Monetaryf(834142.3256, 2) -> "834,142.3256"
func Monetaryf(value float64, precision int) string {
return f(value, precision, "LC_MONETARY", false)
}
// Commaf0 ...
func Commaf0(v float64) string {
p := message.NewPrinter(language.English)
return p.Sprintf("%.0f", v)
// f formats given value v, with d decimal places using thousands and decimal
// separator according to language found in given locale environment variable e.
// If r is true the decimal places are fixed to the given d otherwise d is the
// minimum of decimal places until the first 0.
func f(value float64, precision int, envvar string, fixed bool) string {
parts := strings.Split(strconv.FormatFloat(value, 'f', -1, 64), ".")
if !fixed && len(parts) > 1 {
for ; precision < len(parts[1]); precision += 1 {
if parts[1][precision] == '0' {
break
}
}
}
envlang, ok := os.LookupEnv(envvar)
if !ok {
envlang = "en"
}
lang := language.Make(envlang)
format := fmt.Sprintf("%%.%df", precision)
return message.NewPrinter(lang).Sprintf(format, value)
}

View File

@ -3,35 +3,39 @@ package align
import (
"fmt"
"strings"
"unicode/utf8"
)
// AlignLeft align left
func AlignLeft(s string, n int) string {
if len(s) > n {
slen := utf8.RuneCountInString(s)
if slen > n {
return s[:n]
}
return fmt.Sprintf("%s%s", s, strings.Repeat(" ", n-len(s)))
return fmt.Sprintf("%s%s", s, strings.Repeat(" ", n-slen))
}
// AlignRight align right
func AlignRight(s string, n int) string {
if len(s) > n {
slen := utf8.RuneCountInString(s)
if slen > n {
return s[:n]
}
return fmt.Sprintf("%s%s", strings.Repeat(" ", n-len(s)), s)
return fmt.Sprintf("%s%s", strings.Repeat(" ", n-slen), s)
}
// AlignCenter align center
func AlignCenter(s string, n int) string {
if len(s) > n {
slen := utf8.RuneCountInString(s)
if slen > n {
return s[:n]
}
pad := (n - len(s)) / 2
pad := (n - slen) / 2
lpad := pad
rpad := n - len(s) - lpad
rpad := n - slen - lpad
return fmt.Sprintf("%s%s%s", strings.Repeat(" ", lpad), s, strings.Repeat(" ", rpad))
}

View File

@ -5,6 +5,7 @@ import (
"io"
"sort"
"strings"
"unicode/utf8"
"github.com/miguelmota/cointop/pkg/pad"
"github.com/miguelmota/cointop/pkg/table/align"
@ -129,7 +130,7 @@ func (t *Table) normalizeColWidthPerc() {
// Format format table
func (t *Table) Format() *Table {
for _, c := range t.cols {
c.width = len(c.name) + 1
c.width = utf8.RuneCountInString(c.name) + 1
if c.minWidth > c.width {
c.width = c.minWidth
}
@ -151,8 +152,9 @@ func (t *Table) Format() *Table {
r.strValues[j] = fmt.Sprintf("%v", v)
}
if len(r.strValues[j]) > t.cols[j].width {
t.cols[j].width = len(r.strValues[j])
runeCount := utf8.RuneCountInString(r.strValues[j])
if runeCount > t.cols[j].width {
t.cols[j].width = runeCount
}
}
}