Remove global Keyseq, embed in Keymap

This commit is contained in:
Daisuke Maki 2014-07-05 22:29:34 +09:00
parent 8d84660f67
commit 9264c9fa7e
5 changed files with 55 additions and 49 deletions

View file

@ -1,6 +1,7 @@
package peco
import (
"encoding/json"
"unicode"
"github.com/nsf/termbox-go"
@ -24,7 +25,7 @@ type ActionFunc func(*Input, termbox.Event)
var nameToActions map[string]Action
// This is the default keybinding used by NewKeymap()
var defaultKeyBinding map[termbox.Key]Action
var defaultKeyBinding map[string]Action
// Execute fulfills the Action interface for AfterFunc
func (a ActionFunc) Execute(i *Input, e termbox.Event) {
@ -37,18 +38,22 @@ func (a ActionFunc) Execute(i *Input, e termbox.Event) {
func (a ActionFunc) Register(name string, defaultKeys ...termbox.Key) {
nameToActions["peco."+name] = a
for _, k := range defaultKeys {
Keyseq.Add(keyseq.KeyList{keyseq.NewKeyFromKey(k)}, a)
a.RegisterKeySequence(keyseq.KeyList{keyseq.NewKeyFromKey(k)})
}
}
func (a ActionFunc) RegisterKeySequence(k keyseq.KeyList) {
Keyseq.Add(k, a)
b, err := json.Marshal(k)
if err != nil {
panic(err)
}
defaultKeyBinding[string(b)] = a
}
func init() {
// Build the global maps
nameToActions = map[string]Action{}
defaultKeyBinding = map[termbox.Key]Action{}
defaultKeyBinding = map[string]Action{}
ActionFunc(doBeginningOfLine).Register("BeginningOfLine", termbox.KeyCtrlA)
ActionFunc(doBackwardChar).Register("BackwardChar", termbox.KeyCtrlB)
@ -109,21 +114,19 @@ func init() {
ActionFunc(doKonamiCommand).RegisterKeySequence(
keyseq.KeyList{
keyseq.Key{0,termbox.KeyCtrlX,0},
keyseq.Key{0,termbox.KeyArrowUp,0},
keyseq.Key{0,termbox.KeyArrowUp,0},
keyseq.Key{0,termbox.KeyArrowDown,0},
keyseq.Key{0,termbox.KeyArrowDown,0},
keyseq.Key{0,termbox.KeyArrowLeft,0},
keyseq.Key{0,termbox.KeyArrowRight,0},
keyseq.Key{0,termbox.KeyArrowLeft,0},
keyseq.Key{0,termbox.KeyArrowRight,0},
keyseq.Key{0,0,'b'},
keyseq.Key{0,0,'a'},
keyseq.Key{0, termbox.KeyCtrlX, 0},
keyseq.Key{0, termbox.KeyArrowUp, 0},
keyseq.Key{0, termbox.KeyArrowUp, 0},
keyseq.Key{0, termbox.KeyArrowDown, 0},
keyseq.Key{0, termbox.KeyArrowDown, 0},
keyseq.Key{0, termbox.KeyArrowLeft, 0},
keyseq.Key{0, termbox.KeyArrowRight, 0},
keyseq.Key{0, termbox.KeyArrowLeft, 0},
keyseq.Key{0, termbox.KeyArrowRight, 0},
keyseq.Key{0, 0, 'b'},
keyseq.Key{0, 0, 'a'},
},
)
Keyseq.Compile()
}
// This is a noop action
@ -224,8 +227,8 @@ func doFinish(i *Input, _ termbox.Event) {
}
func doCancel(i *Input, ev termbox.Event) {
if Keyseq.InMiddleOfChain() {
Keyseq.CancelChain()
if i.currentKeymap.Keyseq.InMiddleOfChain() {
i.currentKeymap.Keyseq.CancelChain()
return
}

2
ctx.go
View file

@ -245,7 +245,7 @@ func (c *Ctx) NewInput() *Input {
// Create a new keymap object
k := NewKeymap()
k.ApplyConfig(c.config.Keymap)
return &Input{c, &sync.Mutex{}, nil, k, false}
return &Input{c, &sync.Mutex{}, nil, k}
}
func (c *Ctx) Stop() {

View file

@ -12,7 +12,6 @@ type Input struct {
mutex *sync.Mutex // Currently only used for protecting Alt/Esc workaround
mod *time.Timer
currentKeymap Keymap
chained bool
}
func (i *Input) Loop() {
@ -84,7 +83,7 @@ func (i *Input) handleInputEvent(ev termbox.Event) {
}
func (i *Input) handleKeyEvent(ev termbox.Event) {
if h := i.currentKeymap.Handler(ev, i.chained); h != nil {
if h := i.currentKeymap.Handler(ev); h != nil {
h.Execute(i, ev)
return
}

View file

@ -1,6 +1,7 @@
package peco
import (
"encoding/json"
"fmt"
"os"
"strings"
@ -16,13 +17,9 @@ const (
ModMax
)
// Keyseq does successive matches against key events.
var Keyseq = keyseq.New()
type Keymap [ModMax]RawKeymap
// RawKeymap contains the actual mapping from termbox.Key to Action
type RawKeymap map[termbox.Key]Action
type Keymap struct {
Keyseq *keyseq.Keyseq
}
type KeymapStringKey string
@ -153,24 +150,26 @@ func (ksk KeymapStringKey) ToKey() (k termbox.Key, modifier int, ch rune, err er
}
func NewKeymap() Keymap {
def := RawKeymap{}
for k, v := range defaultKeyBinding {
def[k] = v
}
return Keymap{
def,
{},
k := keyseq.New()
for s, a := range defaultKeyBinding {
kl := keyseq.KeyList{}
if err := json.Unmarshal([]byte(s), &kl); err != nil {
panic(err)
}
k.Add(kl, a)
}
k.Compile()
return Keymap{k}
}
func (km Keymap) Handler(ev termbox.Event, chained bool) Action {
func (km Keymap) Handler(ev termbox.Event) Action {
modifier := ModNone
if (ev.Mod & termbox.ModAlt) != 0 {
modifier = ModAlt
}
key := keyseq.Key{modifier, ev.Key, ev.Ch}
action, err := Keyseq.AcceptKey(key)
action, err := km.Keyseq.AcceptKey(key)
switch err {
case nil:
@ -204,11 +203,11 @@ func (km Keymap) ApplyConfig(c map[string]string) {
continue
}
Keyseq.Add(list, v)
km.Keyseq.Add(list, v)
}
}
// TODO: this needs to be fixed.
func (km Keymap) hasModifierMaps() bool {
return len(km[ModAlt]) > 0
return false
}

View file

@ -39,26 +39,31 @@ func TestKeymapStrToKeyValue(t *testing.T) {
}
func TestKeymapStrToKeyValueWithAlt(t *testing.T) {
expected := map[string]termbox.Key{
"M-v": termbox.Key('v'),
"M-C-v": termbox.KeyCtrlV,
"M-Space": termbox.KeySpace,
"M-MouseLeft": termbox.MouseLeft,
expected := map[string]struct{
key termbox.Key
ch rune
} {
"M-v": {0, 'v'},
"M-C-v": {termbox.KeyCtrlV,rune(0)},
"M-Space": {termbox.KeySpace, rune(0)},
"M-MouseLeft": {termbox.MouseLeft, rune(0)},
}
t.Logf("Checking Alt prefixed key name mapping...")
for n, v := range expected {
t.Logf(" checking %s...", n)
// TODO ch isn't being checked
k, modifier, _, err := KeymapStringKey(n).ToKey()
k, modifier, ch, err := KeymapStringKey(n).ToKey()
if err != nil {
t.Errorf("Failed ToKey: Key name %s", n)
}
if modifier != 1 {
t.Errorf("Key name %s has Alt prefix", n)
}
if k != v {
t.Errorf("Expected '%s' to be '%d', but got '%d'", n, v, stringToKey[n])
if k != v.key {
t.Errorf("Expected '%s' to be '%d', but got '%d'", n, v.key, k)
}
if ch != v.ch {
t.Errorf("Expected '%s' to be '%c', but got '%c'", n, v.ch, ch)
}
}
}