// Copyright 2017 Zack Guo . All rights reserved. // Use of this source code is governed by a MIT license that can // be found in the LICENSE file. package termui import ( "fmt" tb "github.com/nsf/termbox-go" ) /* List of events: mouse events: keyboard events: any uppercase or lowercase letter like j or J etc etc > etc terminal events: keyboard events that do not work: */ type EventType uint const ( KeyboardEvent EventType = iota MouseEvent ResizeEvent ) type Event struct { Type EventType ID string Payload interface{} } // Mouse payload. type Mouse struct { Drag bool X int Y int } // Resize payload. type Resize struct { Width int Height int } // PollEvents gets events from termbox, converts them, then sends them to each of its channels. func PollEvents() <-chan Event { ch := make(chan Event) go func() { for { ch <- convertTermboxEvent(tb.PollEvent()) } }() return ch } var keyboardMap = map[tb.Key]string{ tb.KeyF1: "", tb.KeyF2: "", tb.KeyF3: "", tb.KeyF4: "", tb.KeyF5: "", tb.KeyF6: "", tb.KeyF7: "", tb.KeyF8: "", tb.KeyF9: "", tb.KeyF10: "", tb.KeyF11: "", tb.KeyF12: "", tb.KeyInsert: "", tb.KeyDelete: "", tb.KeyHome: "", tb.KeyEnd: "", tb.KeyPgup: "", tb.KeyPgdn: "", tb.KeyArrowUp: "", tb.KeyArrowDown: "", tb.KeyArrowLeft: "", tb.KeyArrowRight: "", tb.KeyCtrlSpace: ">", // tb.KeyCtrl2 tb.KeyCtrlTilde tb.KeyCtrlA: "", tb.KeyCtrlB: "", tb.KeyCtrlC: "", tb.KeyCtrlD: "", tb.KeyCtrlE: "", tb.KeyCtrlF: "", tb.KeyCtrlG: "", tb.KeyBackspace: ">", // tb.KeyCtrlH tb.KeyTab: "", // tb.KeyCtrlI tb.KeyCtrlJ: "", tb.KeyCtrlK: "", tb.KeyCtrlL: "", tb.KeyEnter: "", // tb.KeyCtrlM tb.KeyCtrlN: "", tb.KeyCtrlO: "", tb.KeyCtrlP: "", tb.KeyCtrlQ: "", tb.KeyCtrlR: "", tb.KeyCtrlS: "", tb.KeyCtrlT: "", tb.KeyCtrlU: "", tb.KeyCtrlV: "", tb.KeyCtrlW: "", tb.KeyCtrlX: "", tb.KeyCtrlY: "", tb.KeyCtrlZ: "", tb.KeyEsc: "", // tb.KeyCtrlLsqBracket tb.KeyCtrl3 tb.KeyCtrl4: "", // tb.KeyCtrlBackslash tb.KeyCtrl5: "", // tb.KeyCtrlRsqBracket tb.KeyCtrl6: "", tb.KeyCtrl7: "", // tb.KeyCtrlSlash tb.KeyCtrlUnderscore tb.KeySpace: "", tb.KeyBackspace2: "", // tb.KeyCtrl8: } // convertTermboxKeyboardEvent converts a termbox keyboard event to a more friendly string format. // Combines modifiers into the string instead of having them as additional fields in an event. func convertTermboxKeyboardEvent(e tb.Event) Event { ID := "%s" if e.Mod == tb.ModAlt { ID = "" } if e.Ch != 0 { ID = fmt.Sprintf(ID, string(e.Ch)) } else { converted, ok := keyboardMap[e.Key] if !ok { converted = "" } ID = fmt.Sprintf(ID, converted) } return Event{ Type: KeyboardEvent, ID: ID, } } var mouseButtonMap = map[tb.Key]string{ tb.MouseLeft: "", tb.MouseMiddle: "", tb.MouseRight: "", tb.MouseRelease: "", tb.MouseWheelUp: "", tb.MouseWheelDown: "", } func convertTermboxMouseEvent(e tb.Event) Event { converted, ok := mouseButtonMap[e.Key] if !ok { converted = "Unknown_Mouse_Button" } Drag := e.Mod == tb.ModMotion return Event{ Type: MouseEvent, ID: converted, Payload: Mouse{ X: e.MouseX, Y: e.MouseY, Drag: Drag, }, } } // convertTermboxEvent turns a termbox event into a termui event. func convertTermboxEvent(e tb.Event) Event { if e.Type == tb.EventError { panic(e.Err) } switch e.Type { case tb.EventKey: return convertTermboxKeyboardEvent(e) case tb.EventMouse: return convertTermboxMouseEvent(e) case tb.EventResize: return Event{ Type: ResizeEvent, ID: "", Payload: Resize{ Width: e.Width, Height: e.Height, }, } } return Event{} }