¿Cuál es una forma rápida de comentar / descomentar líneas en Vim?

Tengo un archivo de código Ruby abierto en vi, hay líneas comentadas con # :

 class Search < ActiveRecord::Migration def self.up # create_table :searches do |t| # t.integer :user_id # t.string :name # t.string :all_of # t.string :any_of # t.string :none_of # t.string :exact_phrase # # t.timestamps # end end def self.down # drop_table :searches end end 

Digamos que quiero descomentar todas las líneas en la primera def ... end sección def ... end . ¿Cuál es una manera eficiente de hacer eso en Vim?

En general, estoy buscando una manera fácil y fluida de comentar y descomentar líneas. Aquí estoy tratando con el código de Ruby, pero podría ser JavaScript ( // ) o Haml ( -# ).

Yo uso la secuencia de comandos NERD Commenter . Le permite comentar, descomentar o alternar fácilmente comentarios en su código.

Como se menciona en los comentarios :

para cualquiera que esté confundido por el uso, el líder predeterminado es “\”, por lo que 10 \ cc comentará diez líneas y 10 \ cu descomentará esas diez líneas

Para esas tareas utilizo la mayor parte del tiempo de selección de bloques .

Coloque el cursor sobre el primer carácter # , presione Ctrl V (o Ctrl Q para gVim), y baje hasta la última línea comentada y presione x , que eliminará todos los # caracteres verticalmente.

Para comentar un bloque de texto es casi lo mismo:

  1. Primero, vaya a la primera línea que desea comentar, presione Ctrl V. Esto colocará el editor en modo VISUAL BLOCK .
  2. Luego, use la tecla de flecha y seleccione hasta la última línea
  3. Ahora presione Shift I , que pondrá el editor en modo INSERT y luego presione # . Esto agregará un hash a la primera línea.
  4. Luego presiona Esc (dale un segundo), e insertará un carácter # en todas las demás líneas seleccionadas.

Para la versión simplificada de vim enviada por defecto con debian / ubuntu, escriba : s/^/# en el tercer paso.

Para comentar los bloques en vim:

  • presione Esc (para salir de la edición u otro modo)
  • presione ctrl + v (modo de bloque visual)
  • use las teclas de flecha arriba / abajo para seleccionar las líneas que desea (no resaltará todo, ¡está bien!)
  • Shift + i (capital I)
  • inserte el texto que desea, es decir, %
  • presione Esc Esc

Para descomentar bloques en vim:

  • presione Esc (para salir de la edición u otro modo)
  • presione ctrl + v (modo de bloque visual)
  • use las teclas de flecha / para seleccionar las líneas para descomentar.

    Si desea seleccionar varios caracteres, use uno o combine estos métodos:

    • use las teclas de flecha izquierda / derecha para seleccionar más texto
    • para seleccionar fragmentos de texto use shift + / tecla de flecha
    • puede presionar repetidamente las teclas de borrar a continuación, como un botón de eliminación normal

  • presione d o x para eliminar caracteres, repetidamente si es necesario

A veces me bombardean en una caja remota donde mis complementos y .vimrc no pueden ayudarme, o a veces NerdCommenter se equivoca (por ejemplo, JavaScript incrustado dentro de html).

En estos casos, una alternativa de baja tecnología es el comando de norm incorporado, que simplemente ejecuta cualquier comando vim arbitrario en cada línea en su rango especificado. Por ejemplo:

Comentando con # :

 1. visually select the text rows (using V as usual) 2. :norm i# 

Esto inserta “#” al comienzo de cada línea. Tenga en cuenta que cuando escriba: el rango se completará, por lo que realmente se verá como :'<,'>norm i#

# Descomentario

 1. visually select the text as before (or type gv to re-select the previous selection) 2. :norm x 

Esto borra el primer carácter de cada línea. Si hubiera usado un comentario de 2 caracteres, como //, simplemente lo haría :norm xx para borrar ambos caracteres.

Si los comentarios están sangrados como en la pregunta del OP, entonces puede anclar su eliminación de esta manera:

 :norm ^x 

lo que significa “ir al primer carácter no espacial, luego eliminar un personaje”.

Nota : Dado que la norm es, literalmente, la ejecución de comandos vim normales, no está limitado solo a los comentarios, podría hacer algunas ediciones complejas en cada línea. Si necesita el carácter de escape como parte de su secuencia de comandos, escriba ctrl-v y luego presione la tecla Escape.

Nota 2 : Por supuesto, también puede agregar un mapeo si se encuentra usando mucho la norm . Poner la siguiente línea en ~ / .vimrc te permite escribir ctrl-n lugar de :norm luego de hacer tu selección visual

 vnoremap  :norm 

Nota 3 : Bare-bones vim a veces no tiene el comando de norm comstackdo en él, así que asegúrese de usar la versión mejorada, es decir, típicamente / usr / bin / vim, no / bin / vi

(Gracias a @Manbroski y @rakslice por las mejoras incorporadas en esta respuesta)

Tengo lo siguiente en mi .vimrc :

 " Commenting blocks of code. autocmd FileType c,cpp,java,scala let b:comment_leader = '// ' autocmd FileType sh,ruby,python let b:comment_leader = '# ' autocmd FileType conf,fstab let b:comment_leader = '# ' autocmd FileType tex let b:comment_leader = '% ' autocmd FileType mail let b:comment_leader = '> ' autocmd FileType vim let b:comment_leader = '" ' noremap  ,cc :silent s/^/=escape(b:comment_leader,'\/')/:nohlsearch noremap  ,cu :silent s/^\V=escape(b:comment_leader,'\/')//e:nohlsearch 

Ahora puede escribir ,cc para comentar una línea y ,cu para descomentar una línea (funciona tanto en modo normal como visual).

(Lo robé de un sitio web hace muchos años, así que no puedo explicar completamente cómo funciona :). Hay un comentario donde se explica.)

