# `onKeyPress`

> Custom definable key bindings and macros

## Description

While Murex aims to have compatibility with common keyboard shortcuts favoured
in other shells, there is still a need for to define your own preferences.

`onKeyPress` enables you to write custom key bindings and macros in Murex using
Murex's scripting language.    

## Usage

```
event onKeyPress name=keystroke { code block }

!event onKeyPress name[.keystroke]
```

## Payload

The following payload is passed to the function via stdin:

```
{
    "Name": "",
    "Interrupt": {
        "Line": "",
        "CursorPos": 0,
        "KeyPress": "",
        "IsMasked": false,
        "InputMode": "",
        "PreviewMode": ""
    }
}
```

### Name

This is the **namespaced** name -- ie the name and operation.

### Interrupt/Name

This is the name you specified when defining the event.

### Interrupt/Line

The current line as it appears in _readline_.

### Interrupt/CursorPos

Where the text input cursor is sat on the line

### Interrupt/KeyPress

The key which was pressed.

If the key stroke is represented by an ANSI escape sequence, then this field
will be multiple multiple characters long.

### Interrupt/IsMasked

This will be `true` if you have a password / input mask (eg `*`). Otherwise it
will be `false`.

### Interrupt/InputMode

This is the input mode of _readline_. Different input modes will utilise
keystrokes differently.

This field is a string and the following constants are supported:

* `Normal`:         regular input
* `VimKeys`:        where input behaves like `vim`
* `VimReplaceOnce`: `vim` mode, but next keystroke might normally overwrite
                    current character
* `VimReplaceMany`: `vim` mode, but where every keystroke overwrites characters
                    rather than inserts
* `VimDelete`:      `vim` mode, but where characters are deleted
* `Autocomplete`:   the autocomplete menu is shown
* `FuzzyFind`:      the autocomplete menu is shown with the Fuzzy Find input
                    enabled

More details about these modes can be found in the [Terminal Hotkeys](/docs/user-guide/terminal-keys.md)
document.

### Interrupt/PreviewMode

Preview mode is independent to input mode.

* `Disabled`:     preview is not running
* `Autocomplete`: regular preview mode
* `CmdLine`:      command line preview

