Qual é a maneira mais simples de remover o espaço em branco final de todas as linhas de um arquivo?

139

É bastante comum ao programar ou abrir arquivos de texto para encontrar arquivos com espaço em branco à direita no final de uma linha. O vim tem uma maneira de mostrar isso configurando a trailopção na listcharsopção e depois ligando list.

No entanto, qual é a maneira mais fácil de eliminar esse espaço em branco global em todo o arquivo (idealmente sem um plug-in)?

Andrew Ferrier
fonte
Aqui está uma entrada de documento no tópico.
Filipp W.
Se você instalou o vim-faq , poderá obter uma resposta offline lá: :h vim-faqe pesquisar /trailing. A tag difícil de memorizar é :h faq-12.1.
Hotschke 23/07

Respostas:

72

Use uma combinação de teclas para remover todo o espaço em branco à direita

Como algumas páginas que eu edito realmente precisam de espaços em branco à direita (por exemplo, markdown) e outras não, eu configurei uma combinação de teclas para F5que seja fácil fazer isso sem ser automático. Para fazer isso, adicione o código abaixo (de vim.wikia) ou alguma variação dele ao seu .vimrc:

"Remove all trailing whitespace by pressing F5
nnoremap <F5> :let _s=@/<Bar>:%s/\s\+$//e<Bar>:let @/=_s<Bar><CR>
  • nnoremap <F5>faz um mapeamento não-recursivo para a chave F5no modo normal
  • :let _s=@/armazena o último termo de pesquisa (da macro @/) na variável_s
  • <Bar>As funções como um símbolo |de barra vertical para separar comandos, no entanto |, encerrariam um comando nesse contexto; portanto, <Bar>devem ser usadas.
  • :%s/\s\+$//eprocura por espaço em branco à direita e exclui-o em todos os lugares do buffer (consulte a resposta do CarpetSmoker para obter uma análise detalhada dessa expressão)
  • let @/=_srestaura seu último termo de pesquisa na macro @/, para que fique disponível na próxima vez que você clicar n.
  • <CR> termina o mapeamento

... ou seja mais seletivo

Se você tiver casos em que não deseja remover todo o espaço em branco à direita, poderá usar um padrão para ser mais seletivo. Por exemplo, o código a seguir mostra como removo o espaço em branco à direita somente se vier após um ponto-e-vírgula (aqui está vinculado F8).

nnoremap <F8> :let _s=@/<Bar>:%s/;\s\+$/;/e<Bar>:let @/=_s<Bar><CR>

Isso é útil se, como eu, você tiver alguns arquivos com heredocs semelhantes a descontos, intercalados entre instruções de programação terminadas em ponto e vírgula.

Christopher Bottoms
fonte
6
Tente :keeppatternsevitar a substituição @/. E também dê uma olhada :keepjumps.
Bohr
@ Boo Qual versão do vim você está usando? Eu tentei :help keeppatterne não recebi nada.
9305 Christopher Bottoms
@ChristopherBottoms Pelo menos a versão 7.4.155 .
Bohr
@Bohr. Obrigado! Venha descobrir que eu ainda estava usando o 7.4.0. Instalei a versão mais recente e ela está disponível.
21415 Christopher Christopher Bottoms
2
Você pode obter o mesmo efeito envolvendo este comando em uma função, pois o último termo de pesquisa é restaurado automaticamente :-) Dessa forma, você também não precisa se preocupar :nohl, se estiver destacando algo, ele continuará destacando (veja minha resposta atualizada).
Martin Tournoij
175

A maneira "mais simples" é usar apenas :substitute:

:%s/\s\+$//e
  • :%spara :substituteultrapassar o intervalo %, que é o buffer inteiro.
  • \s t corresponde a todos os caracteres de espaço em branco.
  • \+ repeti-las 1 ou mais vezes.
  • $ ancorar no final da linha.
  • O esinalizador para não dar erro se não houver correspondência (ou seja, o arquivo já está sem espaço em branco à direita).

No entanto, essa provavelmente não é a melhor maneira, pois causa dois efeitos colaterais:

  1. move o cursor para a última partida;
  2. adiciona o comando ao histórico e ao histórico de pesquisa;
  3. redefine o último termo de pesquisa.

Você pode corrigir os dois itens, transformando isso em uma função:

fun! TrimWhitespace()
    let l:save = winsaveview()
    keeppatterns %s/\s\+$//e
    call winrestview(l:save)
endfun

E então use-o como:

:call TrimWhitespace()
  1. O winsaveview()vai salvar a "visão" atual, que inclui a posição do cursor, dobras, saltos, etc. A winrestview()no final vai restaurar este a partir da variável salvo.
  2. O :keeppatternsimpede que o \s\+$padrão de ser adicionado ao histórico de pesquisa.
  3. O último termo de pesquisa usado é restaurado automaticamente após a saída de uma função; portanto, não precisamos fazer mais nada para isso.

Como isso é um pouco irritante para digitar :callo tempo todo, você pode definir um comando:

command! TrimWhitespace call TrimWhitespace()

Que pode ser usado sem o :call:

:TrimWitespace

E é claro que você pode vinculá-lo a uma chave:

:noremap <Leader>w :call TrimWhitespace()<CR>

Algumas pessoas gostam de fazer isso automaticamente antes de gravar um arquivo em disco, como:

autocmd BufWritePre * :call TrimWhitespace()

Não gosto, pois alguns formatos exigem espaços em branco à direita (como Markdown) e, em outras ocasiões, você deseja espaços em branco no código (como formatar um email e usar o --<Space>marcador para indicar o início de uma assinatura) )


