diff --git a/cmd/mop/main.go b/cmd/mop/main.go index 7075c57..1368303 100644 --- a/cmd/mop/main.go +++ b/cmd/mop/main.go @@ -33,8 +33,8 @@ NO WARRANTIES OF ANY KIND WHATSOEVER. SEE THE LICENSE FILE FOR DETAILS. g Group stocks by advancing/declining issues. o Change column sort order. p Pause market data and stock updates. - PgDn Scroll Down, down arrow key also works. - PgUp Scroll up, up arrow key also works. + Scroll Scroll up/down. + PgUp/PgDn; Up/Down arrow; j/k;J/K also all scroll up/down q Quit mop. esc Ditto. @@ -48,13 +48,18 @@ func mainLoop(screen *mop.Screen, profile *mop.Profile) { var lineEditor *mop.LineEditor var columnEditor *mop.ColumnEditor - keyboardQueue := make(chan termbox.Event) + termbox.SetInputMode(termbox.InputMouse) + + // use buffered channel for keyboard event queue + keyboardQueue := make(chan termbox.Event, 16) + timestampQueue := time.NewTicker(1 * time.Second) quotesQueue := time.NewTicker(5 * time.Second) marketQueue := time.NewTicker(12 * time.Second) showingHelp := false paused := false - pgUpDownLines := 10 + upDownJump := profile.UpDownJump + redrawQuotesFlag := false go func() { for { @@ -96,13 +101,19 @@ loop: showingHelp = true screen.Clear().Draw(help) } else if event.Key == termbox.KeyPgdn || - event.Key == termbox.KeyArrowDown { - screen.IncreaseOffset(pgUpDownLines, len(profile.Tickers)) - screen.Clear().Draw(market, quotes) + event.Ch == 'J' { + screen.IncreaseOffset(upDownJump, len(profile.Tickers)) + redrawQuotesFlag = true } else if event.Key == termbox.KeyPgup || - event.Key == termbox.KeyArrowUp { - screen.DecreaseOffset(pgUpDownLines) - screen.Clear().Draw(market, quotes) + event.Ch == 'K' { + screen.DecreaseOffset(upDownJump) + redrawQuotesFlag = true + } else if event.Key == termbox.KeyArrowUp || event.Ch == 'k' { + screen.DecreaseOffset(1) + redrawQuotesFlag = true + } else if event.Key == termbox.KeyArrowDown || event.Ch == 'j' { + screen.IncreaseOffset(1, len(profile.Tickers)) + redrawQuotesFlag = true } } else if lineEditor != nil { if done := lineEditor.Handle(event); done { @@ -123,6 +134,17 @@ loop: } else { screen.Draw(help) } + case termbox.EventMouse: + if lineEditor == nil && columnEditor == nil && !showingHelp { + switch event.Key { + case termbox.MouseWheelUp: + screen.DecreaseOffset(1) + redrawQuotesFlag = true + case termbox.MouseWheelDown: + screen.IncreaseOffset(1, len(profile.Tickers)) + redrawQuotesFlag = true + } + } } case <-timestampQueue.C: @@ -140,6 +162,10 @@ loop: screen.Draw(market) } } + + if redrawQuotesFlag && len(keyboardQueue) == 0 { + screen.Draw(quotes) + } } } diff --git a/profile.go b/profile.go index 93bbfaa..b3d92c1 100644 --- a/profile.go +++ b/profile.go @@ -31,6 +31,7 @@ type Profile struct { Ascending bool // True when sort order is ascending. Grouped bool // True when stocks are grouped by advancing/declining. Filter string // Filter in human form + UpDownJump int // Number of lines to go up/down when scrolling. Colors struct { // User defined colors Gain string Loss string @@ -93,6 +94,10 @@ func NewProfile(filename string) (*Profile, error) { } profile.selectedColumn = -1 + if profile.UpDownJump < 1 { + profile.UpDownJump = 10 + } + return profile, err } @@ -105,6 +110,7 @@ func (profile *Profile) InitDefaultProfile() { profile.SortColumn = 0 // Stock quotes are sorted by ticker name. profile.Ascending = true // A to Z. profile.Filter = "" + profile.UpDownJump = 10 profile.Colors.Gain = defaultGainColor profile.Colors.Loss = defaultLossColor profile.Colors.Tag = defaultTagColor diff --git a/screen.go b/screen.go index 91dce84..b7c32fe 100644 --- a/screen.go +++ b/screen.go @@ -92,7 +92,7 @@ func (screen *Screen) ClearLine(x int, y int) *Screen { // Increase the offset for scrolling feature by n // Takes number of tickers as max, so not scrolling down forever func (screen *Screen) IncreaseOffset(n int, max int) { - if screen.offset+n < max { + if screen.offset+n+1 < max { screen.offset += n } } @@ -173,9 +173,9 @@ func (screen *Screen) draw(str string, offset bool) { // Write the lines being updated. for row := 0; row < len(allLines); row++ { if offset { - // Did we draw the underlined heading row? This is a crude - // check, but--see comments below... - // --- Heading row only appears for quotes, so offset is true + // Did we draw the underlined heading row? This is a crude + // check, but--see comments below... + // --- Heading row only appears for quotes, so offset is true if strings.Contains(allLines[row], "Ticker") && strings.Contains(allLines[row], "Last") && strings.Contains(allLines[row], "Change") { @@ -189,7 +189,7 @@ func (screen *Screen) draw(str string, offset bool) { } } } else { - screen.DrawLine(0, row, allLines[row]) + screen.DrawLine(0, row, allLines[row]) } } // If the quotes lines in this cycle are shorter than in the previous @@ -205,7 +205,7 @@ func (screen *Screen) draw(str string, offset bool) { // cycle. In that case, padding with blank lines would overwrite the // stocks list.) if drewHeading { - for i := len(allLines) - 1; i < screen.height; i++ { + for i := len(allLines) - 1 - screen.offset; i < screen.height; i++ { screen.DrawLine(0, i, blankLine) } }