More details about these modes can be found in the [Interactive Shell](/docs/user-guide/interactive-shell.md#preview)
document.

## Event Return

`$EVENT_RETURN`, is a special variable that stores a writable structure to
return back to the event caller.

The `$EVENT_RETURN` values available for this event are:

```
{                                                                                                                 
    "Actions": [],
    "Continue": false,
    "SetCursorPos": 0,
    "SetHintText": "",
    "SetLine": ""
}
```

### $EVENT_RETURN.Actions

This is an array of strings, each defining a hotkey function to execute after
the event function has completed.

You can supply multiple functions in the array.

Supported values are:

```
package onkeypress

import "github.com/lmorg/murex/utils/readline"

/*
   This file was automatically generated by ./actions.mx
   DO NOT EDIT THIS FILE DIRECTLY!!
*/

var fnLookup = map[string]func(*readline.Instance){
	"CancelAction":            readline.HkFnCancelAction,
	"ClearAfterCursor":        readline.HkFnClearAfterCursor,
	"ClearLine":               readline.HkFnClearLine,
	"ClearScreen":             readline.HkFnClearScreen,
	"CursorJumpBackwards":     readline.HkFnCursorJumpBackwards,
	"CursorJumpForwards":      readline.HkFnCursorJumpForwards,
	"CursorMoveToEndOfLine":   readline.HkFnCursorMoveToEndOfLine,
	"CursorMoveToStartOfLine": readline.HkFnCursorMoveToStartOfLine,
	"ModeAutocomplete":        readline.HkFnModeAutocomplete,
	"ModeFuzzyFind":           readline.HkFnModeFuzzyFind,
	"ModePreviewLine":         readline.HkFnModePreviewLine,
	"ModePreviewToggle":       readline.HkFnModePreviewToggle,
	"ModeSearchHistory":       readline.HkFnModeSearchHistory,
	"RecallWord1":             readline.HkFnRecallWord1,
	"RecallWord10":            readline.HkFnRecallWord10,
	"RecallWord11":            readline.HkFnRecallWord11,
	"RecallWord12":            readline.HkFnRecallWord12,
	"RecallWord2":             readline.HkFnRecallWord2,
	"RecallWord3":             readline.HkFnRecallWord3,
	"RecallWord4":             readline.HkFnRecallWord4,
	"RecallWord5":             readline.HkFnRecallWord5,
	"RecallWord6":             readline.HkFnRecallWord6,
	"RecallWord7":             readline.HkFnRecallWord7,
	"RecallWord8":             readline.HkFnRecallWord8,
	"RecallWord9":             readline.HkFnRecallWord9,
	"RecallWordLast":          readline.HkFnRecallWordLast,
	"Undo":                    readline.HkFnUndo,
}

```

### $EVENT_RETURN.Continue

This boolean value defines whether to execute other events for the same
keypress after this one.

On the surface of it, you might question why you'd wouldn't want multiple
actions bound to the same keypress. However since _readline_ supports different
operational modes, you might want different events bound to different states
of _readline_. In which case you'd need to set `$EVENT_RETURN.Continue` to
`true`.

### $EVENT_RETURN.SetCursorPos

This allows you to shift the text input cursor to an absolute location.

### $EVENT_RETURN.SetHintText

Forces a different message in the hint text.

### $EVENT_RETURN.SetLine

Change your input line in _readline_.

## Examples

### Arbitrary code execution

The following example will output "Ouch!" when you press `{f3}`:

```
event onKeyPress poke={F3} {
    out "Ouch!"
}
```

### Actions

The following code will perform two undo's:

```
event onKeyPress double-undo={F4} {
    $EVENT_RETURN.Actions = %[
        Undo
        Undo
    ]
}
```

### Readline Modes

The following code will output the operations modes of _readline_ to the
hint text:

```
event onKeyPress status={F5} {
    -> set event
    $EVENT_RETURN.SetHintText = "Readline input mode is $event.Interrupt.InputMode and preview mode is $event.Interrupt.PreviewMode"
}
```

## Detail

### Standard out and error

Stdout and stderr are both written to the terminal.

### Order of execution

Interrupts are run in alphabetical order. So an event named "alfa" would run
before an event named "zulu". If you are writing multiple events and the order
of execution matters, then you can prefix the names with a number, eg `10_jump`

### Namespacing

This event is namespaced as `$(NAME).$(OPERATION)`.

For example, if an event in `onPrompt` was defined as `example=eof` then its
namespace would be `example.eof` and thus a subsequent event with the same name
but different operation, eg `example=abort`, would not overwrite the former
event defined against the interrupt `eof`.

The reason for this namespacing is because you might legitimately want the same
name for different operations (eg a smart prompt that has elements triggered
from different interrupts).

## See Also

* [Interactive Shell](../user-guide/interactive-shell.md):
  What's different about Murex's interactive shell?
* [Murex Event Subsystem (`event`)](../commands/event.md):
  Event driven programming for shell scripts
* [Shell Configuration And Settings (`config`)](../commands/config.md):
  Query or define Murex runtime settings
* [Terminal Hotkeys](../user-guide/terminal-keys.md):
  A list of all the terminal hotkeys and their uses
* [`onCommandCompletion`](../events/oncommandcompletion.md):
  Trigger an event upon a command's completion
* [`onPreview`](../events/onpreview.md):
  Full screen previews for files and command documentation
* [`onPrompt`](../events/onprompt.md):
  Events triggered by changes in state of the interactive shell

<hr/>

This document was generated from [builtins/events/onKeyPress/onkeypress_doc.yaml](https://github.com/lmorg/murex/blob/master/builtins/events/onKeyPress/onkeypress_doc.yaml).