diff --git a/README.md b/README.md
index 717b74f..6a45828 100644
--- a/README.md
+++ b/README.md
@@ -22,12 +22,13 @@
## Features
- Quick sort shortcuts
+- Custom key bindings config
- Vim style keys
-- Pagination
-- 7 day charts
-- Fuzzy Searching
-- Custom key bindings
-- Color coded
+- Fast pagination
+- 7 day charts for coins and global market graphs
+- Fuzzy Searching (name/symbol) for finding coins
+- Save and view favorite coins
+- Color coding
- Works on macOS, Linux, and Windows
## Installing
@@ -90,14 +91,15 @@ Key|Action
Page Down|Jump page down
Home|Go to first line of page
End|Go to last line of page
-Enter|Visit highlighted coin on [CoinMarketCap](https://coinmarketcap.com/)
-Esc|Alias to quit
-Space|Alias to enter key
+Enter|Toggle [c]hart for highlighted coin
+Esc|Quit
+Space|Toggle coin as favorite
Ctrl+c|Alias to quit
Ctrl+d|Jump page down (vim style)
Ctrl+n|Go to next page
Ctrl+p|Go to previous page
Ctrl+r|Force refresh
+Ctrl+s|Save config
Ctrl+u|Jump page up (vim style)
Alt+↑|Sort current column in ascending order
Alt+↓|Sort current column in descending order
@@ -110,6 +112,7 @@ Key|Action
7|Sort table by *[7] day change*
a|Sort table by *[a]vailable supply*
c|Toggle [c]hart for highlighted coin
+f|Toggle show favorites
g|Go to first line of page (vim style)
G|Go to last line of page (vim style)
h|Go to previous page (vim style)
@@ -121,7 +124,7 @@ Key|Action
m|Sort table by *[m]arket cap*
M|Go to middle of visible table window (vim style)
n|Sort table by *[n]ame*
-o|[o]pen row link
+o|[o]pen link to highlighted coin on [CoinMarketCap](https://coinmarketcap.com/)
p|Sort table by *[p]rice*
r|Sort table by *[r]ank*
s|Sort table by *[s]ymbol*
@@ -173,10 +176,12 @@ You can then configure the actions you want for each key:
"ctrl+n" = "next_page"
"ctrl+p" = "previous_page"
"ctrl+r" = "refresh"
+ "ctrl+s" = "save"
"ctrl+u" = "page_up"
end = "move_to_page_last_row"
- enter = "open_link"
+ enter = "toggle_row_chart"
esc = "quit"
+ f = "toggle_show_favorites"
F1 = "help"
g = "move_to_page_first_row"
h = "previous_page"
@@ -193,7 +198,7 @@ You can then configure the actions you want for each key:
q = "quit"
r = "sort_column_rank"
s = "sort_column_symbol"
- space = "open_link"
+ space = "toggle_favorite"
t = "sort_column_total_supply"
u = "sort_column_last_updated"
v = "sort_column_24h_volume"
@@ -238,6 +243,9 @@ Action|Description
`sort_left_column`|Sort the column to the left of the highlighted column
`sort_right_column`|Sort the column to the right of the highlighted column
`toggle_row_chart`|Toggle the chart for the highlighted row
+`toggle_favorite`|Toggle coin as favorite
+`toggle_show_favorites`|Toggle show favorites
+`save`|Save config
## FAQ
diff --git a/cointop/cointop.go b/cointop/cointop.go
index 9fbbe08..b75d4dc 100644
--- a/cointop/cointop.go
+++ b/cointop/cointop.go
@@ -39,6 +39,7 @@ type Cointop struct {
searchfield *gocui.View
favorites map[string]bool
filterByFavorites bool
+ savemux sync.Mutex
}
// Run runs cointop
@@ -53,6 +54,7 @@ func Run() {
forcerefresh: make(chan bool),
maxtablewidth: 175,
shortcutkeys: defaultShortcuts(),
+ favorites: map[string]bool{},
}
err := ct.setupConfig()
if err != nil {
diff --git a/cointop/config.go b/cointop/config.go
index d58985a..4e8db2e 100644
--- a/cointop/config.go
+++ b/cointop/config.go
@@ -11,7 +11,8 @@ import (
)
type config struct {
- Shortcuts map[string]interface{} `toml:"shortcuts"`
+ Shortcuts map[string]interface{} `toml:"shortcuts"`
+ Favorites map[string][]interface{} `toml:"favorites"`
}
func (ct *Cointop) setupConfig() error {
@@ -31,6 +32,24 @@ func (ct *Cointop) setupConfig() error {
if err != nil {
return err
}
+ err = ct.loadFavoritesFromConfig()
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (ct *Cointop) loadFavoritesFromConfig() error {
+ for k, arr := range ct.config.Favorites {
+ if k == "symbols" {
+ for _, ifc := range arr {
+ v, ok := ifc.(string)
+ if ok {
+ ct.favorites[strings.ToUpper(v)] = true
+ }
+ }
+ }
+ }
return nil
}
@@ -74,6 +93,24 @@ func (ct *Cointop) makeConfigFile() error {
return nil
}
+func (ct *Cointop) saveConfig() error {
+ ct.savemux.Lock()
+ defer ct.savemux.Unlock()
+ path := ct.configPath()
+ if _, err := os.Stat(path); err == nil {
+ fo, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0666)
+ defer fo.Close()
+ b, err := ct.configToToml()
+ if err != nil {
+ return err
+ }
+ if _, err := fo.Write(b); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
func (ct *Cointop) parseConfig() error {
var conf config
path := ct.configPath()
@@ -86,14 +123,26 @@ func (ct *Cointop) parseConfig() error {
}
func (ct *Cointop) configToToml() ([]byte, error) {
- s := defaultShortcuts()
- ifcs := map[string]interface{}{}
- for k, v := range s {
+ shortcutsIfcs := map[string]interface{}{}
+ for k, v := range ct.shortcutkeys {
var i interface{} = v
- ifcs[k] = i
+ shortcutsIfcs[k] = i
}
+
+ var favorites []interface{}
+ for k, ok := range ct.favorites {
+ if ok {
+ var i interface{} = strings.ToUpper(k)
+ favorites = append(favorites, i)
+ }
+ }
+ favoritesIfcs := map[string][]interface{}{
+ "symbols": favorites,
+ }
+
var inputs = &config{
- Shortcuts: ifcs,
+ Shortcuts: shortcutsIfcs,
+ Favorites: favoritesIfcs,
}
var b bytes.Buffer
diff --git a/cointop/favorites.go b/cointop/favorites.go
index 4ce47fd..ac5f847 100644
--- a/cointop/favorites.go
+++ b/cointop/favorites.go
@@ -1,5 +1,22 @@
package cointop
+func (ct *Cointop) toggleFavorite() error {
+ coin := ct.highlightedRowCoin()
+ if coin == nil {
+ return nil
+ }
+ _, ok := ct.favorites[coin.Symbol]
+ if ok {
+ delete(ct.favorites, coin.Symbol)
+ coin.Favorite = false
+ } else {
+ ct.favorites[coin.Symbol] = true
+ coin.Favorite = true
+ }
+ ct.updateTable()
+ return nil
+}
+
func (ct *Cointop) toggleShowFavorites() error {
ct.filterByFavorites = !ct.filterByFavorites
ct.updateTable()
diff --git a/cointop/keybindings.go b/cointop/keybindings.go
index 13ea444..0235510 100644
--- a/cointop/keybindings.go
+++ b/cointop/keybindings.go
@@ -264,8 +264,12 @@ func (ct *Cointop) keybindings(g *gocui.Gui) error {
case "open_search":
fn = ct.keyfn(ct.openSearch)
view = ""
- case "show_favorites":
+ case "toggle_favorite":
+ fn = ct.keyfn(ct.toggleFavorite)
+ case "toggle_show_favorites":
fn = ct.keyfn(ct.toggleShowFavorites)
+ case "save":
+ fn = ct.keyfn(ct.save)
case "quit":
fn = ct.keyfn(ct.quit)
view = ""
diff --git a/cointop/refresh.go b/cointop/refresh.go
index c1da215..b0d4dbb 100644
--- a/cointop/refresh.go
+++ b/cointop/refresh.go
@@ -12,12 +12,12 @@ func (ct *Cointop) refresh() error {
func (ct *Cointop) refreshAll() error {
ct.refreshmux.Lock()
+ defer ct.refreshmux.Unlock()
ct.setRefreshStatus()
ct.updateCoins()
ct.updateTable()
ct.updateMarketbar()
ct.updateChart()
- ct.refreshmux.Unlock()
return nil
}
diff --git a/cointop/save.go b/cointop/save.go
new file mode 100644
index 0000000..3967656
--- /dev/null
+++ b/cointop/save.go
@@ -0,0 +1,15 @@
+package cointop
+
+func (ct *Cointop) save() error {
+ ct.setSavingStatus()
+ ct.saveConfig()
+ return nil
+}
+
+func (ct *Cointop) setSavingStatus() {
+ go func() {
+ ct.loadingTicks("saving", 900)
+ ct.updateStatusbar("")
+ ct.rowChanged()
+ }()
+}
diff --git a/cointop/shortcuts.go b/cointop/shortcuts.go
index dd25f19..576a20b 100644
--- a/cointop/shortcuts.go
+++ b/cointop/shortcuts.go
@@ -37,7 +37,8 @@ func actionsMap() map[string]bool {
"sort_right_column": true,
"toggle_row_chart": true,
"open_search": true,
- "show_favorites": true,
+ "toggle_favorite": true,
+ "toggle_show_favorites": true,
}
}
@@ -51,14 +52,15 @@ func defaultShortcuts() map[string]string {
"pageup": "page_up",
"home": "move_to_page_first_row",
"end": "move_to_page_last_row",
- "enter": "open_link",
+ "enter": "toggle_row_chart",
"esc": "quit",
- "space": "open_link",
+ "space": "toggle_favorite",
"ctrl+c": "quit",
"ctrl+d": "page_down",
"ctrl+n": "next_page",
"ctrl+p": "previous_page",
"ctrl+r": "refresh",
+ "ctrl+s": "save",
"ctrl+u": "page_up",
"alt+up": "sort_column_asc",
"alt+down": "sort_column_desc",
@@ -71,7 +73,7 @@ func defaultShortcuts() map[string]string {
"7": "sort_column_7d_change",
"a": "sort_column_available_supply",
"c": "toggle_row_chart",
- "f": "show_favorites",
+ "f": "toggle_show_favorites",
"g": "move_to_page_first_row",
"G": "move_to_page_last_row",
"h": "previous_page",
diff --git a/cointop/statusbar.go b/cointop/statusbar.go
index 2b84e99..c6b8787 100644
--- a/cointop/statusbar.go
+++ b/cointop/statusbar.go
@@ -18,5 +18,5 @@ func (ct *Cointop) updateStatusbar(s string) {
func (ct *Cointop) refreshRowLink() {
url := ct.rowLink()
- ct.updateStatusbar(fmt.Sprintf("[↵]%s", url))
+ ct.updateStatusbar(fmt.Sprintf("[o]pen %s", url))
}
diff --git a/cointop/table.go b/cointop/table.go
index 3c84efb..6739a2b 100644
--- a/cointop/table.go
+++ b/cointop/table.go
@@ -58,10 +58,15 @@ func (ct *Cointop) refreshTable() error {
color7d = color.Red
}
name := coin.Name
+ dots := "..."
+ if coin.Favorite {
+ dots = "..*"
+ name = fmt.Sprintf("%s*", name)
+ }
lastchar := len(name)
if lastchar > 20 {
lastchar = 20
- name = fmt.Sprintf("%s...", name[0:18])
+ name = fmt.Sprintf("%s%s", name[0:18], dots)
}
ct.table.AddRow(
color.White(fmt.Sprintf("%7v ", coin.Rank)),
diff --git a/pkg/open/open.go b/pkg/open/open.go
index 41523c6..6b182da 100644
--- a/pkg/open/open.go
+++ b/pkg/open/open.go
@@ -9,6 +9,7 @@ var possibleCmds = []string{
"xdg-open", // linux
"open", // mac
"start", // windows?
+ "cygstart", // windows?
}
func init() {