Used Visual Studio for many years. Used Vim for many years. Changed to Emacs because its Vim bindings were spot on, and the editor provides discoverability elements that make it easy to extend. This was the final frontier for me, editor extension.
If your editor can do the key points under the “The List of Things You Should Know How to Do With Your Editor”, then there is no reason to pick up Emacs. If your editor can’t do the things in this list (or it’s very very hard and not fun to do), then you are not using a code editor, you’re using a ball and chain clasped firmly around your neck. You’re going to spend probably two decades coding, why be hindered by your editor throughout this journey?
After a while, I got really good and using Vim bindings and felt utterly broken in Visual Studio (I used a weird, half baked AutoHotKey script that gave me some semblance of Vim because I was an idiot and didn’t want to fork over the measly $99 for ViEmu).
Moving around using the mouse and arrow keys added so much cognitive overhead when all I wanted to do was get what I had in my head, through the keyboard, and on the screen as fast as possible. The best way to explain Vim bindings is this:
Imagine you’re a samurai with a razor sharp katana, contemplating how to take down your opponent. You think. You visualize how you’ll cut down your foe. Your blade remains sheathed, because you aren’t ready to strike just yet.
Clarity comes, and the path to victory can be seen in your mind’s eye. You unsheath your katana to attack. Within an instant, each intricate slash is executed, and your blade is placed back at your side. Your foe falls. A butterfly, caught fluttering in the fray, splits in half mid flight… only after realizing it’s been cut.
The unsheathing of the blade is synonymous to going into Vim’s insert mode. Using the mouse and arrow keys, is synonymous to a combination padlock latched on to your sheath (which has to be unlocked every time you want to use it).
With Vim bindings, the cognitive overhead between “thinking time” and “writing time” disappeared. What I also found was that my ability to edit code in all languages increased (albeit with a small productivity loss in editing C#). The same key bindings and motions could be applied to refactor code, no matter the language. I want to reiterate this, Vim bindings makes you efficient in editing and refactoring code in all languages, at the cost of extreme efficiency in one.
I went so far as creating a set of instructions for coding C# in Vim on Windows back in 2012 when it wasn’t cool to use an editor other than Visual Studio to code C#.
If you do anything in this post, take some time to learn Vim bindings in your editor of choice.
My main motivation for moving away from Vim was VimScript and the Tim Pope Bus (if Tim Pope dies, I and many Vim users are screwed because of the many plugins he builds and supports). I just didn’t want to invest in learning VimScript, but felt that my lack of scripting knowledge was limiting my ability to extend Vim even further than my plugin suite. Yes, I’m aware of NeoVim, and if you can do “the list of things you should know how to do with your editor”, in NeoVim, then you’re gold.
Aside: Emacs’s Vim bindings are incredible. As stated earlier, I can’t
imagine editing code without them. It’s the main reason why I
couldn’t make the switch to editors such as Sublime, Atom, Eclipse, or
Xamarin Studio, XCode, AppCode, et al. These other editors have
cursory Vim support, but nuanced commands just aren’t there (such as
[ESC]Ctrl+V 5j$A;[ESC] which appends semicolons at the end of 5 lines).
Typing and editing proficiency is important. I get the following retort a lot when I bring up the subject of typing speed and Vim binding proficiency:
If you’re worried about typing speed and editor proficiency, you’re not thinking about your code enough.
Of course I’m thinking enough (everyone thinks enough). In fact, I want to be able to read and edit code at the speed of thought. From the moment I decide I need to inspect a file/method/line of arbitrary code, I want to instantaneously be there and reading (and have a consistent way of doing this across all languages). From the moment I decide I need to edit something, I want to be able to instantaneously edit it so I can move to my next thought bubble (again, across all languages). We have 30+ terraflops of computing power up there, and response times down in the 13 ms range. Don’t tell me I’m not thinking enough.
Specific to Vim bindings. They are universal and editor agnostic. Most editors support at least cursory Vim bindings (eg. ViEmu for Visual Studio, Vintage Mode for Sublime Text).
Additionally, depending on the language you are required to use, you’ll have to change editors (unless you’re using Emacs, yes I went there):
^Mwhitespace character that will be added to every line).
In essence, as much as you think you have control over the editor you choose, you really don’t. So at least get proficient with universal Vim bindings if you don’t want to invest in Emacs.
Of course every editor can be extended. The emphasis needs to placed on how the editor supports you when you want to extend it. A lot of “The List of Things You Should Know How to Do With Your Editor” is with regards to supporting your ability to extend your code editor. So take a step back and reflect on how hard/easy it is to extend your editor of choice. The list starts of with a challenge. Can you reason about how you would go about doing the challenge in the next section?
Emacs isn’t perfect. That’s not what I’m advocating. What I’m trying to emphasize is that your editor of choice should support you as best as possible (as you change languages, throughout your career as a developer). Editor extension is part of that supporting pillar (a really important part with regards to longevity).
When going through “this list of things”, compare it to your editor of choice. What’s the relative quality of a given editor feature? What’s the relative ease in figuring out X? How are the docs? How’s the community support? Etc.
This is the list, if your editor can’t do these things with ease. Find another editor. You’re going to be coding for one to two decades. Put some investment in it dammit.
Here is a challenge. Extend your editor to do the following:
Ctrl+! to move my cursor down twice. If the character to
the right of the cursor is a vowel, I want it to move once right.
Generally speaking, how easy it is for you to determine what exactly happens when you select an item from a menu, or press a key? Keep that in mind as I go through the explanation of how you would do this in Emacs.
The challenge requires me to press down twice, and (conditionally)
right once. To figure out what functions are invoked to move down and
and right, I press
F1, k, followed by the array key
<right>). Here is what gets printed in the editor when I do this.
<down> I get the following:
<down> runs the command next-line, which is an interactive compiled Lisp function in `simple.el'. It is bound to <down>. (next-line &optional ARG TRY-VSCROLL) Move cursor vertically down ARG lines. Interactively, vscroll tall lines if `auto-window-vscroll' is enabled. Non-interactively, use TRY-VSCROLL to control whether to vscroll tall lines: if either `auto-window-vscroll' or TRY-VSCROLL is nil, this function will not vscroll. ARG defaults to 1. [more]
<right> I get the following:
<right> runs the command right-char, which is an interactive compiled Lisp function in `bindings.el'. It is bound to <right>. (right-char &optional N) Move point N characters to the right (to the left if N is negative). On reaching beginning or end of buffer, stop and signal error. [more]
Aside: I can go all meta with
F1, k and press
F1, k which gives me
the following documentation:
<f1> k runs the command describe-key, which is an interactive compiled Lisp function in `help.el'. It is bound to <f1> k, <help> k, <menu-bar> <help-menu> <describe> <describe-key-1>. (describe-key &optional KEY UNTRANSLATED UP-EVENT) Display documentation of the function invoked by KEY. KEY can be any kind of a key sequence; it can include keyboard events, mouse events, and/or menu events. When calling from a program, pass KEY as a string or a vector. [more]
Generally speaking, how easy is it to start plugin development with your editor? What do you have to do if you want to just conditionally replay/repeat some key strokes (like in the challenge)? Be cognisant of the effort involved.
Let’s say I want to just invoke
next-line. Here is how I do that. I
Alt+: to bring up my mini buffer (this is where I can execute
commands). And I type
(next-line) and press
Let’s say I want to just invoke
right-char. Here is how I do that. I
Alt+: to bring up my mini buffer (this is where I can execute
commands). And I type
(right-char 5) and press
F1, f key combination, I get pretty damn good high level
documentation of what lays behind a keystroke/function
invocation. Additionally I can get look at the source of a plugin if
the documentation isn’t sufficient. What’s the documentation like for
the editor you use, the 3rd party plugins you install? Is there any
Per the challenge, I need to only move right if the character to the
right of me is a vowel. I could take a look at how
implemented (since it doesn’t let me move right past the end of the
line). I press
F1,f and then type
move-right and press
enter. Here is what I get.
right-char is an interactive compiled Lisp function in `bindings.el'.
I can then press enter on
bindings.el link and be taken to the
function to see how it’s implemented. If there is something called in
that function that I don’t understand, I simply run
F1,f for that
function and follow the rabbit hole down as deep as I want. I can
experiment and try any function I want by using
Generally speaking, how much effort does it take “ease in” to the creation of a simple plugin? Keep that in mind when reading the next part.
After I have a good understanding of what functions I need to use, I can open up a scratch buffer and start playing around. Here is the initial function I define in my scratch buffer:
(defun foobar () (interactive) (next-line) (next-line))
I then put my cursor at the end of the function definition and type
eval-last-sexp, which adds the function to Emacs. I can execute the
Alt+:, then type
foobar, then press
Can the editor you work with let you easily do the four steps above, really think about it. This is not a difficult function to write, and lets me become incrementally more proficient with the code I’m writing. Here are some real world example functions I’ve hobbled together:
These were all stitched together using the four steps above.
Well, at least you now understand why Emacs is so powerful. And after reading at least this much, you may be more aware of all the minor inefficiencies that you currently deal with (they add up, especially over decades of coding).
For me, editor extension is a key underpinning (we’ll get into other aspects of editor capabilities further down the list, don’t worry). If an editor is difficult to extend, what does it say about the original creators? Why didn’t they put in the effort to make it as easy as possible for others to help? What was their motivation for make it so difficult?
With every new editor that comes out, the plugin and feature set is small (usually promising). Instead of concentrating on what features a new editor has right now, I look it’s architecture, and how easy it is to extend. That’s how you evaluate the longevity of an editor. Let’s see how the challenge question is solved in Emacs and then we’ll look at higher level features that your editor should support.
Still need to elaborate on these introspection capabilities: