I want to add a config line to my .vimrc so that when I select a grouping of lines in visual mode I can easily call :norm i# and norm x on them (to comment/ uncomment in python.

The desired workflow would be visually highlight multiple lines and then press a key to comment/ uncomment them all.

I'm thinking of adding something like map # :norm i# to my .vimrc but clearly this isn't the correct syntax. I'm new to vim so not super familiar with map vs noremap etc.

Update: I'm aware of this question, but this is not the implementation I'm looking for Making a custom function to comment out a range of lines.

  • 1
    Youre probably missing <CR> at the end of your mapping, but can you clarify why any of the many other QAs we have on comments dont solve your problem? Which part of :help map is unclear? What isn’t working for you? I think I can answer but it would be helpful to know what direction to go, and I’d be thoroughly surprised if this wasn’t a dupe.
    – D. Ben Knoble
    Feb 24, 2019 at 23:09
  • I wish tpope's vim-commentary plugin (or similar, based on text-objects) was built in.
    – Maxim Kim
    Feb 25, 2019 at 7:13

1 Answer 1


This base action can be a single command like '<,'>s/^\s*\zs\(\S\)/#\1. Or, in a function:

" Insert Python comment char # before first non-whitespace char
" for all Visually selected lines
func! PyComment()

I can see how you might run into a few gotchas, though, getting this to run by way of a mapping.

Tricky part #1: Which mapping command? So you want this to be available when lines are visually selected. That means :vmap. Or more accurately it means :vnoremap. Always use the "noremap" variants until you know enough about mappings to recognize a reason to do otherwise. (There are very few circumstances where it comes into play.)

Tricky part #2: What are those weird characters on the command line? When you enter the command line to, say, call a function while you're in Visual mode, vim will prepopulate it with '<,'>. That is the range of lines covered by the Visual selection. This will also happen behind the scenes when we do the same thing as part of a mapping. Well we don't want that, we're handling the range in our function, so the first thing to do is hit Ctrl-U (delete from cursor to beginning of line) or, in mapping speak, add <C-U>.

Tricky part #3: How do I call a function? Well, this isn't really "tricky" but not everyone knows that user functions must be called with :call.

Tricky part #4: It doesn't do anything? As DBK suggested in his comment it's common for people to forget that the mapping must include the carriage return that submits everything for execution. So make the last thing you add to the mapping <CR>.

That gives us

vnoremap X :<C-U>call PyComment()<CR>

(Where X is whatever key(s) you want to use for the mapping.)

  • Actually, you might want xnoremap, because select-mode mappings tend to be weird.
    – D. Ben Knoble
    Feb 25, 2019 at 15:59
  • Also i dont think you need :global, :substitute can take a range
    – D. Ben Knoble
    Feb 25, 2019 at 16:00
  • Yeah. I originally needed g...when I changed directions I got lazy and left it. To my mind this question is not so much about that command as it is about going from a command to a mapping of a function that contains the command. But it's a trivial change so 'tis done.
    – B Layer
    Feb 25, 2019 at 20:47
  • I consider those who use Select mode as I do creatures studied by cryptozoologists. Mysterious, rumored to exist...I've encountered neither in my travels. Yet in spite of being rare at best they claim a 50% stake of the most logical command name for defining pure Visual mode mappings? I'll have none of that. ;)
    – B Layer
    Feb 25, 2019 at 20:48
  • As usual, complete agreement in spirit. Personally the difference has never bothered me, but I do believe at least one snippet plugin (I dont know which; I dont use then) uses it to achieve the sort of Tab-and-type functionality common in IDEs. Again, not enough to warrant drastic changes. I still think xmap should be the select-mapping.
    – D. Ben Knoble
    Feb 25, 2019 at 20:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.