Add support for macros

Closes #270

CtrlU to toggle recording and CtrlJ to playback.
You can also rebind using the "ToggleMacro" and "PlayMacro"
actions.

Note that recursive macros are not yet supported.
This commit is contained in:
Zachary Yedidia
2016-09-06 10:43:45 -04:00
parent 966dac97f8
commit 539495d2f7
6 changed files with 81 additions and 0 deletions

View File

@@ -1476,6 +1476,62 @@ func (v *View) PreviousSplit(usePlugin bool) bool {
return false
}
var curMacro []interface{}
var recordingMacro bool
func (v *View) ToggleMacro(usePlugin bool) bool {
if usePlugin && !PreActionCall("ToggleMacro", v) {
return false
}
recordingMacro = !recordingMacro
if recordingMacro {
curMacro = []interface{}{}
messenger.Message("Recording")
} else {
messenger.Message("Stopped recording")
}
if usePlugin {
return PostActionCall("ToggleMacro", v)
}
return true
}
func (v *View) PlayMacro(usePlugin bool) bool {
if usePlugin && !PreActionCall("PlayMacro", v) {
return false
}
for _, action := range curMacro {
switch t := action.(type) {
case rune:
// Insert a character
if v.Cursor.HasSelection() {
v.Cursor.DeleteSelection()
v.Cursor.ResetSelection()
}
v.Buf.Insert(v.Cursor.Loc, string(t))
v.Cursor.Right()
for _, pl := range loadedPlugins {
_, err := Call(pl+".onRune", string(t), v)
if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") {
TermMessage(err)
}
}
case func(*View, bool) bool:
t(v, true)
}
}
if usePlugin {
return PostActionCall("PlayMacro", v)
}
return true
}
// None is no action
func None() bool {
return false

View File

@@ -79,6 +79,8 @@ var bindingActions = map[string]func(*View, bool) bool{
"NextTab": (*View).NextTab,
"NextSplit": (*View).NextSplit,
"PreviousSplit": (*View).PreviousSplit,
"ToggleMacro": (*View).ToggleMacro,
"PlayMacro": (*View).PlayMacro,
// This was changed to InsertNewline but I don't want to break backwards compatibility
"InsertEnter": (*View).InsertNewline,
@@ -408,6 +410,8 @@ func DefaultBindings() map[string]string {
"CtrlQ": "Quit",
"CtrlE": "CommandMode",
"CtrlW": "NextSplit",
"CtrlU": "ToggleMacro",
"CtrlJ": "PlayMacro",
// Emacs-style keybindings
"Alt-f": "WordRight",

View File

@@ -3,6 +3,8 @@ package main
import (
"os"
"path/filepath"
"reflect"
"runtime"
"strconv"
"strings"
"time"
@@ -217,3 +219,7 @@ func Abs(n int) int {
}
return n
}
func FuncName(i interface{}) string {
return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
}

View File

@@ -340,6 +340,10 @@ func (v *View) HandleEvent(event tcell.Event) {
TermMessage(err)
}
}
if recordingMacro {
curMacro = append(curMacro, e.Rune())
}
} else {
for key, actions := range bindings {
if e.Key() == key.keyCode {
@@ -352,6 +356,12 @@ func (v *View) HandleEvent(event tcell.Event) {
relocate = false
for _, action := range actions {
relocate = action(v, true) || relocate
funcName := FuncName(action)
if funcName != "main.(*View).ToggleMacro" && funcName != "main.(*View).PlayMacro" {
if recordingMacro {
curMacro = append(curMacro, action)
}
}
}
}
}