Bold claim. I know. But I've seen several tutorials on how to set up Vim as an IDE. And I have noticed a pattern:
- A Beginner developer hears about how great Vim is.
- They start using it, learn and fall in love with the editor interface, but realize a bunch of IDE features are missing.
- The developer hears about how customizable Vim is, which can make it as good as any other IDE.
- They find a tutorial on how to use Vim for their chosen language.
- The tutorial gives them a step by step recipe which has a host of plugins that are out of date, add an entire host of unintuitive behavior to an already complicated interface, and eventually fall apart into an unmaintainable mess.
- They go back to another IDE.
I have fallen into this trap multiple times. For the past five years I have been using VSCode with the Vim keybindings plugin and have been happy enough with its behavior. It's nowhere near perfect: the bindings are incomplete, there's no support for Vim-styled tabs, and VSCode's latency means if I hit a combination of keys too fast they may not register. Despite this, I was content with these bindings, as I did not want to waste time making perfect the enemy of good.
Then a VSCode update broke ``<C-w>`` and I couldn't split windows.
With that straw breaking my camel's back, I decided to give the Vim IDE another crack, and I wanted to use the experience to write a beginner's guide that empowers other developers to create their own IDEs. There will be no code to copy/paste into an ``init.vim``, no required plugins, and no lists of essential commands to be an effective Vim developer. Instead, this tutorial will be a high level overview of the methodologies and mentalities I found to be most helpful in putting together my own IDE.
# 1: Be Sure Investing Time into a Vim Setup Will Improve your Life.
As I mentioned before, I did not entertain setting up a Vim IDE until VSCode seriously broke my workflow. Even then I tried working within VSCode splitting windows with mouse clicks until the experience became painful enough that I knew it was time to switch.
However, in my younger attempts I had worse reasons to make an IDE out of Vim. Most of them revolved around virtual peer pressure from people talking on social media like learning Vim gave them arcane powers over their code.
Here's a couple of good reasons to use Vim as an IDE:
- You are extremely peculiar with your current IDE and spend a lot of time fighting it to behave how you want.
- You enjoy tinkering with things and feel rewarded from customizing a sandbox to your liking.
Here's some bad reasons:
- You've heard smart engineers use Vim.
- You've heard there is some zen or bliss in using Vim that can't be achieved in any other environment.
A final good reason to *not* use Vim is when the rest of your team uses a more conventional IDE, and sticking to a coherent toolset can help you work together. You don't want to be the person that says "I use Vim" when they send you over a ``launch.json`` to help debug something.
If you haven't stopped reading here, I will assume you've done your due diligence and soul searching and still think Vim is the right choice for your IDE. What's next?
# 2: Use NeoVim.
VimScript is not good. You want to be working with Lua. Built in LSP support will also make your life a lot easier. You're going to be customizing your editor to work for you and only you, so you don't need POSIX compatibility or other portability guarantees that come with vanilla Vim. If you're trying to set up an IDE on a workstation that can't run NeoVim I have no clue how you found this tutorial in the first place.
# 3: Install a Plugin Manager and Take an Hour or Two to Learn It.
Installing plugins is at the heart of customizing NeoVim. And you're not going to be able to copy/paste from tutorials, github, or stackoverflow to get the behavior you want. The code samples you will see to install plugins will not always be for the plugin manager you chose and you will have to translate installation instructions from one manager to the other.
# 4: Read Documentation Thoroughly.
Maybe I'm telling on myself, but when I'm coding things for the first time I have a habit of skimming docs and trying to get something working as soon as possible. Once I observe it works, I can go back and read docs more thoroughly to fill in the gaps between what I expected to happen and what actually happened.
The problem with doing this in NeoVim, especially when installing a big plugin, is that its interface doesn't make changes in behavior obvious. You may change keybindings without realizing it, or misinterpret a bug as a feature and not fully understand why things just feel "off". When I was adding fold functionality to my setup, one of the plugins I tried to use was bugged, and folded everything after every time I wrote to a file. I thought this was intended behavior I had to learn to be efficient with, no different than when I was first learning how to navigate Vim as a text editor. But if I had paid more attention to the docs, I would have realized there were several initial configurations I could have picked from, and none of them folded an entire file every time I saved it. I switched to a different fold plugin and it worked like a charm.
# 5: Make Changes Slowly.
NeoVim has a massive glossary of unintuitive commands, and the easiest way to make them even more confusing is to add even more commands without having a grasp of what you're changing. If you're already comfortable with default Vim keybindings, you probably learned the absolute basics just to get yourself editing files, and then added commands here and there as you came across different use cases.
Adding new features to NeoVim should work the same way. You don't want to add four plugins to your setup all at once, then add a bunch of keybindings around their features, and find out all the keybindings you set up for plugin A override the bindings in plugin B, and plugin C is incompatible with plugin D. You will spend weeks trying to troubleshoot this mess and have written no actual code along the way.
# 6: Know What You Want out of an IDE.
This plays into the previous point. The easiest way to make changes slowly is to know as precisely as possible what features you want and what features you either dislike or can live without. Because I am currently working on a Typescript project, I knew immediately I was going to want to see type errors inline with my code. I also immediately knew I was going to want intellisense to better work with my types. I began working with this minimalist setup until I realized I was having trouble remembering the directory structure of my files, and using ``:edit`` was becoming increasingly tedious. So I added a directory tree plugin to my setup. From there I started running into screen real-estate issues, so I added a folding plugin as mentioned above.
What's important here is that after I got type checking and intellisense working, I did not add *anything* to my configuration until I knew I was facing a specific pain point worth addressing. I also made sure that any pain points I was feeling couldn't be fixed with a new command or motion or a quick change to my init.lua before I added any plugins. This gave me time to get comfortable with each plugin I added so that as my environment changed, I never came across any unexpected behavior I couldn't immediately revert.
# 7: Get Attached to Features, not Details.
When I tried getting intellisense working for the first time, the first plugin I tried would not autocompete anything that followed after a dot. That's a huge problem for almost every popular language in existence! I wasted a lot of time trying to get this plugin to work. Eventually, I took a step back and realized I did not want the plugin I was using to actually work, I wanted intellisense. So I tried a different plugin, which worked perfectly out of the box.
# 8: Be Comfortable Working without a Visual Debugger.
This is the biggest pain in the ass you will try to get working, and has made me give up on using Vim as an IDE in the past several times. It's not impossible, but expect to have to resort to shell debuggers, browser debuggers, and print statements when things go wrong.
# 9: Read Other Beginner Tutorials for Ideas.
If you've worked your way up to this point in the tutorial, you probably have a good sense of how to modify NeoVim without it turning into a mess of headaches and misery. A lot of the beginner tutorials are going to have workflow-enhancing plugins and configuration ideas that you didn't think of. Just remember to add them slowly and work on understanding them before adding additional features. I'll be doing this shortly to add git integrations to my current setup.
# 10: Periodically Revisit Other IDEs.
VSCode, IntelliJ, and many more are popular for a reason. They have hosts of talented developers working on features and integrations that you may not have thought to be useful. It's always worth keeping up on these updates and seeing if there's ways to add them to your setup. At this point, there are also opinionated NeoVim plugins that will transform the editor into an IDE in one shot. These are worth looking at to compare to, and potentially even replace what you've put together.
<font size=1>Published 2024-07-09</font>
<font size=2>Follow me on Twitter! @RyanMichaelTech</font>