Added colors and proper column alignment

master
Michael Dvorkin 12 years ago
parent cf92c5f858
commit 7cf1d8fba2
  1. 87
      lib/format.go
  2. 180
      lib/google_finance.go
  3. 2
      lib/profile.go
  4. 8
      lib/screen.go
  5. BIN
      mop

@ -4,6 +4,7 @@ package mop
import ( import (
"bytes" "bytes"
"fmt"
"text/template" "text/template"
"time" "time"
) )
@ -15,11 +16,14 @@ func Format(message []Message) string {
Stocks []Message Stocks []Message
}{ }{
time.Now().Format("3:04:05pm PST"), time.Now().Format("3:04:05pm PST"),
message, prettify(message),
} }
markup := `Hello<right>{{.Now}}</right> markup :=
{{range .Stocks}}<green>{{.Ticker}}</green> ${{.LastTrade}} <red>{{.Change}}</red> `Hello<right>{{.Now}}</right>
Ticker Last trade Change % Change Dividend Yield
{{range .Stocks}}{{.Color}}{{.Ticker}} {{.LastTrade}} {{.Change}} {{.ChangePercent}} {{.Dividend}} {{.Yield}}
{{end}}...` {{end}}...`
template, err := template.New("screen").Parse(markup) template, err := template.New("screen").Parse(markup)
@ -35,3 +39,80 @@ func Format(message []Message) string {
return buffer.String() return buffer.String()
} }
func color(m Message) string {
return "x"
}
func prettify(message []Message) []Message {
pretty := make([]Message, len(message))
for i, m := range message {
pretty[i].Ticker = pad(m.Ticker, -10)
pretty[i].LastTrade = pad(with_currency(m.LastTrade), 10)
pretty[i].CurrentPrice = pad(with_currency(m.CurrentPrice), 10)
pretty[i].Change = pad(with_currency(m.Change), 10)
pretty[i].ChangePercent = pad(with_percent(m.ChangePercent), 10)
// ExLastTrade string `json:"el"`
// ExCurrentPrice string `json:"el_cur"`
// ExLastTradeDateTime string `json:"elt"`
// ExChange string `json:"ec"`
// ExChangePercentage string `json:"ecp"`
pretty[i].Dividend = pad(with_currency(nullify(m.Dividend)), 10)
pretty[i].Yield = pad(with_currency(nullify(m.Yield)), 10)
}
// fmt.Printf("%q", pretty)
return pretty
}
func nullify(str string) string {
if len(str) > 0 {
return str
} else {
return "-"
}
}
func with_currency(str string) string {
if str == "-" {
return str
} else {
switch str[0:1] {
case "+", "-":
return str[0:1] + "$" + str[1:]
default:
return "$" + str
}
}
}
func with_percent(str string) string {
if str == "-" {
return str
} else if str[0:1] != "-" {
return "+" + str + "%"
} else {
return str + "%"
}
}
func colorize(str string) string {
if str == "-" {
return str
} else if str[0:1] == "-" {
return "<red>" + str + "</red>"
} else {
return "<green>" + str + "</green>"
}
}
func ticker(str string, change string) string {
if change[0:1] == "-" {
return "<red>" + str + "</red>"
} else {
return "<green>" + str + "</green>"
}
}
func pad(str string, width int) string {
return fmt.Sprintf("%*s", width, str)
}

