Forward key events to child terminal
This commit is contained in:
parent
699f1cf7a6
commit
28f393bdbd
2
go.mod
2
go.mod
|
@ -1,7 +1,7 @@
|
||||||
module git.sr.ht/~sircmpwn/aerc2
|
module git.sr.ht/~sircmpwn/aerc2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.sr.ht/~sircmpwn/go-libvterm v0.0.0-20190317210455-72d6c2838fbe
|
git.sr.ht/~sircmpwn/go-libvterm v0.0.0-20190321231430-3db654768b06
|
||||||
github.com/emersion/go-imap v1.0.0-beta.1
|
github.com/emersion/go-imap v1.0.0-beta.1
|
||||||
github.com/emersion/go-imap-idle v0.0.0-20180114101550-2af93776db6b
|
github.com/emersion/go-imap-idle v0.0.0-20180114101550-2af93776db6b
|
||||||
github.com/emersion/go-sasl v0.0.0-20161116183048-7e096a0a6197 // indirect
|
github.com/emersion/go-sasl v0.0.0-20161116183048-7e096a0a6197 // indirect
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -8,6 +8,10 @@ git.sr.ht/~sircmpwn/go-libvterm v0.0.0-20190317205953-0674b071e8bf h1:6Ynr+M6lUn
|
||||||
git.sr.ht/~sircmpwn/go-libvterm v0.0.0-20190317205953-0674b071e8bf/go.mod h1:hT88+cTemwwESbMptwC7O33qrJfQX0SgRWbXlndUS2c=
|
git.sr.ht/~sircmpwn/go-libvterm v0.0.0-20190317205953-0674b071e8bf/go.mod h1:hT88+cTemwwESbMptwC7O33qrJfQX0SgRWbXlndUS2c=
|
||||||
git.sr.ht/~sircmpwn/go-libvterm v0.0.0-20190317210455-72d6c2838fbe h1:pg73OOcg6PZp+XUOsFaqGG4Heu3kYAJZHSaS6eRRmJk=
|
git.sr.ht/~sircmpwn/go-libvterm v0.0.0-20190317210455-72d6c2838fbe h1:pg73OOcg6PZp+XUOsFaqGG4Heu3kYAJZHSaS6eRRmJk=
|
||||||
git.sr.ht/~sircmpwn/go-libvterm v0.0.0-20190317210455-72d6c2838fbe/go.mod h1:hT88+cTemwwESbMptwC7O33qrJfQX0SgRWbXlndUS2c=
|
git.sr.ht/~sircmpwn/go-libvterm v0.0.0-20190317210455-72d6c2838fbe/go.mod h1:hT88+cTemwwESbMptwC7O33qrJfQX0SgRWbXlndUS2c=
|
||||||
|
git.sr.ht/~sircmpwn/go-libvterm v0.0.0-20190321231235-12f4bd976b20 h1:5oQDpkPYOnIJZnbT5jgUhpRqOkHcbMLe2vmHHRcmcys=
|
||||||
|
git.sr.ht/~sircmpwn/go-libvterm v0.0.0-20190321231235-12f4bd976b20/go.mod h1:hT88+cTemwwESbMptwC7O33qrJfQX0SgRWbXlndUS2c=
|
||||||
|
git.sr.ht/~sircmpwn/go-libvterm v0.0.0-20190321231430-3db654768b06 h1:x9azyMxWqgTq4ARhNbYKHejt0PMhLi8J2XnuEsih9Qc=
|
||||||
|
git.sr.ht/~sircmpwn/go-libvterm v0.0.0-20190321231430-3db654768b06/go.mod h1:hT88+cTemwwESbMptwC7O33qrJfQX0SgRWbXlndUS2c=
|
||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/emersion/go-imap v1.0.0-beta.1 h1:bTCaVlUnb5mKoW9lEukusxguSYYZPer+q0g5t+vw5X0=
|
github.com/emersion/go-imap v1.0.0-beta.1 h1:bTCaVlUnb5mKoW9lEukusxguSYYZPer+q0g5t+vw5X0=
|
||||||
|
|
|
@ -12,6 +12,81 @@ import (
|
||||||
"github.com/kr/pty"
|
"github.com/kr/pty"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type vtermKey struct {
|
||||||
|
Key vterm.Key
|
||||||
|
Rune rune
|
||||||
|
Mod vterm.Modifier
|
||||||
|
}
|
||||||
|
|
||||||
|
var keyMap map[tcell.Key]vtermKey
|
||||||
|
|
||||||
|
func directKey(key vterm.Key) vtermKey {
|
||||||
|
return vtermKey{key, 0, vterm.ModNone}
|
||||||
|
}
|
||||||
|
|
||||||
|
func runeMod(r rune, mod vterm.Modifier) vtermKey {
|
||||||
|
return vtermKey{vterm.KeyNone, r, mod}
|
||||||
|
}
|
||||||
|
|
||||||
|
func keyMod(key vterm.Key, mod vterm.Modifier) vtermKey {
|
||||||
|
return vtermKey{key, 0, mod}
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
keyMap = make(map[tcell.Key]vtermKey)
|
||||||
|
keyMap[tcell.KeyCtrlSpace] = runeMod(' ', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlA] = runeMod('a', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlB] = runeMod('b', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlC] = runeMod('c', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlD] = runeMod('d', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlE] = runeMod('e', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlF] = runeMod('f', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlG] = runeMod('g', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlH] = runeMod('h', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlI] = runeMod('i', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlJ] = runeMod('j', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlK] = runeMod('k', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlL] = runeMod('l', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlM] = runeMod('m', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlN] = runeMod('n', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlO] = runeMod('o', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlP] = runeMod('p', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlQ] = runeMod('q', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlR] = runeMod('r', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlS] = runeMod('s', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlT] = runeMod('t', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlU] = runeMod('u', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlV] = runeMod('v', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlW] = runeMod('w', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlX] = runeMod('x', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlY] = runeMod('y', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlZ] = runeMod('z', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlBackslash] = runeMod('\\', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlCarat] = runeMod('^', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyCtrlUnderscore] = runeMod('_', vterm.ModCtrl)
|
||||||
|
keyMap[tcell.KeyEnter] = directKey(vterm.KeyEnter)
|
||||||
|
keyMap[tcell.KeyTab] = directKey(vterm.KeyTab)
|
||||||
|
keyMap[tcell.KeyBackspace] = directKey(vterm.KeyBackspace)
|
||||||
|
keyMap[tcell.KeyEscape] = directKey(vterm.KeyEscape)
|
||||||
|
keyMap[tcell.KeyUp] = directKey(vterm.KeyUp)
|
||||||
|
keyMap[tcell.KeyDown] = directKey(vterm.KeyDown)
|
||||||
|
keyMap[tcell.KeyLeft] = directKey(vterm.KeyLeft)
|
||||||
|
keyMap[tcell.KeyRight] = directKey(vterm.KeyRight)
|
||||||
|
keyMap[tcell.KeyInsert] = directKey(vterm.KeyIns)
|
||||||
|
keyMap[tcell.KeyDelete] = directKey(vterm.KeyDel)
|
||||||
|
keyMap[tcell.KeyHome] = directKey(vterm.KeyHome)
|
||||||
|
keyMap[tcell.KeyEnd] = directKey(vterm.KeyEnd)
|
||||||
|
keyMap[tcell.KeyPgUp] = directKey(vterm.KeyPageUp)
|
||||||
|
keyMap[tcell.KeyPgDn] = directKey(vterm.KeyPageDown)
|
||||||
|
for i := 0; i < 64; i++ {
|
||||||
|
keyMap[tcell.Key(int(tcell.KeyF1)+i)] =
|
||||||
|
directKey(vterm.Key(int(vterm.KeyFunction0) + i))
|
||||||
|
}
|
||||||
|
keyMap[tcell.KeyTAB] = directKey(vterm.KeyTab)
|
||||||
|
keyMap[tcell.KeyESC] = directKey(vterm.KeyEscape)
|
||||||
|
keyMap[tcell.KeyDEL] = directKey(vterm.KeyBackspace)
|
||||||
|
}
|
||||||
|
|
||||||
type Terminal struct {
|
type Terminal struct {
|
||||||
closed bool
|
closed bool
|
||||||
cmd *exec.Cmd
|
cmd *exec.Cmd
|
||||||
|
@ -43,11 +118,14 @@ func NewTerminal(cmd *exec.Cmd) (*Terminal, error) {
|
||||||
for {
|
for {
|
||||||
n, err := term.pty.Read(buf)
|
n, err := term.pty.Read(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
term.Close(err)
|
// These are generally benine errors when the process exits
|
||||||
|
term.Close(nil)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
n, err = term.vterm.Write(buf[:n])
|
n, err = term.vterm.Write(buf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
term.Close(err)
|
term.Close(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
term.Invalidate()
|
term.Invalidate()
|
||||||
}
|
}
|
||||||
|
@ -87,6 +165,25 @@ func NewTerminal(cmd *exec.Cmd) (*Terminal, error) {
|
||||||
return term, nil
|
return term, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (term *Terminal) flushTerminal() {
|
||||||
|
buf := make([]byte, 2048)
|
||||||
|
for {
|
||||||
|
n, err := term.vterm.Read(buf)
|
||||||
|
if err != nil {
|
||||||
|
term.Close(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if n == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
n, err = term.pty.Write(buf[:n])
|
||||||
|
if err != nil {
|
||||||
|
term.Close(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (term *Terminal) Close(err error) {
|
func (term *Terminal) Close(err error) {
|
||||||
term.err = err
|
term.err = err
|
||||||
if term.vterm != nil {
|
if term.vterm != nil {
|
||||||
|
@ -193,7 +290,44 @@ func (term *Terminal) Focus(focus bool) {
|
||||||
term.resetCursor()
|
term.resetCursor()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func convertMods(mods tcell.ModMask) vterm.Modifier {
|
||||||
|
var (
|
||||||
|
ret uint = 0
|
||||||
|
mask uint = uint(mods)
|
||||||
|
)
|
||||||
|
if mask&uint(tcell.ModShift) > 0 {
|
||||||
|
ret |= uint(vterm.ModShift)
|
||||||
|
}
|
||||||
|
if mask&uint(tcell.ModCtrl) > 0 {
|
||||||
|
ret |= uint(vterm.ModCtrl)
|
||||||
|
}
|
||||||
|
if mask&uint(tcell.ModAlt) > 0 {
|
||||||
|
ret |= uint(vterm.ModAlt)
|
||||||
|
}
|
||||||
|
return vterm.Modifier(ret)
|
||||||
|
}
|
||||||
|
|
||||||
func (term *Terminal) Event(event tcell.Event) bool {
|
func (term *Terminal) Event(event tcell.Event) bool {
|
||||||
|
switch event := event.(type) {
|
||||||
|
case *tcell.EventKey:
|
||||||
|
if event.Key() == tcell.KeyRune {
|
||||||
|
term.vterm.KeyboardUnichar(
|
||||||
|
event.Rune(), convertMods(event.Modifiers()))
|
||||||
|
} else {
|
||||||
|
if key, ok := keyMap[event.Key()]; ok {
|
||||||
|
if key.Key == vterm.KeyNone {
|
||||||
|
term.vterm.KeyboardUnichar(
|
||||||
|
key.Rune, key.Mod)
|
||||||
|
} else if key.Mod == vterm.ModNone {
|
||||||
|
term.vterm.KeyboardKey(key.Key,
|
||||||
|
convertMods(event.Modifiers()))
|
||||||
|
} else {
|
||||||
|
term.vterm.KeyboardKey(key.Key, key.Mod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
term.flushTerminal()
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue