build script

Former-commit-id: 807a38499b5e912a909d18e142ac5ffd27518f47 [formerly 807a38499b5e912a909d18e142ac5ffd27518f47 [formerly 3b23f739d91859165827c1af6a923cf7be19a1d5 [formerly 6f3f3dd824]]]
Former-commit-id: 36948040aa5bec0dd2c25ec210e02349f5bddf0a
Former-commit-id: 4b1b9d17fc425bc764a46d0fdcd12747cca608f5 [formerly 56d4451c69972aa25ed17119773e6af9085b00c1]
Former-commit-id: 7967040e3a6348128010d3bc0ad213e5eabbf567
pull/15/head
Miguel Mota 6 years ago
parent 08c92c9317
commit 77f5c752e9

12
Gopkg.lock generated

@ -65,7 +65,7 @@
branch = "master"
name = "github.com/miguelmota/go-coinmarketcap"
packages = ["."]
revision = "05fd2d0c45f763462f90e630da2ddc0392d2cdd3"
revision = "9c6b4c2a42d7189f8778825da9640c3efda17d7e"
[[projects]]
branch = "master"
@ -79,12 +79,6 @@
packages = ["."]
revision = "e2050e41c8847748ec5288741c0b19a8cb26d084"
[[projects]]
branch = "master"
name = "github.com/willf/pad"
packages = ["."]
revision = "b3d7806010228b1a954b4d9c4ee4cf6cb476b063"
[[projects]]
branch = "master"
name = "go4.org"
@ -98,7 +92,7 @@
"html",
"html/atom"
]
revision = "6078986fec03a1dcc236c34816c71b0e05018fda"
revision = "b68f30494add4df6bd8ef5e82803f308e7f7c59c"
[[projects]]
branch = "master"
@ -109,6 +103,6 @@
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "ff54fa52bac3cde3f10f5c237dad28da497594584e4291356b5efd040501fe4e"
inputs-digest = "cc43de082ffa9bbc96488c9bfc6659269a914a24c4ff2a04e1d43bfc66a992a4"
solver-name = "gps-cdcl"
solver-version = 1

@ -49,10 +49,6 @@
branch = "master"
name = "github.com/miguelmota/go-coinmarketcap"
[[constraint]]
branch = "master"
name = "github.com/willf/pad"
[prune]
go-tests = true
unused-packages = true

@ -2,7 +2,10 @@ all:
@echo "no default"
run:
go run cointop.go keybindings.go navigation.go sort.go
go run cointop.go keybindings.go navigation.go sort.go layout.go status.go chart.go table.go
build:
go build
build: clean
go build -ldflags "-s -w" -o bin/cointop && upx bin/cointop
clean:
go clean && rm -f bin/cointop