Especifique qué líneas comentar en vim:

Revelar los números de línea:

 :set number 

entonces

 :5,17s/^/#/ this will comment out line 5-17 

o esto:

 :%s/^/#/ will comment out all lines in file 

Así es como lo hago:

  1. Ve al primer personaje en la primera línea que quieras comentar.

  2. Presiona Ctrl + q en GVIM o Ctrl + v en VIM, luego baja para seleccionar el primer carácter en las líneas para comentar.

  3. A continuación, presione c y agregue el carácter de comentario.

Descomponer funciona de la misma manera, simplemente escriba un espacio en lugar del carácter de comentario.

He creado una simple adición a mi archivo .vimrc que funciona bastante bien y se puede ampliar fácilmente. Simplemente agrega un nuevo tipo de archivo al comment_map y su líder de comentarios.

Agregué un mapeo a los modos normales y visuales, pero puedes reasignar a lo que quieras. Prefiero solo tener una función de estilo ‘alternar’. Uno tiene múltiples mapeos, etc.

 let s:comment_map = { \ "c": '\/\/', \ "cpp": '\/\/', \ "go": '\/\/', \ "java": '\/\/', \ "javascript": '\/\/', \ "lua": '--', \ "scala": '\/\/', \ "php": '\/\/', \ "python": '#', \ "ruby": '#', \ "rust": '\/\/', \ "sh": '#', \ "desktop": '#', \ "fstab": '#', \ "conf": '#', \ "profile": '#', \ "bashrc": '#', \ "bash_profile": '#', \ "mail": '>', \ "eml": '>', \ "bat": 'REM', \ "ahk": ';', \ "vim": '"', \ "tex": '%', \ } function! ToggleComment() if has_key(s:comment_map, &filetype) let comment_leader = s:comment_map[&filetype] if getline('.') =~ "^\\s*" . comment_leader . " " " Uncomment the line execute "silent s/^\\(\\s*\\)" . comment_leader . " /\\1/" else if getline('.') =~ "^\\s*" . comment_leader " Uncomment the line execute "silent s/^\\(\\s*\\)" . comment_leader . "/\\1/" else " Comment the line execute "silent s/^\\(\\s*\\)/\\1" . comment_leader . " /" end end else echo "No comment leader found for filetype" end endfunction nnoremap  :call ToggleComment() vnoremap  :call ToggleComment() 

Nota:

No utilizo ninguna callback o gancho en los tipos de archivo / carga, porque me parece que desaceleran el inicio de Vim más de lo que lo .vimrc la función / mapa estático de .vimrc , pero esa es solo mi preferencia. También traté de mantenerlo simple y eficiente. Si usa autocomandos, debe asegurarse de ponerlos en un grupo de autocomandos o, de lo contrario, las devoluciones de llamada se agregarán al tipo de archivo varias veces por archivo cargado y provocarán una gran degradación del rendimiento.

