¿Hay alguna forma de buscar una cadena en un archivo fuente C/C++ omitiendo las líneas comentadas?Búsqueda de Vim en líneas de código C/C++
Respuesta
Esta es una pregunta intrigante.
Creo que @sixtyfootersdude tiene la idea correcta: deje que el resaltado de sintaxis de Vim le indique qué es un comentario y qué no, y luego busque coincidencias dentro de los no comentarios.
Vamos a empezar con una función que imita Vim incorporado en search()
rutina, sino que también proporciona un "salto" de parámetros para dejarlo pasar por alto algunos partidos
function! SearchWithSkip(pattern, flags, stopline, timeout, skip)
"
" Returns true if a match is found for {pattern}, but ignores matches
" where {skip} evaluates to false. This allows you to do nifty things
" like, say, only matching outside comments, only on odd-numbered lines,
" or whatever else you like.
"
" Mimics the built-in search() function, but adds a {skip} expression
" like that available in searchpair() and searchpairpos().
" (See the Vim help on search() for details of the other parameters.)
"
" Note the current position, so that if there are no unskipped
" matches, the cursor can be restored to this location.
"
let l:matchpos = getpos('.')
" Loop as long as {pattern} continues to be found.
"
while search(a:pattern, a:flags, a:stopline, a:timeout) > 0
" If {skip} is true, ignore this match and continue searching.
"
if eval(a:skip)
continue
endif
" If we get here, {pattern} was found and {skip} is false,
" so this is a match we don't want to ignore. Update the
" match position and stop searching.
"
let l:matchpos = getpos('.')
break
endwhile
" Jump to the position of the unskipped match, or to the original
" position if there wasn't one.
"
call setpos('.', l:matchpos)
endfunction
Aquí hay un par de funciones que se basan en SearchWithSkip()
para implementar búsquedas de sintaxis sensible:
function! SearchOutside(synName, pattern)
"
" Searches for the specified pattern, but skips matches that
" exist within the specified syntax region.
"
call SearchWithSkip(a:pattern, '', '', '',
\ 'synIDattr(synID(line("."), col("."), 0), "name") =~? "' . a:synName . '"')
endfunction
function! SearchInside(synName, pattern)
"
" Searches for the specified pattern, but skips matches that don't
" exist within the specified syntax region.
"
call SearchWithSkip(a:pattern, '', '', '',
\ 'synIDattr(synID(line("."), col("."), 0), "name") !~? "' . a:synName . '"')
endfunction
aquí tiene ordenes que hacen las sintaxis sensible a las funciones de búsqueda más fácil de usar:
command! -nargs=+ -complete=command SearchOutside call SearchOutside(<f-args>)
command! -nargs=+ -complete=command SearchInside call SearchInside(<f-args>)
Eso fue un largo camino por recorrer, pero ahora podemos hacer cosas como esta:
:SearchInside String hello
que las búsquedas de hello
, pero sólo dentro de Vim texto que considera una cadena.
Y (¡por fin!), Esto busca en todas partes excepto double
comentarios:
:SearchOutside Comment double
Para repetir una búsqueda, utilice la macro @:
para ejecutar el mismo comando en varias ocasiones, como presionar n
a repetir una búsqueda.
(Gracias por hacer esta pregunta, por cierto. Ahora que he construido estas rutinas, espero que les utilizar una gran cantidad.)
Aquí es cómo iba a proceder:
- Borrar Todo C/C++ (utilizando el reemplazar comando
%s
) - proceder a la búsqueda usando búsqueda normal comando
/
- Conjunto una marca en la posición usando
m a
(para establecer la marca "a") - deshacer la eliminación de los comentarios usando
u
- Saltar a la marca "A" con `` a `
- borrar Finalmente la marca usando
delm a
(sería sobrescrita en el caso de que no se elimina, por lo que no gran cosa)
Por supuesto que puede hacer eso en una gran operación/función. No domino el guion de Vim lo suficiente como para dar un ejemplo de eso.
Admito que mi solución es un poco "floja" (y probablemente puedas hacerlo manera mejor) pero eso es todo lo que encontré.
Espero que ayude.
espero que haya una manera más adecuada, pero es mejor que nada .. . :-) –
Bastante peligroso si me preguntas. –
@Ken Bloom: una vida sin peligro debe ser bastante aburrida, ¿no? ;) – ereOn
Este patrón busca una cadena que no esté precedida por las dos convenciones de comentario de C++. También he excluido '*' como el primer personaje que no es de espacio en blanco, ya que es una convención común para comentarios de varias líneas.
/\(\(\/\*\|\/\/\|^\s*\*[^/]\).*\)\@<!foo
Solo coinciden el primer y el cuarto foo.
foo
/* foo
* baz foo
*/ foo
// bar baz foo
Poner \ v en el principio del patrón elimina un montón de barras invertidas:
/\v((\/\*|\/\/|^\s*\*[^/]).*)@<!foo
Puede enlazar una tecla de acceso directo a este patrón, poniendo esto en su .vimrc
"ctrl+s to search uncommented code
noremap <c-s> <c-o>/\v((\/\*\|\/\/\|^\s*\*[^/]).*)@<!
Inteligente, agradable y simple. – ereOn
Incluso funciona con 'hlsearch' –
que no funciona con algunos comentarios/* */comentario sin una estrella al principio de la línea. –
No estoy seguro de si esto es útil pero whe n escribe :syn
tiene todo el formato que se usa en su tipo de archivo. Tal vez puedas referirte a eso de alguna manera. Podría decir algo como:
map n betterN
function betterN{
n keystroke
while currentLine matches comment class
do another n keystroke
}
- 1. Búsqueda avanzada en Vim
- 2. VIM búsqueda de patrón en quickfix
- 3. Limitación del alcance de búsqueda para el código en Vim
- 4. Vim búsqueda y reemplazo - confinar a ciertas líneas
- 5. sangría un montón de líneas en VIM
- 6. Vim tirar rango de líneas
- 7. Búsqueda y reemplazo de VIM
- 8. Vim: formateo automático de líneas largas largas
- 9. Copiar líneas en modo visual en vim
- 10. Vim: resalte las líneas cambiadas
- 11. Vim, líneas largas y desplazamiento
- 12. Detalles de call/cc
- 13. Finalización del código Vim
- 14. Copia del término de búsqueda de vim
- 15. VIM ocultar (no doblar!) Líneas
- 16. Búsqueda de múltiples líneas reemplazar con Perl
- 17. ¿Líneas de alineación de código?
- 18. ¿Cómo concatenar dos líneas rápidamente en Vim?
- 19. Vim: Abrir archivos múltiples en líneas diferentes
- 20. Enrollar automáticamente las líneas largas en VIM
- 21. Cortar y pegar varias líneas en vim
- 22. Agregar espacio vertical entre líneas en vim
- 23. Ocultar todas (no) líneas coincidentes en Vim
- 24. Cómo sangrar líneas múltiples en vim/gvim?
- 25. finalización interna de código en vim
- 26. Vim búsqueda incremental siguiente resultado
- 27. Reparando líneas de comentarios demasiado largas en Vim
- 28. Caso etiqueta insensibles búsqueda en Vim
- 29. Vim - un tirón en la búsqueda registrarse
- 30. Cómo comentar un bloque de código Python en Vim
Gracias por su * gran * respuesta. Espero usarlos también :-) –
¡Esto es genial! Sin embargo, hay un pequeño problema. Si su cadena de búsqueda se encuentra en el archivo, pero solo en lugares que se saltan, obtiene un ciclo infinito. Puedes arreglarlo poniendo un guardia en su lugar. Sobre el ciclo: 'let l: guard = []'. Luego en el ciclo: 'if l: guard == [] | let l: guard = getpos ('.') | elseif l: guard == getpos ('.') | romper | endif'. –
Esto es realmente genial. Tenga en cuenta que puede excluir múltiples SynNames con 'SearchOutside Comment \\\\ | String double', sí necesita cuatro barras invertidas para escapar de la tubería. – Drasill