Substitua por vimscript puro (sem `: s`)

12

Eu tenho o seguinte no meu vimrc:

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

Estou usando o vint para lint meu vimrc e recebi o seguinte aviso:

ProhibitCommandWithUnintendedSideEffect Evite comandos com efeitos colaterais indesejados. Evite usar: s [ubstitute] enquanto move o cursor e imprime mensagens de erro. Preferir funções (como search ()) mais adequadas para scripts. Para muitos comandos do vim, existem funções que fazem a mesma coisa com menos efeitos colaterais. Consulte: funções de ajuda () para obter uma lista das funções internas. Guia de estilo do Google Vimscript

No entanto, não acho que eles sejam uma maneira de fazer a substituição sem usar o :scomando

Por exemplo, a search()função fornece as linhas correspondentes a um padrão, mas não há como fazer a substituição. A substitute()função opera em uma string e não substitui um arquivo inteiro.

Devo implementar um método substituto sozinho ou eles são uma maneira mais inteligente de reescrever minha função?

edi9999
fonte

Respostas:

10

O motivo pelo qual você está alertando sobre efeitos colaterais indesejados é porque :substitutemove o cursor e substitui a pesquisa anterior (se usada fora de uma função) . No entanto, isso não significa que você não deve usá-lo, pois você pode reverter os efeitos colaterais do :substitute. Por exemplo, aqui está uma função que eu criei que usa o comando substitute para remover o espaço em branco à direita:

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

Observe que você também pode usar o :markcomando para salvar a posição do cursor, mas isso também significa que você substituirá a marca que decidir usar. Eu não usei o vint antes, mas uma dica nos linters é que você pode receber os avisos deles com um pouco de sal. Nesse caso, é verdade que :substitutetem efeitos colaterais, mas são efeitos colaterais que podem ser evitados. Além disso, não há realmente nenhuma maneira melhor de fazer uma pesquisa e substituir um arquivo de qualquer maneira.

EvergreenTree
fonte
6
O último termo de pesquisa usado é restaurado automaticamente após a saída de uma função, portanto, é necessário salvar e restaurar que não deve ser necessário ao usá-lo dentro de uma função. Veja:help function-search-undo
Martin Tournoij
1
em vez de usar winsaveview () / winrestview () em vez de cursor () #
Christian Brabandt
9

Aqui está uma implementação simplista de sua função, escrita com 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 o padrão de pesquisa a gosto.

romainl
fonte
1

O :scomando é uma abordagem pura do Vimscript.

Meu palpite é que o aviso apenas significa que o cursor provavelmente será posicionado incorretamente após o uso (que você pode contornar usando a winsaveview()função antes e o winrestview()comando após o uso). Além disso, você precisa cuidar de possíveis erros que possam ocorrer. Isso geralmente é tratado usando a ebandeira. Também é necessário cuidar de algumas configurações, como a gdefaultconfiguração, que inverte o significado da gbandeira.

É preciso cuidar dessas especificidades e essa é provavelmente a causa raiz desses avisos. Mas isso não significa evitar o uso do :scomando. Não há problema em usar o :scomando, se você deseja substituir algo no buffer atual.

(Observe, é claro que é possível percorrer todas as linhas e usar uma abordagem de pesquisa () / getline () / setline (). Mas isso geralmente é mais lento.)

Christian Brabandt
fonte