Beyond Movements: Rethinking Vim's Value Proposition

Note: this post will assume that you have a basic understanding of VIM.


Vim has been on the rise among developers for many reasons. and most users focus on its efficient keyboard-driven movements and editing capabilities. While these aspects are very good, I think that Vim's true power lies elsewhere: its seamless integration with the shell environment.

Don't get me wrong - Vim's movement and editing commands are fantastic, but this integration enables Vim to transcend being just a text editor as it can be:

  1. A simple yet effective software prototyping platform
  2. A powerful workflow creation tool
  3. A command center for your development process

... at this point every category sounds like the one before, but you get the point.


This shell integration is accessible through commands like :!, :r !, and :w !, which allow you to execute shell commands directly from within your editing session and incorporate their results into your buffer.

The Upsides

Quick Automation Without Excessive Investment

One of the most common traps in software development is spending hours automating a task and not getting a clear return on investment in the end. With Vim's shell integration, you can create simple automations quickly and easily, in a matter of minutes. So, even if you use an automation for just one task, it was so simple to set up that you don't incur a negative ROI. Avoiding bad resources-output tradeoffs in the long term will be a far superior productivity gain than any editing movement will ever be.

Reproducible, Debuggable, and Distributable

In my experience, Vim workflows are:

  • Reproducible: They can be easily recreated across machines. There might be some differences in shell environments, Vim version and utility versions, especially if you switch between Linux and BSD based distributions, but nothing that cannot be standardized with script.
  • Debuggable: Each component of the script can be tested separately, and then test the Vim automation part of the workflow by executing the movements and commands manually.
  • Distributable: You can share your configurations and other accessory programs fairly easily, especially if you have a somewhat consistent development environment. Also I would suggest to not worry about creating POSIX compliant scripts right off the bat: If you think you'll need some scripts in the future, then wait and convert just the scripts that you need. Using POSIX compliant version of shell utilities is a bit of a pain.

All of this makes team collaboration and personal workflow consistency at least manageable.

Recycle Unix Utility Knowledge

If you already know Unix/Linux tools, you can leverage that knowledge to create automations. Instead of learning new IDE-specific ways to accomplish tasks, you can use familiar command-line tools and pipes.

Zero VimScript Knowledge Required

You don't need to learn VimScript to create all of this. Basic knowledge of Vim's command mode and mappings is all you need. For any complex behavior that you want to create, you can use shell scripting. Avoiding learning yet another bespoke language is a win, always. There are a couple of tricks that you need to learn working with ex commands, but the Vim manual is, for the most part, amazing.


Practical Examples

Here are some practical scripts. I've used all of them just a couple of times, but it was so quick to set them up that the net saving was probably around two hours per week, not counting the decreased mental load, although that is fairly subjective.

Also, I've left in the comments some rough "notes to self," just to show that even when there is something puzzling, generally it's still worth the hassle to get to the end of the automation development because statistically you are going to get a good ROI anyway.

Example 1: Running Go Code Inside Markdown Files

Sometimes I write documentation with code examples. Wouldn't it be great if you could execute those examples directly from your markdown files to ensure they're correct? With Vim, this is easy:



" RUN GO CODE BLOCK AND INSERT RESULT BELOW
" Tested to select the block correctly for every position of the cursor.

nnoremap <C-b> /```\n<cr>me?```<cr>jV'ek :w! ~/git/scripts/tmp.go<cr>/```<cr>:r
!go run ~/git/scripts/tmp.go

This mapping does the following by basically chaining together movements that you do manually every time. It is basically a macro with some shell interactivity.

  1. Finds the code block boundaries (the ```go markers)
  2. Selects all the code in between
  3. Writes it to a temporary file
  4. Executes the code with go run
  5. Inserts the output directly below the code block

I don't know how long it would be to create a VS-Code or IntelliJ extension for this, but I bet longer.

Example 2: Workflow Automation for Note-Taking

Here's an example of creating a simple workflow that allows you to quickly append selected content to a note file:



" APPEND SELECTED CONTENT TO A NOTE FILE
" '<,'> is already implicit when I do anything in visual line.
"
" :w! will overwrite {file} if already exists
"
" Note that after the <cr> I have to do : before !atf.sh
" because I have to mimic dropping in command mode again.
" :r !cat is an exception because I use :r

vnoremap <C-b> :w! ~/git/scripts/tmp/vtf_tmp.txt<cr>:!vtf.sh /home/bax/git/scripts/tmp/vtf_tmp.txt<cr>
    

This mapping:

  1. Takes your visually selected text
  2. Saves it to a temporary file
  3. Calls a custom shell script (vtf.sh) that processes this content
  4. The script can then append it to your notes, format it, tag it, etc.

This kind of workflow is perfect for collecting code snippets, error messages, or important text fragments while you're working, without breaking your flow.

Example 3: Creating a Simple Templating Engine

Another powerful application is to create an ad-hoc lightweight templating system specifically designed for a particular workflow: the best part is that it is easy to customize templates, because one of the main problems that I always get when I try to use them is that at the beginning you might not know exactly what you need, plus you have to always comply with the possibility of the templating engine offered by your editor.



" WRAP FEW WORDS IN A SINGLE LINE TEMPLATE
" Usage: delete the words to insert in the template to put them in the correct
" register: "-
"
" Be sure that there are some lines below before the end of the file.
"
" Note that in the $(), if I test the code dropping in command mode in vim,
" I don't have to escape the pipe to fzf since I'm doing a !{cmd},
" but here in the remap I need to escape it!! CRAZY that it is not documented
" better.

nnoremap <C-e> mb :r !cat ~/git/templates/$(ls ~/git/templates \| fzf --preview "cat
~/git/templates/{}")<cr>/placeholder<cr>"-P:s/placeholder//<cr>D`bhP

This mapping:

  1. Uses fzf to let you select a template from a directory
  2. Inserts the template into your document
  3. Finds the "placeholder" text in the template
  4. Replaces it with the content you previously deleted (stored in the unnamed register)
  5. Positions your cursor appropriately

The Downsides: When This Approach Is Far From Ideal

While powerful, this approach has some limitations worth considering:

Knowledge Prerequisites

To get a good return on investment, you should already be familiar with both Vim and at least a few Unix tools. Starting to learn all these tools simultaneously from scratch can be overwhelming and might actually reduce productivity in the short term. Also, there is not much of an overlap between what you need to know to use Vim as an editor and as an "Engine": things like ex commands, registers and pipes are not frequently encountered when learning VIM as an editor.

Limited Portability to Other Editors via Plugins

Commands like :r and :w are not supported in ANY editor that offers Vim emulation. While some IDEs like JetBrains products allow workarounds with macros, you lose some of the ease of use that makes this approach valuable in the first place. This means that you are limited to use Vim or Neovim if you want to use this workflow.


The end

Thank you for reading :)

If you want to check out a couple of interesting ways to use VIM give a read to https://vitalyparnas.com/

As always, let me know what you think at XY at gmail.com where X = tommaso and Y = bassignana, no dots between X and Y.