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#
7

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.

| improve this answer | |
  • This is what I was originally thinking...will try now. :g command...need to utilize more than just :gQ – wbg May 13 '16 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 – James May 13 '16 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 '16 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.

| improve this answer | |
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.

| improve this answer | |
  • That makes sense...like sed, I'll try it now. – wbg May 12 '16 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 '16 at 18:35
  • I like this idea but having trouble getting it working. – wbg May 13 '16 at 16:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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