@ -5,95 +5,131 @@ package mop
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
// "io/ioutil" "io/ioutil"
// "net/http" "net/http"
"strings"
"time"
) )
const real_time_url = "http://finance.google.com/finance/info?client=ig&q=" const real_time_url = "http://finance.google.com/finance/info?client=ig&q="
const body = `
// [ // const body = `
{ // // [
"id": "665300" // {
,"t" : "COH" // "id": "22144"
,"e" : "NYSE" // ,"t" : "AAPL"
,"l" : "56.54" // ,"e" : "NASDAQ"
,"l_cur" : "56.54" // ,"l" : "393.78"
,"s": "0" // ,"l_cur" : "393.78"
,"ltt":"4:01PM EDT" // ,"s": "2"
,"lt" : "Jun 21, 4:01PM EDT" // ,"ltt":"4:00PM EDT"
,"c" : "-0.75" // ,"lt" : "Jun 27, 4:00PM EDT"
,"cp" : "-1.31" // ,"c" : "-4.29"
,"ccol" : "chr" // ,"cp" : "-1.08"
} // ,"ccol" : "chr"
,{ // ,"el": "393.40"
"id": "353353" // ,"el_cur": "393.40"
,"t" : "ATVI" // ,"elt" : "Jun 27, 5:04PM EDT"
,"e" : "NASDAQ" // ,"ec" : "-0.38"
,"l" : "13.55" // ,"ecp" : "-0.10"
,"l_cur" : "13.55" // ,"eccol" : "chr"
,"s": "0" // ,"div" : "3.05"
,"ltt":"3:59PM EDT" // ,"yld" : "3.10"
,"lt" : "Jun 21, 3:59PM EDT" // }
,"c" : "-0.33" // ,{
,"cp" : "-2.38" // "id": "353353"
,"ccol" : "chr" // ,"t" : "ATVI"
} // ,"e" : "NASDAQ"
,{ // ,"l" : "13.55"
"id": "17154" // ,"l_cur" : "13.55"
,"t" : "HPQ" // ,"s": "0"
,"e" : "NYSE" // ,"ltt":"3:59PM EDT"
,"l" : "24.15" // ,"lt" : "Jun 21, 3:59PM EDT"
,"l_cur" : "24.15" // ,"c" : "-0.33"
,"s": "0" // ,"cp" : "-2.38"
,"ltt":"4:01PM EDT" // ,"ccol" : "chr"
,"lt" : "Jun 21, 4:01PM EDT" // }
,"c" : "-0.57" // ,{
,"cp" : "-2.31" // "id": "17154"
,"ccol" : "chr" // ,"t" : "HPQ"
} // ,"e" : "NYSE"
,{ // ,"l" : "24.15"
"id": "18241" // ,"l_cur" : "24.15"
,"t" : "IBM" // ,"s": "0"
,"e" : "NYSE" // ,"ltt":"4:01PM EDT"
,"l" : "195.46" // ,"lt" : "Jun 21, 4:01PM EDT"
,"l_cur" : "195.46" // ,"c" : "0.57"
,"s": "0" // ,"cp" : "2.31"
,"ltt":"4:02PM EDT" // ,"ccol" : "chr"
,"lt" : "Jun 21, 4:02PM EDT" // }
,"c" : "-1.89" // ,{
,"cp" : "-0.96" // "id": "18241"
,"ccol" : "chr" // ,"t" : "IBM"
} // ,"e" : "NYSE"
]` // ,"l" : "195.46"
// ,"l_cur" : "195.46"
// ,"s": "0"
// ,"ltt":"4:02PM EDT"
// ,"lt" : "Jun 21, 4:02PM EDT"
// ,"c" : "-1.89"
// ,"cp" : "-0.96"
// ,"ccol" : "chr"
// }
// ]`
type Message struct { type Message struct {
Ticker string `json:"t"` Ticker string `json:"t"`
Exchange string `json:"e"`
LastTrade string `json:"l"` LastTrade string `json:"l"`
CurrentPrice string `json:"l_cur"`
LastTradeTime string `json:"ltt"`
LastTradeDateTime string `json:"lt"`
Change string `json:"c"` Change string `json:"c"`
ChangePercent string `json:"cp"`
ExLastTrade string `json:"el"`
ExCurrentPrice string `json:"el_cur"`
ExLastTradeDateTime string `json:"elt"`
ExChange string `json:"ec"`
ExChangePercent string `json:"ecp"`
Dividend string `json:"div"`
Yield string `json:"yld"`
}
var message []Message
func (m *Message) Color() string {
if strings.Index(m.Change, "-") == -1 {
return "</green><green>"
} else {
return "</red><red>"
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
func Quote(ticker string) []Message { func Quote(ticker string) []Message {
// // Send the request. if len(message) > 0 && time.Now().Second()%5 != 0 { // Fetch quotes every 5 seconds.
// response, err := http.Get(real_time_url + ticker) return message
// if err != nil { }
// panic(err)
// } // Send the request.
// response, err := http.Get(real_time_url + ticker)
// // Fetch response and get its body. if err != nil {
// defer response.Body.Close() panic(err)
// body, err := ioutil.ReadAll(response.Body) }
//
// // Parse JSON. // Fetch response and get its body.
// var message []Message defer response.Body.Close()
// err = json.Unmarshal(sanitize(body), &message) body, err := ioutil.ReadAll(response.Body)
// Parse JSON. // Parse JSON.
var message []Message err = json.Unmarshal(sanitize(body), &message)
err := json.Unmarshal(sanitize([]byte(body)), &message)
// Parse JSON.
// err := json.Unmarshal(sanitize([]byte(body)), &message)
if err != nil { if err != nil {
panic(err) panic(err)
} }
return message return message
} }

@ -4,5 +4,5 @@ package mop
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
func LoadProfile() string { func LoadProfile() string {
return "coh,atvi,hpq,ibm" return "aapl,atvi,c,coh,goog,hpq,ibm,ma,tsla,v,yhoo,inin,crm,saas"
} }

@ -30,9 +30,11 @@ var tags = map[string]termbox.Attribute{
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
func Draw(stocks string) { func Draw(stocks string) {
message := Quote(stocks) message := Quote(stocks)
// for _, m := range message { // for _, m := range message {
// fmt.Printf("%s, %s, %s\n", m.Ticker, m.LastTrade, m.Change) // fmt.Printf("%s, %s, %s\n", m.Ticker, m.LastTrade, m.Change)
// } // }
// fmt.Printf("%s\n", Format(message))
drawScreen(Format(message)) drawScreen(Format(message))
} }
@ -55,7 +57,7 @@ func tagsRegexp() *regexp.Regexp {
// Return true if a string looks like a tag. // Return true if a string looks like a tag.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
func isTag(str string) (is bool, open bool) { func isTag(str string) (is bool, open bool) {
is = (str[0:1] == "<" && str[len(str)-1:] == ">") is = (len(str) > 3 && str[0:1] == "<" && str[len(str)-1:] == ">")
open = (is && str[1:2] != "/") open = (is && str[1:2] != "/")
return return
} }
@ -64,7 +66,9 @@ func isTag(str string) (is bool, open bool) {
// Extract tag name from the given tag, i.e. "<hello>" => "hello" // Extract tag name from the given tag, i.e. "<hello>" => "hello"
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
func tagName(str string) string { func tagName(str string) string {
if str[1:2] != "/" { if len(str) < 3 {
return ""
} else if str[1:2] != "/" {
return str[1 : len(str)-1] return str[1 : len(str)-1]
} else { } else {
return str[2 : len(str)-1] return str[2 : len(str)-1]

BIN
mop

Binary file not shown.
Loading…
Cancel
Save