Utilice Control-V para seleccionar rectangularjs de texto: vaya al primer carácter # , escriba Ctrl + V , desplácese hacia la derecha una vez y luego hacia abajo, hasta el final de los comentarios. Ahora escriba x : está borrando todos los # caracteres seguidos de un espacio.

Alternar comentarios

Si todo lo que necesitas es alternar los comentarios , preferiría ir con commentary.vim por tpope .

enter image description here

Instalación

Patógeno:

 cd ~/.vim/bundle git clone git://github.com/tpope/vim-commentary.git 

vim-plug:

 Plug 'tpope/vim-commentary' 

Vundle:

 Plugin 'tpope/vim-commentary' 

Mayor personalización

Agregue esto a su archivo .vimrc: noremap / :Commentary

Ahora puede alternar comentarios presionando Leader + / , al igual que Sublime y Atom.

Aquí hay una sección de mi .vimrc :

 "insert and remove comments in visual and normal mode vmap ,ic :s/^/#/g:let @/ = "" map ,ic :s/^/#/g:let @/ = "" vmap ,rc :s/^#//g:let @/ = "" map ,rc :s/^#//g:let @/ = "" 

En modo normal y en modo visual, esto me permite presionar , ic para insertar comentarios y , rc para eliminar comentarios.

Me gusta usar el plugin tcomment: http://www.vim.org/scripts/script.php?script_id=1173

He mapeado gc y gcc para comentar una línea o un bloque de código resaltado. Detecta el tipo de archivo y funciona realmente bien.

Con 30 respuestas por delante, intentaré dar una solución aún más fácil: inserte un # al comienzo de la línea. Luego baja por una línea y presiona punto ( . ). Para repetir, haz j , j , etc … Para descomentar, elimine un # (puede presionar x sobre el # ) y haga lo contrario usando k , etc …

Cómo descomentar las siguientes tres líneas en vi:

 #code code #code #code code code 

Coloque el cursor sobre el símbolo # superior izquierdo y presione Ctrl V. Esto te pone en modo de bloque visual. Presione la flecha hacia abajo o J tres veces para seleccionar las tres líneas. Luego presione D. Todos los comentarios desaparecen. Para deshacer, presione U.

Cómo comentar las siguientes tres líneas en vi:

 code code code code code code 

Coloque el cursor sobre el carácter superior izquierdo, presione Ctrl V. Esto te pone en modo de bloque visual. Presione o J tres veces para seleccionar las tres líneas. Entonces presione:

I / / Esc

Esa es una capital I, // y Escape.

Cuando presione ESC , todas las líneas seleccionadas obtendrán el símbolo de comentario que especificó.

Yo uso vim 7.4 y esto funciona para mí.
Suponiendo que estamos comentando / descomentando 3 líneas.

Comentar:

si la línea no tiene tab / espacio al principio:
ctrl + V luego jjj luego shift + I (cappital i) luego // luego esc esc
si la línea tiene tab / espacio al principio, aún puede hacer lo anterior o cambiar por c :
ctrl + V luego jjj luego c luego // luego esc esc

Para descomentar:

si las líneas no tienen tabulación / espacio al principio:
ctrl + V luego jjj luego ll (lower cap L) luego c

si las líneas tienen tab / espacio al principio, entonces espacia uno y esc
ctrl + V luego jjj luego ll (lower cap L) luego c luego space luego esc

Yo uso EnhancedCommentify . Comenta todo lo que necesitaba (lenguajes de progtwigción, scripts, archivos de configuración). Lo uso con enlaces de modo visual. Simplemente seleccione el texto que desea comentar y presione co / cc / cd.

 vmap co :call EnhancedCommentify('','guess') vmap cc :call EnhancedCommentify('','comment') vmap cd :call EnhancedCommentify('','decomment') 

Sí, ya hay 33 respuestas (la mayoría repetitivas) para esta pregunta.

Aquí hay otro enfoque sobre cómo comentar las líneas en Vim: movimientos . La idea básica es comentar o descomentar las líneas usando el mismo método que tirar de un párrafo escribiendo yip o borrando 2 líneas escribiendo dj .

