Vim wants you to control, VSCode wants you to consume

Hillel Wayne — Computer Things Tools

Summary

The article contrasts Vim's focus on user control through programmatic customization with VSCode's emphasis on consumption via heavier plugin development.

<p>Newsletter updates were sporadic in July because of two weddings, two conferences (with two different talks!), and finishing <a href="https://logicforprogrammers.com" target="_blank"><em>Logic for Programmers</em></a>. Huge thank you to everybody who bought a copy, as well as for your patience with the schedule. There's some podcast appearances, a conf talk, and a book sale at the end of this post. </p> <p>Newsletter updates will be sporadic in August because I just started my Developer Educator job at <a href="https://antithesis.com/" target="_blank">Antithesis</a>. I'll have less time to write because I'll be working 40 hour workweeks, about 8 hours of which being actual work and the other 32 being bashing my head against <a href="https://nixos.org/" target="_blank">NixOS</a>.</p> <p>NixOS is the standard developer OS at the company. It's also a notoriously difficult distro to learn even for Linux heads, and I'm coming from Windows. The only way I am going to get anywhere is to go all in and commit fully to the NixOS philosophy.<sup id="fnref:quitters"><a class="footnote-ref" href="#fn:quitters">1</a></sup> For one, I'm seeing how long I can last without my customary 2000-line Neovim config.</p> <p>Which immediately raises the question as to <em>why</em> I have 2000 lines of Neovim config. It's because Vim<sup id="fnref:vim"><a class="footnote-ref" href="#fn:vim">2</a></sup> (and Emacs) think of configuration in a very different way than more popular editors do.</p> <h2>Control and Consumption</h2> <p>Say we want to make <code>ctrl+n</code> to save the current file. In VSCode, you put this in <code>keybindings.json</code>:</p> <div class="codehilite"><pre><span></span><code><span class="p">[</span> <span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="nt">&quot;key&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;ctrl+n&quot;</span><span class="p">,</span> <span class="w"> </span><span class="nt">&quot;command&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;workbench.action.files.save&quot;</span> <span class="w"> </span><span class="p">}</span> <span class="p">]</span> </code></pre></div> <p>In Neovim, you put this in <code>init.lua</code>:</p> <div class="codehilite"><pre><span></span><code><span class="nv">vim</span><span class="p">.</span><span class="py">keymap</span><span class="p">.</span><span class="nf">set</span><span class="p">(</span><span class="s1">&#39;n&#39;</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;&lt;c-n&gt;&#39;</span><span class="p">,</span><span class="w"> </span><span class="kr">function</span><span class="p">()</span><span class="w"> </span><span class="nv">vim</span><span class="p">.</span><span class="py">cmd</span><span class="p">.</span><span class="nf">write</span><span class="p">()</span><span class="w"> </span><span class="kr">end</span><span class="p">)</span> </code></pre></div> <p>Now, a couple of differences to see. First, the VSCode example is invoking a fixed, built-in command, while Neovim can bind an arbitrary function. Second, in VSCode you edit a static configuration file with static data, while in Neovim you execute a command that edits the running editor state. In fact, it doesn't even need to be in a configuration file: you can add a new keymap directly from the command line. Though you'd probably instead do that command in the OG Vim way:</p> <div class="codehilite"><pre><span></span><code>map <span class="p">&lt;</span><span class="k">c</span><span class="p">-</span><span class="k">n</span><span class="p">&gt;</span> :<span class="k">w</span><span class="p">&lt;</span>CR<span class="p">&gt;</span> </code></pre></div> <p>And that does something different than a function: it makes pressing <code>ctrl+n</code> mean "do whatever typing <code>:w</code> and pressing Enter would do." In default Vim that is the same as saving a file, but if you remapped <code>:</code> to <code>o</code> then it would instead do the equivalent of <code>ow&lt;cr&gt;</code>, which would type the character <code>w</code> on its own line. <sup id="fnref:nnoremap"><a class="footnote-ref" href="#fn:nnoremap">3</a></sup></p> <p>In other words, Vim gives you incredible programmatic control over the state of the editor. Want to make typing <code>;r</code> paste from the clipboard? Easy. Want different setting options in normal and insert mode? Go ahead. Want to make "writing a file" do something different during a full moon? You could if you want. <sup id="fnref:bufwrite"><a class="footnote-ref" href="#fn:bufwrite">4</a></sup></p> <p>Now, you can do some amount of customization in VSCode, especially with multicommands, but for the majority of complex stuff you need to write a plugin. And making a plugin in VSCode is a much heavier process than making one in Neo/Vim. <a href="https://github.com/microsoft/vscode-wordcount" target="_blank">If you want to make a command that prints the word count</a>, you have to 1) learn TypeScript, 2) <a href="https://www.npmjs.com/package/generator-code" target="_blank">scaffold a special VSCode extension project</a>, 3) define a <code>wordcount</code> function, 4) register the <code>mycode.wordcount</code> command, 5) add <code>mycode.wordcount</code> as a <code>contributes</code> record in the extension manifest, 6) package or publish your extension, and 7) import the extension. It's very clear that the plugin system is <em>not</em> meant to let you tweak in a bit of functionality, but rather to let specialists produce complete plugins for other developers to consume. And since so much of the advanced functionality of VSCode is only possible through plugins, this limits the control the average user has over their environment.</p> <p>Neovim also has plugins, but they can't do anything you couldn't already do in your default config. Admittedly, some bits of the APIs are meant specifically for plugin specialists, but they're still documented and available for your personal configuration. You never know what someone's gonna need!</p> <p>In summary:</p> <ul> <li>VSCode has a two-tier system, where plugin makers make plugins that users consume. The plugin has more power than the user. Most users aren't expected to make their own extensions.</li> </ul> <ul> <li>Vim has a one-tier system: the user can do anything a plugin can. Everybody is always able to extend the system and have as much control as they want.</li> </ul> <h2>Most people should be consumers</h2> <div class="subscribe-form"></div> <p>Confession: this all is unintentionally a little ragebaity. "Consumer" is a dirty word in software. A consumer is somebody at the mercy of a producer's decisions. I think there's even a connotation of passiveness in being a consumer. It sort of starts leaning into a moral judgment: developers should use Neovim <em>because</em> it gives them control.</p> <p>But, and this is <em>intentionally</em> a little ragebaity, it's the other way around. Most developers are better off sticking with the consumer model and only switching to a control-editor if they really, really want to. <sup id="fnref:minimalism"><a class="footnote-ref" href="#fn:minimalism">5</a></sup></p> <p>First of all, learning to configure and extend Vim is hard. It took me a long time to get comfortable with even making basic scripts. And even if I'm comfortable hacking Vim, I still need to consume other people's plugins if I want a modern developer experience. I'm not writing my own treesitter integration from scratch! <sup id="fnref:taskrunner"><a class="footnote-ref" href="#fn:taskrunner">6</a></sup></p> <p>Second, while the experience of developing plugins is worse on VSCode, the experience of consuming them is far, far better:</p> <ul> <li>All plugins install, set up, and are used the same way. When I install a new plugin I don't have to spend ten minutes reading docs to get it working.</li> </ul> <ul> <li>I can read a list of all the new commands, keybindings, and configuration options added by the extension. I can edit any configuration option in the same settings UI, which has features like global search and input validation.</li> </ul> <ul> <li>I can enable and disable extensions without changing my startup scripts, and I can enable extensions for only specific workspaces.</li> </ul> <ul> <li>If a plugin adds a keybinding that conflicts with my custom keybindings (or another plugin's keybindings), VSCode will <em>tell me</em> instead of silently clobbering the older one.</li> </ul> <ul> <li>I can't break a plugin through a weird script I run at startup or by installing a different plugin.</li> </ul> <ul> <li>A plugin can't break <em>my</em> startup.</li> </ul> <p>These are all possible precisely because the VSCode plugin system is so heavyweight and inflexible and because everything is configured through static JSON files. Figuring out what configuration options a Neovim extension has is tantamount to solving the Halting Problem.</p> <p>(The broader principle here is the <strong>ability-guarantee tradeoff</strong>. <sup id="fnref:tradeoff"><a class="footnote-ref" href="#fn:tradeoff">7</a></sup> A VSCode extension can do fewer things than a Vim extension can, and therefore we have more guarantees about what it actually does. Exploring the AGT is one of the running themes of <em>Logic for Programmers</em>.)</p> <p>The consumption paradigm is worse than the control paradigm in a lot of ways but it's so much better in this one specific, <em>extremely important</em> way that it's the right choice for most developers. To some extent I wonder if preferring control is more a personality trait than a measured tradeoff. I'm <em>unhappy</em> when I can't tweak some software just to my liking, it just grates on me that something's off and can't be fixed. If tomorrow I woke up and was just not bothered by that, would I still prefer Neovim to VSCode? I dunno. Maybe I'll find out as part of The Nix Experience.</p> <hr /> <p>Now there's a third point in the design space I haven't talked about: what if the editor restricted <em>both</em> your control and consumption? <a href="https://helix-editor.com/" target="_blank">Helix</a>, for example, allows adding LSP servers and treesitter grammars but not any other kind of plugin.<sup id="fnref:plugins"><a class="footnote-ref" href="#fn:plugins">8</a></sup> It also has a static and very limited configuration language. You can't even set different keybindings for different filetypes.</p> <p>That seems crazy to me! But a lot of people seem to like it, and I've been interested in <a href="https://kakoune.org/why-kakoune/why-kakoune.html#_improving_on_the_editing_model" target="_blank">Kakoune-style modal editing</a> for a while now. So now I'm running Helix as my main terminal editor. I don't know if I will stick with it; I feel like I'll eventually crave a more hackable editor. But at least then I'll be more comfortable with Nix before trying to import my thousands of lines of Neovim conf.</p> <hr /> <h1>Appearances and stuff</h1> <p>Three this time:</p> <ul> <li>I was on the <a href="https://podcasts.apple.com/us/podcast/formal-methods-with-hillel-wayne/id1769051199?i=1000778935586" target="_blank">Pragmatic Engineer podcast</a>, talking about math, formal methods, AI, and the Crossover Project. Listen if you like the word "like" and <a href="https://www.youtube.com/watch?v=KSkcgIYQy0U&amp;list=PLzwJJv8h-iciW53inSOkQA4mkG8TuQAUh&amp;index=2" target="_blank">check out the video</a> for mad <a href="https://youtu.be/QgRIXntFhww?si=CbiXylqFpPoegh7F&amp;t=6478" target="_blank">Stan hands</a>.</li> <li>I was also on <a href="https://youtu.be/27IJacqgHSU" target="_blank">Leanpub Launch</a> advertising LfP (<a href="https://leanpub.com/blog/leanpub-book-launch-logic-for-programmers-by-hillel-wayne/" target="_blank">accompanying blog</a>).</li> <li>Last month I was at the inaugural <a href="https://softwareshould.work/" target="_blank"><em>Software Should Work</em> conference</a>, giving my standard talk on practical ideas in formal methods. But for some reason my computer wouldn't connect to A/V and <em>nobody</em> on the staff had Powerpoint, and large chunks of the presentation just Didn't Work on keynote. Watch me <a href="https://www.youtube.com/watch?v=zSZkLyD9ILI" target="_blank">tapdance on a tightrope in an earthquake here</a>. Somehow I pulled through.</li> </ul> <p>Oh, also Amazon is selling <em>Logic for Programmers</em> for <a href="https://www.amazon.com/dp/B0HBLP4B26" target="_blank">15% off for some reason</a>. I confirmed I get the same royalties either way, so hey, it's cheaper with no downside. I have no idea how long the sale will last.</p> <div class="footnote"> <hr /> <ol> <li id="fn:quitters"> <p>Technically I don't <em>have</em> to use NixOS because I'm not on the core engineering team, but I'm not a <em>quitter</em>&#160;<a class="footnote-backref" href="#fnref:quitters" title="Jump back to footnote 1 in the text">&#8617;</a></p> </li> <li id="fn:vim"> <p>I'm going to use Vim and Neovim interchangeably because the core essence is the same (even if the APIs and scripting languages are different) and because I have less time than usual to edit this newsletter.&#160;<a class="footnote-backref" href="#fnref:vim" title="Jump back to footnote 2 in the text">&#8617;</a></p> </li> <li id="fn:nnoremap"> <p>For this reason it's best practice to use <code>noremap</code> instead of <code>map</code>, which doesn't do recursive remapping. There are some niche uses for <code>map</code> though!&#160;<a class="footnote-backref" href="#fnref:nnoremap" title="Jump back to footnote 3 in the text">&#8617;</a></p> </li> <li id="fn:bufwrite"> <p>via the <code>BufWriteCmd</code> event. This is useful for things like editing stuff in a zip file or over FTP.&#160;<a class="footnote-backref" href="#fnref:bufwrite" title="Jump back to footnote 4 in the text">&#8617;</a></p> </li> <li id="fn:minimalism"> <p>For the record, this is talking about developers who want/need an IDE like experience. There are reasons to use vim besides controllability, like its ubiquitousness on Linux servers.&#160;<a class="footnote-backref" href="#fnref:minimalism" title="Jump back to footnote 5 in the text">&#8617;</a></p> </li> <li id="fn:taskrunner"> <p>But I will <a href="https://www.hillelwayne.com/post/task-runner-neovim/" target="_blank">write my own task runner</a>.&#160;<a class="footnote-backref" href="#fnref:taskrunner" title="Jump back to footnote 6 in the text">&#8617;</a></p> </li> <li id="fn:tradeoff"> <p>I originally called this the <a href="https://buttondown.com/hillelwayne/archive/the-capability-tractability-tradeoff/" target="_blank">capability-tractability tradeoff</a> but now think "ability-guarantee" is less pretentious.&#160;<a class="footnote-backref" href="#fnref:tradeoff" title="Jump back to footnote 7 in the text">&#8617;</a></p> </li> <li id="fn:plugins"> <p>I know there's been <a href="https://github.com/helix-editor/helix/pull/8675" target="_blank">some work on a Scheme-based plugin system</a> but I don't know how close that is to actually being official.&#160;<a class="footnote-backref" href="#fnref:plugins" title="Jump back to footnote 8 in the text">&#8617;</a></p> </li> </ol> </div>
Original Article
View Cached Full Text

Cached at: 08/19/26, 03:32 AM

# Vim wants you to control, VSCode wants you to consume Source: [https://buttondown.com/hillelwayne/archive/vim-wants-you-to-control-vscode-wants-you-to](https://buttondown.com/hillelwayne/archive/vim-wants-you-to-control-vscode-wants-you-to) Newsletter updates were sporadic in July because of two weddings, two conferences \(with two different talks\!\), and finishing[*Logic for Programmers*](https://logicforprogrammers.com/)\. Huge thank you to everybody who bought a copy, as well as for your patience with the schedule\. There's some podcast appearances, a conf talk, and a book sale at the end of this post\. Newsletter updates will be sporadic in August because I just started my Developer Educator job at[Antithesis](https://antithesis.com/)\. I'll have less time to write because I'll be working 40 hour workweeks, about 8 hours of which being actual work and the other 32 being bashing my head against[NixOS](https://nixos.org/)\. NixOS is the standard developer OS at the company\. It's also a notoriously difficult distro to learn even for Linux heads, and I'm coming from Windows\. The only way I am going to get anywhere is to go all in and commit fully to the NixOS philosophy\.[1](https://buttondown.com/hillelwayne/archive/vim-wants-you-to-control-vscode-wants-you-to#fn:quitters)For one, I'm seeing how long I can last without my customary 2000\-line Neovim config\. Which immediately raises the question as to*why*I have 2000 lines of Neovim config\. It's because Vim[2](https://buttondown.com/hillelwayne/archive/vim-wants-you-to-control-vscode-wants-you-to#fn:vim)\(and Emacs\) think of configuration in a very different way than more popular editors do\. ## Control and Consumption Say we want to make`ctrl\+n`to save the current file\. In VSCode, you put this in`keybindings\.json`: ``` [ { "key": "ctrl+n", "command": "workbench.action.files.save" } ] ``` In Neovim, you put this in`init\.lua`: ``` vim.keymap.set('n', '<c-n>', function() vim.cmd.write() end) ``` Now, a couple of differences to see\. First, the VSCode example is invoking a fixed, built\-in command, while Neovim can bind an arbitrary function\. Second, in VSCode you edit a static configuration file with static data, while in Neovim you execute a command that edits the running editor state\. In fact, it doesn't even need to be in a configuration file: you can add a new keymap directly from the command line\. Though you'd probably instead do that command in the OG Vim way: And that does something different than a function: it makes pressing`ctrl\+n`mean "do whatever typing`:w`and pressing Enter would do\." In default Vim that is the same as saving a file, but if you remapped`:`to`o`then it would instead do the equivalent of`ow<cr\>`, which would type the character`w`on its own line\.[3](https://buttondown.com/hillelwayne/archive/vim-wants-you-to-control-vscode-wants-you-to#fn:nnoremap) In other words, Vim gives you incredible programmatic control over the state of the editor\. Want to make typing`;r`paste from the clipboard? Easy\. Want different setting options in normal and insert mode? Go ahead\. Want to make "writing a file" do something different during a full moon? You could if you want\.[4](https://buttondown.com/hillelwayne/archive/vim-wants-you-to-control-vscode-wants-you-to#fn:bufwrite) Now, you can do some amount of customization in VSCode, especially with multicommands, but for the majority of complex stuff you need to write a plugin\. And making a plugin in VSCode is a much heavier process than making one in Neo/Vim\.[If you want to make a command that prints the word count](https://github.com/microsoft/vscode-wordcount), you have to 1\) learn TypeScript, 2\)[scaffold a special VSCode extension project](https://www.npmjs.com/package/generator-code), 3\) define a`wordcount`function, 4\) register the`mycode\.wordcount`command, 5\) add`mycode\.wordcount`as a`contributes`record in the extension manifest, 6\) package or publish your extension, and 7\) import the extension\. It's very clear that the plugin system is*not*meant to let you tweak in a bit of functionality, but rather to let specialists produce complete plugins for other developers to consume\. And since so much of the advanced functionality of VSCode is only possible through plugins, this limits the control the average user has over their environment\. Neovim also has plugins, but they can't do anything you couldn't already do in your default config\. Admittedly, some bits of the APIs are meant specifically for plugin specialists, but they're still documented and available for your personal configuration\. You never know what someone's gonna need\! In summary: - VSCode has a two\-tier system, where plugin makers make plugins that users consume\. The plugin has more power than the user\. Most users aren't expected to make their own extensions\. - Vim has a one\-tier system: the user can do anything a plugin can\. Everybody is always able to extend the system and have as much control as they want\. ## Most people should be consumers Confession: this all is unintentionally a little ragebaity\. "Consumer" is a dirty word in software\. A consumer is somebody at the mercy of a producer's decisions\. I think there's even a connotation of passiveness in being a consumer\. It sort of starts leaning into a moral judgment: developers should use Neovim*because*it gives them control\. But, and this is*intentionally*a little ragebaity, it's the other way around\. Most developers are better off sticking with the consumer model and only switching to a control\-editor if they really, really want to\.[5](https://buttondown.com/hillelwayne/archive/vim-wants-you-to-control-vscode-wants-you-to#fn:minimalism) First of all, learning to configure and extend Vim is hard\. It took me a long time to get comfortable with even making basic scripts\. And even if I'm comfortable hacking Vim, I still need to consume other people's plugins if I want a modern developer experience\. I'm not writing my own treesitter integration from scratch\![6](https://buttondown.com/hillelwayne/archive/vim-wants-you-to-control-vscode-wants-you-to#fn:taskrunner) Second, while the experience of developing plugins is worse on VSCode, the experience of consuming them is far, far better: - All plugins install, set up, and are used the same way\. When I install a new plugin I don't have to spend ten minutes reading docs to get it working\. - I can read a list of all the new commands, keybindings, and configuration options added by the extension\. I can edit any configuration option in the same settings UI, which has features like global search and input validation\. - I can enable and disable extensions without changing my startup scripts, and I can enable extensions for only specific workspaces\. - If a plugin adds a keybinding that conflicts with my custom keybindings \(or another plugin's keybindings\), VSCode will*tell me*instead of silently clobbering the older one\. - I can't break a plugin through a weird script I run at startup or by installing a different plugin\. - A plugin can't break*my*startup\. These are all possible precisely because the VSCode plugin system is so heavyweight and inflexible and because everything is configured through static JSON files\. Figuring out what configuration options a Neovim extension has is tantamount to solving the Halting Problem\. \(The broader principle here is the**ability\-guarantee tradeoff**\.[7](https://buttondown.com/hillelwayne/archive/vim-wants-you-to-control-vscode-wants-you-to#fn:tradeoff)A VSCode extension can do fewer things than a Vim extension can, and therefore we have more guarantees about what it actually does\. Exploring the AGT is one of the running themes of*Logic for Programmers*\.\) The consumption paradigm is worse than the control paradigm in a lot of ways but it's so much better in this one specific,*extremely important*way that it's the right choice for most developers\. To some extent I wonder if preferring control is more a personality trait than a measured tradeoff\. I'm*unhappy*when I can't tweak some software just to my liking, it just grates on me that something's off and can't be fixed\. If tomorrow I woke up and was just not bothered by that, would I still prefer Neovim to VSCode? I dunno\. Maybe I'll find out as part of The Nix Experience\. --- Now there's a third point in the design space I haven't talked about: what if the editor restricted*both*your control and consumption?[Helix](https://helix-editor.com/), for example, allows adding LSP servers and treesitter grammars but not any other kind of plugin\.[8](https://buttondown.com/hillelwayne/archive/vim-wants-you-to-control-vscode-wants-you-to#fn:plugins)It also has a static and very limited configuration language\. You can't even set different keybindings for different filetypes\. That seems crazy to me\! But a lot of people seem to like it, and I've been interested in[Kakoune\-style modal editing](https://kakoune.org/why-kakoune/why-kakoune.html#_improving_on_the_editing_model)for a while now\. So now I'm running Helix as my main terminal editor\. I don't know if I will stick with it; I feel like I'll eventually crave a more hackable editor\. But at least then I'll be more comfortable with Nix before trying to import my thousands of lines of Neovim conf\. --- ## Appearances and stuff Three this time: - I was on the[Pragmatic Engineer podcast](https://podcasts.apple.com/us/podcast/formal-methods-with-hillel-wayne/id1769051199?i=1000778935586), talking about math, formal methods, AI, and the Crossover Project\. Listen if you like the word "like" and[check out the video](https://www.youtube.com/watch?v=KSkcgIYQy0U&list=PLzwJJv8h-iciW53inSOkQA4mkG8TuQAUh&index=2)for mad[Stan hands](https://youtu.be/QgRIXntFhww?si=CbiXylqFpPoegh7F&t=6478)\. - I was also on[Leanpub Launch](https://youtu.be/27IJacqgHSU)advertising LfP \([accompanying blog](https://leanpub.com/blog/leanpub-book-launch-logic-for-programmers-by-hillel-wayne/)\)\. - Last month I was at the inaugural[*Software Should Work*conference](https://softwareshould.work/), giving my standard talk on practical ideas in formal methods\. But for some reason my computer wouldn't connect to A/V and*nobody*on the staff had Powerpoint, and large chunks of the presentation just Didn't Work on keynote\. Watch me[tapdance on a tightrope in an earthquake here](https://www.youtube.com/watch?v=zSZkLyD9ILI)\. Somehow I pulled through\. Oh, also Amazon is selling*Logic for Programmers*for[15% off for some reason](https://www.amazon.com/dp/B0HBLP4B26)\. I confirmed I get the same royalties either way, so hey, it's cheaper with no downside\. I have no idea how long the sale will last\.

Similar Articles

Lisp in Vim (2019)

Hacker News Top

A detailed comparison of Slimv and Vlime, two Vim plugins for interactive Lisp programming, covering setup, features, and recommendations.