chart date range select shortcut

pull/15/head
Miguel Mota 6 years ago
parent c6c3db7061
commit 7dde1eb1c7

@ -41,6 +41,7 @@ In action
- Vim inspired shortcut keys
- Fast pagination
- Charts for coins and global market graphs
- Quick change chart range
- Fuzzy searching for finding coins
- Save and view favorite coins
- Color support
@ -186,6 +187,10 @@ Key|Action
<kbd>$</kbd>|Go to last page (vim inspired)
<kbd>?</kbd>|Show help|
<kbd>/</kbd>|Search (vim inspired)|
<kbd>]</kbd>|Next chart date range|
<kbd>[</kbd>|Previous chart date range|
<kbd>}</kbd>|Last chart date range|
<kbd>{</kbd>|First chart date range|
## Config
@ -208,6 +213,10 @@ You can then configure the actions you want for each key:
7 = "sort_column_7d_change"
"?" = "help"
"/" = "open_search"
"[" = "previous_chart_range"
"]" = "next_chart_range"
"{" = "first_chart_range"
"}" = "last_chart_range"
G = "move_to_page_last_row"
H = "move_to_page_visible_first_row"
L = "move_to_page_visible_last_row"
@ -263,8 +272,10 @@ This are the action keywords you may use in the config file to change what the s
Action|Description
----|------|
`first_chart_range`|First chart date range (e.g. 1H)
`first_page`|Go to first page
`help`|Show help
`last_chart_range`|Last chart date range (e.g. All Time)
`last_page`|Go to last page
`move_to_page_first_row`|Move to first row on page
`move_to_page_last_row`|Move to last row on page
@ -273,14 +284,17 @@ Action|Description
`move_to_page_visible_middle_row`|Move to middle visible row on page
`move_up`|Move one row up
`move_down`|Move one row down
`next_chart_range`|Next chart date range (e.g. 3D -> 7D)
`next_page`|Go to next page
`open_link`|Open row link
`open_search`|Open search field
`page_down`|Move one row down
`page_up`|Scroll one page up
`previous_chart_range`|Previous chart date range (e.g. 7D -> 3D)
`previous_page`|Go to previous page
`quit`|Quit application
`refresh`|Do a manual refresh on the data
`save`|Save config
`sort_column_1h_change`|Sort table by column *1 hour change*
`sort_column_24h_change`|Sort table by column *24 hour change*
`sort_column_24h_volume`|Sort table by column *24 hour volume*
@ -300,7 +314,6 @@ Action|Description
`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
@ -381,6 +394,21 @@ Action|Description
- A: Yes, but it's slightly buggy.
- Q: My shortcut keys are messed or not correct.
- A: Delete the cointop config directory and rerun cointop.
```bash
rm -rf ~/.cointop
```
- Q: How do I display the chart for the highlighted coin?
- A: Press <kbd>Enter</kbd> to toggle chart for the highlighted coin.
- Q: How do I change the chart date range?
- A: Press <kbd>]</kbd> to cycle to the next date range. Press <kbd>[</kbd> to cycle to the previous date range. Press <kbd>{</kbd> to select the first date range. Press <kbd>}</kbd> to selected the last date range.
## Development
### Go

@ -41,6 +41,10 @@ func actionsMap() map[string]bool {
"open_search": true,
"toggle_favorite": true,
"toggle_show_favorites": true,
"previous_chart_range": true,
"next_chart_range": true,
"first_chart_range": true,
"last_chart_range": true,
}
}

@ -10,8 +10,6 @@ import (
"github.com/miguelmota/cointop/pkg/termui"
)
var oneWeek = (time.Hour * 24) * 7
func (ct *Cointop) updateChart() error {
maxX := ct.maxtablewidth - 3
coin := ct.selectedCoinName()
@ -37,22 +35,35 @@ func (ct *Cointop) updateChart() error {
}
func (ct *Cointop) chartPoints(maxX int, coin string) error {
// TODO: not do this (SOC)
go ct.updateMarketbar()
chart := termui.NewLineChart()
chart.Height = 10
chart.AxesColor = termui.ColorWhite
chart.LineColor = termui.ColorCyan
chart.Border = false
rangeseconds := ct.chartrangesmap[ct.selectedchartrange]
if ct.selectedchartrange == "YTD" {
rangeseconds = ct.chartrangesmap["1Y"]
}
if ct.selectedchartrange == "All Time" {
rangeseconds = ct.chartrangesmap["1Y"]
}
now := time.Now()
secs := now.Unix()
start := secs - int64(oneWeek.Seconds())
end := secs
nowseconds := now.Unix()
start := nowseconds - int64(rangeseconds.Seconds())
end := nowseconds
var data []float64
cachekey := strings.ToLower(coin)
if cachekey == "" {
cachekey = "globaldata"
keyname := coin
if keyname == "" {
keyname = "globaldata"
}
cachekey := strings.ToLower(fmt.Sprintf("%s_%s", keyname, strings.Replace(ct.selectedchartrange, " ", "", -1)))
cached, found := ct.cache.Get(cachekey)
if found {
@ -114,6 +125,55 @@ func (ct *Cointop) chartPoints(maxX int, coin string) error {
}
ct.chartpoints = points
return nil
}
func (ct *Cointop) nextChartRange() error {
sel := 0
max := len(ct.chartranges)
for i, k := range ct.chartranges {
if k == ct.selectedchartrange {
sel = i + 1
break
}
}
if sel > max-1 {
sel = 0
}
ct.selectedchartrange = ct.chartranges[sel]
go ct.updateChart()
return nil
}
func (ct *Cointop) prevChartRange() error {
sel := 0
for i, k := range ct.chartranges {
if k == ct.selectedchartrange {
sel = i - 1
break
}
}
if sel < 0 {
sel = len(ct.chartranges) - 1
}
ct.selectedchartrange = ct.chartranges[sel]
go ct.updateChart()
return nil
}
func (ct *Cointop) firstChartRange() error {
ct.selectedchartrange = ct.chartranges[0]
go ct.updateChart()
return nil
}
func (ct *Cointop) lastChartRange() error {
ct.selectedchartrange = ct.chartranges[len(ct.chartranges)-1]
go ct.updateChart()
return nil
}

@ -1,8 +1,10 @@
package cointop
import (
"fmt"
"log"
"os"
"strings"
"sync"
"time"
@ -23,6 +25,9 @@ type Cointop struct {
chartview *gocui.View
chartviewname string
chartpoints [][]termui.Cell
chartranges []string
chartrangesmap map[string]time.Duration
selectedchartrange string
headersview *gocui.View
headerviewname string
tableview *gocui.View
@ -69,21 +74,48 @@ func Run() {
debug = true
}
ct := Cointop{
api: api.NewCMC(),
refreshticker: time.NewTicker(1 * time.Minute),
sortby: "rank",
sortdesc: false,
page: 0,
perpage: 100,
forcerefresh: make(chan bool),
maxtablewidth: 175,
actionsmap: actionsMap(),
shortcutkeys: defaultShortcuts(),
favorites: map[string]bool{},
cache: cache.New(1*time.Minute, 2*time.Minute),
debug: debug,
marketbarviewname: "market",
chartviewname: "chart",
api: api.NewCMC(),
refreshticker: time.NewTicker(1 * time.Minute),
sortby: "rank",
sortdesc: false,
page: 0,
perpage: 100,
forcerefresh: make(chan bool),
maxtablewidth: 175,
actionsmap: actionsMap(),
shortcutkeys: defaultShortcuts(),
favorites: map[string]bool{},
cache: cache.New(1*time.Minute, 2*time.Minute),
debug: debug,
marketbarviewname: "market",
chartviewname: "chart",
chartranges: []string{
"1H",
"6H",
"24H",
"3D",
"7D",
"1M",
"3M",
"6M",
"1Y",
"YTD",
"All Time",
},
chartrangesmap: map[string]time.Duration{
"All Time": time.Duration(1 * time.Second),
"YTD": time.Duration(1 * time.Second),
"1Y": time.Duration(24 * 7 * 4 * 12 * time.Hour),
"6M": time.Duration(24 * 7 * 4 * 6 * time.Hour),
"3M": time.Duration(24 * 7 * 4 * 3 * time.Hour),
"1M": time.Duration(24 * 7 * 4 * time.Hour),
"7D": time.Duration(24 * 7 * time.Hour),
"3D": time.Duration(24 * 3 * time.Hour),
"24H": time.Duration(24 * time.Hour),
"6H": time.Duration(6 * time.Hour),
"1H": time.Duration(1 * time.Hour),
},
selectedchartrange: "7D",
headerviewname: "header",
tableviewname: "table",
statusbarviewname: "statusbar",
@ -97,16 +129,19 @@ func Run() {
}
allcoinsmap := map[string]types.Coin{}
fcache.Get("allcoinsmap", &allcoinsmap)
ct.cache.Set("allcoinsmap", allcoinsmap, 10*time.Second)
coinscachekey := "allcoinsmap"
fcache.Get(coinscachekey, &allcoinsmap)
ct.cache.Set(coinscachekey, allcoinsmap, 10*time.Second)
var globaldata []float64
fcache.Get("globaldata", &globaldata)
ct.cache.Set("globaldata", globaldata, 10*time.Second)
chartcachekey := strings.ToLower(fmt.Sprintf("%s_%s", "globaldata", strings.Replace(ct.selectedchartrange, " ", "", -1)))
fcache.Get(chartcachekey, &globaldata)
ct.cache.Set(chartcachekey, globaldata, 10*time.Second)
var market types.GlobalMarketData
fcache.Get("market", &market)
ct.cache.Set("market", market, 10*time.Second)
marketcachekey := "market"
fcache.Get(marketcachekey, &market)
ct.cache.Set(marketcachekey, market, 10*time.Second)
g, err := gocui.NewGui(gocui.Output256)
if err != nil {

@ -90,8 +90,20 @@ func (ct *Cointop) parseKeys(s string) (interface{}, gocui.Modifier) {
case "~":
key = gocui.KeyCtrlTilde
case "[":
fallthrough
case "lsqrbracket":
fallthrough
case "leftsqrbracket":
fallthrough
case "leftsquarebracket":
key = gocui.KeyCtrlLsqBracket
case "]":
fallthrough
case "rsqrbracket":
fallthrough
case "rightsqrbracket":
fallthrough
case "rightsquarebracket":
key = gocui.KeyCtrlRsqBracket
case "space":
key = gocui.KeyCtrlSpace
@ -278,6 +290,14 @@ func (ct *Cointop) keybindings(g *gocui.Gui) error {
case "quit":
fn = ct.keyfn(ct.quit)
view = ""
case "next_chart_range":
fn = ct.keyfn(ct.nextChartRange)
case "previous_chart_range":
fn = ct.keyfn(ct.prevChartRange)
case "first_chart_range":
fn = ct.keyfn(ct.firstChartRange)
case "last_chart_range":
fn = ct.keyfn(ct.lastChartRange)
default:
fn = ct.keyfn(ct.noop)
}

@ -2,6 +2,7 @@ package cointop
import (
"fmt"
"strings"
"github.com/miguelmota/cointop/pkg/gocui"
)
@ -39,9 +40,10 @@ func (ct *Cointop) layout(g *gocui.Gui) error {
ct.chartview.Frame = false
go func() {
ct.updateChart()
_, found := ct.cache.Get("globaldata")
cachekey := strings.ToLower(fmt.Sprintf("%s_%s", "globaldata", strings.Replace(ct.selectedchartrange, " ", "", -1)))
_, found := ct.cache.Get(cachekey)
if found {
ct.cache.Delete("globaldata")
ct.cache.Delete(cachekey)
ct.updateChart()
}
}()

@ -37,7 +37,7 @@ func (ct *Cointop) updateMarketbar() error {
}()
}
timeframe := "7 Day"
timeframe := ct.selectedchartrange
chartname := ct.selectedCoinName()
if chartname == "" {
chartname = "Global"

@ -57,5 +57,9 @@ func defaultShortcuts() map[string]string {
"$": "last_page",
"?": "help",
"/": "open_search",
"]": "next_chart_range",
"[": "prev_chart_range",
"}": "last_chart_range",
"{": "first_chart_range",
}
}

@ -11,12 +11,12 @@ func (ct *Cointop) updateStatusbar(s string) {
ct.statusbarview.Clear()
currpage := ct.currentDisplayPage()
totalpages := ct.totalPages()
base := "[q]Quit [?]Help [c]Chart [/]Search"
fmt.Fprintln(ct.statusbarview, pad.Right(fmt.Sprintf("%v [← →]Page %v/%v %s", base, currpage, totalpages, s), ct.maxtablewidth, " "))
base := fmt.Sprintf("%sQuit %sHelp %sChart %sRange %sSearch", "[Q]", "[?]", "[Enter]", "[[ ]]", "[/]")
fmt.Fprintln(ct.statusbarview, pad.Right(fmt.Sprintf("%v %sPage %v/%v %s", base, "[← →]", currpage, totalpages, s), ct.maxtablewidth, " "))
})
}
func (ct *Cointop) refreshRowLink() {
url := ct.rowLink()
ct.updateStatusbar(fmt.Sprintf("[o]Open %s", url))
ct.updateStatusbar(fmt.Sprintf("%sOpen %s", "[O]", url))
}

@ -5,6 +5,8 @@ import "github.com/fatih/color"
var (
// Black color
Black = color.New(color.FgBlack).SprintFunc()
// BlackBg color
BlackBg = color.New(color.BgBlack, color.FgWhite).SprintFunc()
// White color
White = color.New(color.FgWhite).SprintFunc()
// WhiteBold bold

Loading…
Cancel
Save