4

I use Vim to write my Python source and use the debugging library pdb.

Let's say I have this code with break points commented out:

import pdb

#pdb.set_trace()

def func1():
    #pdb.set_trace()
    foo_bar

I then want to globally un-comment all the pdb.set_trace() commands. Also, I'll want to re-comment them.

I figured out how to search for the commented string:

^\(\s*#\)\@!\s*pdb.set_trace() 

After this I don't know how to build a string of commands that would globally find the string and add a # to the beginning of the string so as not to mess up the indentation.

UPDATE:

I realized that I need to not re-comment lines with an existing # so I built upon the accepted answer:

To comment out:

:g/\s*\(#\)\@<!pdb.set_trace()/normal I#

3 Answers 3

8

Alternatively, you could use the :g command. I would do:

:g/\s*#pdb.set_trace()/normal ^x

to uncomment and

:g/\s*pdb.set_trace()/normal I#

to comment. This is nice because it's more readable (and shorter) than a search and replace command. Explanation:

:g/\s*#pdb.set_trace()/             "For every line matching this regex
                       normal       "Execute the following normal mode keystrokes:
                               ^x   "Go to first non-whitespace character and delete it.

The recommenting works the same, except it searches for a different string, and it uses I# instead of ^x. I# means insert # at the first non-whitespace column.

3
  • This is what I was originally thinking...will try now. :g command...need to utilize more than just :gQ
    – wbg
    May 13, 2016 at 16:55
  • @wbg Glad I could help! For more reading on the :g command, see an old question of mine: vi.stackexchange.com/q/5091/2920
    – DJMcMayhem
    May 13, 2016 at 16:56
  • 1
    This works well for me. Other answers are good as well however I'm choosing this one because it worked without tinkering, and is easily grokked.
    – wbg
    May 13, 2016 at 16:58
5

There is a solution which can be pretty simple if you are willing to use a plugin: NERDCommenter.

This plugin is made for "intensely orgasmic commenting" according to their github page. More precisely it creates several mappings to handle comments and one of the mappings is <Leader>ci which allows to toggle the comments of a line.

Combined to a global command it allows you do to what you can. Let's say your leader is , is can use the following command:

:g/pdb.set_trace()/normal ,ci

And that will toggle the comments on the lines matching pdb.set_trace()

Note that you cannot easily use <leader>directly in the normal command (see my question about that)

If your leader is <space> you'll have to do:

:g/pdb.Set_trace()/normal 1 ci

Note that it is easy to map it to a key:

nnoremap <key> :g/pdb.set_trace()/normal ,ci<CR>

And finally the big advantage of this method is that NERDcommenter handles automatically the language you are editing so you can create a command which will togle the comments on lines matching a defined pattern no matter what language you're editing:

command! -nargs=1 ToggleCom :execute "g/" . <f-args> . "/normal ,ci"

Now no matter which language you're editing you can use :ToogleCom foo to toggle the comment of all the lines matching foo. (If your leader is not , see the previous paragraph of my answer)

If you need different commenting styles you can change the mapping used, see :h NERDComFunctionalitySummary for more information.

3

You should be able to do a search and replace.

:%s/^\(\s*\)#\(\s*pdb.set_trace()\)/\1\2/

To un-comment and

:%s/^\(\s*\)\(pdb.set_trace()\)/\1#\2/

To re-comment.

This is done by using back-references. Anything matched in between memory parentheses \(\) can be recalled by using a back-reference (\1 and \2 in this case).

Edit: Oh, and I kind of forgot that you said you wanted this in a script. For using this in a script just omit the first colon. :)

Here's an example of using it in a function:

function! UncommentSetTrace()
   %s/^\(\s*\)#\(\s*pdb.set_trace()\)/\1\2/
endfunction

function! CommentSetTrace()
   %s/^\(\s*\)\(pdb.set_trace()\)/\1#\2/
endfunction

You should be able to just call this function and it will comment/uncomment all instances in your current file. If you want to use a single keystroke you can map it to the function:

noremap <A-c> :call CommentSetTrace()<CR>

This maps Alt+c to comment all the instances.

3
  • That makes sense...like sed, I'll try it now.
    – wbg
    May 12, 2016 at 18:17
  • Having an issue with the match...I'll need to step away for a bit but will come back to this.
    – wbg
    May 12, 2016 at 18:35
  • I like this idea but having trouble getting it working.
    – wbg
    May 13, 2016 at 16:58

Your Answer

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

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