Added basics of line editor

master
Michael Dvorkin 11 years ago
parent 713b87609d
commit 8f727f1204
  1. 10
      lib/format.go
  2. 64
      lib/line_editor.go
  3. 9
      lib/profile.go
  4. 92
      lib/screen.go
  5. 10
      lib/yahoo_market.go
  6. 8
      lib/yahoo_quotes.go
  7. 11
      mop.go

@ -3,12 +3,12 @@
package mop
import (
"fmt"
"time"
"bytes"
"fmt"
"regexp"
"strings"
"text/template"
"time"
)
//-----------------------------------------------------------------------------
@ -172,8 +172,10 @@ func pad(str string, width int) string {
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)
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)
}
}

@ -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, "<white>"+self.prompt+"</white>")
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
}

@ -1,11 +1,12 @@
// Copyright (c) 2013 by Michael Dvorkin. All Rights Reserved.
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
package mop
import (
"strings"
"os/user"
"io/ioutil"
"encoding/json"
"io/ioutil"
"os/user"
"strings"
)
const rcfile = "/.moprc"
@ -27,7 +28,7 @@ func LoadProfile() string {
// Set default values.
profile.MarketRefreshRate = 12
profile.QuotesRefreshRate = 5
profile.Tickers = []string{ "AAPL", "C", "GOOG", "IBM", "KO", "ORCL", "V" }
profile.Tickers = []string{"AAPL", "C", "GOOG", "IBM", "KO", "ORCL", "V"}
profile.SortBy = "Ticker"
profile.SortOrder = "Desc"
profile.Save()

@ -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, "<right>" + now + "</right>")
}
//
// 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, "|"))
DrawLine(0, 0, "<right>"+now+"</right>")
}
//
// 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>" => "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
@ -133,6 +93,42 @@ func drawLine(x int, y int, str string) {
//-----------------------------------------------------------------------------
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>" => "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]
}
}

@ -3,12 +3,11 @@
package mop
import (
//"fmt"
"bytes"
"io/ioutil"
"net/http"
"regexp"
"strings"
"net/http"
"io/ioutil"
)
type Market struct {
@ -59,7 +58,7 @@ func extract(snippet []byte) Market {
regex := []string{
"(Dow)", any, price, some, arrow, any, price, some, percent, any,
"(Nasdaq)", 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,
@ -90,6 +89,7 @@ func extract(snippet []byte) Market {
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]
@ -146,5 +146,5 @@ func extract(snippet []byte) Market {
m.Lows[`nyse`] = matches[0][35]
m.Lows[`nasdaq`] = matches[0][36]
return m;
return m
}

@ -3,11 +3,11 @@
package mop
import (
"fmt"
"bytes"
"strings"
"net/http"
"fmt"
"io/ioutil"
"net/http"
"strings"
)
// See http://www.gummy-stuff.org/Yahoo-data.htm
@ -93,7 +93,7 @@ func parse(body []byte) Quotes {
lines := bytes.Split(body, []byte{'\n'})
quotes := make(Quotes, len(lines))
for i,line := range lines {
for i, line := range lines {
// fmt.Printf("\n\n{%d} -> [%s]\n\n", i, string(line))
parse_line(line, &quotes[i])
}

@ -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)
@ -38,8 +39,18 @@ loop:
case event := <-keyboard_queue:
switch event.Type {
case termbox.EventKey:
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)

Loading…
Cancel
Save