123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- /*
- * Public Domain Software
- *
- * I (Matthias Ladkau) am the author of the source code in this file.
- * I have placed the source code in this file in the public domain.
- *
- * For further information see: http://creativecommons.org/publicdomain/zero/1.0/
- */
- /*
- Package getch implements a platform agnostic character-wise input capture.
- Things which work on all platforms:
- - Detection of special keys F1-F12, Esc, Enter, Cursor keys, etc.
- - Key combinations: CTRL+<Letter>, Shift+<Letter>
- - Normal character input via KeyEvent.Rune
- Example code:
- func main() {
- var err error
- var e *getch.KeyEvent
- if err = getch.Start(); err != nil {
- fmt.Println(err)
- return
- }
- defer getch.Stop()
- for e == nil || e.Code != getch.KeyTab {
- e, err = getch.Getch()
- fmt.Println("==>", e, err)
- }
- }
- */
- package getch
- import (
- "errors"
- "fmt"
- )
- // Static errors
- /*
- ErrNotImplemented is returned if the platform is not supported by getch
- */
- var ErrNotImplemented = errors.New("Not implemented")
- // Detail specific (dynamic) errors
- /*
- ErrUnknownEscapeSequence is returned if an unknown escape sequence was retrieved.
- The sequence in question is located in the Detail byte slice.
- */
- type ErrUnknownEscapeSequence struct {
- Detail []byte
- }
- /*
- Error returns a string representation of this error.
- */
- func (e *ErrUnknownEscapeSequence) Error() string {
- return fmt.Sprintf("Unknown escape sequence: %v", e.Detail)
- }
- /*
- KeyCode is a platform-independent key code
- */
- type KeyCode string
- /*
- Key codes for the KeyEvent object
- */
- const (
- // Function keys
- KeyF1 = "Key_F1"
- KeyF2 = "Key_F2"
- KeyF3 = "Key_F3"
- KeyF4 = "Key_F4"
- KeyF5 = "Key_F5"
- KeyF6 = "Key_F6"
- KeyF7 = "Key_F7"
- KeyF8 = "Key_F8"
- KeyF9 = "Key_F9"
- KeyF10 = "Key_F10"
- KeyF11 = "Key_F11"
- KeyF12 = "Key_F12"
- // Control keys
- KeyEnter = "Key_ENTER"
- KeyBackspace = "Key_BACKSPACE"
- KeyEsc = "Key_ESC"
- KeyTab = "Key_TAB"
- KeyInsert = "Key_INSERT"
- KeyDelete = "Key_DELETE"
- KeyHome = "Key_HOME"
- KeyEnd = "Key_END"
- KeyPgup = "Key_PAGE_UP"
- KeyPgdn = "Key_PAGE_DOWN"
- KeyArrowUp = "Key_ARROW_UP"
- KeyArrowDown = "Key_ARROW_DOWN"
- KeyArrowLeft = "Key_ARROW_LEFT"
- KeyArrowRight = "Key_ARROW_RIGHT"
- KeyCommand = "Key_CMD" // "Windows" key
- // Normal letters
- KeyA = "Key_A"
- KeyB = "Key_B"
- KeyC = "Key_C"
- KeyD = "Key_D"
- KeyE = "Key_E"
- KeyF = "Key_F"
- KeyG = "Key_G"
- KeyH = "Key_H"
- KeyI = "Key_I"
- KeyJ = "Key_J"
- KeyK = "Key_K"
- KeyL = "Key_L"
- KeyM = "Key_M"
- KeyN = "Key_N"
- KeyO = "Key_O"
- KeyP = "Key_P"
- KeyQ = "Key_Q"
- KeyR = "Key_R"
- KeyS = "Key_S"
- KeyT = "Key_T"
- KeyU = "Key_U"
- KeyV = "Key_V"
- KeyW = "Key_W"
- KeyX = "Key_X"
- KeyY = "Key_Y"
- KeyZ = "Key_Z"
- // Normal numbers
- Key1 = "Key_1"
- Key2 = "Key_2"
- Key3 = "Key_3"
- Key4 = "Key_4"
- Key5 = "Key_5"
- Key6 = "Key_6"
- Key7 = "Key_7"
- Key8 = "Key_8"
- Key9 = "Key_9"
- Key0 = "Key_0"
- // Normal Symbols
- KeyBacktick = "Key_BACKTICK"
- KeyMinus = "Key_MINUS"
- KeyEqual = "Key_EQUAL"
- KeyBracketOpen = "Key_BRACKET_OPEN"
- KeyBracketClose = "Key_BRACKET_CLOSE"
- KeySemiColon = "Key_SEMICOLON"
- KeyQuote = "Key_QUOTE"
- KeyHash = "Key_HASH"
- KeyBackslash = "Key_BACKSLASH"
- KeyComma = "Key_COMMA"
- KeyDot = "Key_DOT"
- KeySlash = "Key_SLASH"
- // Special states
- KeyUnknown = "Key_UNKNOWN"
- )
- /*
- KeyEvent objects are produced by an input reader.
- */
- type KeyEvent struct {
- Code KeyCode // Code of the pressed key
- Ctrl bool // Flag if the ctrl key is also pressed
- Alt bool // Flag if the alt key is also pressed
- Shift bool // Flag if the shift key is also pressed
- Rune rune // Produced rune if the key is printable
- RawBuf []byte // Raw input buffer since the last key event
- }
- func (k *KeyEvent) String() string {
- ret := fmt.Sprintf("%v %c [%#v - 0x%x]", k.Code, k.Rune, k.Rune, k.Rune)
- if k.Shift {
- ret += " + SHIFT"
- }
- if k.Ctrl {
- ret += " + CTRL"
- }
- if k.Alt {
- ret += " + ALT"
- }
- return ret
- }
- /*
- internalKeyEvent is used to pass additional information to the getch function
- */
- type internalKeyEvent struct {
- *KeyEvent
- err error
- }
- /*
- getch is a platform-native single character input reader object.
- */
- type getch interface {
- /*
- GetKey returns the next key event or an error. This function blocks if no key
- event is available.
- */
- GetKey() *internalKeyEvent
- /*
- GetKeyAsync returns the next key event or an error. This function does not block if no key
- event is available - in this case nil is returned.
- */
- GetKeyAsync() *internalKeyEvent
- /*
- CursorPosition returns the current cursor position.
- */
- CursorPosition() (int, int, error)
- /*
- SetCursorPosition sets the current cursor position
- */
- SetCursorPosition(int, int) error
- /*
- Close detaches the character reader.
- */
- Close()
- }
- /*
- Singleton getch instance.
- */
- var g getch
- /*
- Start starts the character reader.
- */
- func Start() error {
- var err error
- if g == nil {
- g, err = attachReader()
- }
- return err
- }
- /*
- CursorPosition returns the current cursor position.
- */
- func CursorPosition() (int, int, error) {
- var x, y int
- var err error
- if g != nil {
- x, y, err = g.CursorPosition()
- }
- return x, y, err
- }
- /*
- SetCursorPosition sets the current cursor position.
- */
- func SetCursorPosition(x, y int) error {
- var err error
- if g != nil {
- err = g.SetCursorPosition(x, y)
- }
- return err
- }
- /*
- Getch reads a single character.
- */
- func Getch() (*KeyEvent, error) {
- var ret *KeyEvent
- var err error
- if g != nil {
- ke := g.GetKey()
- if err = ke.err; err == nil {
- ret = ke.KeyEvent
- }
- }
- return ret, err
- }
- /*
- Stop stops the character reader.
- */
- func Stop() {
- if g != nil {
- g.Close()
- g = nil
- }
- }
|