Este enfoque te permitirá hacer cosas como:

  • ccj para comentar las siguientes 2 líneas, y cuk para descomentarlas;

  • cci{ comentar un locking, y cui{ descomentarlo;

  • ccip para comentar un párrafo entero, y cuip para descomentarlo.

  • ccG para comentar todo hasta la última línea, y cugg para descomentar todo hasta la primera línea.

Todo lo que necesita son 2 funciones que operan sobre movimientos , y 2 mapeos para cada función. Primero, las asignaciones:

 nnoremap  cc :set opfunc=CommentOutg@ vnoremap  cc :call CommentOut(visualmode(), 1) nnoremap  cu :set opfunc=Uncommentg@ vnoremap  cu :call Uncomment(visualmode(), 1) 

(Consulte el manual sobre el operador g@ y la variable operatorfunc ).

Y ahora las funciones:

 function! CommentOut(type, ...) if a:0 silent exe "normal! :'<,'>s/^/#/\`<" else silent exe "normal! :'[,']s/^/#/\'[" endif endfunction function! Uncomment(type, ...) if a:0 silent exe "normal! :'<,'>s/^\\(\\s*\\)#/\\1/\`<" else silent exe "normal! :'[,']s/^\\(\\s*\\)#/\\1/\`[" endif endfunction 

Modifique las expresiones regulares anteriores para que se adapten a su gusto en cuanto a dónde debería estar # :

Si ya conoce los números de línea, entonces n,ms/# // funcionaría.

Marqué la primera y la última línea (ma y mb), y luego hago: ‘a,’ bs / ^ # //

Yo uso el plugin vim-commentary de Tim Pope.

Combiné la respuesta de Phil y jqno e hice comentarios de rechazo con espacios:

 autocmd FileType c,cpp,java,scala let b:comment_leader = '//' autocmd FileType sh,ruby,python let b:comment_leader = '#' autocmd FileType conf,fstab let b:comment_leader = '#' autocmd FileType tex let b:comment_leader = '%' autocmd FileType mail let b:comment_leader = '>' autocmd FileType vim let b:comment_leader = '"' function! CommentToggle() execute ':silent! s/\([^ ]\)/' . b:comment_leader . ' \1/' execute ':silent! s/^\( *\)' . b:comment_leader . ' \?' . b:comment_leader . ' \?/\1/' endfunction map  :call CommentToggle() 

Hay un plugin que cambia la vida por tpope llamado vim-commentary

https://github.com/tpope/vim-commentary

Este complemento proporciona :

  • Cordura
  • Comentarios apropiadamente sangrados
  • No hace comentarios sobre líneas vacías / innecesarias

Uso :

  • Instalar a través de Vundle (o Pathogen, supongo).
  • Resalta tu texto y presiona : que se mostrará como :<,'>
  • Escriba Comentario aquí :<,'>Commentary y presione Entrar .
  • Auge. Tu brote hecho

Aquí hay una línea básica basada en el Cv seguido por el método I descrito anteriormente.

Este comando ( :Comment ) agrega una cadena elegida al comienzo de cualquier línea seleccionada.

 command! -range -nargs=1 Comment :execute "'<,'>normal! 0I" .  . "" 

Agregue esta línea a su .vimrc para crear un comando que acepte un único argumento y coloque el argumento al comienzo de cada línea en la selección actual.

Por ejemplo, si se selecciona el siguiente texto:

 1 2 

y ejecuta esto:: :Comment // , el resultado será:

 //1 //2 

Comenzando con las ideas en las respuestas aquí, comencé mi propia función de comentarios. Activa y desactiva los comentarios. Puede manejar cosas como //print('blue'); //this thing is blue //print('blue'); //this thing is blue y solo cambia el primer comentario. Además, agrega comentarios y un solo espacio justo donde está el primer espacio no en blanco y no al principio de la línea. Además, no copia innecesariamente los espacios en blanco, sino que utiliza los acercamientos (: h \ zs para obtener ayuda) para evitar este trabajo adicional, al hacer comentarios y líneas sangradas. Espero que ayude a algunos minimalistas por ahí. Sugerencias son bienvenidas.

 " these lines are needed for ToggleComment() autocmd FileType c,cpp,java let b:comment_leader = '//' autocmd FileType arduino let b:comment_leader = '//' autocmd FileType sh,ruby,python let b:comment_leader = '#' autocmd FileType zsh let b:comment_leader = '#' autocmd FileType conf,fstab let b:comment_leader = '#' autocmd FileType matlab,tex let b:comment_leader = '%' autocmd FileType vim let b:comment_leader = '"' " l:pos --> cursor position " l:space --> how many spaces we will use b:comment_leader + ' ' function! ToggleComment() if exists('b:comment_leader') let l:pos = col('.') let l:space = ( &ft =~ '\v(c|cpp|java|arduino)' ? '3' : '2' ) if getline('.') =~ '\v(\s*|\t*)' .b:comment_leader let l:space -= ( getline('.') =~ '\v.*\zs' . b:comment_leader . '(\s+|\t+)@!' ? 1 : 0 ) execute 'silent s,\v^(\s*|\t*)\zs' .b:comment_leader.'[ ]?,,g' let l:pos -= l:space else exec 'normal! 0i' .b:comment_leader .' ' let l:pos += l:space endif call cursor(line("."), l:pos) else echo 'no comment leader found for filetype' end endfunction nnoremap t :call ToggleComment() inoremap t :call ToggleComment() xnoremap t :'<,'>call ToggleComment() 

Yo uso comments.vim de Jasmeet Singh Anand (encontrado en vim.org),

Funciona con C, C ++, Java, PHP [2345], proc, CSS, HTML, htm, XML, XHTML, vim, vimrc, SQL, sh, ksh, csh, Perl, tex, fortran, ml, caml, ocaml, vhdl, haskel y archivos normales

Comenta y elimina líneas de comentarios en diferentes archivos fuente tanto en modo normal como visual

Uso:

  • Ctrl C para comentar una sola línea
  • Ctrl X para dejar de comentar una sola línea
  • Shift V y seleccione varias líneas, luego Ctrl C para comentar las líneas múltiples seleccionadas
  • Shift V y seleccione varias líneas, luego Ctrl X para dejar de comentar las múltiples líneas seleccionadas

El método más rápido y el más intuitivo de todos ellos es volver a asignar ) para caminar-hacia abajo-comentando líneas, y luego ( para caminar-hasta-descomentar. Pruébalo y no volverás.

En Ruby o Bash , con sangrías de 2 espacios:

 map ) I# j map ( k^2x 

En C / C ++ o PHP , con sangrías de 4 espacios:

 map ) I// j map ( k^4x 

