diff --git a/lib/format.go b/lib/format.go
index acb20a3..549dbf5 100644
--- a/lib/format.go
+++ b/lib/format.go
@@ -52,15 +52,15 @@ func FormatMarket(m *Market) string {
}
//-----------------------------------------------------------------------------
-func FormatQuotes(quotes Quotes) string {
+func FormatQuotes(q *Quotes) string {
vars := struct {
Now string
Header string
- Stocks Quotes
+ Stocks []Stock
}{
time.Now().Format(`3:04:05pm PST`),
header(),
- prettify(quotes),
+ prettify(q.stocks),
}
markup := `{{.Now}}
@@ -85,6 +85,7 @@ func FormatQuotes(quotes Quotes) string {
return buffer.String()
}
+//-----------------------------------------------------------------------------
func header() string {
str := fmt.Sprintf(`%-7s `, `Ticker`)
str += fmt.Sprintf(`%9s `, `Last`)
@@ -105,9 +106,10 @@ func header() string {
return str
}
-func prettify(quotes Quotes) Quotes {
- pretty := make(Quotes, len(quotes))
- for i, q := range quotes {
+//-----------------------------------------------------------------------------
+func prettify(stocks []Stock) []Stock {
+ pretty := make([]Stock, len(stocks))
+ for i, q := range stocks {
pretty[i].Ticker = pad(q.Ticker, -7)
pretty[i].LastTrade = pad(with_currency(q.LastTrade), 9)
pretty[i].Change = pad(with_currency(q.Change), 9)
@@ -127,6 +129,7 @@ func prettify(quotes Quotes) Quotes {
return pretty
}
+//-----------------------------------------------------------------------------
func nullify(str string) string {
if len(str) == 3 && str[0:3] == `N/A` {
return `-`
@@ -135,6 +138,7 @@ func nullify(str string) string {
}
}
+//-----------------------------------------------------------------------------
func last_of_pair(str string) string {
if len(str) >= 6 && str[0:6] != `N/A - ` {
return str
@@ -143,6 +147,7 @@ func last_of_pair(str string) string {
}
}
+//-----------------------------------------------------------------------------
func with_currency(str string) string {
if str == `N/A` || str == `0.00` {
return `-`
@@ -156,6 +161,7 @@ func with_currency(str string) string {
}
}
+//-----------------------------------------------------------------------------
func with_percent(str string) string {
if str == `N/A` {
return `-`
@@ -164,6 +170,7 @@ func with_percent(str string) string {
}
}
+//-----------------------------------------------------------------------------
func colorize(str string) string {
if str == `N/A` {
return `-`
@@ -174,6 +181,7 @@ func colorize(str string) string {
}
}
+//-----------------------------------------------------------------------------
func ticker(str string, change string) string {
if change[0:1] == `-` {
return `` + str + ``
@@ -182,6 +190,7 @@ func ticker(str string, change string) string {
}
}
+//-----------------------------------------------------------------------------
func pad(str string, width int) string {
re := regexp.MustCompile(`(\.\d+)[MB]?$`)
match := re.FindStringSubmatch(str)
diff --git a/lib/line_editor.go b/lib/line_editor.go
index e9aaa0b..5b09011 100644
--- a/lib/line_editor.go
+++ b/lib/line_editor.go
@@ -14,13 +14,13 @@ type LineEditor struct {
cursor int
input string
screen *Screen
- profile *Profile
+ quotes *Quotes
}
//-----------------------------------------------------------------------------
-func (self *LineEditor) Initialize(screen *Screen, profile *Profile) *LineEditor {
+func (self *LineEditor) Initialize(screen *Screen, quotes *Quotes) *LineEditor {
self.screen = screen
- self.profile = profile
+ self.quotes = quotes
return self
}
@@ -147,17 +147,17 @@ func (self *LineEditor) execute() {
case '+':
tickers := self.tokenize()
if len(tickers) > 0 {
- self.profile.AddTickers(tickers)
- self.screen.DrawQuotes(self.profile.Quotes())
+ self.quotes.profile.AddTickers(tickers)
+ self.screen.DrawQuotes(self.quotes)
}
case '-':
tickers := self.tokenize()
if len(tickers) > 0 {
- before := len(self.profile.Tickers)
- self.profile.RemoveTickers(tickers)
- after := len(self.profile.Tickers)
+ before := len(self.quotes.profile.Tickers)
+ self.quotes.profile.RemoveTickers(tickers)
+ after := len(self.quotes.profile.Tickers)
if after < before {
- self.screen.DrawQuotes(self.profile.Quotes())
+ self.screen.DrawQuotes(self.quotes)
for i := before; i > after; i-- {
self.screen.ClearLine(0, i + 4)
}
diff --git a/lib/profile.go b/lib/profile.go
index 5fa4702..96b14bc 100644
--- a/lib/profile.go
+++ b/lib/profile.go
@@ -47,7 +47,7 @@ func (self *Profile) Save() error {
}
//-----------------------------------------------------------------------------
-func (self *Profile) Quotes() string {
+func (self *Profile) ListOfTickers() string {
return strings.Join(self.Tickers, `+`)
}
diff --git a/lib/screen.go b/lib/screen.go
index 40059dd..3709877 100644
--- a/lib/screen.go
+++ b/lib/screen.go
@@ -60,13 +60,12 @@ func (self *Screen) Close() {
//-----------------------------------------------------------------------------
func (self *Screen) DrawMarket(market *Market) {
- self.draw(FormatMarket(market))
+ self.draw(FormatMarket(market.Fetch()))
}
//-----------------------------------------------------------------------------
-func (self *Screen) DrawQuotes(stocks string) {
- quotes := GetQuotes(stocks)
- self.draw(FormatQuotes(quotes))
+func (self *Screen) DrawQuotes(quotes *Quotes) {
+ self.draw(FormatQuotes(quotes.Fetch()))
}
//-----------------------------------------------------------------------------
diff --git a/lib/yahoo_quotes.go b/lib/yahoo_quotes.go
index 2d5e0a4..833aa89 100644
--- a/lib/yahoo_quotes.go
+++ b/lib/yahoo_quotes.go
@@ -10,10 +10,10 @@ import (
`strings`
)
-// See http://www.gummy-stuff.org/Yahoo-data.htm
+// See http://www.gummy-stuff.org/Yahoo-stocks.htm
// Also http://query.yahooapis.com/v1/public/yql
// ?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in(%22ALU%22,%22AAPL%22)
-// &env=http%3A%2F%2Fdatatables.org%2Falltables.env
+// &env=http%3A%2F%2Fstockstables.org%2Falltables.env
// &format=json'
//
// Current, Change, Open, High, Low, 52-W High, 52-W Low, Volume, AvgVolume, P/E, Yield, Market Cap.
@@ -36,7 +36,7 @@ import (
const yahoo_quotes_url = `http://download.finance.yahoo.com/d/quotes.csv?s=%s&f=,l1c6k2oghjkva2r2rdyj3j1`
-type Quote struct {
+type Stock struct {
Ticker string
LastTrade string
Change string
@@ -55,12 +55,26 @@ type Quote struct {
MarketCap string
MarketCapX string
}
-type Quotes []Quote
-func GetQuotes(tickers string) Quotes {
+type Quotes struct {
+ market *Market
+ profile *Profile
+ stocks []Stock
+}
+
+//-----------------------------------------------------------------------------
+func (self *Quotes) Initialize(market *Market, profile *Profile) *Quotes {
+ self.market = market
+ self.profile = profile
+
+ return self
+}
+
+//-----------------------------------------------------------------------------
+func (self *Quotes) Fetch() *Quotes {
// Format the URL and send the request.
- url := fmt.Sprintf(yahoo_quotes_url, tickers)
+ url := fmt.Sprintf(yahoo_quotes_url, self.profile.ListOfTickers())
response, err := http.Get(url)
if err != nil {
panic(err)
@@ -73,51 +87,48 @@ func GetQuotes(tickers string) Quotes {
panic(err)
}
- return parse(sanitize(body))
-}
-
-func (q *Quote) Color() string {
- if strings.Index(q.Change, "-") == -1 {
- return ``
- } else {
- return `` // ``
- }
+ return self.parse(self.sanitize(body))
}
-func sanitize(body []byte) []byte {
- return bytes.Replace(bytes.TrimSpace(body), []byte{'"'}, []byte{}, -1)
-}
-
-func parse(body []byte) Quotes {
+//-----------------------------------------------------------------------------
+func (self *Quotes) parse(body []byte) *Quotes {
lines := bytes.Split(body, []byte{'\n'})
- quotes := make(Quotes, len(lines))
+ self.stocks = make([]Stock, len(lines))
for i, line := range lines {
- // fmt.Printf("\n\n{%d} -> [%s]\n\n", i, string(line))
- parse_line(line, "es[i])
+ columns := bytes.Split(bytes.TrimSpace(line), []byte{','})
+ self.stocks[i].Ticker = string(columns[0])
+ self.stocks[i].LastTrade = string(columns[1])
+ self.stocks[i].Change = string(columns[2])
+ self.stocks[i].ChangePercent = string(columns[3])
+ self.stocks[i].Open = string(columns[4])
+ self.stocks[i].Low = string(columns[5])
+ self.stocks[i].High = string(columns[6])
+ self.stocks[i].Low52 = string(columns[7])
+ self.stocks[i].High52 = string(columns[8])
+ self.stocks[i].Volume = string(columns[9])
+ self.stocks[i].AvgVolume = string(columns[10])
+ self.stocks[i].PeRatio = string(columns[11])
+ self.stocks[i].PeRatioX = string(columns[12])
+ self.stocks[i].Dividend = string(columns[13])
+ self.stocks[i].Yield = string(columns[14])
+ self.stocks[i].MarketCap = string(columns[15])
+ self.stocks[i].MarketCapX = string(columns[16])
}
- return quotes
+ return self
+}
+
+//-----------------------------------------------------------------------------
+func (self *Quotes) sanitize(body []byte) []byte {
+ return bytes.Replace(bytes.TrimSpace(body), []byte{'"'}, []byte{}, -1)
}
-func parse_line(line []byte, quote *Quote) {
- 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])
+//-----------------------------------------------------------------------------
+func (stock *Stock) Color() string {
+ if strings.Index(stock.Change, "-") == -1 {
+ return ``
+ } else {
+ return `` // ``
+ }
}
diff --git a/mop.go b/mop.go
index bc84317..cd95946 100644
--- a/mop.go
+++ b/mop.go
@@ -23,9 +23,10 @@ func mainLoop(screen *mop.Screen, profile *mop.Profile) {
}()
market := new(mop.Market).Initialize().Fetch()
+ quotes := new(mop.Quotes).Initialize(market, profile)
screen.Clear()
screen.DrawMarket(market)
- screen.DrawQuotes(profile.Quotes())
+ screen.DrawQuotes(quotes)
loop:
for {
@@ -37,7 +38,7 @@ loop:
if event.Key == termbox.KeyEsc {
break loop
} else if event.Ch == '+' || event.Ch == '-' {
- line_editor = new(mop.LineEditor).Initialize(screen, profile)
+ line_editor = new(mop.LineEditor).Initialize(screen, quotes)
line_editor.Prompt(event.Ch)
}
} else {
@@ -48,18 +49,18 @@ loop:
}
case termbox.EventResize:
screen.Resize().Clear()
- screen.DrawMarket(market.Fetch())
- screen.DrawQuotes(profile.Quotes())
+ screen.DrawMarket(market)
+ screen.DrawQuotes(quotes)
}
case <-timestamp_queue.C:
screen.DrawTime()
case <-quotes_queue.C:
- screen.DrawQuotes(profile.Quotes())
+ screen.DrawQuotes(quotes)
case <-market_queue.C:
- screen.DrawMarket(market.Fetch())
+ screen.DrawMarket(market)
}
}
}