Added basics of line editor

master
Michael Dvorkin 12 years ago
parent 713b87609d
commit 8f727f1204
  1. 102
      lib/format.go
  2. 64
      lib/line_editor.go
  3. 63
      lib/profile.go
  4. 96
      lib/screen.go
  5. 236
      lib/yahoo_market.go
  6. 108
      lib/yahoo_quotes.go
  7. 23
      mop.go

@ -3,25 +3,25 @@
package mop
import (
"fmt"
"time"
"bytes"
"regexp"
"strings"
"fmt"
"regexp"
"strings"
"text/template"
"time"
)
//-----------------------------------------------------------------------------
func FormatMarket(m Market) string {
markup := `{{.Dow.name}}: {{.Dow.change}} ({{.Dow.percent}}) at {{.Dow.latest}}, `
markup += `{{.Sp500.name}}: {{.Sp500.change}} ({{.Sp500.percent}}) at {{.Sp500.latest}}, `
markup += `{{.Nasdaq.name}}: {{.Nasdaq.change}} ({{.Nasdaq.percent}}) at {{.Nasdaq.latest}}`
markup += "\n"
markup += `{{.Advances.name}}: {{.Advances.nyse}} ({{.Advances.nysep}}) on NYSE and {{.Advances.nasdaq}} ({{.Advances.nasdaqp}}) on Nasdaq. `
markup += `{{.Declines.name}}: {{.Declines.nyse}} ({{.Declines.nysep}}) on NYSE and {{.Declines.nasdaq}} ({{.Declines.nasdaqp}}) on Nasdaq`
markup += "\n"
markup += `New highs: {{.Highs.nyse}} on NYSE and {{.Highs.nasdaq}} on Nasdaq. `
markup += `New lows: {{.Lows.nyse}} on NYSE and {{.Lows.nasdaq}} on Nasdaq.`
markup += `{{.Sp500.name}}: {{.Sp500.change}} ({{.Sp500.percent}}) at {{.Sp500.latest}}, `
markup += `{{.Nasdaq.name}}: {{.Nasdaq.change}} ({{.Nasdaq.percent}}) at {{.Nasdaq.latest}}`
markup += "\n"
markup += `{{.Advances.name}}: {{.Advances.nyse}} ({{.Advances.nysep}}) on NYSE and {{.Advances.nasdaq}} ({{.Advances.nasdaqp}}) on Nasdaq. `
markup += `{{.Declines.name}}: {{.Declines.nyse}} ({{.Declines.nysep}}) on NYSE and {{.Declines.nasdaq}} ({{.Declines.nasdaqp}}) on Nasdaq`
markup += "\n"
markup += `New highs: {{.Highs.nyse}} on NYSE and {{.Highs.nasdaq}} on Nasdaq. `
markup += `New lows: {{.Lows.nyse}} on NYSE and {{.Lows.nasdaq}} on Nasdaq.`
template, err := template.New("market").Parse(markup)
if err != nil {
panic(err)
@ -33,18 +33,18 @@ func FormatMarket(m Market) string {
panic(err)
}
return buffer.String()
return buffer.String()
}
//-----------------------------------------------------------------------------
func FormatQuotes(quotes Quotes) string {
vars := struct {
Now string
Header string
Header string
Stocks Quotes
}{
time.Now().Format("3:04:05pm PST"),
header(),
header(),
prettify(quotes),
}
@ -67,27 +67,27 @@ func FormatQuotes(quotes Quotes) string {
panic(err)
}
return buffer.String()
return buffer.String()
}
func header() string {
str := fmt.Sprintf("%-7s ", "Ticker")
str += fmt.Sprintf("%9s ", "Last")
str += fmt.Sprintf("%9s ", "Change")
str += fmt.Sprintf("%9s ", "%Change")
str += fmt.Sprintf("%9s ", "Open")
str += fmt.Sprintf("%9s ", "Low")
str += fmt.Sprintf("%9s ", "High")
str += fmt.Sprintf("%9s ", "52w Low")
str += fmt.Sprintf("%9s ", "52w High")
str += fmt.Sprintf("%10s ", "Volume")
str += fmt.Sprintf("%10s ", "AvgVolume")
str += fmt.Sprintf("%9s ", "P/E")
str += fmt.Sprintf("%9s ", "Dividend")
str += fmt.Sprintf("%9s ", "Yield")
str += fmt.Sprintf("%10s", "MktCap")
return str
str := fmt.Sprintf("%-7s ", "Ticker")
str += fmt.Sprintf("%9s ", "Last")
str += fmt.Sprintf("%9s ", "Change")
str += fmt.Sprintf("%9s ", "%Change")
str += fmt.Sprintf("%9s ", "Open")
str += fmt.Sprintf("%9s ", "Low")
str += fmt.Sprintf("%9s ", "High")
str += fmt.Sprintf("%9s ", "52w Low")
str += fmt.Sprintf("%9s ", "52w High")
str += fmt.Sprintf("%10s ", "Volume")
str += fmt.Sprintf("%10s ", "AvgVolume")
str += fmt.Sprintf("%9s ", "P/E")
str += fmt.Sprintf("%9s ", "Dividend")
str += fmt.Sprintf("%9s ", "Yield")
str += fmt.Sprintf("%10s", "MktCap")
return str
}
func prettify(quotes Quotes) Quotes {
@ -113,19 +113,19 @@ func prettify(quotes Quotes) Quotes {
}
func nullify(str string) string {
if len(str) == 3 && str[0:3] == "N/A" {
return "-"
} else {
return str
}
if len(str) == 3 && str[0:3] == "N/A" {
return "-"
} else {
return str
}
}
func last_of_pair(str string) string {
if len(str) >= 6 && str[0:6] != "N/A - " {
if len(str) >= 6 && str[0:6] != "N/A - " {
return str
} else {
return str[6:]
}
} else {
return str[6:]
}
}
func with_currency(str string) string {
@ -168,14 +168,16 @@ func ticker(str string, change string) string {
}
func pad(str string, width int) string {
re := regexp.MustCompile(`(\.\d+)[MB]?$`)
match := re.FindStringSubmatch(str)
if len(match) > 0 {
switch len(match[1]) {
case 2: str = strings.Replace(str, match[1], match[1] + "0", 1)
case 4, 5: str = strings.Replace(str, match[1], match[1][0:3], 1)
}
}
re := regexp.MustCompile(`(\.\d+)[MB]?$`)
match := re.FindStringSubmatch(str)
if len(match) > 0 {
switch len(match[1]) {
case 2:
str = strings.Replace(str, match[1], match[1]+"0", 1)
case 4, 5:
str = strings.Replace(str, match[1], match[1][0:3], 1)
}
}
return fmt.Sprintf("%*s", width, str)
}

@ -0,0 +1,64 @@
// Copyright (c) 2013 by Michael Dvorkin. All Rights Reserved.
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
package mop
import (
"github.com/nsf/termbox-go"
)
// const (
// add_prompt = "Add tickers: "
// remove_prompt = "Remove tickers: "
// )
// const prompts = map[rune]string{'+': `Add tickers: `, '-': `Remove tickers: `}
type LineEditor struct {
command rune
prompt string
cursor int
input string
}
//-----------------------------------------------------------------------------
func (self *LineEditor) Prompt(command rune) {
prompts := map[rune]string{'+': `Add tickers: `, '-': `Remove tickers: `}
self.command = command
switch self.command {
case '+', '-':
self.prompt = prompts[self.command]
// if self.command == '+' {
// self.prompt = add_prompt
// } else {
// self.prompt = remove_prompt
// }
DrawLine(0, 3, "<white>"+self.prompt+"</white>")
termbox.SetCursor(len(self.prompt), 3)
termbox.Flush()
}
}
//-----------------------------------------------------------------------------
func (self *LineEditor) Handle(ev termbox.Event) bool {
switch ev.Key {
case termbox.KeyEsc:
ClearLine(0, 3)
termbox.HideCursor()
termbox.Flush()
return true
case termbox.KeyEnter:
ClearLine(0, 3)
termbox.HideCursor()
termbox.Flush()
return true
default:
if ev.Ch != 0 {
self.input += string(ev.Ch)
DrawLine(len(self.prompt), 3, self.input)
termbox.SetCursor(len(self.prompt)+len(self.input), 3)
termbox.Flush()
}
}
return false
}

@ -1,56 +1,57 @@
// Copyright (c) 2013 by Michael Dvorkin. All Rights Reserved.
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
package mop
import (
"strings"
"os/user"
"io/ioutil"
"encoding/json"
"encoding/json"
"io/ioutil"
"os/user"
"strings"
)
const rcfile = "/.moprc"
type Profile struct {
MarketRefreshRate int
QuotesRefreshRate int
Tickers []string
SortBy string
SortOrder string
MarketRefreshRate int
QuotesRefreshRate int
Tickers []string
SortBy string
SortOrder string
}
var profile Profile
//-----------------------------------------------------------------------------
func LoadProfile() string {
data, err := ioutil.ReadFile(defaultProfile())
if err != nil {
// Set default values.
profile.MarketRefreshRate = 12
profile.QuotesRefreshRate = 5
profile.Tickers = []string{ "AAPL", "C", "GOOG", "IBM", "KO", "ORCL", "V" }
profile.SortBy = "Ticker"
profile.SortOrder = "Desc"
profile.Save()
} else {
json.Unmarshal(data, &profile)
}
data, err := ioutil.ReadFile(defaultProfile())
if err != nil {
// Set default values.
profile.MarketRefreshRate = 12
profile.QuotesRefreshRate = 5
profile.Tickers = []string{"AAPL", "C", "GOOG", "IBM", "KO", "ORCL", "V"}
profile.SortBy = "Ticker"
profile.SortOrder = "Desc"
profile.Save()
} else {
json.Unmarshal(data, &profile)
}
return strings.Join(profile.Tickers, "+")
}
//-----------------------------------------------------------------------------
func (profile *Profile) Save() error {
if data, err := json.Marshal(profile); err != nil {
return err
} else {
return ioutil.WriteFile(defaultProfile(), data, 0644)
}
if data, err := json.Marshal(profile); err != nil {
return err
} else {
return ioutil.WriteFile(defaultProfile(), data, 0644)
}
}
//-----------------------------------------------------------------------------
func defaultProfile() string {
usr, err := user.Current()
if err != nil {
panic(err)
}
return usr.HomeDir + rcfile
usr, err := user.Current()
if err != nil {
panic(err)
}
return usr.HomeDir + rcfile
}

@ -5,9 +5,9 @@ package mop
import (
"github.com/michaeldv/just"
"github.com/nsf/termbox-go"
"time"
"regexp"
"strings"
"time"
)
// Can combine attributes and a single color using bitwise OR.
@ -31,71 +31,31 @@ var tags = map[string]termbox.Attribute{
//-----------------------------------------------------------------------------
func DrawMarket() {
market := GetMarket()
// for _, m := range message {
// fmt.Printf("%s, %s, %s\n", m.Ticker, m.LastTrade, m.Change)
// }
// fmt.Printf("%s\n", Format(message))
drawScreen(FormatMarket(market))
}
//-----------------------------------------------------------------------------
func DrawQuotes(stocks string) {
quotes := GetQuotes(stocks)
// for _, m := range message {
// fmt.Printf("%s, %s, %s\n", m.Ticker, m.LastTrade, m.Change)
// }
// fmt.Printf("%s\n", Format(message))
drawScreen(FormatQuotes(quotes))
}
//-----------------------------------------------------------------------------
func DrawTime() {
now := time.Now().Format("3:04:05pm PST")
drawLine(0, 0, "<right>" + now + "</right>")
}
//
// Return regular expression that matches all possible tags, i.e.
// </?black>|</?red>| ... |</?white>
//-----------------------------------------------------------------------------
func tagsRegexp() *regexp.Regexp {
arr := []string{}
for tag, _ := range tags {
arr = append(arr, "</?"+tag+">")
}
return regexp.MustCompile(strings.Join(arr, "|"))
now := time.Now().Format("3:04:05pm PST")
DrawLine(0, 0, "<right>"+now+"</right>")
}
//
// Return true if a string looks like a tag.
//-----------------------------------------------------------------------------
func isTag(str string) (is bool, open bool) {
is = (len(str) > 3 && str[0:1] == "<" && str[len(str)-1:] == ">")
open = (is && str[1:2] != "/")
return
}
//
// Extract tag name from the given tag, i.e. "<hello>" => "hello"
//-----------------------------------------------------------------------------
func tagName(str string) string {
if len(str) < 3 {
return ""
} else if str[1:2] != "/" {
return str[1 : len(str)-1]
} else {
return str[2 : len(str)-1]
func ClearLine(x int, y int) {
width, _ := termbox.Size()
for i := x; i < width; i++ {
termbox.SetCell(i, y, ' ', termbox.ColorDefault, termbox.ColorDefault)
}
}
//-----------------------------------------------------------------------------
func drawLine(x int, y int, str string) {
func DrawLine(x int, y int, str string) {
column, right := 0, false
foreground, background := termbox.ColorDefault, termbox.ColorDefault
@ -127,12 +87,48 @@ func drawLine(x int, y int, str string) {
column += 1
}
}
termbox.Flush()
termbox.Flush()
}
//-----------------------------------------------------------------------------
func drawScreen(str string) {
for row, line := range strings.Split(str, "\n") {
drawLine(0, row, line)
DrawLine(0, row, line)
}
}
//
// Return regular expression that matches all possible tags, i.e.
// </?black>|</?red>| ... |</?white>
//-----------------------------------------------------------------------------
func tagsRegexp() *regexp.Regexp {
arr := []string{}
for tag, _ := range tags {
arr = append(arr, "</?"+tag+">")
}
return regexp.MustCompile(strings.Join(arr, "|"))
}
//
// Return true if a string looks like a tag.
//-----------------------------------------------------------------------------
func isTag(str string) (is bool, open bool) {
is = (len(str) > 3 && str[0:1] == "<" && str[len(str)-1:] == ">")
open = (is && str[1:2] != "/")
return
}
//
// Extract tag name from the given tag, i.e. "<hello>" => "hello"
//-----------------------------------------------------------------------------
func tagName(str string) string {
if len(str) < 3 {
return ""
} else if str[1:2] != "/" {
return str[1 : len(str)-1]
} else {
return str[2 : len(str)-1]
}
}

@ -3,23 +3,22 @@
package mop
import (
//"fmt"
"bytes"
"regexp"
"strings"
"net/http"
"io/ioutil"
"bytes"
"io/ioutil"
"net/http"
"regexp"
"strings"
)
type Market struct {
Dow map[string]string
Nasdaq map[string]string
Sp500 map[string]string
Advances map[string]string
Declines map[string]string
Unchanged map[string]string
Highs map[string]string
Lows map[string]string
Dow map[string]string
Nasdaq map[string]string
Sp500 map[string]string
Advances map[string]string
Declines map[string]string
Unchanged map[string]string
Highs map[string]string
Lows map[string]string
}
const yahoo_market_url = `http://finance.yahoo.com/marketupdate/overview`
@ -37,114 +36,115 @@ func GetMarket() Market {
panic(err)
}
return extract(trim(body))
return extract(trim(body))
}
func trim(body []byte) []byte {
start := bytes.Index(body, []byte("<table id=\"yfimktsumm\""))
finish := bytes.LastIndex(body, []byte("<table id=\"yfimktsumm\""))
snippet := bytes.Replace(body[start:finish], []byte{'\n'}, []byte{}, -1)
snippet = bytes.Replace(snippet, []byte("&amp;"), []byte{'&'}, -1)
return snippet
start := bytes.Index(body, []byte("<table id=\"yfimktsumm\""))
finish := bytes.LastIndex(body, []byte("<table id=\"yfimktsumm\""))
snippet := bytes.Replace(body[start:finish], []byte{'\n'}, []byte{}, -1)
snippet = bytes.Replace(snippet, []byte("&amp;"), []byte{'&'}, -1)
return snippet
}
func extract(snippet []byte) Market {
const any = `\s*<.+?>`
const some = `<.+?`
const space = `\s*`
const arrow = `"(Up|Down)">\s*`
const price = `([\d\.,]+)`
const percent = `\(([\d\.,%]+)\)`
regex := []string{
"(Dow)", any, price, some, arrow, any, price, some, percent, any,
"(Nasdaq)", any, price, some, arrow, any, price, some, percent, any,
"(S&P 500)", any, price, some, arrow, any, price, some, percent, any,
"(Advances)", any, price, space, percent, any, price, space, percent, any,
"(Declines)", any, price, space, percent, any, price, space, percent, any,
"(Unchanged)", any, price, space, percent, any, price, space, percent, any,
"(New Hi's)", any, price, any, price, any,
"(New Lo's)", any, price, any, price, any,
}
re := regexp.MustCompile(strings.Join(regex, ""))
matches := re.FindAllStringSubmatch(string(snippet), -1)
// if len(matches) > 0 {
// fmt.Printf("%d matches\n", len(matches[0]))
// for i, str := range matches[0][1:] {
// fmt.Printf("%d) [%s]\n", i, str)
// }
// } else {
// println("No matches")
// }
m := Market{
Dow: make(map[string]string),
Nasdaq: make(map[string]string),
Sp500: make(map[string]string),
Advances: make(map[string]string),
Declines: make(map[string]string),
Unchanged: make(map[string]string),
Highs: make(map[string]string),
Lows: make(map[string]string),
}
m.Dow[`name`] = matches[0][1]
m.Dow[`latest`] = matches[0][2]
m.Dow[`change`] = matches[0][4]
if matches[0][3] == "Up" {
m.Dow[`change`] = "+" + matches[0][4]
m.Dow[`percent`] = "+" + matches[0][5]
} else {
m.Dow[`change`] = "-" + matches[0][4]
m.Dow[`percent`] = "-" + matches[0][5]
}
m.Nasdaq[`name`] = matches[0][6]
m.Nasdaq[`latest`] = matches[0][7]
if matches[0][8] == "Up" {
m.Nasdaq[`change`] = "+" + matches[0][9]
m.Nasdaq[`percent`] = "+" + matches[0][10]
} else {
m.Nasdaq[`change`] = "-" + matches[0][9]
m.Nasdaq[`percent`] = "-" + matches[0][10]
}
m.Sp500[`name`] = matches[0][11]
m.Sp500[`latest`] = matches[0][12]
if matches[0][13] == "Up" {
m.Sp500[`change`] = "+" + matches[0][14]
m.Sp500[`percent`] = "+" + matches[0][15]
} else {
m.Sp500[`change`] = "-" + matches[0][14]
m.Sp500[`percent`] = "-" + matches[0][15]
}
m.Advances[`name`] = matches[0][16]
m.Advances[`nyse`] = matches[0][17]
m.Advances[`nysep`] = matches[0][18]
m.Advances[`nasdaq`] = matches[0][19]
m.Advances[`nasdaqp`] = matches[0][20]
m.Declines[`name`] = matches[0][21]
m.Declines[`nyse`] = matches[0][22]
m.Declines[`nysep`] = matches[0][23]
m.Declines[`nasdaq`] = matches[0][24]
m.Declines[`nasdaqp`] = matches[0][25]
m.Unchanged[`name`] = matches[0][26]
m.Unchanged[`nyse`] = matches[0][27]
m.Unchanged[`nysep`] = matches[0][28]
m.Unchanged[`nasdaq`] = matches[0][29]
m.Unchanged[`nasdaqp`] = matches[0][30]
m.Highs[`name`] = matches[0][31]
m.Highs[`nyse`] = matches[0][32]
m.Highs[`nasdaq`] = matches[0][33]
m.Lows[`name`] = matches[0][34]
m.Lows[`nyse`] = matches[0][35]
m.Lows[`nasdaq`] = matches[0][36]
return m;
const any = `\s*<.+?>`
const some = `<.+?`
const space = `\s*`
const arrow = `"(Up|Down)">\s*`
const price = `([\d\.,]+)`
const percent = `\(([\d\.,%]+)\)`
regex := []string{
"(Dow)", any, price, some, arrow, any, price, some, percent, any,
"(Nasdaq)", any, price, /*some, arrow,*/ any, price, some, percent, any,
"(S&P 500)", any, price, some, arrow, any, price, some, percent, any,
"(Advances)", any, price, space, percent, any, price, space, percent, any,
"(Declines)", any, price, space, percent, any, price, space, percent, any,
"(Unchanged)", any, price, space, percent, any, price, space, percent, any,
"(New Hi's)", any, price, any, price, any,
"(New Lo's)", any, price, any, price, any,
}
re := regexp.MustCompile(strings.Join(regex, ""))
matches := re.FindAllStringSubmatch(string(snippet), -1)
// if len(matches) > 0 {
// fmt.Printf("%d matches\n", len(matches[0]))
// for i, str := range matches[0][1:] {
// fmt.Printf("%d) [%s]\n", i, str)
// }
// } else {
// println("No matches")
// }
m := Market{
Dow: make(map[string]string),
Nasdaq: make(map[string]string),
Sp500: make(map[string]string),
Advances: make(map[string]string),
Declines: make(map[string]string),
Unchanged: make(map[string]string),
Highs: make(map[string]string),
Lows: make(map[string]string),
}
return m
m.Dow[`name`] = matches[0][1]
m.Dow[`latest`] = matches[0][2]
m.Dow[`change`] = matches[0][4]
if matches[0][3] == "Up" {
m.Dow[`change`] = "+" + matches[0][4]
m.Dow[`percent`] = "+" + matches[0][5]
} else {
m.Dow[`change`] = "-" + matches[0][4]
m.Dow[`percent`] = "-" + matches[0][5]
}
m.Nasdaq[`name`] = matches[0][6]
m.Nasdaq[`latest`] = matches[0][7]
if matches[0][8] == "Up" {
m.Nasdaq[`change`] = "+" + matches[0][9]
m.Nasdaq[`percent`] = "+" + matches[0][10]
} else {
m.Nasdaq[`change`] = "-" + matches[0][9]
m.Nasdaq[`percent`] = "-" + matches[0][10]
}
m.Sp500[`name`] = matches[0][11]
m.Sp500[`latest`] = matches[0][12]
if matches[0][13] == "Up" {
m.Sp500[`change`] = "+" + matches[0][14]
m.Sp500[`percent`] = "+" + matches[0][15]
} else {
m.Sp500[`change`] = "-" + matches[0][14]
m.Sp500[`percent`] = "-" + matches[0][15]
}
m.Advances[`name`] = matches[0][16]
m.Advances[`nyse`] = matches[0][17]
m.Advances[`nysep`] = matches[0][18]
m.Advances[`nasdaq`] = matches[0][19]
m.Advances[`nasdaqp`] = matches[0][20]
m.Declines[`name`] = matches[0][21]
m.Declines[`nyse`] = matches[0][22]
m.Declines[`nysep`] = matches[0][23]
m.Declines[`nasdaq`] = matches[0][24]
m.Declines[`nasdaqp`] = matches[0][25]
m.Unchanged[`name`] = matches[0][26]
m.Unchanged[`nyse`] = matches[0][27]
m.Unchanged[`nysep`] = matches[0][28]
m.Unchanged[`nasdaq`] = matches[0][29]
m.Unchanged[`nasdaqp`] = matches[0][30]
m.Highs[`name`] = matches[0][31]
m.Highs[`nyse`] = matches[0][32]
m.Highs[`nasdaq`] = matches[0][33]
m.Lows[`name`] = matches[0][34]
m.Lows[`nyse`] = matches[0][35]
m.Lows[`nasdaq`] = matches[0][36]
return m
}

@ -3,11 +3,11 @@
package mop
import (
"fmt"
"bytes"
"strings"
"net/http"
"io/ioutil"
"bytes"
"fmt"
"io/ioutil"
"net/http"
"strings"
)
// See http://www.gummy-stuff.org/Yahoo-data.htm
@ -37,31 +37,31 @@ const yahoo_quotes_url = `http://download.finance.yahoo.com/d/quotes.csv?s=%s&f=
// "TSLA", 120.09, "+4.85", "N/A - +4.21%", 118.75, 115.70, 120.28, 25.52, 121.89, 6827497, 9464530, N/A, N/A, 0.00, N/A, N/A, 13.877B
type Quote struct {
Ticker string
LastTrade string
Change string
ChangePercent string
Open string
Low string
High string
Low52 string
High52 string
Volume string
AvgVolume string
PeRatio string
PeRatioX string
Dividend string
Yield string
MarketCap string
MarketCapX string
Ticker string
LastTrade string
Change string
ChangePercent string
Open string
Low string
High string
Low52 string
High52 string
Volume string
AvgVolume string
PeRatio string
PeRatioX string
Dividend string
Yield string
MarketCap string
MarketCapX string
}
type Quotes []Quote
func GetQuotes(tickers string) Quotes {
// Format the URL and send the request.
// url := fmt.Sprintf(yahoo_quotes_url, strings.Join(tickers, "+"))
url := fmt.Sprintf(yahoo_quotes_url, tickers)
// Format the URL and send the request.
// url := fmt.Sprintf(yahoo_quotes_url, strings.Join(tickers, "+"))
url := fmt.Sprintf(yahoo_quotes_url, tickers)
response, err := http.Get(url)
if err != nil {
panic(err)
@ -74,7 +74,7 @@ func GetQuotes(tickers string) Quotes {
panic(err)
}
return parse(sanitize(body))
return parse(sanitize(body))
}
func (q *Quote) Color() string {
@ -86,46 +86,46 @@ func (q *Quote) Color() string {
}
func sanitize(body []byte) []byte {
return bytes.Replace(bytes.TrimSpace(body), []byte{'"'}, []byte{}, -1)
return bytes.Replace(bytes.TrimSpace(body), []byte{'"'}, []byte{}, -1)
}
func parse(body []byte) Quotes {
lines := bytes.Split(body, []byte{'\n'})
quotes := make(Quotes, len(lines))
lines := bytes.Split(body, []byte{'\n'})
quotes := make(Quotes, len(lines))
for i,line := range lines {
// fmt.Printf("\n\n{%d} -> [%s]\n\n", i, string(line))
parse_line(line, &quotes[i])
}
for i, line := range lines {
// fmt.Printf("\n\n{%d} -> [%s]\n\n", i, string(line))
parse_line(line, &quotes[i])
}
return quotes
return quotes
}
func parse_line(line []byte, quote *Quote) {
columns := bytes.Split(bytes.TrimSpace(line), []byte{','})
columns := bytes.Split(bytes.TrimSpace(line), []byte{','})
quote.Ticker = string(columns[0])
quote.LastTrade = string(columns[1])
quote.Change = string(columns[2])
quote.ChangePercent = string(columns[3])
quote.Open = string(columns[4])
quote.Low = string(columns[5])
quote.High = string(columns[6])
quote.Low52 = string(columns[7])
quote.High52 = string(columns[8])
quote.Volume = string(columns[9])
quote.AvgVolume = string(columns[10])
quote.PeRatio = string(columns[11])
quote.PeRatioX = string(columns[12])
quote.Dividend = string(columns[13])
quote.Yield = string(columns[14])
quote.MarketCap = string(columns[15])
quote.MarketCapX = string(columns[16])
quote.Ticker = string(columns[0])
quote.LastTrade = string(columns[1])
quote.Change = string(columns[2])
quote.ChangePercent = string(columns[3])
quote.Open = string(columns[4])
quote.Low = string(columns[5])
quote.High = string(columns[6])
quote.Low52 = string(columns[7])
quote.High52 = string(columns[8])
quote.Volume = string(columns[9])
quote.AvgVolume = string(columns[10])
quote.PeRatio = string(columns[11])
quote.PeRatioX = string(columns[12])
quote.Dividend = string(columns[13])
quote.Yield = string(columns[14])
quote.MarketCap = string(columns[15])
quote.MarketCapX = string(columns[16])
}
// func (quotes Quotes) Format() string {
// str := time.Now().Format("3:04:05pm PST\n")
//
//
// for _, q := range quotes {
// str += fmt.Sprintf("%s - %s - %s - %s\n", q.Ticker, q.Ask, q.Change, q.ChangePercent)
// }
@ -319,4 +319,4 @@ func parse_line(line []byte, quote *Quote) {
// ]
// }
// }
// }
// }

@ -18,6 +18,7 @@ func initTermbox() {
//-----------------------------------------------------------------------------
func mainLoop(profile string) {
var line_editor *mop.LineEditor
keyboard_queue := make(chan termbox.Event)
timestamp_queue := time.NewTicker(1 * time.Second)
quotes_queue := time.NewTicker(5 * time.Second)
@ -29,7 +30,7 @@ func mainLoop(profile string) {
}
}()
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
mop.DrawMarket()
mop.DrawQuotes(profile)
loop:
@ -38,13 +39,23 @@ loop:
case event := <-keyboard_queue:
switch event.Type {
case termbox.EventKey:
if event.Key == termbox.KeyEsc {
break loop
if line_editor == nil {
if event.Key == termbox.KeyEsc {
break loop
} else if event.Ch == '+' || event.Ch == '-' {
line_editor = new(mop.LineEditor)
line_editor.Prompt(event.Ch)
}
} else {
done := line_editor.Handle(event)
if done {
line_editor = nil
}
}
case termbox.EventResize:
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
mop.DrawMarket()
mop.DrawQuotes(profile)
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
mop.DrawMarket()
mop.DrawQuotes(profile)
}
case <-timestamp_queue.C:

Loading…
Cancel
Save