diff --git a/lib/layout.go b/lib/layout.go
index 0bc4c19..0443da8 100644
--- a/lib/layout.go
+++ b/lib/layout.go
@@ -49,19 +49,19 @@ func (self *Layout) Initialize() *Layout {
func (self *Layout) Market(m *Market) string {
markup := `{{.Dow.name}}: `
if m.Dow[`change`][0:1] != `-` {
- markup += `{{.Dow.change}} ({{.Dow.percent}}) at {{.Dow.latest}}, `
+ markup += `{{.Dow.change}} ({{.Dow.percent}})> at {{.Dow.latest}}, `
} else {
markup += `{{.Dow.change}} ({{.Dow.percent}}) at {{.Dow.latest}}, `
}
markup += `{{.Sp500.name}}: `
if m.Sp500[`change`][0:1] != `-` {
- markup += `{{.Sp500.change}} ({{.Sp500.percent}}) at {{.Sp500.latest}}, `
+ markup += `{{.Sp500.change}} ({{.Sp500.percent}})> at {{.Sp500.latest}}, `
} else {
markup += `{{.Sp500.change}} ({{.Sp500.percent}}) at {{.Sp500.latest}}, `
}
markup += `{{.Nasdaq.name}}: `
if m.Nasdaq[`change`][0:1] != `-` {
- markup += `{{.Nasdaq.change}} ({{.Nasdaq.percent}}) at {{.Nasdaq.latest}}`
+ markup += `{{.Nasdaq.change}} ({{.Nasdaq.percent}})> at {{.Nasdaq.latest}}`
} else {
markup += `{{.Nasdaq.change}} ({{.Nasdaq.percent}}) at {{.Nasdaq.latest}}`
}
@@ -100,7 +100,7 @@ func (self *Layout) Quotes(quotes *Quotes) string {
self.prettify(quotes),
}
- markup := `{{.Now}}
+ markup := `{{.Now}}>
@@ -256,26 +256,6 @@ func percent(str string) string {
}
}
-//-----------------------------------------------------------------------------
-func colorize(str string) string {
- if str == `N/A` {
- return `-`
- } 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 {
re := regexp.MustCompile(`(\.\d+)[MB]?$`)
diff --git a/lib/line_editor.go b/lib/line_editor.go
index 039ed59..39864e1 100644
--- a/lib/line_editor.go
+++ b/lib/line_editor.go
@@ -32,7 +32,7 @@ func (self *LineEditor) Prompt(command rune) {
self.prompt = prompt
self.command = command
- self.screen.DrawLine(0, 3, `` + self.prompt + ``)
+ self.screen.DrawLine(0, 3, `` + self.prompt + `>`)
termbox.SetCursor(len(self.prompt), 3)
termbox.Flush()
}
diff --git a/lib/markup.go b/lib/markup.go
new file mode 100644
index 0000000..aedb2df
--- /dev/null
+++ b/lib/markup.go
@@ -0,0 +1,138 @@
+// Copyright (c) 2013 by Michael Dvorkin. All Rights Reserved.
+//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+package mop
+
+import (
+ `github.com/nsf/termbox-go`
+ `regexp`
+ `strings`
+)
+
+type Markup struct {
+ tags map[string]termbox.Attribute
+ Foreground termbox.Attribute
+ Background termbox.Attribute
+ RightAligned bool
+}
+
+//-----------------------------------------------------------------------------
+func (self *Markup) Initialize() *Markup {
+ self.tags = make(map[string]termbox.Attribute)
+ self.tags[`/`] = termbox.ColorDefault
+ self.tags[`black`] = termbox.ColorBlack
+ self.tags[`red`] = termbox.ColorRed
+ self.tags[`green`] = termbox.ColorGreen
+ self.tags[`yellow`] = termbox.ColorYellow
+ self.tags[`blue`] = termbox.ColorBlue
+ self.tags[`magenta`] = termbox.ColorMagenta
+ self.tags[`cyan`] = termbox.ColorCyan
+ self.tags[`white`] = termbox.ColorWhite
+ self.tags[`right`] = termbox.ColorDefault // Termbox can combine attributes and a single color using bitwise OR.
+ self.tags[`b`] = termbox.AttrBold // Attribute = 1 << (iota + 4)
+ self.tags[`u`] = termbox.AttrUnderline
+ self.tags[`r`] = termbox.AttrReverse
+ self.Foreground = termbox.ColorDefault
+ self.Background = termbox.ColorDefault
+ self.RightAligned = false
+
+ return self
+}
+
+//-----------------------------------------------------------------------------
+func (self *Markup) Tokenize(str string) []string {
+ matches := self.supported_tags().FindAllStringIndex(str, -1)
+ strings := make([]string, 0, len(matches))
+
+ head, tail := 0, 0
+ for _, match := range matches {
+ tail = match[0]
+ if match[1] != 0 {
+ if head != 0 || tail != 0 {
+ strings = append(strings, str[head:tail]) // Apend text between tags.
+ }
+ strings = append(strings, str[match[0]:match[1]]) // Append tag.
+ }
+ head = match[1]
+ }
+
+ if head != len(str) && tail != len(str) {
+ strings = append(strings, str[head:])
+ }
+
+ return strings
+}
+
+//-----------------------------------------------------------------------------
+func (self *Markup) IsTag(str string) bool {
+ tag, open := probe_tag(str)
+
+ if tag == `` {
+ return false
+ }
+
+ return self.process(tag, open)
+}
+
+//-----------------------------------------------------------------------------
+func (self *Markup) process(tag string, open bool) bool {
+ if attribute, ok := self.tags[tag]; ok {
+ switch tag {
+ case `right`:
+ self.RightAligned = open
+ default:
+ if open {
+ if attribute >= termbox.AttrBold {
+ self.Foreground |= attribute
+ } else {
+ self.Foreground = attribute
+ }
+ } else {
+ if attribute >= termbox.AttrBold {
+ self.Foreground &= ^attribute
+ } else {
+ self.Foreground = termbox.ColorDefault
+ }
+ }
+ }
+ }
+
+ return true
+}
+
+//
+// Return regular expression that matches all possible tags, i.e.
+// ?black>|?red>| ... |?white>
+//-----------------------------------------------------------------------------
+func (self *Markup) supported_tags() *regexp.Regexp {
+ arr := []string{}
+
+ for tag, _ := range self.tags {
+ arr = append(arr, `?` + tag + `>`)
+ }
+
+ return regexp.MustCompile(strings.Join(arr, `|`))
+}
+
+//-----------------------------------------------------------------------------
+func probe_tag(str string) (string, bool) {
+ if len(str) > 2 && str[0:1] == `<` && str[len(str)-1:] == `>` {
+ return extract_tag_name(str), str[1:2] != `/`
+ }
+
+ return ``, false
+}
+
+//
+// Extract tag name from the given tag, i.e. `` => `hello`
+//-----------------------------------------------------------------------------
+func extract_tag_name(str string) string {
+ if len(str) < 3 {
+ return ``
+ } else if str[1:2] != `/` {
+ return str[1 : len(str)-1]
+ } else if len(str) > 3 {
+ return str[2 : len(str)-1]
+ } else {
+ return `/`
+ }
+}
diff --git a/lib/screen.go b/lib/screen.go
index b3b78db..49ddc0f 100644
--- a/lib/screen.go
+++ b/lib/screen.go
@@ -3,18 +3,15 @@
package mop
import (
- `github.com/michaeldv/just`
`github.com/nsf/termbox-go`
- `regexp`
`strings`
`time`
)
type Screen struct {
- width int
- height int
- cleared bool
- tags map[string]termbox.Attribute
+ width int
+ height int
+ cleared bool
}
//-----------------------------------------------------------------------------
@@ -24,28 +21,14 @@ func (self *Screen) Initialize() *Screen {
panic(err)
}
- self.Resize()
- self.tags = make(map[string]termbox.Attribute)
- self.tags[`black`] = termbox.ColorBlack
- self.tags[`red`] = termbox.ColorRed
- self.tags[`green`] = termbox.ColorGreen
- self.tags[`yellow`] = termbox.ColorYellow
- self.tags[`blue`] = termbox.ColorBlue
- self.tags[`magenta`] = termbox.ColorMagenta
- self.tags[`cyan`] = termbox.ColorCyan
- self.tags[`white`] = termbox.ColorWhite
- self.tags[`right`] = termbox.ColorDefault // Termbox can combine attributes and a single color using bitwise OR.
- self.tags[`b`] = termbox.AttrBold // Attribute = 1 << (iota + 4)
- self.tags[`u`] = termbox.AttrUnderline
- self.tags[`r`] = termbox.AttrReverse
-
- return self
+ return self.Resize()
}
//-----------------------------------------------------------------------------
func (self *Screen) Resize() *Screen {
self.width, self.height = termbox.Size()
self.cleared = false
+
return self
}
@@ -53,12 +36,15 @@ func (self *Screen) Resize() *Screen {
func (self *Screen) Clear() *Screen {
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
self.cleared = true
+
return self
}
//-----------------------------------------------------------------------------
-func (self *Screen) Close() {
+func (self *Screen) Close() *Screen {
termbox.Close()
+
+ return self
}
//-----------------------------------------------------------------------------
@@ -92,43 +78,21 @@ func (self *Screen) ClearLine(x int, y int) {
//-----------------------------------------------------------------------------
func (self *Screen) DrawLine(x int, y int, str string) {
- column, right := 0, false
- foreground, background := termbox.ColorDefault, termbox.ColorDefault
-
- for _, token := range just.Split(self.possible_tags(), str) {
- if tag, open := self.is_tag(token); tag {
- key := self.tag_name(token)
- if value, ok := self.tags[key]; ok {
- token = ``
- switch key {
- case `right`:
- right = open
- default:
- if open {
- if value >= termbox.AttrBold {
- foreground |= value
- } else {
- foreground = value
- }
- } else {
- if value >= termbox.AttrBold {
- foreground &= ^value
- } else {
- foreground = termbox.ColorDefault
- }
- }
+ start, column := 0, 0
+
+ markup := new(Markup).Initialize()
+ for _, token := range markup.Tokenize(str) {
+ if !markup.IsTag(token) {
+ for i, char := range token {
+ if !markup.RightAligned {
+ start = x + column
+ column++
+ } else {
+ start = self.width - len(token) + i
}
+ termbox.SetCell(start, y, char, markup.Foreground, markup.Background)
}
}
-
- for i, char := range token {
- if !right {
- termbox.SetCell(x+column, y, char, foreground, background)
- } else {
- termbox.SetCell(self.width-len(token)+i, y, char, foreground, background)
- }
- column++
- }
}
termbox.Flush()
}
@@ -143,39 +107,3 @@ func (self *Screen) draw(str string) {
self.DrawLine(0, row, line)
}
}
-
-//
-// Return regular expression that matches all possible tags, i.e.
-// ?black>|?red>| ... |?white>
-//-----------------------------------------------------------------------------
-func (self *Screen) possible_tags() *regexp.Regexp {
- arr := []string{}
-
- for tag, _ := range self.tags {
- arr = append(arr, `?` + tag + `>`)
- }
-
- return regexp.MustCompile(strings.Join(arr, `|`))
-}
-
-//
-// Return true if a string looks like a tag.
-//-----------------------------------------------------------------------------
-func (self *Screen) is_tag(str string) (is bool, open bool) {
- is = (len(str) > 2 && str[0:1] == `<` && str[len(str)-1:] == `>`)
- open = (is && str[1:2] != `/`)
- return
-}
-
-//
-// Extract tag name from the given tag, i.e. `` => `hello`
-//-----------------------------------------------------------------------------
-func (self *Screen) tag_name(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_quotes.go b/lib/yahoo_quotes.go
index db45094..64453dc 100644
--- a/lib/yahoo_quotes.go
+++ b/lib/yahoo_quotes.go
@@ -151,7 +151,7 @@ func (self *Quotes) sanitize(body []byte) []byte {
//-----------------------------------------------------------------------------
func (stock *Stock) Color() string {
if strings.Index(stock.Change, "-") == -1 {
- return ``
+ return `>`
} else {
return `` // ``
}