Skip to content

master-key.replayFromHistory

Replay both previously run commands via master keybindings as well simple textual edits to a buffer.

Recording Limitations

API limitations mean this command cannot replay everything. Master key has no knowledge of commands or keybindings outside of master key. This is because replay uses a history of commands updated when calling into commands like master-key.do. Furthermore while Master Key records text edits for modes where whenNoBinding = 'insertCharacters' these textual edits are limited. A maximum number of characters are stored between each call to a master-key command (determined by the setting Text History Maximum) and only simple insertion of text is handled. Given the limits of the VSCode API for observing edits, this will miss some automated insertions such as code completion and automated parentheses insertion. Also note that any edits that occur before the extension is activated are not recorded.

Excluding the aforementioned limitations, both commands and textual edits are recorded, up until the the history limit (defined by the Command History Maximum). When selecting command history to replay, you use one or more expressions.

Arguments

There are two ways the history can be selected:

  • range.from: an expression specifying the index of the first command in the history
  • range.to: an expression specifying the index of the last command in the history

OR

  • index: an expression specifying a single index from the command history

Expression evaluation for History

Expressions have access to a variable called history which is an indexable container of previously run commands. On this container you can

  • call history.len() to get the number of available commands
  • index values via history[0]; values range from 0 to history.len()-1 and indexing outside this range returns a null value. The most recently run commands are at the largest indices.
  • use last_history_index() to call a predicate function for each index from history.len()-1 to 0 and return the first index that is found to be true for this predicate.

Each element of this history contains the following properties

  • commands: an array of objects with the command field from each run command. All commands are regularized to be objects here: e.g. ["a", "b"] will be regularized to [{command = "a"}, {command = "b"}].
  • mode: the mode the command was executed from
  • repeat: the number of times the command was repeated
  • tags: the tags defined by the [[bind]] entry
  • doc: all documentation fields as defined in [[bind]]

Example

As an example, here's how Larkin runs the most recent action.

toml
[[bind]]
default = "{{bind.edit_action_history}}"
doc.name = "repeat action"
doc.description = """
Repeat the last action command. Actions usually modify the text of a document in one
way or another. (But, e.g. sending text to the REPL is also considered an editor action).
See also `,` which repeats the last "subject" of an action (the selection preceding an
action).
"""
key = "."
command = "runCommands"
repeat = "{{key.count}}"

[[bind.args.commands]]
command = "master-key.replayFromHistory"
# we can repeat any action but history-related actions; we make an exception for
# replaying macros, which *can* be repeated
args.index = """{{
last_history_index(|x|
    x.tags.contains("action") &&
    !(x.tags.contains("history") && !x.docs.name == "replay")
}}"""

[[bind.args.commands]]
command = "master-key.enterNormal"

The key argument of relevance here is the expression defined in args.index where we select the most recent command that has the tag "action", excluding those actions that are related to manipulating the history of commands.

Avoid Self-references

Replay commands should normally avoid replaying themselves. Follow the examples in Larkin to avoid this. Confusing behavior can arise from the self-referencing of replay commands. Sometimes nesting is desirable however: we want to be able to replay a command sequence that includes the 'repeat action' command.