diff --git a/Makefile b/Makefile index a7335d0..ca05144 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ version: commit_rev: @echo $(COMMIT_REV) -run: +start: go run main.go deps: diff --git a/README.md b/README.md index 7a5310e..677a7d2 100644 --- a/README.md +++ b/README.md @@ -809,6 +809,22 @@ Frequently asked questions: - A: Sometimes the coin APIs will make updates and break things. If you see this problem please [submit an issue](https://github.com/miguelmota/cointop/issues/new). +- Q: How can run cointop with just the table? + + - A: Run cointop with the `--only-table` flag. + +- Q: How can I hide the top marketbar? + + - A: Run cointop with the `--hide-marketbar` flag. + +- Q: How can I hide the chart? + + - A: Run cointop with the `--hide-chart` flag. + +- Q: How can I hide the bottom statusbar? + + - A: Run cointop with the `--hide-statusbar` flag. + - Q: How can I delete the cache? - A: Run `cointop -clean` to delete the cache files. Cointop will generate new cache files after fetching data. diff --git a/cmd/cointop.go b/cmd/cointop.go index 0f09a27..9aa3f17 100644 --- a/cmd/cointop.go +++ b/cmd/cointop.go @@ -9,18 +9,23 @@ import ( // Run ... func Run() { - var v, ver, test, clean, reset bool + var v, ver, test, clean, reset, hideMarketbar, hideChart, hideStatusbar, onlyTable bool var config, cmcAPIKey, apiChoice, colorscheme string flag.BoolVar(&v, "v", false, "Version") flag.BoolVar(&ver, "version", false, "Version") flag.BoolVar(&test, "test", false, "Run test") flag.BoolVar(&clean, "clean", false, "Clean cache") flag.BoolVar(&reset, "reset", false, "Reset config") + flag.BoolVar(&hideMarketbar, "hide-marketbar", false, "Hide marketbar") + flag.BoolVar(&hideChart, "hide-chart", false, "Hide chart view") + flag.BoolVar(&hideStatusbar, "hide-statusbar", false, "Hide statusbar") + flag.BoolVar(&onlyTable, "only-table", false, "Show only the table") flag.StringVar(&config, "config", "", "Config filepath") flag.StringVar(&cmcAPIKey, "coinmarketcap-api-key", "", "CoinMarketCap API key") flag.StringVar(&apiChoice, "api", cointop.CoinGecko, "API choice") flag.StringVar(&colorscheme, "colorscheme", "", "Colorscheme name") flag.Parse() + if v || ver { fmt.Printf("cointop v%s", cointop.Version()) } else if test { @@ -35,6 +40,10 @@ func Run() { CoinMarketCapAPIKey: cmcAPIKey, APIChoice: apiChoice, Colorscheme: colorscheme, + HideMarketbar: hideMarketbar, + HideChart: hideChart, + HideStatusbar: hideStatusbar, + OnlyTable: onlyTable, }).Run() } } diff --git a/cointop/chart.go b/cointop/chart.go index 4dd7c8b..3dcbe3d 100644 --- a/cointop/chart.go +++ b/cointop/chart.go @@ -15,6 +15,10 @@ var chartlock sync.Mutex var chartpointslock sync.Mutex func (ct *Cointop) updateChart() error { + if ct.chartview == nil { + return nil + } + chartlock.Lock() defer chartlock.Unlock() diff --git a/cointop/cointop.go b/cointop/cointop.go index 2aefe8c..e2ed580 100644 --- a/cointop/cointop.go +++ b/cointop/cointop.go @@ -93,6 +93,10 @@ type Cointop struct { defaultView string apiKeys *apiKeys limiter <-chan time.Time + hideMarketbar bool + hideChart bool + hideStatusbar bool + onlyTable bool } // CoinMarketCap is API choice @@ -119,6 +123,10 @@ type Config struct { ConfigFilepath string CoinMarketCapAPIKey string NoPrompts bool + HideMarketbar bool + HideChart bool + HideStatusbar bool + OnlyTable bool } // apiKeys is api keys structure @@ -220,6 +228,10 @@ func NewCointop(config *Config) *Cointop { inputviewname: "input", apiKeys: new(apiKeys), limiter: time.Tick(2 * time.Second), + hideMarketbar: config.HideMarketbar, + hideChart: config.HideChart, + hideStatusbar: config.HideStatusbar, + onlyTable: config.OnlyTable, } err := ct.setupConfig() diff --git a/cointop/colorscheme.go b/cointop/colorscheme.go index b88cb61..2987ba9 100644 --- a/cointop/colorscheme.go +++ b/cointop/colorscheme.go @@ -1,6 +1,8 @@ package cointop import ( + "strconv" + fcolor "github.com/fatih/color" gocui "github.com/jroimartin/gocui" xtermcolor "github.com/tomnomnom/xtermcolor" @@ -337,6 +339,17 @@ func (c *Colorscheme) toGocuiAttr(v string) (gocui.Attribute, bool) { } func hexToAnsi(h string) (uint8, bool) { + if h == "" { + return 0, false + } + + n, err := strconv.Atoi(h) + if err == nil { + if n <= 255 { + return uint8(n), true + } + } + code, err := xtermcolor.FromHexStr(h) if err != nil { return 0, false @@ -344,3 +357,5 @@ func hexToAnsi(h string) (uint8, bool) { return code, true } + +// gocui can use xterm colors diff --git a/cointop/layout.go b/cointop/layout.go index c64abe8..ad500b0 100644 --- a/cointop/layout.go +++ b/cointop/layout.go @@ -10,43 +10,69 @@ import ( // layout sets initial layout func (ct *Cointop) layout(g *gocui.Gui) error { maxX, maxY := ct.size() - chartHeight := 10 topOffset := 0 - if v, err := g.SetView(ct.marketbarviewname, 0, topOffset, maxX, 2); err != nil { - if err != gocui.ErrUnknownView { - return err - } - ct.marketbarview = v - ct.marketbarview.Frame = false - ct.colorscheme.SetViewColor(ct.marketbarview, "marketbar") - go func() { - ct.updateMarketbar() - _, found := ct.cache.Get(ct.marketbarviewname) - if found { - ct.cache.Delete(ct.marketbarviewname) - ct.updateMarketbar() - } - }() + marketbarHeight := 1 + chartHeight := 10 + statusbarHeight := 1 + + if ct.onlyTable { + ct.hideMarketbar = true + ct.hideChart = true + ct.hideStatusbar = true } - topOffset = topOffset + 1 - if v, err := g.SetView(ct.chartviewname, 0, topOffset, maxX, topOffset+chartHeight+1); err != nil { - if err != gocui.ErrUnknownView { - return err + if ct.hideMarketbar { + marketbarHeight = 0 + } + + if ct.hideChart { + chartHeight = 0 + } + + if ct.hideStatusbar { + statusbarHeight = 0 + } + + if !ct.hideMarketbar { + if v, err := g.SetView(ct.marketbarviewname, 0, topOffset, maxX, 2); err != nil { + if err != gocui.ErrUnknownView { + return err + } + ct.marketbarview = v + ct.marketbarview.Frame = false + ct.colorscheme.SetViewColor(ct.marketbarview, "marketbar") + go func() { + ct.updateMarketbar() + _, found := ct.cache.Get(ct.marketbarviewname) + if found { + ct.cache.Delete(ct.marketbarviewname) + ct.updateMarketbar() + } + }() } - ct.chartview = v - ct.chartview.Frame = false - ct.colorscheme.SetViewColor(ct.chartview, "chart") - go func() { - ct.updateChart() - cachekey := strings.ToLower(fmt.Sprintf("%s_%s", "globaldata", strings.Replace(ct.selectedchartrange, " ", "", -1))) - _, found := ct.cache.Get(cachekey) - if found { - ct.cache.Delete(cachekey) - ct.updateChart() + } + + topOffset = topOffset + marketbarHeight + + if !ct.hideChart { + if v, err := g.SetView(ct.chartviewname, 0, topOffset, maxX, topOffset+chartHeight+marketbarHeight); err != nil { + if err != gocui.ErrUnknownView { + return err } - }() + ct.chartview = v + ct.chartview.Frame = false + ct.colorscheme.SetViewColor(ct.chartview, "chart") + go func() { + ct.updateChart() + cachekey := strings.ToLower(fmt.Sprintf("%s_%s", "globaldata", strings.Replace(ct.selectedchartrange, " ", "", -1))) + _, found := ct.cache.Get(cachekey) + if found { + ct.cache.Delete(cachekey) + ct.updateChart() + } + }() + } } topOffset = topOffset + chartHeight @@ -61,7 +87,7 @@ func (ct *Cointop) layout(g *gocui.Gui) error { } topOffset = topOffset + 1 - if v, err := g.SetView(ct.tableviewname, 0, topOffset, ct.maxtablewidth, maxY-1); err != nil { + if v, err := g.SetView(ct.tableviewname, 0, topOffset, ct.maxtablewidth, maxY-statusbarHeight); err != nil { if err != gocui.ErrUnknownView { return err } @@ -79,14 +105,16 @@ func (ct *Cointop) layout(g *gocui.Gui) error { }() } - if v, err := g.SetView(ct.statusbarviewname, 0, maxY-2, ct.maxtablewidth, maxY); err != nil { - if err != gocui.ErrUnknownView { - return err + if !ct.hideStatusbar { + if v, err := g.SetView(ct.statusbarviewname, 0, maxY-2, ct.maxtablewidth, maxY); err != nil { + if err != gocui.ErrUnknownView { + return err + } + ct.statusbarview = v + ct.statusbarview.Frame = false + ct.colorscheme.SetViewColor(ct.statusbarview, "statusbar") + go ct.updateStatusbar("") } - ct.statusbarview = v - ct.statusbarview.Frame = false - ct.colorscheme.SetViewColor(ct.statusbarview, "statusbar") - go ct.updateStatusbar("") } if v, err := g.SetView(ct.searchfieldviewname, 0, maxY-2, ct.maxtablewidth, maxY); err != nil { @@ -100,7 +128,7 @@ func (ct *Cointop) layout(g *gocui.Gui) error { ct.colorscheme.SetViewColor(ct.searchfield, "searchbar") } - if v, err := g.SetView(ct.helpviewname, 1, 1, ct.maxtablewidth-2, maxY-1); err != nil { + if v, err := g.SetView(ct.helpviewname, 1, 1, ct.maxtablewidth-1, maxY-1); err != nil { if err != gocui.ErrUnknownView { return err } @@ -109,7 +137,7 @@ func (ct *Cointop) layout(g *gocui.Gui) error { ct.colorscheme.SetViewColor(ct.helpview, "menu") } - if v, err := g.SetView(ct.portfolioupdatemenuviewname, 1, 1, ct.maxtablewidth-2, maxY-1); err != nil { + if v, err := g.SetView(ct.portfolioupdatemenuviewname, 1, 1, ct.maxtablewidth-1, maxY-1); err != nil { if err != gocui.ErrUnknownView { return err } @@ -129,7 +157,7 @@ func (ct *Cointop) layout(g *gocui.Gui) error { ct.colorscheme.SetViewColor(ct.inputview, "menu") } - if v, err := g.SetView(ct.convertmenuviewname, 1, 1, ct.maxtablewidth-2, maxY-1); err != nil { + if v, err := g.SetView(ct.convertmenuviewname, 1, 1, ct.maxtablewidth-1, maxY-1); err != nil { if err != gocui.ErrUnknownView { return err } diff --git a/cointop/marketbar.go b/cointop/marketbar.go index 80c308f..38fa6ce 100644 --- a/cointop/marketbar.go +++ b/cointop/marketbar.go @@ -13,6 +13,10 @@ import ( ) func (ct *Cointop) updateMarketbar() error { + if ct.marketbarview == nil { + return nil + } + maxX := ct.width() logo := "❯❯❯cointop" if ct.colorschemename == "cointop" { @@ -58,10 +62,18 @@ func (ct *Cointop) updateMarketbar() error { arrow = "▼" } + chartInfo := "" + if !ct.hideChart { + chartInfo = fmt.Sprintf( + "[ Chart: %s %s ] ", + charttitle, + timeframe, + ) + } + content = fmt.Sprintf( - "[ Chart: %s %s ] Total Portfolio Value: %s • 24H: %s", - charttitle, - timeframe, + "%sTotal Portfolio Value: %s • 24H: %s", + chartInfo, ct.colorscheme.MarketBarLabelActive(fmt.Sprintf("%s%s", ct.currencySymbol(), totalstr)), color24h(fmt.Sprintf("%.2f%%%s", percentChange24H, arrow)), ) @@ -98,10 +110,18 @@ func (ct *Cointop) updateMarketbar() error { chartname = "Global" } + chartInfo := "" + if !ct.hideChart { + chartInfo = fmt.Sprintf( + "[ Chart: %s %s ] ", + ct.colorscheme.MarketBarLabelActive(chartname), + timeframe, + ) + } + content = fmt.Sprintf( - "[ Chart: %s %s ] Global ▶ Market Cap: %s • 24H Volume: %s • BTC Dominance: %.2f%%", - ct.colorscheme.MarketBarLabelActive(chartname), - timeframe, + "%sGlobal ▶ Market Cap: %s • 24H Volume: %s • BTC Dominance: %.2f%%", + chartInfo, fmt.Sprintf("%s%s", ct.currencySymbol(), humanize.Commaf(market.TotalMarketCapUSD)), fmt.Sprintf("%s%s", ct.currencySymbol(), humanize.Commaf(market.Total24HVolumeUSD)), market.BitcoinPercentageOfMarketCap, diff --git a/cointop/statusbar.go b/cointop/statusbar.go index 96ed45a..07314a1 100644 --- a/cointop/statusbar.go +++ b/cointop/statusbar.go @@ -6,7 +6,11 @@ import ( "github.com/miguelmota/cointop/cointop/common/pad" ) -func (ct *Cointop) updateStatusbar(s string) { +func (ct *Cointop) updateStatusbar(s string) error { + if ct.statusbarview == nil { + return nil + } + currpage := ct.currentDisplayPage() totalpages := ct.totalPagesDisplay() var quitText string @@ -36,6 +40,8 @@ func (ct *Cointop) updateStatusbar(s string) { str = str[:len(str)-len(v)+2] + v fmt.Fprintln(ct.statusbarview, str) }) + + return nil } func (ct *Cointop) refreshRowLink() {