IDEs provide the user with a lot of neat features beside pure text editing capabilities: auto-completion, refactoring, project management, etc. What are the key features that are really needed? More generally speaking, what makes a good IDE? Some fancy IDE features are rarely used. Let’s tackle a few examples.
Refactoring (renaming symbols) is convenient but in practice should happen as less often as possible. Avoid the issue altogether by thinking twice before naming a symbol instead.
Auto-completion certainly stands among the most famous features. But is it essential? If we know in advance what we want to write, good touch-typing skills will often be faster than the time needed for selecting the right item from the auto-completion list. (Unless the name is long and cumbersome to write, in which case auto-completion proves helpful.)
The thinking process “list first, then think about what you want, then select” is a bad habit: it is slower than “think what you want and write it down”. More on that later.
Completion comes in handy, so we think, when listing members of a class. But if the class is documented, the list of members should be obvious. Going to the definition will provide more documentation than the auto-completion list. This falls short in the event of inherited members, or worse, diamond inheritance, in which case it becomes really hard for a human being to describe an object mentally or by going to the definition of both its parents and descendants. Then a completion framework becomes essential to describe an object.
This solution only applies to ill-designed languages however: a better, more permanent solution resides in avoiding the use of diamond inheritance in the first place. Nothing good can result from not knowing the objects you manipulate.
The myth of the too-good-an-editor
Emacs and Vim have the reputation of the being the geek’s best friends, the tools to rule them all. And yet many professional programmers discard them from their toolbox to fallback to the “reputable corporate programs.” Why is that so?
To quote Paul Graham:
“Lisp is worth learning for the profound enlightenment experience you will have when you finally get it; that experience will make you a better programmer for the rest of your days, even if you never actually use Lisp itself a lot.”
This is the same argument you tend to hear for learning Latin. It won’t get you a job, except perhaps as a classics professor, but it will improve your mind, and make you a better writer in languages you do want to use, like English.
But wait a minute. This metaphor doesn’t stretch that far. The reason Latin won’t get you a job is that no one speaks it. If you write in Latin, no one can understand you. But Lisp is a computer language, and computers speak whatever language you, the programmer, tell them to.
So if Lisp makes you a better programmer, like he says, why wouldn’t you want to use it? If a painter were offered a brush that would make him a better painter, it seems to me that he would want to use it in all his paintings, wouldn’t he? I’m not trying to make fun of Eric Raymond here. On the whole, his advice is good. What he says about Lisp is pretty much the conventional wisdom. But there is a contradiction in the conventional wisdom: Lisp will make you a better programmer, and yet you won’t use it.
- Why would the big IDEs be more corporate-friendly than the venerable Emacs and Vim?
- The users of the corporate IDEs argue that Emacs/Vim users sacrifice the ergonomy and the technical advance of “real” IDEs for the sake of saying “Look!, I use Emacs/Vim!”.
- A lot of myths surround us.
- Using Emacs/Vim to its full potential implies learning how to customize it. The learning curve might be steep. Thus it is not so apparent at first how Emacs/Vim can overtake the big IDEs. A naive use of those editors will seem very tedious and unproductive.
- One of the strongest selling point for IDEs in corporate environments is that they are supposed to have an out-of-the-box UI, thus avoiding costly training programs for using the more geeky editors.
- As Paul Graham hints it, there is a popular misconception that too powerful tools can be nice fooling around with, but they better stay out of the way of the professional case.
I can recall the times when I was studying, our dean would say (and write in the syllabus):
- Nano: a simple editor
- Vim: an advanced editor
- Emacs: too-powerful an editor
What is the one feature we need from a text editor?
Have you ever faced a one-time situation where you wished that the editor could automatically do this and that? Something specific enough that you know nobody will ever be in such a situation again. Like remove all the roman numerals at the beginning of every two paragraphs, or remove the XML tags while keeping a subset of it?
No editor developer can predict what use the user will make of it. Boosting the user’s productivity by implementing every single corner case of editing capabilities is not possible.
As such, an editor needs just one core feature to boost the productivity of every user:
Be an extensible editor.
That’s it. Well, let’s add some frivolities to the list:
- Any action can be bound to a keyboard shortcut.
Touch-typing is what will make you write code fast, not fancy IDE features. Mouse actions will disrupt the flow which is why a keyboard-oriented editor will allow for a faster flow. See Mastering the keyboard.
- Capable of running in text mode (e.g. TTY) is a plus for historical reasons.
Text mode is not strictly required, but as of 2016 it is still prevalent in many contexts in which you really want to keep your favorite tool at hand.
Extensibility alone implies many features commonly found in other editors. For instance:
- Syntax highlighting (some don’t like it).
- Compilation feedback (go to error, etc.).
- Advanced character editing (capitalize, etc.).
- Keyboard macros.
- Automatic indentation.
- Regexp support (search and replace).
- Rectangular selection and editing.
- Abbreviation expansion.
- Spell checking.
- Fully keyboard controlled, without relying on arrows. (This would disrupt the flow when the hands are on the homerow.)
- Fast navigation (function, paragraph, word, matching parenthesis, page, search, etc.).
- Multiple cursors.
- Shell piping (output to buffer), call shell commands on files and process output.
- Display editing windows side-by-side, including of the same document.
- Templates / snippets.
- Whitespace management, automatic code formatting.
- Fast buffer switching. (Tabs are slow to browse.)
- Fullscreen text editing area. This is where you’ll spend most of your time reading and writing. Paradoxically, some IDEs forget they should be editors before anything else and bundle so many features in side windows that the text area is less than half the screen space by default.
Text editors that are extensible, keyboard controlled and work in text mode are not legions. The most popular are, by far, the ancient, legendary Emacs and Vim. TextAdept is another one that offers some interesting feats.
Vim inherits from
vi, a historical text editor that is very minimalist. Both
editors are sometimes mixed up, in so far as some systems actually symlink
to Vim. This is dangerous so let’s stress this out: if you find yourself
wondering why so many people follow the Cult of Vim while it seems to be the
most limited editor you’ve ever encountered, you might be using the wrong piece
The war between Emacs and Vim is, in my opinion, futile. To the point that Emacs has a mode to emulate Vim. Both editors have all the fundamental features: a Turing-complete configuration that allows for binding any action to keyboard shortcuts. (Plus they run in text mode.)
Maybe the only significant difference between the two is that Emacs uses Emacs Lisp as a configuration language while Vim uses Vimscript.
Another difference is that Emacs has a greedy tendency for bundling its community extensions (for the sake of GPL3 protection?) while Vim keeps it slightly lighter.
An editor is not the easiest tool to master. It takes time getting used to the bindings. It will only start proving efficient once the bindings have been hard-wired to your brain.
But this is not what matters most. The hardest part will be to become comfortable at customizing the editor, that is, learning the scripting language and the editor API to make it fit all your needs. And your needs will become legions over the years.
vi has left its mark in computer history: its modal approach has
inspired many unrelated programs to use its bindings. Getting familiar with the
vi will help using many programs smoothly.
Emacs has generated a similar phenomenon, maybe a tad more limited. Some tools (shells, Matlab) also offer Emacs key bindings.
This had become prevalent to the point that bindings can be classified into families:
CUA are the bindings that IBM had laid down in the 1980s and that are now (2016)
Ctrl-v and the like. If you think that Emacs
vi go “against the rule”, note that they were first…
Switching from a keybinding family to another can be disturbing: I personally try to stick to one as much as possible. Which also means that it might be a good idea not to change the default bindings of the most common actions within Emacs and Vim. That is more a matter of personal taste though.
Last but not least, an extensible text editor means you will want to save and sync your configuration across machines. If the configuration is not saved in a versionable format, the editor is not an acceptable tool for the purpose.
Using a text editor a programmer is often bound to managing big sets of files for each projects. This has set the need for IDEs. But not so fast. What is most needed?
Building the project? A console to run the build command will do. (Calling it from the text editor can be a plus if the error output can direct to the spurious files and lines.)
Versioning? Use your favorite interface to the VCS, there is little need for interfacing it from the text editor.
File browsing? There are efficient ways for doing that (better than just a file tree) within or outside a text editor. More on that later.
What you will need most in big projects:
Surfing the whole code base as fast as possible.
It is not only about finding files, it is about finding chunks of code. With little typing and little cognitive effort. When you write code, you actually spend a lot of time reading the existing code:
- Looking for comments.
- Looking for functions, types, etc.
- Checking out algorithms.
- Looking for files as a whole (head comment and content).
Incremental narrowing search
Above we mentioned the following thinking process: “list first, then think about what you want, then select”. This is counter-productive since you should know what you are looking for beforehand. I advocate for the following, more productive mindset: “think what you want and write it down”. This allows for a different UI approach.
The “classic” UI design bound the the former thinking process is made of lists of objects the user is looking for: file lists, buffer lists, text search lists, etc. The user browses them and picks the desired items.
Incremental narrowing search is a much more productive design reflecting the latter mindset: the list of results is filtered as you type while it is ordered by best match. The typed text needs only be approximate. Which makes it very fast to look for anything, should you know the exact name, remember part of it, or just be looking for some keywords.
Implementations of such UI designs include fzf and Emacs Helm.
fzf runs from
the shell, it will let you search files, shell history and so on. Emacs Helm is
similar but runs for any lookup action within Emacs.
The strong point of this design is its universality: it is not specific to one action, it can be used pretty much anywhere the user can make a request with words:
- Looking for content (most important!).
- Looking for commands.
- Looking for files.
- Looking for functions and declarations in code (methods, attributes…).
- Looking for a buffer.
- Looking for a man page.
- Looking for an entry in some command history or in the copy-paste clipboard.
- You name it!
It’s the content that matter, it’s not actually the files.
It is most important to be able to browse your project by content as it should not matter if a portion of code got moved to another file.
It is also a cheap way to find references: forcing exact matches with a regexp
\<name\> will make it reasonably accurate.
It is an inefficient
go to definition however, which only proves useful if you
don’t have any semantic analysis at hand for your programming language.
Go to definition
I used to work for a company that was working on a massive code base. On my
first day I was told “disable auto-completion and all those cumbersome, slow
features, then activate
go to definition.” As a matter of fact, all
programmers in the company were using and abusing of this one feature, almost
exclusively. Since the code base was immense and the documentation somewhat
lacking (don’t be surprised…), contributing to the code-base implied reading
big portions of the existing code and thus going down the huge hierarchy of
structures and functions.
Go to definition proved to be by far the most useful navigation function. If
the code base is well written, a glimpse at the definition will give you a full
understanding of the functions you are calling and the data structures you are
manipulating, both from comments and code. When badly written (lacking in
clarity or comments…), you can jump straight to the code to decrypt what it