I wanted to make Nano have more common shortcuts (i.e. Ctrl-F for search, Ctrl-H for replace, etc) and edited the nanorc file to add:

bind ^F whereis all
bind ^H replace all
bind ^M mark all

To my astonishment, pressing Backspace activates the Replace function and pressing Enter activates Mark.

Then i realized their virtual keycodes are: Backspace 0x08, H 0x48, Enter 0x0D, M 0x4D.

Are the Ctrl keybindings actually bitmasked on 0x40?


The virtual terminal you are using nano on is modelled after the physical serial terminals of past decades. By convention, these terminals produced ASCII control codes when a letter key or one of the keys labelled @, [, \, ], ^, _ were pressed together with the Ctrl key. The control code emitted has the ASCII code of the code of the letter subtracted by 64. Thus pressing Ctrl-M produces the ASCII code of M (0x53) subtracted by 0x40 = 0x13, which is the code for Carriage Return. The Return key also produces Carriage Return, because that's the function of the the key.


These are not virtual keycodes.

You are using a terminal.

Terminals operate with a simple 8-bit, sometimes even 7-bit, character stream. For all that a TUI application like nano knows, there are a serial port, two modems, the PSTN, and an honest-to-goodness DEC VT525 between you and it. All that it sees is that character stream, a terminal device file descriptor, a TERM environment variable, and record in the terminfo database.

There's no such thing as a control key modifier for an alphabetic key in that character stream. When you write bind ^M the software is actually understanding that as binding character number 13. That's how the software has to work internally, because that is the actual terminal I/O model that it has to work with. The ^M is an artefact of the software's command parser, a way to denote character number 13 in configuration commands that you type.

Some operating systems, like FreeBSD, provide common library functions that applications softwares can use in their parsers, to yield uniform semantics for such denotations across applications.

% printf '\x08\x0d' | vis -w ; echo

There are no virtual key codes here, moreover. All of the translation caused by the ⎈ Control modifier key happens in your terminal or terminal emulator, before the characters are transmitted down the (virtual or actual) wire.

It just so happens that your terminal produces character #8 (␈) for ⎈ Control+H and ⌫ Backspace and character 13 (␍) for ⎈ Control+M and Enter. This is entirely up to the terminal/terminal emulator. With many emulators there is a keyboard map of some sort where one can change this. For bona fide DEC VTs, there is in fact an output control sequence, DECBKM, that switches ⌫ Backspace between sending character #8 and sending character #127 (DEL).

Further reading

  • Thanks for the explanation. So let's say i change my terminal to add 128 to the character code when i press Ctrl. How do i configure Nano to accept bytes 128-255? – iamanigeeit Oct 1 '18 at 9:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.