diff --git a/lib/format.go b/lib/format.go
index a3da2ba..7c63e57 100644
--- a/lib/format.go
+++ b/lib/format.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)
}
diff --git a/lib/line_editor.go b/lib/line_editor.go
new file mode 100644
index 0000000..ea81415
--- /dev/null
+++ b/lib/line_editor.go
@@ -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, ""+self.prompt+"")
+ 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
+}
diff --git a/lib/profile.go b/lib/profile.go
index fb00171..c6c09a4 100644
--- a/lib/profile.go
+++ b/lib/profile.go
@@ -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
}
diff --git a/lib/screen.go b/lib/screen.go
index 4c679de..b924c24 100644
--- a/lib/screen.go
+++ b/lib/screen.go
@@ -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, "" + now + "")
-}
-
-//
-// 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, ""+now+"")
}
-//
-// 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"
//-----------------------------------------------------------------------------
-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"
+//-----------------------------------------------------------------------------
+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]
}
}
diff --git a/lib/yahoo_market.go b/lib/yahoo_market.go
index 186c0f6..70b492c 100644
--- a/lib/yahoo_market.go
+++ b/lib/yahoo_market.go
@@ -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("`
- 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
}
diff --git a/lib/yahoo_quotes.go b/lib/yahoo_quotes.go
index f49e329..7f0f324 100644
--- a/lib/yahoo_quotes.go
+++ b/lib/yahoo_quotes.go
@@ -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, "es[i])
- }
+ for i, line := range lines {
+ // fmt.Printf("\n\n{%d} -> [%s]\n\n", i, string(line))
+ parse_line(line, "es[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) {
// ]
// }
// }
-// }
\ No newline at end of file
+// }
diff --git a/mop.go b/mop.go
index 8a7a926..f7c6a82 100644
--- a/mop.go
+++ b/mop.go
@@ -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: