gobot.io/x/gobot/v2@v2.1.0/platforms/keyboard/keyboard.go (about)

     1  package keyboard
     2  
     3  import (
     4  	"os"
     5  	"os/exec"
     6  )
     7  
     8  type bytes [3]byte
     9  
    10  // KeyEvent contains data about a keyboard event
    11  type KeyEvent struct {
    12  	Bytes bytes
    13  	Key   int
    14  	Char  string
    15  }
    16  
    17  const (
    18  	Tilde = iota + 96
    19  	A
    20  	B
    21  	C
    22  	D
    23  	E
    24  	F
    25  	G
    26  	H
    27  	I
    28  	J
    29  	K
    30  	L
    31  	M
    32  	N
    33  	O
    34  	P
    35  	Q
    36  	R
    37  	S
    38  	T
    39  	U
    40  	V
    41  	W
    42  	X
    43  	Y
    44  	Z
    45  )
    46  
    47  const (
    48  	Escape   = 27
    49  	Spacebar = 32
    50  	Hyphen   = 45
    51  	Asterisk = 42
    52  	Plus     = 43
    53  	Slash    = 47
    54  	Dot      = 46
    55  )
    56  
    57  const (
    58  	Zero = iota + 48
    59  	One
    60  	Two
    61  	Three
    62  	Four
    63  	Five
    64  	Six
    65  	Seven
    66  	Eight
    67  	Nine
    68  )
    69  
    70  const (
    71  	ArrowUp = iota + 65
    72  	ArrowDown
    73  	ArrowRight
    74  	ArrowLeft
    75  )
    76  
    77  // used to hold the original stty state
    78  var originalState string
    79  
    80  func Parse(input bytes) KeyEvent {
    81  	var event = KeyEvent{Bytes: input, Char: string(input[:])}
    82  
    83  	var code byte
    84  
    85  	// basic input codes
    86  	if input[1] == 0 && input[2] == 0 {
    87  		code = input[0]
    88  
    89  		// space bar
    90  		if code == Spacebar {
    91  			event.Key = Spacebar
    92  		}
    93  
    94  		// vanilla escape
    95  		if code == Escape {
    96  			event.Key = Escape
    97  		}
    98  
    99  		// Hyphen
   100  		if code == Hyphen {
   101  			event.Key = Hyphen
   102  		}
   103  
   104  		// Asterisk
   105  		if code == Asterisk {
   106  			event.Key = Asterisk
   107  		}
   108  
   109  		// Plus
   110  		if code == Plus {
   111  			event.Key = Plus
   112  		}
   113  
   114  		// Slash
   115  		if code == Slash {
   116  			event.Key = Slash
   117  		}
   118  
   119  		// Dot
   120  		if code == Dot {
   121  			event.Key = Dot
   122  		}
   123  
   124  		// number keys
   125  		if code >= 48 && code <= 57 {
   126  			event.Key = int(code)
   127  		}
   128  
   129  		// alphabet
   130  		if code >= 97 && code <= 122 {
   131  			event.Key = int(code)
   132  		}
   133  
   134  		return event
   135  	}
   136  
   137  	// arrow keys
   138  	if input[0] == Escape && input[1] == 91 {
   139  		code = input[2]
   140  
   141  		if code >= 65 && code <= 68 {
   142  			event.Key = int(code)
   143  			return event
   144  		}
   145  	}
   146  
   147  	return event
   148  }
   149  
   150  // fetches original state, sets up TTY for raw (unbuffered) input
   151  func configure() (err error) {
   152  	state, err := stty("-g")
   153  	if err != nil {
   154  		return err
   155  	}
   156  
   157  	originalState = state
   158  
   159  	// -echo: terminal doesn't echo typed characters back to the terminal
   160  	// -icanon: terminal doesn't interpret special characters (like backspace)
   161  	if _, err := stty("-echo", "-icanon"); err != nil {
   162  		return err
   163  	}
   164  
   165  	return
   166  }
   167  
   168  // restores the TTY to the original state
   169  func restore() (err error) {
   170  	if _, err = stty("echo"); err != nil {
   171  		return
   172  	}
   173  
   174  	if _, err = stty(originalState); err != nil {
   175  		return
   176  	}
   177  
   178  	return
   179  }
   180  
   181  func stty(args ...string) (string, error) {
   182  	cmd := exec.Command("stty", args...)
   183  	cmd.Stdin = os.Stdin
   184  
   185  	out, err := cmd.Output()
   186  	if err != nil {
   187  		return "", err
   188  	}
   189  
   190  	return string(out), nil
   191  }