Refactored markup

master
Michael Dvorkin 11 years ago
parent 438f3f2f8a
commit 86037e627d
  1. 28
      lib/layout.go
  2. 2
      lib/line_editor.go
  3. 138
      lib/markup.go
  4. 114
      lib/screen.go
  5. 2
      lib/yahoo_quotes.go

@ -49,19 +49,19 @@ func (self *Layout) Initialize() *Layout {
func (self *Layout) Market(m *Market) string { func (self *Layout) Market(m *Market) string {
markup := `{{.Dow.name}}: ` markup := `{{.Dow.name}}: `
if m.Dow[`change`][0:1] != `-` { if m.Dow[`change`][0:1] != `-` {
markup += `<green>{{.Dow.change}} ({{.Dow.percent}})</green> at {{.Dow.latest}}, ` markup += `<green>{{.Dow.change}} ({{.Dow.percent}})</> at {{.Dow.latest}}, `
} else { } else {
markup += `{{.Dow.change}} ({{.Dow.percent}}) at {{.Dow.latest}}, ` markup += `{{.Dow.change}} ({{.Dow.percent}}) at {{.Dow.latest}}, `
} }
markup += `{{.Sp500.name}}: ` markup += `{{.Sp500.name}}: `
if m.Sp500[`change`][0:1] != `-` { if m.Sp500[`change`][0:1] != `-` {
markup += `<green>{{.Sp500.change}} ({{.Sp500.percent}})</green> at {{.Sp500.latest}}, ` markup += `<green>{{.Sp500.change}} ({{.Sp500.percent}})</> at {{.Sp500.latest}}, `
} else { } else {
markup += `{{.Sp500.change}} ({{.Sp500.percent}}) at {{.Sp500.latest}}, ` markup += `{{.Sp500.change}} ({{.Sp500.percent}}) at {{.Sp500.latest}}, `
} }
markup += `{{.Nasdaq.name}}: ` markup += `{{.Nasdaq.name}}: `
if m.Nasdaq[`change`][0:1] != `-` { if m.Nasdaq[`change`][0:1] != `-` {
markup += `<green>{{.Nasdaq.change}} ({{.Nasdaq.percent}})</green> at {{.Nasdaq.latest}}` markup += `<green>{{.Nasdaq.change}} ({{.Nasdaq.percent}})</> at {{.Nasdaq.latest}}`
} else { } else {
markup += `{{.Nasdaq.change}} ({{.Nasdaq.percent}}) at {{.Nasdaq.latest}}` markup += `{{.Nasdaq.change}} ({{.Nasdaq.percent}}) at {{.Nasdaq.latest}}`
} }
@ -100,7 +100,7 @@ func (self *Layout) Quotes(quotes *Quotes) string {
self.prettify(quotes), self.prettify(quotes),
} }
markup := `<right><white>{{.Now}}</white></right> markup := `<right><white>{{.Now}}</></right>
@ -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 `<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 { func pad(str string, width int) string {
re := regexp.MustCompile(`(\.\d+)[MB]?$`) re := regexp.MustCompile(`(\.\d+)[MB]?$`)

@ -32,7 +32,7 @@ func (self *LineEditor) Prompt(command rune) {
self.prompt = prompt self.prompt = prompt
self.command = command self.command = command
self.screen.DrawLine(0, 3, `<white>` + self.prompt + `</white>`) self.screen.DrawLine(0, 3, `<white>` + self.prompt + `</>`)
termbox.SetCursor(len(self.prompt), 3) termbox.SetCursor(len(self.prompt), 3)
termbox.Flush() termbox.Flush()
} }

@ -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>` => `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 `/`
}
}

@ -3,18 +3,15 @@
package mop package mop
import ( import (
`github.com/michaeldv/just`
`github.com/nsf/termbox-go` `github.com/nsf/termbox-go`
`regexp`
`strings` `strings`
`time` `time`
) )
type Screen struct { type Screen struct {
width int width int
height int height int
cleared bool cleared bool
tags map[string]termbox.Attribute
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -24,28 +21,14 @@ func (self *Screen) Initialize() *Screen {
panic(err) panic(err)
} }
self.Resize() return 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
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
func (self *Screen) Resize() *Screen { func (self *Screen) Resize() *Screen {
self.width, self.height = termbox.Size() self.width, self.height = termbox.Size()
self.cleared = false self.cleared = false
return self return self
} }
@ -53,12 +36,15 @@ func (self *Screen) Resize() *Screen {
func (self *Screen) Clear() *Screen { func (self *Screen) Clear() *Screen {
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault) termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
self.cleared = true self.cleared = true
return self return self
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
func (self *Screen) Close() { func (self *Screen) Close() *Screen {
termbox.Close() 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) { func (self *Screen) DrawLine(x int, y int, str string) {
column, right := 0, false start, column := 0, 0
foreground, background := termbox.ColorDefault, termbox.ColorDefault
markup := new(Markup).Initialize()
for _, token := range just.Split(self.possible_tags(), str) { for _, token := range markup.Tokenize(str) {
if tag, open := self.is_tag(token); tag { if !markup.IsTag(token) {
key := self.tag_name(token) for i, char := range token {
if value, ok := self.tags[key]; ok { if !markup.RightAligned {
token = `` start = x + column
switch key { column++
case `right`: } else {
right = open start = self.width - len(token) + i
default:
if open {
if value >= termbox.AttrBold {
foreground |= value
} else {
foreground = value
}
} else {
if value >= termbox.AttrBold {
foreground &= ^value
} else {
foreground = termbox.ColorDefault
}
}
} }
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() termbox.Flush()
} }
@ -143,39 +107,3 @@ func (self *Screen) draw(str string) {
self.DrawLine(0, row, line) 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>` => `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]
}
}

@ -151,7 +151,7 @@ func (self *Quotes) sanitize(body []byte) []byte {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
func (stock *Stock) Color() string { func (stock *Stock) Color() string {
if strings.Index(stock.Change, "-") == -1 { if strings.Index(stock.Change, "-") == -1 {
return `</green><green>` return `</><green>`
} else { } else {
return `` // `</red><red>` return `` // `</red><red>`
} }

Loading…
Cancel
Save