Sustituir con vimscript puro (sin `: s`)

12

Tengo lo siguiente en mi vimrc:

func! AddSpaceBeforeEqual()
  s/\([a-z)_0-9"'\[\]]\)=/\1 =/ge
endfunc

Estoy usando vint para unir mi vimrc, y recibí la siguiente advertencia:

ProhibitCommandWithUnintendedSideEffect Evita los comandos con efectos secundarios no deseados. Evite usar: s [ubstitute] ya que mueve el cursor e imprime mensajes de error. Prefiere funciones (como search ()) más adecuadas para scripts. Para muchos comandos vim, existen funciones que hacen lo mismo con menos efectos secundarios. Consulte: funciones de ayuda () para obtener una lista de las funciones integradas. Guía de estilo de Google Vimscript

Sin embargo, no creo que sean una forma de hacer la sustitución sin usar el :scomando.

Por ejemplo, la search()función proporciona las líneas que coinciden con un patrón, pero no hay forma de hacer una sustitución. La substitute()función opera en una cadena y no sustituye a un archivo completo.

¿Debo implementar un método sustituto yo mismo o es una forma más inteligente de reescribir mi función?

edi9999
fuente

Respuestas:

10

Aquí hay una implementación simplista de su función, escrita con substitute():

function! AddSpaceBeforeEqualInWholeBuffer()
    let l = 1
    for line in getline(1,"$")
        call setline(l, substitute(line, '\([^= ]\)=', '\1 =', "g"))
        let l = l + 1
    endfor
endfunction

Ajuste el patrón de búsqueda al gusto.

romainl
fuente
10

La razón por la que le advierte sobre los efectos secundarios no deseados es porque :substitutemueve el cursor y sobrescribe la búsqueda anterior (si se usa fuera de una función) . Sin embargo, esto no significa que no deba usarlo, ya que puede revertir los efectos secundarios de :substitute. Por ejemplo, aquí hay una función que hice que usa el comando sustituto para eliminar los espacios en blanco finales:

function! StripTrailingWhitespace()
    " Save cursor position
    let l:save = winsaveview()
    " Remove trailing whitespace
    %s/\s\+$//e
    " Move cursor to original position
    call winrestview(l:save)
    echo "Stripped trailing whitespace"
endfunction

Tenga en cuenta que también puede usar el :markcomando para guardar la posición del cursor, pero eso también significa que sobrescribirá la marca que decida usar. No he usado vint antes, pero un consejo sobre las linters es que puedes tomar sus advertencias con un grano de sal. En este caso, es cierto que :substitutetiene efectos secundarios, pero son efectos secundarios que pueden prevenirse. Además, realmente no hay mejor manera de hacer una búsqueda y reemplazar en un archivo de todos modos.

Árbol de hoja perenne
fuente
66
El último término de búsqueda utilizado se restaura automáticamente después de salir de una función, por lo que guardar y restaurar eso no debería ser necesario al usarlo dentro de una función. Ver:help function-search-undo
Martin Tournoij
1
en lugar de usar winsaveview () / winrestview () en lugar de cursor ()
Christian Brabandt
1

El :scomando es un enfoque puro de Vimscript.

Mi suposición es que la advertencia solo significa que el cursor probablemente estará mal colocado después de su uso (lo que puede evitar utilizando la winsaveview()función antes y el winrestview()comando después de su uso). También debe ocuparse de los posibles errores que puedan ocurrir. Esto generalmente se maneja usando la ebandera. También hay que cuidar algunas configuraciones como la gdefaultconfiguración, que invierte el significado de la gbandera.

Uno necesita cuidar esos detalles y esa es probablemente la causa principal de esas advertencias. Pero eso no significa evitar el uso del :scomando. Está perfectamente bien usar el :scomando, si desea reemplazar algo en el búfer actual.

(Tenga en cuenta que, por supuesto, uno podría recorrer todas las líneas y utilizar un enfoque de búsqueda () / getline () / setline (). Pero eso suele ser más lento).

Christian Brabandt
fuente