Envy
Text editing supercharger
Envy is an Atom :atom: package that provides a switchable mode in which letter keypresses are mapped to text editing operations.
This approach is shared with the Vim family of editors, but only conceptually. Envy doesn't have any key bindings in common with Vim and augments, rather than modifies, the standard Atom editing experience. It simply wouldn't make sense to create yet another Vim clone or derivative – there are already so many. Instead, Envy is built from scratch to be an ergonomic modal editing system without any legacy baggage.
Where applicable, Envy's design choices seek to avoid problems associated with Vim and its descendants. Envy = N.V. = Not Vim. Unlike Vim/vim-mode, Envy
- takes mere minutes to learn and master
- embraces multiple selections
- has a logical, easy to remember keyboard layout designed with ergonomics in mind
- has no Ctrl/Cmd key bindings and therefore doesn't interfere with other editor shortcuts
- works great with international keyboards 🌍
Envy offers a much smaller set of operations than Vim, but the easy accessibility of those operations and their tight integration with Atom's editing model means they can be used to their fullest, making Atom+Envy a competitive alternative to established modal text editors.
Installation
Either run
apm install envy
from the command line or search for envy
in Atom's Install Packages settings screen and click the Install button on the package card.
Keymap
Vim's default keymap is largely based on mnemonic abbreviations, that is, the letter pressed is found in the English name for the action performed. For example, in Vim, B and E move the cursor to the beginning and end of the word, respectively.
By contrast, Envy's keymap is based on the location of keys on the keyboard. The keyboard is divided into connected groups of keys that perform related actions in a consistent and predictable manner. Thus, on the default QWERTY layout, E/R move the selection to the previous/next bracket, D/F move it to the previous/next block (word, line or paragraph), and C/V move it to the previous/next match. For layouts other than QWERTY, patches are provided that produce the same key arrangement.
Alt+J enters Envy mode and P leaves it. In Envy mode, this keymap applies:
(Based on https://commons.wikimedia.org/wiki/File:KB_United_States.svg by Denelson83.)
A detailed listing of all commands and their mapping follows. Note that the Key column shows the label of the letter key in the QWERTY keyboard layout, which may be different in another layout (but the physical position of the key is the same across all layouts).
Cursor movement
Arrow keys
Key | Command | Description |
---|---|---|
J | Move left | ⬅️ Moves each cursor one position to the left. With Shift: Selects instead of moving. With Alt: Moves one subword boundary instead of one position. |
L | Move right | ➡️ Moves each cursor one position to the right. With Shift: Selects instead of moving. With Alt: Moves one subword boundary instead of one position. |
I | Move up | ⬆️ Moves each cursor one line up. With Shift: Selects instead of moving. With Alt: Adds a selection above each selection instead of moving cursors. Cannot be combined with Shift. |
K | Move down | ⬇️ Moves each cursor one line down. With Shift: Selects instead of moving. With Alt: Adds a selection below each selection instead of moving cursors. Cannot be combined with Shift. |
Other
Key | Command | Description |
---|---|---|
Y | Move to beginning of previous paragraph | Moves each cursor to the start of the paragraph preceding the cursor. With Shift: Selects instead of moving. |
H | Move to beginning of next paragraph | Moves each cursor to the start of the paragraph succeeding the cursor. With Shift: Selects instead of moving. |
Alt+Y | Page up | Moves each cursor one editor page up. With Shift: Selects instead of moving. |
Alt+H | Page down | Moves each cursor one editor page down. With Shift: Selects instead of moving. |
U | Move to beginning of line | Moves each cursor to the start of the line it is on. With Shift: Selects instead of moving. |
O | Move to end of line | Moves each cursor to the end of the line it is on. With Shift: Selects instead of moving. |
Selection manipulation
Brackets
Supported bracket pairs include all pairs defined by the bracket-matcher Atom core package.
Key | Command | Description |
---|---|---|
W | Select surrounding brackets | Expands each selection to cover the inside of the nearest surrounding bracket pair. If a selection already completely covers the inside of a bracket pair, expands the selection to the outside of that bracket pair. |
Shift+W | Select all brackets | Repeatedly applies the Move bracket selection backward/forward commands (see below) to each selection and creates a selection containing all of the results. |
E | Move bracket selection backward | Moves each selection to the outside of the first bracket pair that completely precedes the selection. With Shift: Preserves the existing selection. |
R | Move bracket selection forward | Moves each selection to the outside of the first bracket pair that completely succeeds the selection. With Shift: Preserves the existing selection. |
Blocks
In Envy, a block is either
- a homogeneous sequence of word characters, non-word characters (excluding whitespace), or whitespace characters (e.g.
abc
,{.-
and - a single line of text, or
- a single paragraph of text.
Key | Command | Description |
---|---|---|
S | Select surrounding block | Expands each selection to cover the nearest block that completely contains the selection. |
Shift+S | Select all blocks | Repeatedly applies the Move block selection backward/forward commands (see below) to each selection and creates a selection containing all of the results. |
D | Move block selection backward | Moves each selection to the first block of the same type that completely precedes the selection. With Shift: Preserves the existing selection. With Alt: Considers all first-tier blocks (runs of word/non-word/whitespace characters) to be of the same type. |
F | Move block selection forward | Moves each selection to the first block of the same type that completely succeeds the selection. With Shift: Preserves the existing selection. With Alt: Considers all first-tier blocks (runs of word/non-word/whitespace characters) to be of the same type. |
Matches
Key | Command | Description |
---|---|---|
X | Select all matches | For each selection, selects all occurrences of the selected text in the lines covered by the selection. With Shift: Selects all matches in the entire buffer instead. |
C | Select previous match | Moves each selection to the previous occurrence of the selected text. With Shift: Preserves the existing selection. |
V | Select next match | Moves each selection to the next occurrence of the selected text. With Shift: Preserves the existing selection. |
Other
Key | Command | Description |
---|---|---|
Q | Remove every second selection | Drops all selections (not the selection contents) with even-numbered indices, where the first selection has index 1. With Shift: Drops odd-numbered selections instead. |
A | Consolidate selections | Drops all selections except the first one. |
Shift+A | Split selections into cursors | Turns every non-empty selection into two cursors, one at the start of the selection and one at the end. |
Z | Invert selections | Selects all unselected text and deselects all selected text in the lines covered by selections. With Shift: Inverts selections in the entire buffer instead. |
Text manipulation
Key | Command | Description |
---|---|---|
N | Swap selections | Assuming the selections are indexed starting from 1, swaps the contents of selections 1 and 2, 3 and 4, etc. With Shift: Swaps selections 1 and 3, 2 and 4, etc. instead. |
Alt+N | Rotate selections | Cyclically replaces the contents of each selection with those of the preceding selection. With Shift: Uses the contents of the succeeding selection instead. |
M | Align selections | Left-aligns all selections by inserting spaces to the left of them. If there are multiple selections on a single line, those selections are aligned with the corresponding selections on other lines. With Shift: Right-aligns selections instead. |
Clipboard
Key | Command | Description |
---|---|---|
T | Copy | Copies the selected text to the system clipboard. With Shift: Uses Envy's internal ("secondary") clipboard instead. |
G | Paste | Pastes the text from the system clipboard. With Shift: Uses Envy's internal ("secondary") clipboard instead. |
B | Cut | Cuts the selected text to the system clipboard. With Shift: Uses Envy's internal ("secondary") clipboard instead. |
Using Envy with non-US keyboards
Envy's keymap consists exclusively of letters. As the shapes and positions of the letter keys are identical for all standard keyboards (as opposed to, say, the Enter and left Shift keys), it is possible to achieve exactly the same Envy mode layout regardless of the keyboard layout used.
The only thing needed is to swap the bindings for any letter keys that in the local keyboard layout are rearranged compared to Envy's default layout (QWERTY). Most regional layouts have only minor rearrangements, and the necessary changes can be easily achieved by adding a "patch" to Atom's keymap.cson
.
🇩🇪 QWERTZ keymap patch
QWERTZ keyboard layouts are used mainly in the German-speaking world and in parts of Eastern Europe. As far as letter keys go, QWERTZ differs from QWERTY only in that Y and Z are exchanged, so the following will make Envy use its default positional arrangement on a QWERTZ keyboard:
'atom-text-editor.envy-mode':
'y': 'envy:invert-selections-in-lines'
'Y': 'envy:invert-selections'
'z': 'editor:move-to-beginning-of-previous-paragraph'
'Z': 'editor:select-to-beginning-of-previous-paragraph'
'alt-z': 'core:page-up'
'alt-Z': 'core:select-page-up'
🇫🇷 AZERTY keymap patch
AZERTY is the predominant keyboard layout in France, and is also used by French speakers in Belgium and some other countries. Compared to QWERTY, it swaps A and Q, W and Z, and has ,/? in place of M, giving rise to this patch:
'atom-text-editor.envy-mode':
'a': 'envy:remove-every-second-selection-even'
'A': 'envy:remove-every-second-selection-odd'
'q': 'editor:consolidate-selections'
'Q': 'envy:split-selections-into-cursors'
'w': 'envy:invert-selections-in-lines'
'W': 'envy:invert-selections'
'z': 'envy:select-surrounding-brackets'
'Z': 'envy:select-all-brackets'
',': 'envy:left-align-selections'
'?': 'envy:right-align-selections'
Contributing
Contributors are always welcome. However, please file an issue describing what you intend to add before opening a pull request, especially for new features! I have a clear vision of what I want (and do not want) Envy to be, so discussing potential additions might help you avoid duplication and wasted work.
By contributing, you agree to release your changes under the same license as the rest of the project (see below).
License
Copyright © 2017 Philipp Emanuel Weidmann (pew@worldwidemann.com)
Released under the terms of the MIT License