Awesome Emacs Keymap (emacs-mcx)Emacs emulation for Visual Studio Code
It's inspired by Emacs Keymap by hiro-sun and its forks such as Emacs Friendly Keymap by Sebastian Zaha, Emacs Keymap Improved by rkwan94, and Emacs Friendly Keybindings (Neon) by NotKyon, but totally revamped and improved for better feature coverage, Emacs emulation, and usability (also getting rid of some bugs). FAQ/TipsThe cursor cannot be moved on the find widget as the widget closes with movement keys.It's an intended design that simulates the original Emacs' behavior.
You can disable it with i-search (
|
| Command | Desc |
|---|---|
Escape g |
Jump to line (command palette) |
emacs-mcx.useMetaPrefixCtrlLeftBracket
If set as true, ctrl+[ works as the Meta prefix like original Emacs.
emacs-mcx.useMetaPrefixAlt
If set as true, alt key (option (⌥) key on macOS) works as the Meta prefix.
emacs-mcx.useMetaPrefixMacCmd
If set as true, Command (⌘) key works as the Meta prefix on macOS. This option only works on macOS.
emacs-mcx.killRingMax
Configures the maximum number of kill ring entries. The default is 60.
emacs-mcx.killWholeLine
This simulates the original Emacs' kill-whole-line variable.
The default is false.
emacs-mcx.cursorMoveOnFindWidget
If set to true, cursor move commands of this extension such as C-f and C-b are disabled when the find widget is focused, to allow the widget to keep open and the cursor to move on it.
emacs-mcx.enableOverridingTypeCommand
Prefix arguments do not work on character inputs with IMEs by default and you can set this config to true in order to enable it.
Note that this config makes use of VSCode API's type command under the hood and can cause problems in some cases.
- If you are using IME, text input may sometimes fail.
- If another extension that also uses the
typecommand is installed, an error occurs (See https://github.com/Microsoft/vscode/issues/13441).
emacs-mcx.enableDigitArgument
Indicates whether M-<digit> (the emacs-mcx.digitArgument command) is enabled.
Set false when M-<digit> conflicts with some other necessary commands. See https://github.com/whitphx/vscode-emacs-mcx/issues/1208 for the background.
emacs-mcx.shiftSelectMode
Toggle Shift Selection (Emacs shift-select-mode). When true, holding Shift while running movement commands starts mark mode to extend the selection; the default is false to avoid ctrl+shift+p conflicts with the Command Palette on Windows/Linux.
emacs-mcx.lineMoveVisual
When true, line-move moves point by visual lines (same as an Emacs variable line-move-visual).
emacs-mcx.paredit.parentheses
Key-value pairs of parentheses like the following example to be used in the ParEdit commands.
{
"[": "]",
"(": ")",
"{": "}"
}
emacs-mcx.debug.*
Configurations for debugging.
'when' clause context
This extension provides some contexts that you can refer to in "when" clauses of your keybindings.json.
emacs-mcx.inMarkMode
boolean
This indicates whether mark-mode is enabled.
emacs-mcx.acceptingArgument
boolean
This indicates the editor is accepting argument input following C-u.
emacs-mcx.prefixArgumentExists (experimental)
boolean
This indicates if a prefix argument exists.
Use this boolean context to check the existence of a prefix argument, instead of using emacs-mcx.prefixArgument with null check.
emacs-mcx.prefixArgument (experimental)
number | undefined
This is a currently input prefix argument.
Keybindings
Alt key is mapped to the Meta prefix (M) by default and you can configure for Escape, ctrl+[, or Command (⌘) key (macOS only) to work as it with the settings above.
Move commands
| Command | Prefix argument | Desc |
|---|---|---|
C-f |
✓ | Move forward (forward-char) |
C-b |
✓ | Move backward (backward-char) |
C-n |
✓ | Move to the next line (next-line) |
C-p |
✓ | Move to the previous line (previous-line) |
C-a |
✓ | Move to the beginning of line (move-beginning-of-line) |
C-e |
✓ | Move to the end of line (move-end-of-line) |
M-f |
✓ | Move forward by one word unit (forward-word) |
M-b |
✓ | Move backward by one word unit (backward-word) |
C-<right>, M-<right> |
✓ | This command (right-word) behaves like M-f |
C-<left>, M-<left> |
✓ | This command (left-word) behaves like M-b |
M-m |
Move (forward or back) to the first non-whitespace character on the current line (back-to-indentation) | |
C-v |
✓ | Scroll down by one screen unit (scroll-up-command) |
M-v |
✓ | Scroll up by one screen unit (scroll-down-command) |
M-S-[ (M-{ with US keyboard), C-<up> |
✓ | Move back to previous paragraph beginning (backward-paragraph) |
M-S-] (M-} with US keyboard), C-<down> |
✓ | Move forward to next paragraph end (forward-paragraph) |
M-S-, (M-< with US keyboard) |
Move to the top of the buffer (beginning-of-buffer) | |
M-S-. (M-> with US keyboard) |
Move to the end of the buffer (end-of-buffer) | |
M-g g (M-g M-g) |
✓ | Read a number n and move point to the beginning of line number n (goto-line) |
M-g n (M-g M-n, C-x ` ) |
Jump to next error | |
M-g p (M-g M-p) |
Jump to previous error | |
C-l |
Center screen on current line (recenter-top-bottom) |
Search Commands
| Command | Desc |
|---|---|
C-s |
Incremental search forward (isearch-forward). |
C-r |
Incremental search backward (isearch-backward). |
C-M-s |
Begin incremental regexp search (isearch-forward-regexp). |
C-M-r |
Begin reverse incremental regexp search (isearch-backward-regexp). |
M-S-5 (M-% with US keyboard) |
Replace (query-replace) |
C-M-S-5 (C-M-% with US keyboard) |
Replace with regexp (query-replace-regexp) |
C-M-n |
Add selection to next find match |
C-M-p |
Add selection to previous find match |
M-s o |
Open Quick Search, which is like Emacs' occur command. |
M-c |
Toggles the case sensitivity of the find widget. |
Edit commands
| Command | Prefix argument | Desc |
|---|---|---|
C-d |
✓ | Delete right (DEL) |
C-h |
✓ | Delete left (BACKSPACE) |
M-\ |
✓ | Delete spaces and tabs around point (delete-horizontal-space). |
C-x C-o |
Delete blank lines around (delete-blank-lines) | |
C-t |
✓ | Transpose characters (transpose-chars). |
C-x C-t |
✓ | Transpose lines (transpose-lines). |
M-S-6 (M-^ with US keyboard) |
join two lines cleanly (delete-indentation) | |
M-d |
✓ | Kill word (kill-word) |
M-Bksp |
✓ | Kill word left (backward-kill-word) |
C-k |
✓ | Kill from the current cursor to the end of line (kill-line) |
C-S-Bksp |
Kill whole line (kill-whole-line) | |
C-w |
Kill region | |
M-w |
Copy region to kill ring | |
C-y |
✓ | Yank |
M-y |
✓ | Yank pop |
C-c y |
Browse kill ring | |
C-o |
Open line | |
C-j |
✓ | New line |
C-m |
✓ | New line |
C-x h |
Select All | |
C-x u, C-/, C-S-- (C-_ with US keyboard) |
Undo | |
C-; |
Toggle line comment in and out | |
M-; |
Toggle region comment in and out | |
C-x C-l (M-l) |
Convert to lower case (On the Emacs' original behavior, C-x C-l and M-l are assigned to the different functionalities. However, this extension assigns these keys to the same emacs-mcx.transformToLowercase command which calls editor.action.transformToLowercase command internally and works similarly to both the original Emacs' functionalities based on the context. Upper case and title case (below) are same) |
|
C-x C-u (M-u) |
Convert to upper case | |
M-c |
Convert to title case |
Mark Commands
| Command | Desc |
|---|---|
C-SPC, C-S-2 (C-@ with US keyboard) |
Set the mark at point, and activate it (set-mark-command). |
C-SPC C-SPC |
Set the mark, pushing it onto the mark ring, without activating it. |
C-u C-SPC |
Move point to where the mark was, and restore the mark from the ring of former marks. |
C-x C-x |
Set the mark at point, and activate it; then move point where the mark used to be (exchange-point-and-mark). |
See this page and this page about the mark and the mark ring.
Intellisense
| Command | Desc |
|---|---|
C-M-i, M-TAB, M-/, C-' |
Trigger suggest. These keybindings call editor.action.triggerSuggest command, alternating Emacs' completion-at-point or dabbrev-expand |
Text registers
| Command | Desc |
|---|---|
C-x r s r |
Copy region into register r (copy-to-register). |
C-x r i r |
Insert text from register r (insert-register). |
See this page about the text registers.
Position registers
| Command | Desc |
|---|---|
C-x r SPC r |
Record the position of point and the current buffer in register r (point-to-register). |
C-x r j r |
Jump to the position and buffer saved in register r (jump-to-register). |
Rectangles
| Command | Desc |
|---|---|
C-x r k |
Kill the text of the region-rectangle, saving its contents as the last killed rectangle (kill-rectangle). |
C-x r M-w |
Save the text of the region-rectangle as the last killed rectangle (copy-rectangle-as-kill). |
C-x r d |
Delete the text of the region-rectangle (delete-rectangle). |
C-x r y |
Yank the last killed rectangle with its upper left corner at point (yank-rectangle). |
C-x r p |
Replace last kill ring to each line of rectangle if the kill ring top only contains one line. |
C-x r o |
Insert blank space to fill the space of the region-rectangle (open-rectangle). |
C-x r c |
Clear the region-rectangle by replacing all of its contents with spaces (clear-rectangle). |
C-x r t |
Replace rectangle contents with string on each line (string-rectangle). |
C-x SPC |
Toggle Rectangle Mark mode (rectangle-mark-mode). |
Rectangle Registers
| Command | Desc |
|---|---|
C-x r r r |
Copy the region-rectangle into register r (copy-rectangle-to-register). With prefix argument, delete it as well. |
C-x r i r |
Insert the rectangle stored in register r (if it contains a rectangle) (insert-register). |
Other Commands
| Command | Desc |
|---|---|
C-g (ESC) |
Quit |
ESC ESC ESC |
Quit (keyboard-escape-quit, but this extension does not distinguish it from C-g) |
C-' (M-/) |
IntelliSense Suggestion |
M-x |
Open command palette |
C-M-SPC |
Toggle SideBar visibility |
C-x z |
Toggle Zen Mode |
C-x C-c |
Close window (save-buffers-kill-terminal) |
File Commands
| Command | Desc |
|---|---|
C-x C-f |
QuickOpen a file (Tips: This extension assigns C-x C-f to the VSCode's native quick file navigation. If you prefer more Emacs-like behavior, The "File Browser" extension by Bodil Stokke (bodil.file-browser) may help.) |
C-x C-s |
Save |
C-x C-w |
Save as |
C-x s |
Save all files |
C-x C-n |
Open new window |
Tab / Buffer Manipulation Commands
| Command | Desc |
|---|---|
C-x b |
Switch to another open buffer |
C-x k |
Close current tab (buffer) |
C-x 0 |
Close editors in the current group. |
C-x 1 |
Close editors in other (split) group. |
C-x 2 |
Split editor horizontal |
C-x 3 |
Split editor vertical |
C-x 4 |
Toggle split layout (vertical to horizontal) |
C-x o |
Focus other split editor |
C-x LEFT |
Select the previous tab (previous-buffer). |
C-x RIGHT |
Select the next tab (next-buffer). |
Prefix argument
See https://www.gnu.org/software/emacs/manual/html_node/emacs/Arguments.html for detail
| Command | Desc |
|---|---|
C-u |
universal-argument |
M-<number> |
digit-argument |
M-- |
negative-argument |
sexp
| Command | Prefix argument | Desc |
|---|---|---|
C-M-f |
✓ | Move forward over a balanced expression (forward-sexp) |
C-M-b |
✓ | Move backward over a balanced expression (backward-sexp) |
C-M-S-2 (C-M-@ with US keyboard) |
✓ | Set mark after end of following balanced expression (mark-sexp). This does not move point. |
C-M-k |
✓ | Kill balanced expression forward (kill-sexp) |
C-M-Bksp |
✓ | Kill balanced expression backward (backward-kill-sexp) |
C-S-k |
✓ | Kill a line as if with kill-line, but respecting delimiters. (paredit-kill) |
This extension makes use of paredit.js to provide sexp functionalities. Thank you for this great library.
Looking up identifiers
| Command | Desc |
|---|---|
M-. |
Find definitions of an identifier (xref-find-definitions). It's just bound to VSCode's "Go to Definition" (editor.action.revealDefinition). |
M-, |
Go back to where you previously invoked M-. and friends (xref-go-back). It's just bound to VSCode's "Go Back" (workbench.action.navigateBack). |
C-M-, |
Go forward to where you previously invoked M-, (xref-go-forward). It's just bound to VSCode's "Go Forward" (workbench.action.navigateForward). |
M-S-/ (M-? with US keyboard) |
Find references of an identifier (xref-find-references). It's just bound to VSCode's "References: Find All References" (references-view.findReferences). |
Other commands/APIs
emacs-mcx.executeCommandWithPrefixArgument
This command calls another command with the prefix argument. This is mainly for extension developers who want to make the extensions collaborative with this extension's prefix argument. See [the issue #1146](https://github.com/whitphx/vscode-emacs-mcx/issues/1146) for the discussion about it.
For example, if you define the keybinding below,
C-x ewill call the commandfoowith the argument{}.C-u C-x ewill call the commandfoowith the argument{ prefixArgument: 4 }.
{
"key": "ctrl+x e",
"command": "emacs-mcx.executeCommandWithPrefixArgument",
"args": {
"command": "foo"
}
}
You can pass the arguments to the target command as below. In this case,
C-x ewill call the commandfoowith the argument{ baz: 42 }.C-u C-x ewill call the commandfoowith the argument{ prefixArgument: 4, baz: 42 }.
{
"key": "ctrl+x e",
"command": "emacs-mcx.executeCommandWithPrefixArgument",
"args": {
"command": "foo",
"args": {
"baz": 42
}
}
}
You can change the key name of the prefix argument.
{
"key": "ctrl+x e",
"command": "emacs-mcx.executeCommandWithPrefixArgument",
"args": {
"command": "foo",
"prefixArgumentKey": "repeat"
}
}
C-x ewill call the commandfoowith the argument{}.C-u C-x ewill call the commandfoowith the argument{ repeat: 4 }.
Overriding the prefix argument
When you define a keybinding for emacs-mcx.* commands, you can override the prefix argument by specifying the prefixArgument in the keybinding's arguments.
For example:
{
"key": "alt+shift+y",
"command": "emacs-mcx.yankPop",
"args": {
"prefixArgument": -1
}
}
With this keybinding, you can call emacs-mcx.yankPop command with a prefix argument -1 by pressing alt+shift+y.
Conflicts with default key bindings
ctrl+d: editor.action.addSelectionToNextFindMatch => Usectrl+alt+ninstead;ctrl+g: workbench.action.gotoLine => Usealt+g ginstead;ctrl+b: workbench.action.toggleSidebarVisibility => Usectrl+alt+spaceinstead;ctrl+j: workbench.action.togglePanel => Usectrl+x jinstead;ctrl+space: toggleSuggestionDetails, editor.action.triggerSuggest => Usectrl+'instead;ctrl+x: editor.action.clipboardCutAction => Usectrl+winstead;ctrl+v: editor.action.clipboardPasteAction => Usectrl+yinstead;ctrl+k: editor.debug.action.showDebugHover, editor.action.trimTrailingWhitespace, editor.action.showHover, editor.action.removeCommentLine, editor.action.addCommentLine, editor.action.openDeclarationToTheSide;ctrl+k z: workbench.action.toggleZenMode => Usectrl+x zinstead;ctrl+y: redo;ctrl+m: editor.action.toggleTabFocusMode;ctrl+/: editor.action.commentLine => Usectrl+;instead;ctrl+p&ctrl+e: workbench.action.quickOpen => Usectrl+x binstead;ctrl+p: workbench.action.quickOpenNavigateNext => Usectrl+ninstead.ctrl+o: workbench.action.files.openFileFolder;
Contributions/Development
Your contributions are very welcome!
Please see DEVELOPMENT.md about development of this extension.


