Keyboard#

A terminal sends bytes to a program, and the same bytes can mean different keys. The classic encoding sends the same byte for Enter and for SHIFT+Enter. A full-screen program (a TUI) can ask the terminal for an extended encoding that separates the two. A shell cannot.

Nash handles both cases with the ShiftEnterOrNewline action. This page explains what the action does, where it stops, and how to change it. It also describes how Nash treats the Kitty keyboard protocol when a program resets it.

The tab-related key changes in Nash 0.9.0 (SUPER+9 and SUPER+0) are on the Tabs page.

To jump between panes, hold Ctrl+Alt+Super (Control+Option+Command on macOS) and type a pane number. See Quick Pane Navigation for configuration, folded panes, and shortcut conflicts. Open the Command Palette to find other actions.

SHIFT+Enter#

Nash 0.9.0 or newer binds SHIFT+Enter to ShiftEnterOrNewline in its bundled key configuration. For each key press the action looks at the pane that has focus:

  • If the pane can tell SHIFT+Enter from Enter, Nash sends the real SHIFT+Enter key, with its modifiers.
  • If not, Nash sends ESC CR, the same bytes that Alt+Enter sends. A shell that reads ESC CR as "insert a newline" lets you write a command over more than one line without running it. In the default keymap of zsh, ESC CR is bound to self-insert-unmeta, which does this. Check the binding of your own shell if SHIFT+Enter does not insert a newline.

The result is that a shell still gets its multiline key, and a TUI that asks for SHIFT+Enter gets SHIFT+Enter and not Alt+Enter.

What the program receives#

The pane is in this stateThe program receives for SHIFT+Enter
No extended keyboard mode is onESC CR
The program turned on the Kitty keyboard protocol, and enable_kitty_keyboard = trueThe key event ESC [ 13 ; 2 u, and release events if the program asked for them
The program turned on xterm modifyOtherKeysThe key event ESC [ 27 ; 2 ; 13 ~
You set enable_csi_u_key_encoding = trueThe key event ESC [ 13 ; 2 u
On Windows, Win32 input mode is active and allow_win32_input_mode is onThe key event in the Win32 input encoding

The Kitty keyboard protocol is off by default. To let programs use it, put this in ~/.config/nash/custom.lua:

return { enable_kitty_keyboard = true }

Since Nash 0.11.5, mux-server panes also report their Kitty, Win32, and other keyboard modes to the GUI. This includes [mux] enabled = true, unix and TLS domains, and SSH domains using Nash multiplexing. To use Kitty, set enable_kitty_keyboard = true in both the GUI and server configuration; it remains opt-in. Mode changes can take a network trip to reach the GUI, so SHIFT+Enter chooses using the latest state it knows.

Limits#

The action works in direct key bindings only. It does not work from a command palette command, from Multiple, or from a Lua window:perform_action call. Nash does not list it in the palette.

Before Nash 0.11.5, mux-client panes always sent ESC CR. Since that release, direct bindings of ShiftEnterOrNewline follow the server pane's reported mode and can send native SHIFT+Enter, as in a GUI-owned pane.

Tmux control-mode domains still always send ESC CR: they do not expose the program's keyboard mode.

A pane that runs tmux inside a normal pane is different. Nash sees the modes that tmux negotiated, not the modes of the program inside tmux. If tmux has extended keys on, SHIFT+Enter can pass through, and a plain shell inside tmux then receives Enter instead of a newline key. Test this with your own shell before you rely on it.

An SSH session without Nash multiplexing is a normal pane and follows the rules in the table.

Change or remove the binding#

Bindings that you add to nash.toml or keys.lua come after the bundled bindings, so your binding for the same key wins. If you added a SHIFT+Enter binding before Nash 0.9.0, for example one that always sends ESC CR, remove it so that programs get the real key. Since Nash 0.11.5, this also applies to mux-client panes. Tmux control-mode panes may still need their workaround.

To always send ESC CR:

[[keys]] key = "Return" mods = "SHIFT" action = "SendString" text = '\u001b\r'

To remove the binding, so that SHIFT+Enter has no special action:

[[keys]] key = "Return" mods = "SHIFT" action = "DisableDefaultAssignment"

Programs that tell Alt+Enter from SHIFT+Enter need the real SHIFT+Enter key. An unconditional ESC CR for SHIFT+Enter removes that difference.

Kitty keyboard protocol reset#

A program turns on Kitty keyboard modes by pushing flags onto a stack. A program or a shell can later set the flags to zero. In Nash 0.9.0 or newer, a flag value of zero restores the legacy encoding for all keys.

  • The keyboard stack and the replies to a keyboard capability query (CSI ? u) stay as they were. Only the key encoding goes back to legacy.
  • Nash keeps the keyboard state separately for the normal screen and the alternate screen.
  • Explicit settings still apply. If you set enable_csi_u_key_encoding = true, or a program turns on modifyOtherKeys, those encodings stay active.

This matters for SHIFT+Enter. When a program that used the Kitty protocol exits and resets the flags to zero, your shell gets ESC CR for SHIFT+Enter again.