Los inconvenientes son que pierdes ( y ) por el movimiento de oraciones (pero das pueden completarse allí), y ocasionalmente recurres a seleccionar y reemplazar o Ctrl V para manejar secciones largas. Pero eso es bastante raro.

Y para C-style, los comentarios largos se manejan mejor con:

 set cindent set formatoptions=tcqr 

… que combina bien con el uso de V[move]gq para rehacer el V[move]gq de palabras.

Este fragmento simple es de mi .vimrc:

 function! CommentToggle() execute ':silent! s/\([^ ]\)/\/\/ \1/' execute ':silent! s/^\( *\)\/\/ \/\/ /\1/' endfunction map  :call CommentToggle() 

Es para // – Comentarios, pero puedes adaptarlo fácilmente para otros personajes. Puede usar autocmd para establecer un líder como se sugirió jqno.

Esta es una manera muy simple y eficiente de trabajar con rangos y modo visual de forma natural.

Puede usar vim-commentary por tpope ( https://github.com/tpope/vim-commentary ) puede usarlo de la siguiente manera:

Ingrese al modo visual presionando

 'v' 

Entonces presione

 'j' repeatedly or eg 4j to select 4 row 

Ahora todo lo que tiene que hacer con la selección es ingresar claves:

 'gc' 

Esto comentará toda la selección, para descomentar claves repeadas:

 'gc' 

Yo uso vim-multiple-cursores para esto.

  1. Para seleccionar la región, vaya al primer carácter de la primera o la última línea de la región a comentar haciendo clic en 0 (es cero, no la letra “o”). Luego presione V y seleccione la región usando J , K o las teclas de flecha hacia arriba y hacia abajo.
  2. Luego, coloque un cursor virtual en cada línea de la selección presionando Ctrl N.
  3. Luego presione I para editar simultáneamente cada línea de la selección.

Esta respuesta está aquí para 1) mostrar el código correcto para pegar en un .vimrc para obtener vim 7.4+ para bloquear comentarios / comentarios mientras se mantiene el nivel de sangría con 1 atajo en el modo visual y 2) para explicarlo.

