From 6c53407e6d6097e11b6073eebfb3432132d1be50 Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Mon, 29 Jun 2020 00:50:19 -0400 Subject: [PATCH] Improve internal keyevent names --- internal/action/events.go | 117 ++++++++++++++++++++++++++++++++++++- internal/action/keytree.go | 12 ++++ internal/action/rawpane.go | 6 +- 3 files changed, 129 insertions(+), 6 deletions(-) create mode 100644 internal/action/keytree.go diff --git a/internal/action/events.go b/internal/action/events.go index 5bf6c58e..7daeca52 100644 --- a/internal/action/events.go +++ b/internal/action/events.go @@ -1,10 +1,17 @@ package action import ( + "bytes" + "errors" + "fmt" + "strings" + "github.com/zyedidia/tcell" ) -type Event interface{} +type Event interface { + String() string +} // RawEvent is simply an escape code // We allow users to directly bind escape codes @@ -13,6 +20,10 @@ type RawEvent struct { esc string } +func (r RawEvent) String() string { + return r.esc +} + // KeyEvent is a key event containing a key code, // some possible modifiers (alt, ctrl, etc...) and // a rune if it was simply a character press @@ -22,6 +33,60 @@ type KeyEvent struct { code tcell.Key mod tcell.ModMask r rune + any bool +} + +func (k KeyEvent) String() string { + if k.any { + return "" + } + s := "" + m := []string{} + if k.mod&tcell.ModShift != 0 { + m = append(m, "Shift") + } + if k.mod&tcell.ModAlt != 0 { + m = append(m, "Alt") + } + if k.mod&tcell.ModMeta != 0 { + m = append(m, "Meta") + } + if k.mod&tcell.ModCtrl != 0 { + m = append(m, "Ctrl") + } + + ok := false + if s, ok = tcell.KeyNames[k.code]; !ok { + if k.code == tcell.KeyRune { + s = string(k.r) + } else { + s = fmt.Sprintf("Key[%d,%d]", k.code, int(k.r)) + } + } + if len(m) != 0 { + if k.mod&tcell.ModCtrl != 0 && strings.HasPrefix(s, "Ctrl-") { + s = s[5:] + if len(s) == 1 { + s = strings.ToLower(s) + } + } + return fmt.Sprintf("%s-%s", strings.Join(m, "-"), s) + } + return s +} + +// A KeySequence defines a list of consecutive +// key events +type KeySequenceEvent struct { + keys []KeyEvent +} + +func (k KeySequenceEvent) String() string { + buf := bytes.Buffer{} + for _, e := range k.keys { + buf.WriteString(e.String()) + } + return buf.String() } // MouseEvent is a mouse event with a mouse button and @@ -31,8 +96,54 @@ type MouseEvent struct { mod tcell.ModMask } -type KeyAction func(Handler) bool -type MouseAction func(Handler, tcell.EventMouse) bool +func (m MouseEvent) String() string { + mod := "" + if m.mod&tcell.ModShift != 0 { + mod = "Shift-" + } + if m.mod&tcell.ModAlt != 0 { + mod = "Alt-" + } + if m.mod&tcell.ModMeta != 0 { + mod = "Meta-" + } + if m.mod&tcell.ModCtrl != 0 { + mod = "Ctrl-" + } + + for k, v := range mouseEvents { + if v == m.btn { + return fmt.Sprintf("%s%s", mod, k) + } + } + return "" +} + +// ConstructEvent takes a tcell event and returns a micro +// event. Note that tcell events can't express certain +// micro events such as key sequences. This function is +// mostly used for debugging/raw panes or constructing +// intermediate micro events while parsing a sequence. +func ConstructEvent(event tcell.Event) (Event, error) { + switch e := event.(type) { + case *tcell.EventKey: + return KeyEvent{ + code: e.Key(), + mod: e.Modifiers(), + r: e.Rune(), + }, nil + case *tcell.EventRaw: + return RawEvent{ + esc: e.EscSeq(), + }, nil + case *tcell.EventMouse: + return MouseEvent{ + btn: e.Buttons(), + mod: e.Modifiers(), + }, nil + } + return nil, errors.New("No micro event equivalent") +} // A Handler will take a tcell event and execute it // appropriately diff --git a/internal/action/keytree.go b/internal/action/keytree.go new file mode 100644 index 00000000..4b7fec17 --- /dev/null +++ b/internal/action/keytree.go @@ -0,0 +1,12 @@ +package action + +type KeyAction func(Pane) bool +type MouseAction func(Pane, *MouseEvent) bool +type KeyAnyAction func(Pane, keys []KeyEvent) + +type KeyTreeNode struct { + children map[Event]KeyTreeNode + + // action KeyAction + // any KeyAnyAction +} diff --git a/internal/action/rawpane.go b/internal/action/rawpane.go index d39adddb..7541c288 100644 --- a/internal/action/rawpane.go +++ b/internal/action/rawpane.go @@ -36,9 +36,9 @@ func (h *RawPane) HandleEvent(event tcell.Event) { h.Buf.Insert(h.Cursor.Loc, reflect.TypeOf(event).String()[7:]) - switch e := event.(type) { - case *tcell.EventKey: - h.Buf.Insert(h.Cursor.Loc, fmt.Sprintf(": %s", e.Name())) + e, err := ConstructEvent(event) + if err == nil { + h.Buf.Insert(h.Cursor.Loc, fmt.Sprintf(": %s", e.String())) } h.Buf.Insert(h.Cursor.Loc, fmt.Sprintf(": %q\n", event.EscSeq()))