Merge branch 'master' into table-alignment

pull/118/head
Alexis Hildebrandt 3 years ago
commit cae7d520f0

@ -0,0 +1,8 @@
**
!go.*
!*.go
!assets
!cmd
!cointop
!pkg
!vendor

@ -4,14 +4,15 @@ RUN mkdir /app
WORKDIR /app WORKDIR /app
ARG VERSION ARG VERSION
ADD . /app/ COPY . ./
RUN go build -ldflags=-s -ldflags=-w -ldflags=-X=github.com/miguelmota/cointop/cointop.version=$VERSION -o main . RUN go build -ldflags=-s -ldflags=-w -ldflags=-X=github.com/miguelmota/cointop/cointop.version=$VERSION -o main .
RUN git clone https://github.com/cointop-sh/colors && rm -Rf colors/.git* ADD https://github.com/cointop-sh/colors/archive/master.tar.gz ./
RUN tar zxf master.tar.gz --exclude images
FROM busybox:glibc FROM busybox:glibc
RUN mkdir -p /etc/ssl RUN mkdir -p /etc/ssl
COPY --from=build /etc/ssl/certs/ /etc/ssl/certs COPY --from=build /etc/ssl/certs/ /etc/ssl/certs
COPY --from=build /app/main /bin/cointop COPY --from=build /app/main /bin/cointop
COPY --from=build /app/colors /root/.config/cointop/colors COPY --from=build /app/colors-master /root/.config/cointop/colors
ENTRYPOINT cointop ENTRYPOINT ["/bin/cointop"]
CMD [] CMD []

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

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

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

@ -69,7 +69,7 @@ func GetCoinPrices(config *PricesConfig) ([]string, error) {
} }
symbol := CurrencySymbol(config.Currency) 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) prices = append(prices, value)
} }

@ -96,7 +96,7 @@ func (ct *Cointop) GetPriceAlertsTable() *table.Table {
}) })
case "target_price": 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.SetTableColumnWidthFromString(header, targetPrice)
ct.SetTableColumnAlignLeft(header, false) ct.SetTableColumnAlignLeft(header, false)
rowCells = append(rowCells, &table.RowCell{ rowCells = append(rowCells, &table.RowCell{
@ -107,7 +107,7 @@ func (ct *Cointop) GetPriceAlertsTable() *table.Table {
Text: targetPrice, Text: targetPrice,
}) })
case "price": case "price":
text := humanize.Commaf(coin.Price) text := humanize.Monetaryf(coin.Price, 2)
ct.SetTableColumnWidthFromString(header, text) ct.SetTableColumnWidthFromString(header, text)
ct.SetTableColumnAlignLeft(header, false) ct.SetTableColumnAlignLeft(header, false)
rowCells = append(rowCells, &table.RowCell{ rowCells = append(rowCells, &table.RowCell{
@ -187,7 +187,7 @@ func (ct *Cointop) CheckPriceAlert(alert *PriceAlert) error {
} }
var msg string var msg string
title := "Cointop Alert" 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 alert.Operator == ">" {
if coin.Price > alert.TargetPrice { if coin.Price > alert.TargetPrice {
msg = fmt.Sprintf("%s price is greater than %v", alert.CoinName, priceStr) msg = fmt.Sprintf("%s price is greater than %v", alert.CoinName, priceStr)
@ -251,7 +251,8 @@ func (ct *Cointop) UpdatePriceAlertsUpdateMenu(isNew bool, coin *Coin) error {
if ok { if ok {
coin.Name = entry.CoinName coin.Name = entry.CoinName
currentPrice = strconv.FormatFloat(coin.Price, 'f', -1, 64) currentPrice = strconv.FormatFloat(coin.Price, 'f', -1, 64)
value = fmt.Sprintf("%s %v", entry.Operator, entry.TargetPrice) targetPrice := strconv.FormatFloat(entry.TargetPrice, 'f', -1, 64)
value = fmt.Sprintf("%s %v", entry.Operator, targetPrice)
ct.State.priceAlertEditID = entry.ID ct.State.priceAlertEditID = entry.ID
isEdit = true isEdit = true
} }

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

@ -22,6 +22,22 @@ func UserPreferredConfigDir() string {
return config return config
} }
// UserPreferredCacheDir returns the preferred cache directory for the user
func UserPreferredCacheDir() string {
defaultCacheDir := "/tmp"
cache, err := os.UserCacheDir()
if err != nil {
return defaultCacheDir
}
if cache == "" {
return defaultCacheDir
}
return cache
}
// UserPreferredHomeDir returns the preferred home directory for the user // UserPreferredHomeDir returns the preferred home directory for the user
func UserPreferredHomeDir() string { func UserPreferredHomeDir() string {
home, err := os.UserHomeDir() home, err := os.UserHomeDir()
@ -36,6 +52,7 @@ func UserPreferredHomeDir() string {
func NormalizePath(path string) string { func NormalizePath(path string) string {
userHome := UserPreferredHomeDir() userHome := UserPreferredHomeDir()
userConfigHome := UserPreferredConfigDir() userConfigHome := UserPreferredConfigDir()
userCacheHome := UserPreferredCacheDir()
// expand tilde // expand tilde
if strings.HasPrefix(path, "~/") { if strings.HasPrefix(path, "~/") {
@ -44,6 +61,7 @@ func NormalizePath(path string) string {
path = strings.Replace(path, ":HOME:", userHome, -1) path = strings.Replace(path, ":HOME:", userHome, -1)
path = strings.Replace(path, ":PREFERRED_CONFIG_HOME:", userConfigHome, -1) path = strings.Replace(path, ":PREFERRED_CONFIG_HOME:", userConfigHome, -1)
path = strings.Replace(path, ":PREFERRED_CACHE_HOME:", userCacheHome, -1)
path = strings.Replace(path, "/", string(filepath.Separator), -1) path = strings.Replace(path, "/", string(filepath.Separator), -1)
return filepath.Clean(path) return filepath.Clean(path)

Loading…
Cancel
Save