diff --git a/README.md b/README.md index 3d78119..8cfcd74 100644 --- a/README.md +++ b/README.md @@ -30,14 +30,6 @@ - Color coded - Works on macOS, Linux, and Windows -#### Future releases - -- Advanced search -- "Favorites" list -- Currency conversion (i.e. Euro, Yen) -- Markets/Exchanges -- CryptoCompare API - ## Installing Make sure to have [go](https://golang.org/) (1.9+) installed, then do: diff --git a/cointop/cointop.go b/cointop/cointop.go index 7bed8a0..3209703 100644 --- a/cointop/cointop.go +++ b/cointop/cointop.go @@ -8,36 +8,37 @@ import ( "github.com/gizak/termui" "github.com/jroimartin/gocui" "github.com/miguelmota/cointop/pkg/api" - apt "github.com/miguelmota/cointop/pkg/api/types" "github.com/miguelmota/cointop/pkg/table" ) // Cointop cointop type Cointop struct { - g *gocui.Gui - marketview *gocui.View - chartview *gocui.View - chartpoints [][]termui.Cell - headersview *gocui.View - tableview *gocui.View - table *table.Table - statusbarview *gocui.View - sortdesc bool - sortby string - api api.Interface - allcoins []*apt.Coin - coins []*apt.Coin - allcoinsmap map[string]apt.Coin - page int - perpage int - refreshmux sync.Mutex - refreshticker *time.Ticker - forcerefresh chan bool - selectedcoin *apt.Coin - maxtablewidth int - shortcutkeys map[string]string - config config // toml config - searchfield *gocui.View + g *gocui.Gui + marketview *gocui.View + chartview *gocui.View + chartpoints [][]termui.Cell + headersview *gocui.View + tableview *gocui.View + table *table.Table + statusbarview *gocui.View + sortdesc bool + sortby string + api api.Interface + allcoins []*coin + coins []*coin + allcoinsmap map[string]coin + page int + perpage int + refreshmux sync.Mutex + refreshticker *time.Ticker + forcerefresh chan bool + selectedcoin *coin + maxtablewidth int + shortcutkeys map[string]string + config config // toml config + searchfield *gocui.View + favorites map[string]bool + filterByFavorites bool } // Run runs cointop @@ -52,6 +53,10 @@ func Run() { forcerefresh: make(chan bool), maxtablewidth: 175, shortcutkeys: defaultShortcuts(), + favorites: map[string]bool{ + "ETH": true, + "ADT": true, + }, } _ = ct.setupConfig() g, err := gocui.NewGui(gocui.Output256) diff --git a/cointop/favorites.go b/cointop/favorites.go new file mode 100644 index 0000000..082165d --- /dev/null +++ b/cointop/favorites.go @@ -0,0 +1,21 @@ +package cointop + +func (ct *Cointop) toggleShowFavorites() error { + for _, v := range ct.allcoinsmap { + if ct.favorites[v.Symbol] { + v.Favorite = true + } + } + + ct.filterByFavorites = !ct.filterByFavorites + ct.sort(ct.sortby, ct.sortdesc, ct.coins) + //ct.updateCoins() + /* + ct.update(func() { + ct.tableview.Clear() + ct.updateTable() + }) + ct.rowChanged() + */ + return nil +} diff --git a/cointop/keybindings.go b/cointop/keybindings.go index 23f3adf..ab33d37 100644 --- a/cointop/keybindings.go +++ b/cointop/keybindings.go @@ -261,12 +261,15 @@ func (ct *Cointop) keybindings(g *gocui.Gui) error { fn = ct.sortfn("24hvolume", true) case "last_page": fn = ct.keyfn(ct.lastPage) - case "quit": - fn = ct.keyfn(ct.quit) - view = "" case "open_search": fn = ct.keyfn(ct.openSearch) view = "" + case "show_favorites": + fn = ct.keyfn(ct.toggleShowFavorites) + view = "" + case "quit": + fn = ct.keyfn(ct.quit) + view = "" default: fn = ct.keyfn(ct.noop) } diff --git a/cointop/layout.go b/cointop/layout.go index 52bb6de..87853f4 100644 --- a/cointop/layout.go +++ b/cointop/layout.go @@ -2,10 +2,8 @@ package cointop import ( "fmt" - "math" "github.com/jroimartin/gocui" - apt "github.com/miguelmota/cointop/pkg/api/types" ) func (ct *Cointop) layout(g *gocui.Gui) error { @@ -105,13 +103,34 @@ func (ct *Cointop) setActiveView(v string) error { } func (ct *Cointop) updateCoins() error { - list := []*apt.Coin{} + list := []*coin{} allcoinsmap, err := ct.api.GetAllCoinData() if err != nil { return err } - ct.allcoinsmap = allcoinsmap + if len(ct.allcoinsmap) == 0 { + ct.allcoinsmap = map[string]coin{} + } + + for k, v := range allcoinsmap { + ct.allcoinsmap[k] = coin{ + ID: v.ID, + Name: v.Name, + Symbol: v.Symbol, + Rank: v.Rank, + PriceUSD: v.PriceUSD, + PriceBTC: v.PriceBTC, + USD24HVolume: v.USD24HVolume, + MarketCapUSD: v.MarketCapUSD, + AvailableSupply: v.AvailableSupply, + TotalSupply: v.TotalSupply, + PercentChange1H: v.PercentChange1H, + PercentChange24H: v.PercentChange24H, + PercentChange7D: v.PercentChange7D, + LastUpdated: v.LastUpdated, + } + } if len(ct.allcoins) == 0 { for i := range ct.allcoinsmap { coin := ct.allcoinsmap[i] @@ -148,22 +167,6 @@ func (ct *Cointop) updateCoins() error { return nil } -func (ct *Cointop) updateTable() error { - start := ct.page * ct.perpage - end := start + ct.perpage - if end >= len(ct.allcoins)-1 { - start = int(math.Floor(float64(start/100)) * 100) - - end = len(ct.allcoins) - 1 - } - - sliced := ct.allcoins[start:end] - ct.coins = sliced - ct.sort(ct.sortby, ct.sortdesc, ct.coins) - ct.refreshTable() - return nil -} - func (ct *Cointop) intervalFetchData() { go func() { for { diff --git a/cointop/navigation.go b/cointop/navigation.go index c525751..c17a248 100644 --- a/cointop/navigation.go +++ b/cointop/navigation.go @@ -17,7 +17,7 @@ func (ct *Cointop) totalPerPage() int { } func (ct *Cointop) getListCount() int { - return len(ct.allcoins) + return len(ct.allCoins()) } func (ct *Cointop) setPage(page int) int { diff --git a/cointop/shortcuts.go b/cointop/shortcuts.go index 393996a..dd25f19 100644 --- a/cointop/shortcuts.go +++ b/cointop/shortcuts.go @@ -37,6 +37,7 @@ func actionsMap() map[string]bool { "sort_right_column": true, "toggle_row_chart": true, "open_search": true, + "show_favorites": true, } } @@ -70,6 +71,7 @@ func defaultShortcuts() map[string]string { "7": "sort_column_7d_change", "a": "sort_column_available_supply", "c": "toggle_row_chart", + "f": "show_favorites", "g": "move_to_page_first_row", "G": "move_to_page_last_row", "h": "previous_page", diff --git a/cointop/sort.go b/cointop/sort.go index 7ae7257..1df4bc4 100644 --- a/cointop/sort.go +++ b/cointop/sort.go @@ -3,7 +3,6 @@ package cointop import ( "github.com/bradfitz/slice" "github.com/jroimartin/gocui" - apt "github.com/miguelmota/cointop/pkg/api/types" ) var colorder = []string{ @@ -20,7 +19,7 @@ var colorder = []string{ "lastupdated", } -func (ct *Cointop) sort(sortby string, desc bool, list []*apt.Coin) { +func (ct *Cointop) sort(sortby string, desc bool, list []*coin) { ct.sortby = sortby ct.sortdesc = desc slice.Sort(list[:], func(i, j int) bool { diff --git a/cointop/table.go b/cointop/table.go index a769dda..2197bc9 100644 --- a/cointop/table.go +++ b/cointop/table.go @@ -2,11 +2,11 @@ package cointop import ( "fmt" + "math" "strconv" "strings" "time" - apt "github.com/miguelmota/cointop/pkg/api/types" "github.com/miguelmota/cointop/pkg/color" "github.com/miguelmota/cointop/pkg/humanize" "github.com/miguelmota/cointop/pkg/table" @@ -84,6 +84,30 @@ func (ct *Cointop) refreshTable() error { return nil } +func (ct *Cointop) updateTable() error { + start := ct.page * ct.perpage + end := start + ct.perpage + if start >= len(ct.allCoins())-1 { + start = 0 + } + if end >= len(ct.allCoins())-1 { + start = int(math.Floor(float64(start/100)) * 100) + + end = len(ct.allCoins()) - 1 + } + if start < 0 { + start = 0 + } + if end >= len(ct.allCoins()) { + end = len(ct.allCoins()) - 1 + } + sliced := ct.allCoins()[start:end] + ct.coins = sliced + ct.sort(ct.sortby, ct.sortdesc, ct.coins) + ct.refreshTable() + return nil +} + func (ct *Cointop) highlightedRowIndex() int { _, y := ct.tableview.Origin() _, cy := ct.tableview.Cursor() @@ -97,7 +121,7 @@ func (ct *Cointop) highlightedRowIndex() int { return idx } -func (ct *Cointop) highlightedRowCoin() *apt.Coin { +func (ct *Cointop) highlightedRowCoin() *coin { idx := ct.highlightedRowIndex() return ct.coins[idx] } @@ -106,3 +130,18 @@ func (ct *Cointop) rowLink() string { slug := strings.ToLower(strings.Replace(ct.highlightedRowCoin().Name, " ", "-", -1)) return fmt.Sprintf("https://coinmarketcap.com/currencies/%s", slug) } + +func (ct *Cointop) allCoins() []*coin { + if ct.filterByFavorites { + var list []*coin + for i := range ct.allcoins { + coin := ct.allcoins[i] + if coin.Favorite { + list = append(list, coin) + } + } + return list + } + + return ct.allcoins +} diff --git a/cointop/types.go b/cointop/types.go new file mode 100644 index 0000000..e7eef32 --- /dev/null +++ b/cointop/types.go @@ -0,0 +1,19 @@ +package cointop + +type coin struct { + ID string + Name string + Symbol string + Rank int + PriceUSD float64 + PriceBTC float64 + USD24HVolume float64 + MarketCapUSD float64 + AvailableSupply float64 + TotalSupply float64 + PercentChange1H float64 + PercentChange24H float64 + PercentChange7D float64 + LastUpdated string + Favorite bool +} diff --git a/pkg/levenshtein/levenshtein.go b/pkg/levenshtein/levenshtein.go index 4355748..7ea40bf 100644 --- a/pkg/levenshtein/levenshtein.go +++ b/pkg/levenshtein/levenshtein.go @@ -88,7 +88,7 @@ func DamerauLevenshteinDistance(s1, s2 string) int { // min returns the minimum number of passed int slices. func min(is ...int) int { - min := int(math.MaxInt64) + min := int(math.MaxInt32) for _, v := range is { if min > v { min = v