package macroimport ()// validMacroKeys - All valid macro IDs (keys) for read/write Vim registers.var validMacroKeys = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\""// Engine manages all things related to keyboard macros:// recording, dumping and feeding (running) them to the shell.typeEnginestruct { recording bool current []rune// Key sequence of the current macro being recorded. currentKey rune// The identifier of the macro being recorded. macros map[rune]string// All previously recorded macros. started bool keys *core.Keys// The engine feeds macros directly in the key stack. hint *ui.Hint// The engine notifies when macro recording starts/stops. status string// The hint status displaying the currently recorded macro.}// NewEngine is a required constructor to setup a working macro engine.func ( *core.Keys, *ui.Hint) *Engine {return &Engine{current: make([]rune, 0),macros: make(map[rune]string),keys: ,hint: , }}// RecordKeys is being passed every key read by the shell, and will save// those entered while the engine is in record mode. All others are ignored.func ( *Engine) {if !.recording {return } := core.MacroKeys(.keys)iflen() == 0 {return }// The first call to record should not add // the caller keys that started the recording.if !.started { .current = append(.current, ...) } .started = false .hint.Persist(.status + inputrc.EscapeMacro(string(.current)) + color.Reset)}// StartRecord starts saving all user key input to record a macro.// If the key parameter is an alphanumeric character, the macro recorded will be// stored and used through this letter argument, just like macros work in Vim.// If the key is neither valid nor the null value, the engine does not start.// A notification containing the saved sequence is given through the hint section.func ( *Engine) ( rune) {switch {caseisValidMacroID(), == 0: .currentKey = default:return } .started = true .recording = true .status = color.Dim + "Recording macro: " + color.Bold .hint.Persist(.status)}// StopRecord stops using key input as part of a macro.// The hint section displaying the currently saved sequence is cleared.func ( *Engine) ( ...rune) { .recording = false// Remove the hint. .hint.ResetPersist()iflen(.current) == 0 {return } .current = append(.current, ...) := inputrc.EscapeMacro(string(.current)) .macros[.currentKey] = .macros[rune(0)] = .current = make([]rune, 0)}// Recording returns true if the macro engine is recording the keys for a macro.func ( *Engine) () bool {return .recording}// RunLastMacro feeds keys the last recorded macro to the shell's key stack,// so that the macro is replayed.// Note that this function only feeds the keys of the macro back into the key// stack: it does not dispatch them to commands, therefore not running any.func ( *Engine) () {iflen(.macros) == 0 {return } := inputrc.Unescape(.macros[rune(0)])iflen() == 0 {return } .keys.Feed(false, []rune()...)}// RunMacro runs a given macro, injecting its key sequence back into the shell key stack.// The key argument should either be one of the valid alphanumeric macro identifiers, or// a nil rune (in which case the last recorded macro is ran).// Note that this function only feeds the keys of the macro back into the key// stack: it does not dispatch them to commands, therefore not running any.func ( *Engine) ( rune) {if !isValidMacroID() && != 0 {return } := .macros[]iflen() == 0 {return } = strings.ReplaceAll(, `\e`, "\x1b") .keys.Feed(false, []rune()...)}// PrintLastMacro dumps the last recorded macro sequence to the screen.func ( *Engine) () {iflen(.macros) == 0 {return }// Print the macro and the prompt. // The shell takes care of clearing itself // before printing, and refreshing after.fmt.Printf("\n%s\n", .macros[.currentKey])}// PrintAllMacros dumps all macros to the screen, which one line// per saved macro sequence, next to its corresponding key ID.func ( *Engine) () {var []runefor := range .macros { = append(, ) }sort.Slice(, func(, int) bool {return [] < [] })for , := range { := .macros[]if == "" {continue }if == 0 { = '"' }fmt.Printf("\"%s\": %s\n", string(), ) }}func isValidMacroID( rune) bool {for , := rangevalidMacroKeys {if == {returntrue } }returnfalse}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.