@ -14,6 +14,11 @@ Make sure to have [golang](https://golang.org/) installed, then do:
go install github.com/miguelmota/cointop
```
### Alternatively
```
```
## Usage
```bash

@ -0,0 +1 @@
afb3d36c7d062f773b2646a50def45506046b9e8

@ -0,0 +1,84 @@
package main
import (
"fmt"
"log"
"time"
"github.com/gizak/termui"
)
func (ct *Cointop) updateChart() error {
maxX, _ := ct.g.Size()
if len(ct.chartpoints) == 0 {
ct.chartPoints(maxX, "bitcoin")
}
for i := range ct.chartpoints {
var s string
for j := range ct.chartpoints[i] {
p := ct.chartpoints[i][j]
s = fmt.Sprintf("%s%c", s, p.Ch)
}
fmt.Fprintln(ct.chartview, s)
}
return nil
}
func (ct *Cointop) chartPoints(maxX int, coin string) error {
chart := termui.NewLineChart()
chart.Height = 10
chart.AxesColor = termui.ColorWhite
chart.LineColor = termui.ColorCyan
chart.Border = false
now := time.Now()
secs := now.Unix()
start := secs - oneDay
end := secs
_ = coin
//graphData, err := cmc.GetCoinGraphData(coin, start, end)
graphData, err := ct.api.GetGlobalMarketGraphData(start, end)
if err != nil {
log.Fatal(err)
return nil
}
var data []float64
/*
for i := range graphData.PriceUSD {
data = append(data, graphData.PriceUSD[i][1])
}
*/
for i := range graphData.MarketCapByAvailableSupply {
data = append(data, graphData.MarketCapByAvailableSupply[i][1])
}
chart.Data = data
termui.Body = termui.NewGrid()
termui.Body.Width = maxX
termui.Body.AddRows(
termui.NewRow(
termui.NewCol(12, 0, chart),
),
)
var points [][]termui.Cell
// calculate layout
termui.Body.Align()
w := termui.Body.Width
h := 10
row := termui.Body.Rows[0]
b := row.Buffer()
for i := 0; i < h; i = i + 1 {
var rowpoints []termui.Cell
for j := 0; j < w; j = j + 1 {
p := b.At(j, i)
rowpoints = append(rowpoints, p)
}
points = append(points, rowpoints)
}
ct.chartpoints = points
return nil
}

@ -3,19 +3,13 @@ package main
import (
"fmt"
"log"
"os/exec"
"strconv"
"strings"
"time"
humanize "github.com/dustin/go-humanize"
"github.com/gizak/termui"
"github.com/jroimartin/gocui"
"github.com/miguelmota/cointop/apis"
apitypes "github.com/miguelmota/cointop/apis/types"
"github.com/miguelmota/cointop/color"
"github.com/miguelmota/cointop/pad"
"github.com/miguelmota/cointop/table"
"github.com/miguelmota/cointop/pkg/api"
apitypes "github.com/miguelmota/cointop/pkg/api/types"
"github.com/miguelmota/cointop/pkg/pad"
"github.com/miguelmota/cointop/pkg/table"
)
var (
@ -30,6 +24,7 @@ var (
// Cointop cointop
type Cointop struct {
g *gocui.Gui
marketview *gocui.View
chartview *gocui.View
chartpoints [][]termui.Cell
headersview *gocui.View
@ -38,81 +33,10 @@ type Cointop struct {
statusview *gocui.View
sortdesc bool
currentsort string
api apis.Interface
api api.Interface
coins []*apitypes.Coin
}
func (ct *Cointop) layout(g *gocui.Gui) error {
maxX, maxY := g.Size()
chartHeight := 10
if v, err := g.SetView("chart", 0, 0, maxX, chartHeight); err != nil {
if err != gocui.ErrUnknownView {
return err
}
ct.chartview = v
ct.chartview.Frame = false
ct.updateChart()
}
if v, err := g.SetView("header", 0, chartHeight, maxX, maxY); err != nil {
if err != gocui.ErrUnknownView {
return err
}
t := table.New().SetWidth(maxX)
headers := []string{
pad.Right("[r]ank", 13, " "),
pad.Right("[n]ame", 13, " "),
pad.Right("[s]ymbol", 8, " "),
pad.Left("[p]rice", 10, " "),
pad.Left("[m]arket cap", 17, " "),
pad.Left("24H [v]olume", 15, " "),
pad.Left("[1]H%", 9, " "),
pad.Left("[2]4H%", 9, " "),
pad.Left("[7]D%", 9, " "),
pad.Left("[t]otal supply", 20, " "),
pad.Left("[a]vailable supply", 19, " "),
pad.Left("[l]ast updated", 17, " "),
}
for _, h := range headers {
t.AddCol(h)
}
t.Format().Fprint(v)
ct.headersview = v
ct.headersview.Frame = false
ct.headersview.Highlight = true
ct.headersview.SelBgColor = gocui.ColorGreen
ct.headersview.SelFgColor = gocui.ColorBlack
}
if v, err := g.SetView("table", 0, chartHeight+1, maxX, maxY-1); err != nil {
if err != gocui.ErrUnknownView {
return err
}
ct.tableview = v
ct.tableview.Frame = false
ct.tableview.Highlight = true
ct.tableview.SelBgColor = gocui.ColorCyan
ct.tableview.SelFgColor = gocui.ColorBlack
ct.updateTable()
ct.rowChanged()
}
if v, err := g.SetView("status", 0, maxY-2, maxX, maxY); err != nil {
if err != gocui.ErrUnknownView {
return err
}
ct.statusview = v
ct.statusview.Frame = false
ct.statusview.Highlight = true
ct.statusview.SelBgColor = gocui.ColorCyan
ct.statusview.SelFgColor = gocui.ColorBlack
ct.updateStatus("")
}
return nil
}
func (ct *Cointop) rowChanged() {
ct.showLink()
}
@ -133,188 +57,13 @@ func (ct *Cointop) fetchData() ([]*apitypes.Coin, error) {
return result, nil
}
func (ct *Cointop) chartPoints(maxX int, coin string) error {
chart := termui.NewLineChart()
chart.Height = 10
chart.AxesColor = termui.ColorWhite
chart.LineColor = termui.ColorCyan
chart.Border = false
now := time.Now()
secs := now.Unix()
start := secs - oneDay
end := secs
_ = coin
//graphData, err := cmc.GetCoinGraphData(coin, start, end)
graphData, err := ct.api.GetGlobalMarketGraphData(start, end)
if err != nil {
log.Fatal(err)
return nil
}
var data []float64
/*
for i := range graphData.PriceUSD {
data = append(data, graphData.PriceUSD[i][1])
}
*/
for i := range graphData.MarketCapByAvailableSupply {
data = append(data, graphData.MarketCapByAvailableSupply[i][1])
}
chart.Data = data
termui.Body = termui.NewGrid()
termui.Body.Width = maxX
termui.Body.AddRows(
termui.NewRow(
termui.NewCol(12, 0, chart),
),
)
var points [][]termui.Cell
// calculate layout
termui.Body.Align()
w := termui.Body.Width
h := 10
row := termui.Body.Rows[0]
b := row.Buffer()
for i := 0; i < h; i = i + 1 {
var rowpoints []termui.Cell
for j := 0; j < w; j = j + 1 {
p := b.At(j, i)
rowpoints = append(rowpoints, p)
}
points = append(points, rowpoints)
}
ct.chartpoints = points
return nil
}
func (ct *Cointop) updateChart() error {
func (ct *Cointop) updateMarket() error {
maxX, _ := ct.g.Size()
if len(ct.chartpoints) == 0 {
ct.chartPoints(maxX, "bitcoin")
}
for i := range ct.chartpoints {
var s string
for j := range ct.chartpoints[i] {
p := ct.chartpoints[i][j]
s = fmt.Sprintf("%s%c", s, p.Ch)
}
fmt.Fprintln(ct.chartview, s)
}
s := "barfoo"
fmt.Fprintln(ct.marketview, pad.Right(fmt.Sprintf("[q]uit %s", s), maxX, " "))
return nil
}
func (ct *Cointop) updateTable() error {
maxX, _ := ct.g.Size()
ct.table = table.New().SetWidth(maxX)
ct.table.AddCol("")
ct.table.AddCol("")
ct.table.AddCol("")
ct.table.AddCol("")
ct.table.AddCol("")
ct.table.AddCol("")
ct.table.AddCol("")
ct.table.AddCol("")
ct.table.AddCol("")
ct.table.AddCol("")
ct.table.AddCol("")
ct.table.AddCol("")
ct.table.HideColumHeaders = true
var err error
if len(ct.coins) == 0 {
ct.coins, err = ct.fetchData()
if err != nil {
return err
}
}
for _, coin := range ct.coins {
unix, _ := strconv.ParseInt(coin.LastUpdated, 10, 64)
lastUpdated := time.Unix(unix, 0).Format("15:04:05 Jan 02")
colorprice := color.Cyan
color1h := color.White
color24h := color.White
color7d := color.White
if coin.PercentChange1H > 0 {
color1h = color.Green
}
if coin.PercentChange1H < 0 {
color1h = color.Red
}
if coin.PercentChange24H > 0 {
color24h = color.Green
}
if coin.PercentChange24H < 0 {
color24h = color.Red
}
if coin.PercentChange7D > 0 {
color7d = color.Green
}
if coin.PercentChange7D < 0 {
color7d = color.Red
}
ct.table.AddRow(
pad.Left(fmt.Sprint(coin.Rank), 4, " "),
pad.Right(coin.Name, 22, " "),
pad.Right(coin.Symbol, 6, " "),
colorprice(pad.Left(humanize.Commaf(coin.PriceUSD), 12, " ")),
pad.Left(humanize.Commaf(coin.MarketCapUSD), 17, " "),
pad.Left(humanize.Commaf(coin.USD24HVolume), 15, " "),
color1h(pad.Left(fmt.Sprintf("%.2f%%", coin.PercentChange1H), 9, " ")),
color24h(pad.Left(fmt.Sprintf("%.2f%%", coin.PercentChange24H), 9, " ")),
color7d(pad.Left(fmt.Sprintf("%.2f%%", coin.PercentChange7D), 9, " ")),
pad.Left(humanize.Commaf(coin.TotalSupply), 20, " "),
pad.Left(humanize.Commaf(coin.AvailableSupply), 18, " "),
pad.Left(fmt.Sprintf("%s", lastUpdated), 18, " "),
// add %percent of cap
)
}
ct.table.Format().Fprint(ct.tableview)
return nil
}
func (ct *Cointop) updateStatus(s string) {
maxX, _ := ct.g.Size()
ct.statusview.Clear()
fmt.Fprintln(ct.statusview, pad.Right(fmt.Sprintf("[q]uit %s", s), maxX, " "))
}
func (ct *Cointop) showLink() {
url := ct.rowLink()
ct.g.Update(func(g *gocui.Gui) error {
ct.updateStatus(fmt.Sprintf("[enter]=%s", url))
return nil
})
}
func (ct *Cointop) enter(g *gocui.Gui, v *gocui.View) error {
exec.Command("open", ct.rowLink()).Output()
return nil
}
func (ct *Cointop) quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}
func (ct *Cointop) selectedRowIndex() int {
_, y := ct.tableview.Origin()
_, cy := ct.tableview.Cursor()
return y + cy
}
func (ct *Cointop) selectedCoin() *apitypes.Coin {
return ct.coins[ct.selectedRowIndex()]
}
func (ct *Cointop) rowLink() string {
slug := strings.ToLower(strings.Replace(ct.selectedCoin().Name, " ", "-", -1))
return fmt.Sprintf("https://coinmarketcap.com/currencies/%s", slug)
}
func main() {
g, err := gocui.NewGui(gocui.Output256)
if err != nil {
@ -324,17 +73,14 @@ func main() {
g.Cursor = true
g.Mouse = true
g.Highlight = true
ct := Cointop{
g: g,
api: apis.NewCMC(),
api: api.NewCMC(),
}
g.SetManagerFunc(ct.layout)
if err := ct.keybindings(g); err != nil {
log.Fatalf("keybindings: %v", err)
}
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
log.Fatalf("main loop: %v", err)
}

@ -2,6 +2,7 @@ package main
import (
"log"
"os/exec"
"github.com/jroimartin/gocui"
)
@ -45,3 +46,12 @@ func (ct *Cointop) keybindings(g *gocui.Gui) error {
ct.setKeybinding(gocui.KeyEsc, ct.quit)
return nil
}
func (ct *Cointop) enter(g *gocui.Gui, v *gocui.View) error {
exec.Command("open", ct.rowLink()).Output()
return nil
}
func (ct *Cointop) quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}

@ -0,0 +1,93 @@
package main
import (
"github.com/jroimartin/gocui"
"github.com/miguelmota/cointop/pkg/pad"
"github.com/miguelmota/cointop/pkg/table"
)
func (ct *Cointop) layout(g *gocui.Gui) error {
maxX, maxY := g.Size()
chartHeight := 10
topOffset := 0
if v, err := g.SetView("market", 0, topOffset, maxX, 2); err != nil {
if err != gocui.ErrUnknownView {
return err
}
ct.marketview = v
ct.marketview.Frame = false
ct.marketview.BgColor = gocui.ColorBlack
ct.marketview.FgColor = gocui.ColorWhite
ct.updateMarket()
}
topOffset = topOffset + 1
if v, err := g.SetView("chart", 0, topOffset, maxX, topOffset+chartHeight); err != nil {
if err != gocui.ErrUnknownView {
return err
}
ct.chartview = v
ct.chartview.Frame = false
ct.updateChart()
}
topOffset = topOffset + chartHeight
if v, err := g.SetView("header", 0, topOffset, maxX, topOffset+2); err != nil {
if err != gocui.ErrUnknownView {
return err
}
t := table.New().SetWidth(maxX)
headers := []string{
pad.Right("[r]ank", 13, " "),
pad.Right("[n]ame", 13, " "),
pad.Right("[s]ymbol", 8, " "),
pad.Left("[p]rice", 10, " "),
pad.Left("[m]arket cap", 17, " "),
pad.Left("24H [v]olume", 15, " "),
pad.Left("[1]H%", 9, " "),
pad.Left("[2]4H%", 9, " "),
pad.Left("[7]D%", 9, " "),
pad.Left("[t]otal supply", 20, " "),
pad.Left("[a]vailable supply", 19, " "),
pad.Left("[l]ast updated", 17, " "),
}
for _, h := range headers {
t.AddCol(h)
}
t.Format().Fprint(v)
ct.headersview = v
ct.headersview.Frame = false
ct.headersview.Highlight = true
ct.headersview.SelBgColor = gocui.ColorGreen
ct.headersview.SelFgColor = gocui.ColorBlack
}
topOffset = topOffset + 1
if v, err := g.SetView("table", 0, topOffset, maxX, maxY-1); err != nil {
if err != gocui.ErrUnknownView {
return err
}
ct.tableview = v
ct.tableview.Frame = false
ct.tableview.Highlight = true
ct.tableview.SelBgColor = gocui.ColorCyan
ct.tableview.SelFgColor = gocui.ColorBlack
ct.updateTable()
ct.rowChanged()
}
if v, err := g.SetView("status", 0, maxY-2, maxX, maxY); err != nil {
if err != gocui.ErrUnknownView {
return err
}
ct.statusview = v
ct.statusview.Frame = false
ct.statusview.BgColor = gocui.ColorCyan
ct.statusview.FgColor = gocui.ColorBlack
ct.updateStatus("")
}
return nil
}

@ -1,7 +1,7 @@
package apis
package api
import (
cmc "github.com/miguelmota/cointop/apis/cmc"
cmc "github.com/miguelmota/cointop/pkg/api/cmc"
)
// NewCMC new CoinMarketCap api

@ -1,7 +1,7 @@
package apis
package api
import (
types "github.com/miguelmota/cointop/apis/types"
types "github.com/miguelmota/cointop/pkg/api/types"
cmc "github.com/miguelmota/go-coinmarketcap"
)

@ -1,7 +1,7 @@
package apis
package api
import (
types "github.com/miguelmota/cointop/apis/types"
types "github.com/miguelmota/cointop/pkg/api/types"
)
// Interface interface

@ -1,4 +1,4 @@
package apis
package api
// Coin struct
type Coin struct {

@ -6,7 +6,7 @@ import (
"sort"
"strings"
"github.com/miguelmota/cointop/table/align"
"github.com/miguelmota/cointop/pkg/table/align"
)
// Table table

@ -0,0 +1,22 @@
package main
import (
"fmt"
"github.com/jroimartin/gocui"
"github.com/miguelmota/cointop/pkg/pad"
)
func (ct *Cointop) updateStatus(s string) {
maxX, _ := ct.g.Size()
ct.statusview.Clear()
fmt.Fprintln(ct.statusview, pad.Right(fmt.Sprintf("[q]uit %s", s), maxX, " "))
}
func (ct *Cointop) showLink() {
url := ct.rowLink()
ct.g.Update(func(g *gocui.Gui) error {
ct.updateStatus(fmt.Sprintf("[↵]%s", url))
return nil
})
}

@ -0,0 +1,98 @@
package main
import (
"fmt"
"strconv"
"strings"
"time"
humanize "github.com/dustin/go-humanize"
apitypes "github.com/miguelmota/cointop/pkg/api/types"
"github.com/miguelmota/cointop/pkg/color"
"github.com/miguelmota/cointop/pkg/pad"
"github.com/miguelmota/cointop/pkg/table"
)
func (ct *Cointop) updateTable() error {
maxX, _ := ct.g.Size()
ct.table = table.New().SetWidth(maxX)
ct.table.AddCol("")
ct.table.AddCol("")
ct.table.AddCol("")
ct.table.AddCol("")
ct.table.AddCol("")
ct.table.AddCol("")
ct.table.AddCol("")
ct.table.AddCol("")
ct.table.AddCol("")
ct.table.AddCol("")
ct.table.AddCol("")
ct.table.AddCol("")
ct.table.HideColumHeaders = true
var err error
if len(ct.coins) == 0 {
ct.coins, err = ct.fetchData()
if err != nil {
return err
}
}
for _, coin := range ct.coins {
unix, _ := strconv.ParseInt(coin.LastUpdated, 10, 64)
lastUpdated := time.Unix(unix, 0).Format("15:04:05 Jan 02")
colorprice := color.Cyan
color1h := color.White
color24h := color.White
color7d := color.White
if coin.PercentChange1H > 0 {
color1h = color.Green
}
if coin.PercentChange1H < 0 {
color1h = color.Red
}
if coin.PercentChange24H > 0 {
color24h = color.Green
}
if coin.PercentChange24H < 0 {
color24h = color.Red
}
if coin.PercentChange7D > 0 {
color7d = color.Green
}
if coin.PercentChange7D < 0 {
color7d = color.Red
}
ct.table.AddRow(
pad.Left(fmt.Sprint(coin.Rank), 4, " "),
pad.Right(coin.Name, 22, " "),
pad.Right(coin.Symbol, 6, " "),
colorprice(pad.Left(humanize.Commaf(coin.PriceUSD), 12, " ")),
pad.Left(humanize.Commaf(coin.MarketCapUSD), 17, " "),
pad.Left(humanize.Commaf(coin.USD24HVolume), 15, " "),
color1h(pad.Left(fmt.Sprintf("%.2f%%", coin.PercentChange1H), 9, " ")),
color24h(pad.Left(fmt.Sprintf("%.2f%%", coin.PercentChange24H), 9, " ")),
color7d(pad.Left(fmt.Sprintf("%.2f%%", coin.PercentChange7D), 9, " ")),
pad.Left(humanize.Commaf(coin.TotalSupply), 20, " "),
pad.Left(humanize.Commaf(coin.AvailableSupply), 18, " "),
pad.Left(fmt.Sprintf("%s", lastUpdated), 18, " "),
// add %percent of cap
)
}
ct.table.Format().Fprint(ct.tableview)
return nil
}
func (ct *Cointop) selectedRowIndex() int {
_, y := ct.tableview.Origin()
_, cy := ct.tableview.Cursor()
return y + cy
}
func (ct *Cointop) selectedCoin() *apitypes.Coin {
return ct.coins[ct.selectedRowIndex()]
}
func (ct *Cointop) rowLink() string {
slug := strings.ToLower(strings.Replace(ct.selectedCoin().Name, " ", "-", -1))
return fmt.Sprintf("https://coinmarketcap.com/currencies/%s", slug)
}
Loading…
Cancel
Save