diff --git a/lib/format.go b/lib/format.go index 44a48d6..0a72da2 100644 --- a/lib/format.go +++ b/lib/format.go @@ -4,6 +4,7 @@ package mop import ( "bytes" + "fmt" "text/template" "time" ) @@ -15,11 +16,14 @@ func Format(message []Message) string { Stocks []Message }{ time.Now().Format("3:04:05pm PST"), - message, + prettify(message), } - markup := `Hello{{.Now}} -{{range .Stocks}}{{.Ticker}} ${{.LastTrade}} {{.Change}} + markup := + `Hello{{.Now}} + +Ticker Last trade Change % Change Dividend Yield +{{range .Stocks}}{{.Color}}{{.Ticker}} {{.LastTrade}} {{.Change}} {{.ChangePercent}} {{.Dividend}} {{.Yield}} {{end}}...` template, err := template.New("screen").Parse(markup) @@ -35,3 +39,80 @@ func Format(message []Message) 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 "" + str + "" + } else { + return "" + str + "" + } +} + +func ticker(str string, change string) string { + if change[0:1] == "-" { + return "" + str + "" + } else { + return "" + str + "" + } +} + +func pad(str string, width int) string { + return fmt.Sprintf("%*s", width, str) +} diff --git a/lib/google_finance.go b/lib/google_finance.go index 9d6cc77..948fddf 100644 --- a/lib/google_finance.go +++ b/lib/google_finance.go @@ -5,95 +5,131 @@ package mop import ( "bytes" "encoding/json" - // "io/ioutil" - // "net/http" + "io/ioutil" + "net/http" + "strings" + "time" ) const real_time_url = "http://finance.google.com/finance/info?client=ig&q=" -const body = ` -// [ -{ -"id": "665300" -,"t" : "COH" -,"e" : "NYSE" -,"l" : "56.54" -,"l_cur" : "56.54" -,"s": "0" -,"ltt":"4:01PM EDT" -,"lt" : "Jun 21, 4:01PM EDT" -,"c" : "-0.75" -,"cp" : "-1.31" -,"ccol" : "chr" -} -,{ -"id": "353353" -,"t" : "ATVI" -,"e" : "NASDAQ" -,"l" : "13.55" -,"l_cur" : "13.55" -,"s": "0" -,"ltt":"3:59PM EDT" -,"lt" : "Jun 21, 3:59PM EDT" -,"c" : "-0.33" -,"cp" : "-2.38" -,"ccol" : "chr" -} -,{ -"id": "17154" -,"t" : "HPQ" -,"e" : "NYSE" -,"l" : "24.15" -,"l_cur" : "24.15" -,"s": "0" -,"ltt":"4:01PM EDT" -,"lt" : "Jun 21, 4:01PM EDT" -,"c" : "-0.57" -,"cp" : "-2.31" -,"ccol" : "chr" -} -,{ -"id": "18241" -,"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" -} -]` + +// const body = ` +// // [ +// { +// "id": "22144" +// ,"t" : "AAPL" +// ,"e" : "NASDAQ" +// ,"l" : "393.78" +// ,"l_cur" : "393.78" +// ,"s": "2" +// ,"ltt":"4:00PM EDT" +// ,"lt" : "Jun 27, 4:00PM EDT" +// ,"c" : "-4.29" +// ,"cp" : "-1.08" +// ,"ccol" : "chr" +// ,"el": "393.40" +// ,"el_cur": "393.40" +// ,"elt" : "Jun 27, 5:04PM EDT" +// ,"ec" : "-0.38" +// ,"ecp" : "-0.10" +// ,"eccol" : "chr" +// ,"div" : "3.05" +// ,"yld" : "3.10" +// } +// ,{ +// "id": "353353" +// ,"t" : "ATVI" +// ,"e" : "NASDAQ" +// ,"l" : "13.55" +// ,"l_cur" : "13.55" +// ,"s": "0" +// ,"ltt":"3:59PM EDT" +// ,"lt" : "Jun 21, 3:59PM EDT" +// ,"c" : "-0.33" +// ,"cp" : "-2.38" +// ,"ccol" : "chr" +// } +// ,{ +// "id": "17154" +// ,"t" : "HPQ" +// ,"e" : "NYSE" +// ,"l" : "24.15" +// ,"l_cur" : "24.15" +// ,"s": "0" +// ,"ltt":"4:01PM EDT" +// ,"lt" : "Jun 21, 4:01PM EDT" +// ,"c" : "0.57" +// ,"cp" : "2.31" +// ,"ccol" : "chr" +// } +// ,{ +// "id": "18241" +// ,"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 { - Ticker string `json:"t"` - LastTrade string `json:"l"` - Change string `json:"c"` + Ticker string `json:"t"` + Exchange string `json:"e"` + LastTrade string `json:"l"` + CurrentPrice string `json:"l_cur"` + LastTradeTime string `json:"ltt"` + LastTradeDateTime string `json:"lt"` + 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 "" + } else { + return "" + } } //----------------------------------------------------------------------------- func Quote(ticker string) []Message { - // // Send the request. - // response, err := http.Get(real_time_url + ticker) - // if err != nil { - // panic(err) - // } - // - // // Fetch response and get its body. - // defer response.Body.Close() - // body, err := ioutil.ReadAll(response.Body) - // - // // Parse JSON. - // var message []Message - // err = json.Unmarshal(sanitize(body), &message) + if len(message) > 0 && time.Now().Second()%5 != 0 { // Fetch quotes every 5 seconds. + return message + } + + // Send the request. + response, err := http.Get(real_time_url + ticker) + if err != nil { + panic(err) + } + + // Fetch response and get its body. + defer response.Body.Close() + body, err := ioutil.ReadAll(response.Body) // Parse JSON. - var message []Message - err := json.Unmarshal(sanitize([]byte(body)), &message) + err = json.Unmarshal(sanitize(body), &message) + + // Parse JSON. + // err := json.Unmarshal(sanitize([]byte(body)), &message) if err != nil { panic(err) } + return message } diff --git a/lib/profile.go b/lib/profile.go index b418aab..73a9bca 100644 --- a/lib/profile.go +++ b/lib/profile.go @@ -4,5 +4,5 @@ package mop //----------------------------------------------------------------------------- func LoadProfile() string { - return "coh,atvi,hpq,ibm" + return "aapl,atvi,c,coh,goog,hpq,ibm,ma,tsla,v,yhoo,inin,crm,saas" } diff --git a/lib/screen.go b/lib/screen.go index dc3c32b..97d8d8f 100644 --- a/lib/screen.go +++ b/lib/screen.go @@ -30,9 +30,11 @@ var tags = map[string]termbox.Attribute{ //----------------------------------------------------------------------------- func Draw(stocks string) { message := Quote(stocks) + // 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)) } @@ -55,7 +57,7 @@ func tagsRegexp() *regexp.Regexp { // Return true if a string looks like a tag. //----------------------------------------------------------------------------- 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] != "/") return } @@ -64,7 +66,9 @@ func isTag(str string) (is bool, open bool) { // Extract tag name from the given tag, i.e. "" => "hello" //----------------------------------------------------------------------------- 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] } else { return str[2 : len(str)-1] diff --git a/mop b/mop new file mode 100755 index 0000000..144fd25 Binary files /dev/null and b/mop differ