Aquí está el código:

 let b:commentChar='//' autocmd BufNewFile,BufReadPost *.[ch] let b:commentChar='//' autocmd BufNewFile,BufReadPost *.cpp let b:commentChar='//' autocmd BufNewFile,BufReadPost *.py let b:commentChar='#' autocmd BufNewFile,BufReadPost *.*sh let b:commentChar='#' function! Docomment () "make comments on all the lines we've grabbed execute '''<,''>s/^\s*/&'.escape(b:commentChar, '\/').' /e' endfunction function! Uncomment () "uncomment on all our lines execute '''<,''>s/\v(^\s*)'.escape(b:commentChar, '\/').'\v\s*/\1/e' endfunction function! Comment () "does the first line begin with a comment? let l:line=getpos("'<")[1] "if there's a match if match(getline(l:line), '^\s*'.b:commentChar)>-1 call Uncomment() else call Docomment() endif endfunction vnoremap   :call Comment() 

Cómo funciona:

  • let b:commentChar='//' : This creates a variable in vim. the b here refers to the scope, which in this case is contained to the buffer, meaning the currently opened file. Your comment characters are strings and need to be wrapped in quotes, the quotes are not part of what will be substituted in when toggling comments.

  • autocmd BufNewFile,BufReadPost *... : Autocommands trigger on different things, in this case, these are triggering when a new file or the read file ends with a certain extension. Once triggered, the execute the following command, which allows us to change the commentChar depending on filetype. There are other ways to do this, but they are more confusing to novices (like me).

  • function! Docomment() : Functions are declared by starting with function and ending with endfunction . Functions must start with a capital. the ! ensures that this function overwrites any previous functions defined as Docomment() with this version of Docomment() . Without the ! , I had errors, but that might be because I was defining new functions through the vim command line.

  • execute '''<,''>s/^\s*/&'.escape(b:commentChar, '\/').' /e' : Execute calls a command. In this case, we are executing substitute , which can take a range (by default this is the current line) such as % for the whole buffer or '<,'> for the highlighted section. ^\s* is regex to match the start of a line followed by any amount of whitespace, which is then appended to (due to & ). El . here is used for string concatenation, since escape() can’t be wrapped in quotes. escape() allows you to escape character in commentChar that matches the arguments (in this case, \ and / ) by prepending them with a \ . After this, we concatenate again with the end of our substitute string, which has the e flag. This flag lets us fail silently, meaning that if we do not find a match on a given line, we won’t yell about it. As a whole, this line lets us put a comment character followed by a space just before the first text, meaning we keep our indentation level.

  • execute '''<,''>s/\v(^\s*)'.escape(b:commentChar, '\/').'\v\s*/\1/e' : This is similar to our last huge long command. Unique to this one, we have \v , which makes sure that we don’t have to escape our () , and 1 , which refers to the group we made with our () . Basically, we’re matching a line that starts with any amount of whitespace and then our comment character followed by any amount of whitespace, and we are only keeping the first set of whitespace. Again, e lets us fail silently if we don’t have a comment character on that line.

  • let l:line=getpos("'<")[1] : this sets a variable much like we did with our comment character, but l refers to the local scope (local to this function). getpos() gets the position of, in this case, the start of our highlighting, and the [1] means we only care about the line number, not other things like the column number.

  • if match(getline(l:line), '^\s*'.b:commentChar)>-1 : you know how if works. match() checks if the first thing contains the second thing, so we grab the line that we started our highlighting on, and check if it starts with whitespace followed by our comment character. match() returns the index where this is true, and -1 if no matches were found. Since if evaluates all nonzero numbers to be true, we have to compare our output to see if it's greater than -1. Comparison in vim returns 0 if false and 1 if true, which is what if wants to see to evaluate correctly.

  • vnoremap :call Comment() : vnoremap means map the following command in visual mode, but don't map it recursively (meaning don't change any other commands that might use in other ways). Basically, if you're a vim novice, always use noremap to make sure you don't break things. means "I don't want your words, just your actions" and tells it not to print anything to the command line. is the thing we're mapping, which is ctrl+r in this case (note that you can still use Cr normally for "redo" in normal mode with this mapping). Cu is kinda confusing, but basically it makes sure you don't lose track of your visual highlighting (according to this answer it makes your command start with '<,'> which is what we want). call here just tells vim to execute the function we named, and refers to hitting the enter button. We have to hit it once to actually call the function (otherwise we've just typed call function() on the command line, and we have to hit it again to get our substitutes to go through all the way (not really sure why, but whatever).

Anyway, hopefully this helps. This will take anything highlighted with v , V , or Cv , check if the first line is commented, if yes, try to uncomment all highlighted lines, and if not, add an extra layer of comment characters to each line. This is my desired behavior; I did not just want it to toggle whether each line in the block was commented or not, so it works perfectly for me after asking multiple questions on the subject.