176 lines
3.3 KiB
Go
176 lines
3.3 KiB
Go
package main
|
|
|
|
import (
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/nsf/termbox-go"
|
|
)
|
|
|
|
const (
|
|
DefaultExpireTime = time.Second / 2
|
|
)
|
|
|
|
type EventBuffer struct {
|
|
UpdateTime time.Time
|
|
TimeoutLen time.Duration
|
|
Buffer []termbox.Event
|
|
CursorPos int
|
|
}
|
|
|
|
func NewEventBuffer() *EventBuffer {
|
|
return &EventBuffer{
|
|
TimeoutLen: DefaultExpireTime,
|
|
CursorPos: -1,
|
|
}
|
|
}
|
|
|
|
func (eb *EventBuffer) checkExpiration() {
|
|
if eb.TimeoutLen != -1 && time.Now().Sub(eb.UpdateTime) > eb.TimeoutLen {
|
|
eb.Clear()
|
|
}
|
|
}
|
|
|
|
func (eb *EventBuffer) StartsWith(r rune) bool {
|
|
eb.checkExpiration()
|
|
return len(eb.Buffer) > 0 && eb.Buffer[0].Ch == r
|
|
}
|
|
|
|
func (eb *EventBuffer) Add(event termbox.Event) {
|
|
eb.checkExpiration()
|
|
if event.Key == termbox.KeyCtrlU {
|
|
eb.Clear()
|
|
} else if event.Key == termbox.KeyBackspace || event.Key == termbox.KeyBackspace2 {
|
|
eb.Backspace()
|
|
} else {
|
|
eb.Buffer = append(eb.Buffer, event)
|
|
}
|
|
eb.UpdateTime = time.Now()
|
|
}
|
|
|
|
func (eb *EventBuffer) Backspace() {
|
|
eb.checkExpiration()
|
|
if len(eb.Buffer) >= 1 {
|
|
eb.Buffer = eb.Buffer[:len(eb.Buffer)-1]
|
|
}
|
|
eb.UpdateTime = time.Now()
|
|
}
|
|
|
|
func (eb *EventBuffer) MoveCursorBack() {
|
|
if eb.CursorPos > 0 {
|
|
eb.CursorPos--
|
|
}
|
|
}
|
|
|
|
func (eb *EventBuffer) MoveCursorForward() {
|
|
if eb.CursorPos < len(eb.Buffer) {
|
|
eb.CursorPos++
|
|
}
|
|
}
|
|
|
|
func (eb *EventBuffer) SetCursorToStart() {
|
|
eb.CursorPos = 0
|
|
}
|
|
|
|
func (eb *EventBuffer) SetCursorToEnd() {
|
|
eb.CursorPos = len(eb.Buffer)
|
|
}
|
|
|
|
func (eb *EventBuffer) Clear() {
|
|
eb.Buffer = nil
|
|
eb.UpdateTime = time.Now()
|
|
}
|
|
|
|
func (eb *EventBuffer) Events() []termbox.Event {
|
|
eb.checkExpiration()
|
|
return eb.Buffer
|
|
}
|
|
|
|
func (eb *EventBuffer) String() string {
|
|
eb.checkExpiration()
|
|
var ret string
|
|
for _, v := range eb.Buffer {
|
|
if v.Ch != 0 {
|
|
ret = ret + string(v.Ch)
|
|
} else {
|
|
switch v.Key {
|
|
case termbox.KeySpace:
|
|
ret = ret + " "
|
|
case termbox.KeyArrowUp:
|
|
ret = ret + string(ChUpKeyValue)
|
|
case termbox.KeyArrowRight:
|
|
ret = ret + string(ChRightKeyValue)
|
|
case termbox.KeyArrowDown:
|
|
ret = ret + string(ChDownKeyValue)
|
|
case termbox.KeyArrowLeft:
|
|
ret = ret + string(ChLeftKeyValue)
|
|
case termbox.KeyEnter:
|
|
ret = ret + string(ChEnterKeyValue)
|
|
}
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (eb *EventBuffer) SetToString(s string) {
|
|
eb.Clear()
|
|
for _, v := range s {
|
|
if v == '\n' {
|
|
eb.Add(termbox.Event{Ch: 0, Key: termbox.KeyEnter})
|
|
} else {
|
|
eb.Add(termbox.Event{Ch: v})
|
|
}
|
|
}
|
|
}
|
|
|
|
func (eb *EventBuffer) MatchesString(s string) bool {
|
|
eb.checkExpiration()
|
|
if len(s) != len(eb.Buffer) {
|
|
return false
|
|
}
|
|
return s == eb.String()
|
|
}
|
|
|
|
func (eb *EventBuffer) MatchesEvents(events []termbox.Event) bool {
|
|
eb.checkExpiration()
|
|
if len(events) != len(eb.Buffer) {
|
|
return false
|
|
}
|
|
for k := range events {
|
|
if events[k].Ch != eb.Buffer[k].Ch || events[k].Key != eb.Buffer[k].Key {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (eb *EventBuffer) StartsWithKey(key termbox.Key) bool {
|
|
eb.checkExpiration()
|
|
if len(eb.Buffer) > 0 {
|
|
return eb.Buffer[0].Key == key
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (eb *EventBuffer) Size() int {
|
|
eb.checkExpiration()
|
|
return len(eb.Buffer)
|
|
}
|
|
|
|
func (eb *EventBuffer) IsNumber() bool {
|
|
_, err := strconv.Atoi(eb.String())
|
|
return err == nil
|
|
}
|
|
|
|
func (eb *EventBuffer) Number() (int, error) {
|
|
return strconv.Atoi(eb.String())
|
|
}
|
|
|
|
func (eb *EventBuffer) OptNumber(def int) int {
|
|
ret, err := strconv.Atoi(eb.String())
|
|
if err != nil {
|
|
return def
|
|
}
|
|
return ret
|
|
}
|