Modo de plugue sem vergonha: há algum tempo, escrevi um pequeno script Python para limpar o espaço em branco de um projeto inteiro de uma só vez.

Martin Tournoij
fonte
1
Se você não deseja criar uma função para ir para a posição anterior, basta pressionar ​`​duas vezes após a substituição. Isso abre a possibilidade de criar um oneliner como este:%s/\s\+$//e | exe "normal ``"
Neaţu Ovidiu Gabriel
1
@ NeaţuOvidiuGabriel, é claro que o backtick duplo não funcionará da mesma maneira depois que o oneliner for executado. ;)
Caractere curinga
Similar: stackoverflow.com/a/1618401 . Mas eu gosto mais do código de Martin.
john cj
11

Para excluir todo o espaço em branco à direita (no final de cada linha), você pode usar o comando:

:%s/ \+$//

Para incluir guias, use em \svez do espaço.


Na linha de comando:

$ ex +'%s/\s\+$//e' -cwq file.c

Todos os arquivos no diretório atual (use recursivamente **/*.*):

$ ex +'bufdo!%s/\s\+$//e' -cxa *.*

Maneira Python:

:py import vim
:pydo vim.current.buffer[linenr - 1] = vim.current.buffer[linenr - 1].strip()

ou:

:py import vim
:py for i, l in enumerate(vim.current.buffer): vim.current.buffer[i] = l.rstrip()

Use lstrip()para a faixa esquerda (à direita), rstrip()para a faixa direita (à esquerda) ou strip()para remover de ambas as extremidades.


Aqui está uma função útil que remove o espaço em branco supérfluo do final de uma linha que você pode adicionar ao seu .vimrc:

" Removes superfluous white space from the end of a line
function! RemoveWhiteSpace()
   :%s/\s*$//g
    :'^
    "`.
endfunction

Há também o plugin DeleteTrailingWhitespace para isso.


Destacando espaços em branco

Para verificar se todos os espaços à direita se foram, use:

  1. Digite / $para encontrá-los. Se houver, o vim os destacará para você.

  2. Use cores para destacá-las:

    :highlight ws ctermbg=red guibg=red
    :match ws /\s\+$/
    
  3. Use caracteres visíveis ( origem ):

    :set encoding=utf-8
    :set listchars=trail:·
    :set list
    

Veja também: Destacar espaços indesejados

Para destacar o espaço em branco à direita, por padrão, você pode configurar o seu da .vimrcseguinte maneira:

highlight ws ctermbg=red guibg=red
match ws /\s\+$/
autocmd BufWinEnter * match ws / \+$/

Removendo espaços em branco por padrão

Se você deseja garantir que todos os espaços em branco à direita de um arquivo sejam removidos automaticamente ao salvar, você pode adicionar o seguinte comando ao seu .vimrc:

autocmd BufWritePre *.c,*.php :%s/ \+$//ge

o que não é recomendado, pois removerá os espaços em branco finais de todos os arquivos que um usuário salvar (mesmo onde os espaços em branco possam ser desejados).


Veja também:

kenorb
fonte
5

Explicando um pouco a resposta de Christopher Bottoms : Jonathan Palardy escreveu um bom artigo sobre isso . Nele, ele escreve funções, Preserve(command)que preservam o estado do editor (principalmente a posição do cursor e o último padrão de pesquisa) enquanto executa um comando arbitrário:

function! Preserve(command)
  " Preparation: save window state
  let l:saved_winview = winsaveview()
  " Run the command:
  execute a:command
  " Clean up: restore previous window position
  call winrestview(l:saved_winview)
endfunction

Isso tem a vantagem de ser multiuso, por exemplo, você pode usá-lo para substituir todos os espaços em branco à direita (como Jonathan faz) mapeando isso para:

nnoremap <F5> :call Preserve("%s/\\s\\+$//e")<CR>

Você também pode usá-lo para um mapeamento de modo visual para remover apenas os espaços finais nas linhas visualmente selecionadas:

xnoremap <F5> :call Preserve("'<,'>s/\\s\\+$//e")<CR>

E você pode usá-lo para outras chamadas, como formatar todo o documento =enquanto mantém seu lugar (use uma tecla diferente dessa vez para não entrar em conflito):

nnoremap <F6> :call Preserve("normal gg=G")<CR>

No geral, achei a Preserve(command)função uma boa ferramenta para ter.

Alex
fonte
2
O último termo de pesquisa usado deve ser preservado automaticamente quando você sai de uma função; portanto @/, não é necessário se preocupar com isso (neste caso, de qualquer maneira).
Martin Tournoij
3
winsaveview()e winrestview()são muito superiores.
traço-tom-bang
Muito bem! Atualizado com base nos seus comentários.
Alex
0

Outra versão da função StripTrailingSpaces:

if !exists('*StripTrailingWhitespace')
    function! StripTrailingWhitespace() range
        if !&binary && &filetype != 'diff'
            call Preserve(":" . a:firstline . "," . a:lastline . "s/\\s\\+$//e")
        endif
    endfunction
endif

REALMENTE EXISTE UM ERRO NESTA FUNÇÃO (este): a possibilidade não está sendo mantida devido à opção "alcance". ele é removido, funciona muito bem, no entanto, estou compartilhando o código para receber alguma ajuda.

Como você pode ver, ele também usa a função Preserve vista acima, mas de uma maneira um pouco diferente.

A diferença aqui é que eu posso selecionar um intervalo de linhas ou um parágrafo vipe, em seguida, o intervalo :'<,'>aparecerá automaticamente no prompt de comando.

A ideia veio do post Bez Hermoso .

SergioAraujo
fonte