0
votes

In my code I have multiple scattered lines which help me to debug my program and show me what is going on during execution. Is there an easy and fast way to comment and uncomment (toggle) these fixed lines in vim? I thought about marking these lines with a special sign (e.g. //) like this in python:

print "Debug!" # //   

and everytime a sepcific shortcut is pressed all lines which end with a "# 'some optional descriptive text' //" are commented or uncommented, respectively.

I've looked at NERD Commenter, but from what I read the lines to be commented / uncommented have to be selected each time?

1
What language are you using? It might be better to look some sort of logging framework which you can turn on or off when you run the program. Or maybe a command line flag.FDinoff
I use python (just updated the answer). I thought about adding a 'if (debugFlag == True): ...' as well, but I don't really like it, because it further extends the code with something which does not have something to do with the program logic and (minimally) slows down the program.efie
Python has a logging framework. docs.python.org/2/library/logging.html You should be able to disable it fairly easily. I wouldn't worry about the slow down of the program. Unless you have determined (with a profiler) that the log statements are actually the problem.FDinoff

1 Answers

3
votes

First, find a pattern that selects the right lines. If you have :set hls, it will help spot the matches. I think something like /#.*\/\/$ is what you want.

Next, comment out the selected lines with

:g/<pattern>/s/^/# /

if # will comment out the line, and un-comment them with

:g/<pattern>/s/^# //

Now, you want a single command to toggle. You can either use a variable to keep track of the toggle state, or you can try to figure out the current state by examining the lines that match. Using a variable seems simpler.

The variable could be global, local to the buffer, or local to the script. I like using script-local variables in order to avoid cluttering the namespace. In this case, using a script-local variable might mean that vim will get confused when you switch buffers, so let's use a buffer-local variable, say b:commentToggle.

The first time the function is called, it notices that the variable is not set, so use search() to look for a line that starts with # (There is a space there!) and ends with the pattern we already have. The n flag means not to move the cursor, and w means to wrap around the end of the file (like searching with 'wrapscan' set). The search() function returns the line number (1-based!) if the pattern is found, 0 if not. See :help search().

This seems to work in a small test:

fun! CommentToggle()
  if !exists('b:commentToggle')
    let b:commentToggle = !search('^# .*#.*\/\/$', 'nw')
  endif
  if b:commentToggle == 1
    g/#.*\/\/$/s/^/# /
  else
    g/#.*\/\/$/s/^# //e
  endif
  let b:commentToggle = !b:commentToggle
endfun
nnoremap <F4> :call CommentToggle()<CR>

If you want to put # in front of the first non-blank, then use ^\s*# in the search() command; s/\ze\S/# / or s/\S/\1# / in the first :g line; and s/^\s*\zs# // in the second :g line. See :help /\zs, :help /\ze, and :help sub-replace-special.