For the better part of the last 20 years or so I’ve been a heavy Vim user and I’ve been using Vim as my main development environment. However, around a year ago I tried Visual Studio Code and I’ve been using it continuously ever since, tweaking some minor bits here and there. While I still use Vim as my main plain text editor (as a matter of fact I’m typing this post using Vim), when it comes to writing code either in a small or large code base, I tend to use VSC. Note most projects I work on are based on C/C++.
The reason for the change is simple: I just believe VSC is a better development environment. It’s not about the way the editor looks or about bells and whistles. VSC, simply put, has all the features most people expect to have in a modern IDE preconfigured and more or less working out of the box, or at least accessible with a few simple clicks and adjustments. It’s true you can configure Vim to give you a similar experience to VSC but it requires learning a respectable amount of new key combinations that you need to get used to (and slowly incorporate into your muscle memory) and, in addition, you need to add and manage every bit of new configuration yourself.
For example, if you search on the web for a list of useful Vim plugins for coders you’ll find plenty of articles and posts like this one from Alex Hunt recommending many things I was using in Vim, like fzf to quickly find files by name in the tree, lightline, a multiple cursors plugin, NerdTree, EditorConfig support, etc. Those are definitely great but VSC has all of that out of the box without having to do anything, save for installing a couple of extensions with a few mouse clicks, and I don’t need to use Vundle and remember to keep my plugins updated.
Obviously, not everything is perfect in the world of VSC. Thanks to Vim’s cindent, I remember having a more seamless experience indenting code, almost requiring no input from my side. In VSC I find myself hitting the Tab key or Shift+Tab key combination more frequently than I used to. Or, for example, Vim’s macros and pattern substitution commands were more powerful for automating text replacement compared to multiple cursors, but the reality is that multiple cursors are easier to use and good enough for 90% of the cases.
Strengths of Visual Studio Code
I’ve already mentioned a better experience out of the box and, in general, being easier to use. Not long ago, this “Making Emacs popular again” LWN.net article was circulating around and reached the front page in Hacker News. It’s about an internal discussion in the Emacs community regarding how to make Emacs more attractive to newcomers and pointing to a Stack Overflow survey that revealed Visual Studio Code was chosen as the main development environment by more than 50% of respondents. Both in LWN.net and Hacker News, some people were surprised about how fast, in a matter of a few years, Visual Studio Code was offering a better out-of-the-box experience than Emacs, which has been out there for more than 40 years, but I don’t think that’s a fair comparison.
If you’ve ever had to work writing code for Windows or know someone who does, you probably know or have heard that Visual Studio, the original proprietary tool, is a great development environment. You can blame Microsoft for many things, but definitely not for forgetting to put man-hours and resources behind its development tools. Visual Studio has been praised for years for being powerful, smart and having excellent debugging facilities. So Visual Studio Code is not a new project coming out of nowhere. It’s a bunch of people from Microsoft trying to replicate and refine that experience using a multiplatform interface based on Electron, something that’s possible today but wouldn’t have been possible several years ago.
While doing that, they have embraced or created open specifications and standards to ease interoperability. For example, while Visual Studio is known for its “project approach” in C/C++, where you typically create a “solution” that may contain one or more configured “projects”, Visual Studio Code is way more relaxed. Coupled with Microsoft’s proprietary C/C++ plugin (more on that later), it will happily launch in a directory containing the source code for a C/C++ project and find a compile_commands.json file in there (a standard originating in the LLVM project). It will start indexing source code files and extracting the code structure, and it will be ready to assist you writing new code in seconds or a few minutes if the project is very large (you can, of course, start writing code immediately but its smart code completion features may not be fully available until it finishes indexing the project). It launches fast and caches important data and editor state, so the second day you will be able to continue where you left off immediately.
For its smart “IntelliSense” features it relies on an open standard called “Language Server Protocol” that originated precisely in Visual Studio Code. Those smart features aim to give you all the information you need to write code while requiring the absolute minimum from you. For example, lets suppose you’re writing a new statement that calls a function. If VSC can locate where that function is declared, it will display a tooltip with its prototype (or a list of prototypes to choose if the function is overloaded) and will let you easily see the function arguments and their types, highlighting which one is next as you fill the list. If you wrote that function and you happened to include a comment above the function explaining what it does (just a comment, no special Doxygen-style formatting is required), it will display it too as part of the tooltip. Of course, when typing a period or an arrow to call an object method, it will also list the available methods and so on.
Also worth mentioning are the C/C++ debugging facilities provided by the proprietary C/C++ plugin. Sometimes it’s a joy to be able to so easily browse local variables, STL data structures or to get the value of variables merely by hovering the mouse cursor over them while reviewing the code (values will be revealed in a tooltip while in debugging mode), to name a few things it does right. For these tasks, VSC typically relies on GDB or LLDB in their “machine interface” modes on Linux, so it’s again leveraging interoperability.
In addition, it’s an extensible IDE with an add-ons market similar to the ones for Chrome and Firefox which has allowed a community to grow around the project. Finally, the editor itself is fully available as real open source but let me clarify that a bit before closing this post.
Visual Studio Code license
Like I said, the core of the editor is available under a real open source license. However, when you install Visual Studio Code using one of its official repositories (like the one available for Fedora), you will be downloading a binary that contains a few extra things and is itself released under a Freeware (not Free Software) license.
In that regard, you can choose to use binaries provided by the VSCodium project. VSCodium is to VSC what Chromium is to Chrome (hence, I believe, the name of the project). If you use VSCodium, a few extensions and plugins that are available for VSC will not be available in Codium. For example, Microsoft’s official C/C++ plugin, which is not released under a Free Software license either. Its source code is available but the binary releases you get from the add-ons market are also released under a Freeware license. Specifically, its license prohibits using it in anything else than VSC as you can read in the first numbered point.
This otherwise excellent C/C++ extension provides two key aspects of the VSC experience: “IntelliSense” and the debugging interface. As I mentioned before, code completion and assistance uses the language server protocol under the hood. This matches what, for example, YouCompleteMe uses for Vim. As far as free software implementations of a language server go, for C/C++ you typically have clangd (YCM uses this one) and also ccls. Both have a VSC extension in its market under a proper FOSS license. I have tried both and I think ccls is better as of the time I’m writing this. ccls is, in my humble opinion, 95% there compared to Microsoft’s extension. It provides 90% of what Microsoft gives you and 5% more details that are missing from their proprietary extension, which is pretty cool.
The project wiki for ccls has some neat instructions about how to use it for code completion while relying on Microsoft’s extension for the debugger, which made me wonder if there’s any FOSS extension out there providing a nice debugger interface that can replace the one by Microsoft. So far I’ve found Native Debug. It might be good enough for you but I’ve found it to be a bit lacking in some aspects. At Igalia we currently do not have the resources needed to develop a better debugging extension or helping improve that one. However, I truly believe someone with deeper pockets and an interest in the free software ecosystem could and should fund an initiative to get the debugging facilities in VSC to the next level, releasing the result under a FOSS license. Coupled with clangd or ccls, that would make the C/C++ proprietary extension not needed and we could rely on an entirely free software solution.