Vim visual mode and an unfortunate restriction on the filter operation

October 26, 2021

Since discovering Vim's visual (selection) mode I've found myself using it periodically for various things (which I may write up some other day, as there are a couple of common cases where it comes in handy). However, I recently re-discovered an unfortunate restriction on operators on the visual area, specifically filtering. This is that no matter what (as far as I know), they apply on a line-wise basis even if you made a visual block selection.

Suppose, hypothetically, that you have a shell script or a program with a block of comments:

# This is a comment that
# I am in the process of editing and
# shuffling words around. And
# sentences too. It's wound up
# all ragged.

What I often want to do is reflow this paragraph of comments. If you're an innocent or forgetful person, one way to do this in Vim is to use Ctrl-V to make a block selection of the actual comment text, excluding the '# ' that starts them all, and then reflow it with !fmt (my normal choice). Unfortunately, as explicitly documented, filtering operates in line mode even if you made a visual selection, which means that if you do this fmt will reflow your leading '# ' comment markers with the text and suddenly you won't have a comment block.

(Fortunately you can undo this, which is what I immediately did when I noticed that my reflow seemed to have gone very wrong. Then I remembered the special 'always line based' operation of filtering.)

The Vim documentation for the visual gq command and comment formatting suggests that under the right circumstances, Vim will magically recognize comments and do the right thing. However, processing a block of text through fmt is more general (it works in any context where you have a captive block of text that you want to reflow, not just comments), and I'm a person of fixed Vim habits.

I kind of wish that Vim always did filtering with only the selection regardless of what sort of visual selection it was, but I sort of see why Vim does it the current way. For block mode specifically, Vim would definitely need a rule to describe when it introduced newlines (you'd normally want them at the end of each line of the block selection).

(For my own use I have a more general replacement for fmt (also), but this doesn't help when I'm editing a configuration file or script as root or I'm on a system where I haven't dragged over my usual set of tools.)

Comments on this page:

You can try to pipe all lines through fmt -p "\# " in vim.

The # character seems to be special in vim, others, e.g., >, do not require escaping. I use this all the time for reflowing email quotes.

Written on 26 October 2021.
« Go 1.18 will embed source version information into binaries
We're seeing increasingly targeted and dangerous phish spam attempts »

Page tools: View Source, View Normal, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Tue Oct 26 23:29:41 2021
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.