adventofcode/2019/day25/event_buffer.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
}