]> git.lizzy.rs Git - micro.git/commitdiff
Improve internal keyevent names
authorZachary Yedidia <zyedidia@gmail.com>
Mon, 29 Jun 2020 04:50:19 +0000 (00:50 -0400)
committerZachary Yedidia <zyedidia@gmail.com>
Sun, 9 Aug 2020 20:42:03 +0000 (16:42 -0400)
internal/action/events.go
internal/action/keytree.go [new file with mode: 0644]
internal/action/rawpane.go

index 5bf6c58ed90cf7f37f80d156d104636ee5d25fae..7daeca52ce5d6dcea8fe93d76aee13900d4d051f 100644 (file)
@@ -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 "<any>"
+       }
+       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 (file)
index 0000000..4b7fec1
--- /dev/null
@@ -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
+}
index d39adddb5c50383ebb5296c3c1ca71c2b1a58939..7541c2885310b2a45179ad90cdae47318ce9a782 100644 (file)
@@ -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()))