Refactor input mapping
All checks were successful
timw4mail/gilo/pipeline/head This commit looks good

This commit is contained in:
Timothy Warren 2021-04-02 11:57:24 -04:00
parent f4a252a294
commit f2e9cd3075

View File

@ -80,6 +80,13 @@ func (e *editor) SetStatusMessage(template string, a ...interface{}) {
func (e *editor) ProcessKeypress() bool {
ch, _ := terminal.ReadKey()
return e.processKeypressChar(ch)
}
/**
* Determine what to do with an individual character of input
*/
func (e *editor) processKeypressChar(ch rune) bool {
switch ch {
case key.Ctrl('q'):
if e.document.dirty && e.quitTimes > 0 {
@ -106,34 +113,51 @@ func (e *editor) ProcessKeypress() bool {
// Modifier keys that return ANSI escape sequences
str := parseEscapeSequence()
switch str {
case keyUp,
keyDown,
keyLeft,
keyRight,
keyPageUp,
keyPageDown,
keyHome,
keyEnd:
e.moveCursor(str)
case keyDelete:
e.moveCursor(keyRight)
e.delChar()
// Don't swallow a character after ESC if it doesn't
// start an ANSI escape sequence
if len(str) == 1 {
return e.processKeypressChar(rune(str[0]))
}
e.processKeypressStr(str)
default:
e.insertChar(ch)
}
// Clear the quit message and restart the
// confirmation count if confirmation is not
// completed
if e.quitTimes != KiloQuitTimes {
e.quitTimes = KiloQuitTimes
e.SetStatusMessage("")
}
return true
}
/**
* Determine what do do with a parsed ANSI escape sequence
*/
func (e *editor) processKeypressStr(key string) {
switch key {
case keyUp,
keyDown,
keyLeft,
keyRight,
keyPageUp,
keyPageDown,
keyHome,
keyEnd:
e.moveCursor(key)
case keyDelete:
e.moveCursor(keyRight)
e.delChar()
}
}
func (e *editor) moveCursor(key string) {
var row *row
if e.cursor.y >= e.document.rowCount() {
@ -229,64 +253,84 @@ func (e *editor) delChar() {
// Convert the raw ANSI escape sequences to the type of key input
func parseEscapeSequence() string {
var runes []rune
// If we aren't starting an escape sequence,
// return the character
startChar, _ := terminal.ReadKey()
if startChar != '[' && startChar != 'O' {
return string(startChar)
}
for i := 0; i < 3; i++ {
// Read one or two characters after
// \e[ or \eO, which is the end of the
// handled escape sequences
runes := [2]rune{'\000', '\000'}
for i := 0; i < 2; i++ {
ch, size := terminal.ReadKey()
if size == 0 {
return "\x1b"
return string(rune(key.Esc))
}
runes = append(runes, ch)
runes[i] = ch
if i == 1 && runes[1] >= 'A' {
// \eOH \eOF
if runes[0] == 'O' {
switch runes[1] {
case 'H':
return keyHome
case 'F':
return keyEnd
}
}
// \e[A
if runes[0] == '[' {
switch runes[1] {
case 'A':
return keyUp
case 'B':
return keyDown
case 'C':
return keyRight
case 'D':
return keyLeft
case 'H':
return keyHome
case 'F':
return keyEnd
}
}
if i == 0 && runes[0] >= 'A' && runes[0] <= 'Z' {
return escSeqToKey([]rune{startChar, runes[0]})
}
// \e[1~
if i == 2 && runes[0] == '[' && runes[2] == '~' {
switch runes[1] {
case '1':
return keyHome
case '3':
return keyDelete
case '4':
return keyEnd
case '5':
return keyPageUp
case '6':
return keyPageDown
case '7':
return keyHome
case '8':
return keyEnd
}
// \e[*~
if i == 1 && startChar == '[' && runes[1] == '~' {
return escSeqToKey([]rune{startChar, runes[0], runes[1]})
}
}
return string('\x1b')
return string(rune(key.Esc))
}
func escSeqToKey (seq []rune) string {
// \eO*
// \e[*
if len(seq) == 2 {
startChar, cmd := seq[0], seq[1]
if startChar == 'O' {
switch cmd {
case 'H':
return keyHome
case 'F':
return keyEnd
}
} else if startChar == '[' {
switch cmd {
case 'A':
return keyUp
case 'B':
return keyDown
case 'C':
return keyRight
case 'D':
return keyLeft
case 'H':
return keyHome
case 'F':
return keyEnd
}
}
} else if len(seq) == 3 { // \e[*~
cmd := seq[1]
switch cmd {
case '1':
return keyHome
case '3':
return keyDelete
case '4':
return keyEnd
case '5':
return keyPageUp
case '6':
return keyPageDown
case '7':
return keyHome
case '8':
return keyEnd
}
}
return string(rune(key.Esc))
}