Implement String() on type Key and make key constants type KeyType

This commit is contained in:
Christian Rocha 2021-03-02 10:35:10 -05:00
parent 86b93a31c0
commit 65e8067a82
1 changed files with 114 additions and 99 deletions

213
key.go
View File

@ -42,23 +42,10 @@ import (
// IMEs) can input multiple runes at once. // IMEs) can input multiple runes at once.
type KeyMsg Key type KeyMsg Key
// String returns a friendly name for a key. // String returns a string representation for a key message. It's safe (and
// // encouraged) for use in key comparison.
// k := KeyType{Type: KeyEnter} func (k KeyMsg) String() (str string) {
// fmt.Println(k) return Key(k).String()
// // Output: enter
func (k *KeyMsg) String() (str string) {
if k.Alt {
str += "alt+"
}
if k.Type == KeyRunes {
str += string(k.Runes)
return str
} else if s, ok := keyNames[int(k.Type)]; ok {
str += s
return str
}
return ""
} }
// Key contains information about a keypress. // Key contains information about a keypress.
@ -68,9 +55,30 @@ type Key struct {
Alt bool Alt bool
} }
// KeyType indicates the key pressed, such as KeyEnter or KeyBreak or // String returns a friendly string representation for a key. It's safe (and
// KeyCtrlC. All other keys will be type KeyRunes. To get the rune value, check // encouraged) for use in key comparison.
// the Rune method on a Key struct, or use the Key.String() method: //
// k := Key{Type: KeyEnter}
// fmt.Println(k)
// // Output: enter
//
func (k Key) String() (str string) {
if k.Alt {
str += "alt+"
}
if k.Type == KeyRunes {
str += string(k.Runes)
return str
} else if s, ok := keyNames[k.Type]; ok {
str += s
return str
}
return ""
}
// KeyType indicates the key pressed, such as KeyEnter or KeyBreak or KeyCtrlC.
// All other keys will be type KeyRunes. To get the rune value, check the Rune
// method on a Key struct, or use the Key.String() method:
// //
// k := Key{Type: KeyRunes, Runes: []rune{'a'}, Alt: true} // k := Key{Type: KeyRunes, Runes: []rune{'a'}, Alt: true}
// if k.Type == KeyRunes { // if k.Type == KeyRunes {
@ -84,97 +92,104 @@ type Key struct {
// } // }
type KeyType int type KeyType int
func (k KeyType) String() (str string) {
if s, ok := keyNames[k]; ok {
return s
}
return ""
}
// Control keys. I know we could do this with an iota, but the values are very // Control keys. I know we could do this with an iota, but the values are very
// specific, so we set the values explicitly to avoid any confusion. // specific, so we set the values explicitly to avoid any confusion.
// //
// See also: // See also:
// https://en.wikipedia.org/wiki/C0_and_C1_control_codes // https://en.wikipedia.org/wiki/C0_and_C1_control_codes
const ( const (
keyNUL = 0 // null, \0 keyNUL KeyType = 0 // null, \0
keySOH = 1 // start of heading keySOH KeyType = 1 // start of heading
keySTX = 2 // start of text keySTX KeyType = 2 // start of text
keyETX = 3 // break, ctrl+c keyETX KeyType = 3 // break, ctrl+c
keyEOT = 4 // end of transmission keyEOT KeyType = 4 // end of transmission
keyENQ = 5 // enquiry keyENQ KeyType = 5 // enquiry
keyACK = 6 // acknowledge keyACK KeyType = 6 // acknowledge
keyBEL = 7 // bell, \a keyBEL KeyType = 7 // bell, \a
keyBS = 8 // backspace keyBS KeyType = 8 // backspace
keyHT = 9 // horizontal tabulation, \t keyHT KeyType = 9 // horizontal tabulation, \t
keyLF = 10 // line feed, \n keyLF KeyType = 10 // line feed, \n
keyVT = 11 // vertical tabulation \v keyVT KeyType = 11 // vertical tabulation \v
keyFF = 12 // form feed \f keyFF KeyType = 12 // form feed \f
keyCR = 13 // carriage return, \r keyCR KeyType = 13 // carriage return, \r
keySO = 14 // shift out keySO KeyType = 14 // shift out
keySI = 15 // shift in keySI KeyType = 15 // shift in
keyDLE = 16 // data link escape keyDLE KeyType = 16 // data link escape
keyDC1 = 17 // device control one keyDC1 KeyType = 17 // device control one
keyDC2 = 18 // device control two keyDC2 KeyType = 18 // device control two
keyDC3 = 19 // device control three keyDC3 KeyType = 19 // device control three
keyDC4 = 20 // device control four keyDC4 KeyType = 20 // device control four
keyNAK = 21 // negative acknowledge keyNAK KeyType = 21 // negative acknowledge
keySYN = 22 // synchronous idle keySYN KeyType = 22 // synchronous idle
keyETB = 23 // end of transmission block keyETB KeyType = 23 // end of transmission block
keyCAN = 24 // cancel keyCAN KeyType = 24 // cancel
keyEM = 25 // end of medium keyEM KeyType = 25 // end of medium
keySUB = 26 // substitution keySUB KeyType = 26 // substitution
keyESC = 27 // escape, \e keyESC KeyType = 27 // escape, \e
keyFS = 28 // file separator keyFS KeyType = 28 // file separator
keyGS = 29 // group separator keyGS KeyType = 29 // group separator
keyRS = 30 // record separator keyRS KeyType = 30 // record separator
keyUS = 31 // unit separator keyUS KeyType = 31 // unit separator
keySP = 32 // space keySP KeyType = 32 // space
keyDEL = 127 // delete. on most systems this is mapped to backspace, I hear keyDEL KeyType = 127 // delete. on most systems this is mapped to backspace, I hear
) )
// Control key aliases. // Control key aliases.
const ( const (
KeyNull = keyNUL KeyNull KeyType = keyNUL
KeyBreak = keyETX KeyBreak KeyType = keyETX
KeyEnter = keyCR KeyEnter KeyType = keyCR
KeyBackspace = keyDEL KeyBackspace KeyType = keyDEL
KeyTab = keyHT KeyTab KeyType = keyHT
KeySpace = keySP KeySpace KeyType = keySP
KeyEsc = keyESC KeyEsc KeyType = keyESC
KeyEscape = keyESC KeyEscape KeyType = keyESC
KeyCtrlAt = keyNUL // ctrl+@ KeyCtrlAt KeyType = keyNUL // ctrl+@
KeyCtrlA = keySOH KeyCtrlA KeyType = keySOH
KeyCtrlB = keySTX KeyCtrlB KeyType = keySTX
KeyCtrlC = keyETX KeyCtrlC KeyType = keyETX
KeyCtrlD = keyEOT KeyCtrlD KeyType = keyEOT
KeyCtrlE = keyENQ KeyCtrlE KeyType = keyENQ
KeyCtrlF = keyACK KeyCtrlF KeyType = keyACK
KeyCtrlG = keyBEL KeyCtrlG KeyType = keyBEL
KeyCtrlH = keyBS KeyCtrlH KeyType = keyBS
KeyCtrlI = keyHT KeyCtrlI KeyType = keyHT
KeyCtrlJ = keyLF KeyCtrlJ KeyType = keyLF
KeyCtrlK = keyVT KeyCtrlK KeyType = keyVT
KeyCtrlL = keyFF KeyCtrlL KeyType = keyFF
KeyCtrlM = keyCR KeyCtrlM KeyType = keyCR
KeyCtrlN = keySO KeyCtrlN KeyType = keySO
KeyCtrlO = keySI KeyCtrlO KeyType = keySI
KeyCtrlP = keyDLE KeyCtrlP KeyType = keyDLE
KeyCtrlQ = keyDC1 KeyCtrlQ KeyType = keyDC1
KeyCtrlR = keyDC2 KeyCtrlR KeyType = keyDC2
KeyCtrlS = keyDC3 KeyCtrlS KeyType = keyDC3
KeyCtrlT = keyDC4 KeyCtrlT KeyType = keyDC4
KeyCtrlU = keyNAK KeyCtrlU KeyType = keyNAK
KeyCtrlV = keySYN KeyCtrlV KeyType = keySYN
KeyCtrlW = keyETB KeyCtrlW KeyType = keyETB
KeyCtrlX = keyCAN KeyCtrlX KeyType = keyCAN
KeyCtrlY = keyEM KeyCtrlY KeyType = keyEM
KeyCtrlZ = keySUB KeyCtrlZ KeyType = keySUB
KeyCtrlOpenBracket = keyESC // ctrl+[ KeyCtrlOpenBracket KeyType = keyESC // ctrl+[
KeyCtrlBackslash = keyFS // ctrl+\ KeyCtrlBackslash KeyType = keyFS // ctrl+\
KeyCtrlCloseBracket = keyGS // ctrl+] KeyCtrlCloseBracket KeyType = keyGS // ctrl+]
KeyCtrlCaret = keyRS // ctrl+^ KeyCtrlCaret KeyType = keyRS // ctrl+^
KeyCtrlUnderscore = keyUS // ctrl+_ KeyCtrlUnderscore KeyType = keyUS // ctrl+_
KeyCtrlQuestionMark = keyDEL // ctrl+? KeyCtrlQuestionMark KeyType = keyDEL // ctrl+?
) )
// Other keys. // Other keys.
const ( const (
KeyRunes = -(iota + 1) KeyRunes KeyType = -(iota + 1)
KeyUp KeyUp
KeyDown KeyDown
KeyRight KeyRight
@ -188,7 +203,7 @@ const (
) )
// Mapping for control keys to friendly consts. // Mapping for control keys to friendly consts.
var keyNames = map[int]string{ var keyNames = map[KeyType]string{
keyNUL: "ctrl+@", // also ctrl+` keyNUL: "ctrl+@", // also ctrl+`
keySOH: "ctrl+a", keySOH: "ctrl+a",
keySTX: "ctrl+b", keySTX: "ctrl+b",
@ -342,9 +357,9 @@ func readInput(input io.Reader) (Msg, error) {
} }
// Is the first rune a control character? // Is the first rune a control character?
r := runes[0] r := KeyType(runes[0])
if numBytes == 1 && r <= keyUS || r == keyDEL { if numBytes == 1 && r <= keyUS || r == keyDEL {
return KeyMsg(Key{Type: KeyType(r)}), nil return KeyMsg(Key{Type: r}), nil
} }
// Welp, it's just a regular, ol' single rune // Welp, it's just a regular, ol' single rune