diff --git a/widgets/mapkeys/mapkeys.go b/widgets/mapkeys/mapkeys.go new file mode 100644 index 0000000..77fe1a8 --- /dev/null +++ b/widgets/mapkeys/mapkeys.go @@ -0,0 +1,75 @@ +// Copyright 2019-2020 Graham Clark. All rights reserved. Use of this source +// code is governed by the MIT license that can be found in the LICENSE +// file. + +// Package mapkeys provides a widget that can map one keypress to a sequence of +// keypresses. If the user pnovides as input a key that is mapped, the sequence of +// resulting keypresses is played to the subwidget before control returns. If the key is +// not mapped, it is passed through as normal. I'm going to use this to provide a vim-like +// macro feature in termshark. +package mapkeys + +import ( + "github.com/gcla/gowid" + "github.com/gcla/gowid/vim" + "github.com/gdamore/tcell" +) + +//====================================================================== + +type Widget struct { + gowid.IWidget + kmap map[vim.KeyPress]vim.KeySequence +} + +var _ gowid.IWidget = (*Widget)(nil) + +func New(w gowid.IWidget) *Widget { + res := &Widget{ + IWidget: w, + kmap: make(map[vim.KeyPress]vim.KeySequence), + } + return res +} + +func (w *Widget) UserInput(ev interface{}, size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) bool { + switch ev := ev.(type) { + case *tcell.EventKey: + kp := vim.KeyPressFromTcell(ev) + if seq, ok := w.kmap[kp]; ok { + var res bool + for _, k := range seq { + // What should the handled value be?? + res = w.IWidget.UserInput(tcell.NewEventKey(k.Key, k.Ch, k.Mod), size, focus, app) + } + return res + } else { + return w.IWidget.UserInput(ev, size, focus, app) + } + default: + return w.IWidget.UserInput(ev, size, focus, app) + } +} + +func (w *Widget) AddMapping(from vim.KeyPress, to vim.KeySequence, app gowid.IApp) { + w.kmap[from] = to +} + +func (w *Widget) RemoveMapping(from vim.KeyPress, app gowid.IApp) { + delete(w.kmap, from) +} + +// ClearMappings will remove all mappings. I deliberately preserve the same dictionary, +// though in case I decide in the future it's useful to let clients have direct access to +// the map (and so maybe store it somewhere). +func (w *Widget) ClearMappings(app gowid.IApp) { + for k := range w.kmap { + delete(w.kmap, k) + } +} + +//====================================================================== +// Local Variables: +// mode: Go +// fill-column: 90 +// End: