In CodeRunner, you can create commands with advanced behaviors by using compound commands. A compound command is a procedural-style collection of commands written in JSON format.
A series of commands are supplied in a JSON list []
, referred to as a command list. Command lists may be nested. Commands are supplied in quotes (as JSON strings) within the list. If the command name contains a colon :
, the next element in the command list is an argument to this command, rather than a new command. If two colons appear in the command name, there are two arguments expected, etc. Example:
["moveLeft", "insertText:", "hello", "surroundSelectionWithString:endString:", "(", ")"]
In this example, the editor command moveLeft
has no arguments, so the next element is interpreted as a new command. insertText:
takes one argument, so the next element, "hello"
, is an argument to this command (i.e. the text to be inserted). surroundSelectionWithString:endString:
takes two arguments. Note that all commands are quoted so as to be valid JSON. The most important commands are listed below, and you can discover all available commands by using the code completion facility when writing compound commands.
Some commands, referred to as tests, have a positive/negative return value associated with them. Tests typically begin with the words test
or find
. When a test appears in a command list and the test fails, the execution of the command list containing the test is aborted. No further commands are executed in this command list and the state of the document is restored to the state it was in before entering the failed command list. This means that any changes made to the state of the document (text content, selection, etc.) within the failed command list are discarded. If this behavior is undesired, for example when using find
commands, use nested command lists.
If a test appears in the top-most command list of a compound command, and the test fails, the keystrokes that triggered the compound command are routed to other compound commands, if applicable, and if these fail, the default behaviors of the keystrokes are performed. If the top-most command list does not contain any tests or the tests are positive, the keystrokes are consumed by this compound command and further behaviors are suppressed.
Typically, a compound command begins with a few tests to check whether the command is applicable in the current context. This prevents it from being triggered in undesirable situations. A useful command for this purpose is testActiveSyntax:
, which allows you to quickly check the syntax language at the current selection location. The test will fail if the current selection is inside of a string or comment. The argument should be a top level scope selector beginning with source
or text
. You can discover which scopes are active at the current selection in a document by using .
JSON objects {}
may appear alongside command lists. If the root element of the JSON is an object rather than a command list, the compound command has multiple entry points of execution depending on what keystrokes are pressed. The object's keys refer to key equivalents as defined below, or alternatively, they are custom names which may be invoked manually by calls to callCompoundCommand:
or includeCompoundCommand:
. The associated values of the objects are always command lists. If an object appears inside of a command list, execution is paused at this point awaiting keystrokes from the user. The pressed keystrokes are checked against the object's keys and the associated command list is executed.
A key equivalent is a technical string that denotes a key combination. The string may be prefixed by a series of special characters representing modifier keys, followed by a single letter or symbol representing the pressed key. The following characters are used to represent modifier keys:
@
" for ~
" for ^
" for $
" for (or use a capital letter instead of $
)Examples of key equivalents:
@~k
" denotes ⌃⌘K@~^X
" denotes ⌃⌥⇧⌘Xe
" denotes the E key, without any modifier keysFor arrow keys, function keys, etc, use the appropriate Unicode escape sequence, such as "\uF700
". These can be found here.
Discover all available commands by using the code completion facility when writing compound commands.
break:
Breaks out of enclosing command lists with a positive return value. Supply 1 to break one level, supply 2 to break two levels, etc.exit
Stops the processing of all key binding commands, suppressing default behavior of the pressed keys.fail:
Breaks out of enclosing command lists with a negative return value. Supply 1 to break one level, supply 2 to break two levels, etc. The state of the document is restored to the state prior to the invocation of the failed command list.callCompoundCommand:
Supply the name of a compound command to execute. The name of the command must match exactly. The return value of the called command is ignored.includeCompoundCommand:
Similar to callCompoundCommand:
, but the contents of the referenced command are included directly within the enclosing command list, as if they were pasted in.callEnclosingCommandList:
Supply 1 to recursively call the parent list in which this call appears, supply 2 to call the list containing the parent list, 3 for the list above that, etc. The return value of the called command list is ignored.selectMenuItem:
Takes one argument after the command, the name of the menu item to select. The name of the menu item may contain the wildcard characters *
and ?
. You can specify a path to the item to identify it in submenus. Each respective submenu name is separated by a forward slash. If no matching menu item is found, or it is disabled, the processing of the command list containing selectMenuItem:
is aborted and the state is restored.testPrecedingText:
, testSelectedText:
, testSucceedingText:
, test...
Tests are useful for restricting the execution of commands to specific circumstances depending the text and selection situation in the document.find...
Find commands are tests that also set the selection to the matching location(s).find...Locally...
Find that automatically limits the search based on syntax, indentation, etc.insertText:
Inserts text as if typed by the user. Takes one argument after the command, the string to be inserted.insertSnippet:
Inserts text interpreted as a code snippet. Snippets are modified to match in indentation before insertion.saveSelectionWithName:
, restoreSelectionWithName:
Save and restore the selection in the document by name.copyWithName:
, pasteWithName:
Copy or paste the selected text into a named buffer that can be referenced in subsequent commands and tests.move...
, move...AndModifySelection
System commands for moving the selection, which by default are bound to the arrow keys (with optional modifiers such as Shift for modifying the selection). Many move commands refer to the current line or paragraph. Line commands are concerned with a single visual line which may be delimited by line wraps, while a paragraph refers to a logical line which is always delimited by hard line breaks. For most programming-related applications, you want to use the paragraph version of these commands.testActiveSyntax:
Tests whether the active syntax at the current selection location matches a given scope selector. Fails if the selection is inside a string or comment.and:
Supply a command list with a series of tests to execute. The return value of the call to and:
is positive if all tests were positive. (Note: The only difference between using and:
and opening a new command list is that and:
inherits the return value of the supplied list argument.)or:
Supply a command list with a series of tests to execute. The return value of the call to or:
is positive if any test was positive.negate:
Supply a command list with a series of tests to execute. The return value of the call to negate:
is the negated return value of this list.debug
Enable debug alerts, which are helpful when troubleshooting compound commands.If a compound command is invoked when multiple selections are set, the compound command is executed separately for each selection.
A key binding set may optionally define compound commands titled "Load" and "Unload". The "Load" command is executed when a new document is instantiated or this key binding set is made active. This allows for any initialization operations that may be required by the key binding set. "Unload" is executed to reverse any setup done in "Load", for example when a different key binding set is chosen.
For examples, take a look at the numerous compound commands included in CodeRunner by default. View these under Preferences ‣ Key Bindings > (Global) Compound Commands. The "Vim" key binding set implements the majority of its functionality using compound commands.