Vim Tips Wiki
Register
Advertisement

bug in the visual mapping[]

There is (what users would likely see as) a bug in this snippet:

vnoremap <silent> <buffer> J :<C-U>'<+1,'>s/^\s*"\s*/<Space>/e<CR>gvJ

- running this map on a highlighted region started with one or more blank lines strips the comment leader from the first nonblank line. This is because the first nonblank line is only protected if it is the first line of the selection, but when there is a preceding line this is not the case.

This could be amended to search for the first non-whitespace like this:

vnoremap <silent> <buffer> J :<C-U>'<;/\s/+1,'>s/^\s*#\s*/<Space>/e<CR>gvJ

That doesn't work if the first line is one of the comment lines, so we can have it back up a line before searching:

vnoremap <silent> <buffer> J :<C-U>'<;-1/\s/+1,'>s/^\s*#\s*/<Space>/e<CR>gvJ

This works all right for me, not that I like it much... It would be better to actually search for the first line with a comment character, but this is becoming a really awkward one-liner. It's already pretty hard to read, and still only works in visual mode - so binding it to J will mean inconsistent results without a second solution for nonvisual modes. But that second solution can easily handle the visual case too, and not require a mapping with different behavior. So there are several good reasons to wrap this up in a function or command. Is there any good reason to prefer the "opaque one-liner" approach?

Sashahart 05:22, March 29, 2011 (UTC)


Interesting! I never join lines starting from a blank line so I've never seen this behavior.

It looks like this problem in normal mode is a special case of the failure noted in the "limitations" section. A solution is given (for normal mode) which uses the cursor position in the pattern so that the leader is only removed on lines which have a leader already, prior to the cursor. This does ruin the possibility of using this tip to join continuation lines to the first line but you can still join multiple continuation lines together.

I'm not sure of the best way to do visual mode. As you note, we could search for the first comment line after the start of the visual selection. But, what if the visual selection contains no comment lines after the first line (or none at all)? Then the command will fail. I think you're right that to actually solve the problem we'll need to move it into a function and do a real search for the first non-blank line, with logic to simply move down a single line if no comment lines are found inside the visual selection.

This gets more complicated if we want to also handle comments which have a different start character than the character we are removing by joining (e.g. /* ... */ comments in C). We could pass in a "start of comment" string to the function instead of using the same as the comment we're removing.

But this is getting very complicated! I like the simplicity of the existing visual mode mapping. It is easy to understand and to explain, and works for the most part, except when you try to join non-comment lines to comment lines.

Maybe the best solution is to mention the shortcoming in the "Limitations" section, and present our alternate function? We would need to split the current section into 2 subsections for this to work well.

--Fritzophrenic 14:42, March 29, 2011 (UTC)

Advertisement