Como substituir abas por espaços?

85

É possível converter guias em espaços, mantendo o alinhamento do texto?

Simplesmente substituir apenas funciona de maneira útil quando não há caracteres iniciais.

ideasman42
fonte
Se você instalou o vim-faq , poderá obter uma resposta offline lá: :h vim-faqe pesquisar /tab characters. A tag difícil de memorizar é :h faq-14.16.
Hotschke

Respostas:

98

Você pode usar o :retabcomando De :help :retab

Substitua todas as seqüências de espaço em branco que contêm a <Tab>por novas cadeias de espaço em branco usando o novo valor de tabstop fornecido. Se você não especificar um novo tamanho de tabstop ou for zero, o Vim utilizará o valor atual de 'tabstop'. [...] Com 'expandtab'ativado, o Vim substitui todas as guias pelo número apropriado de espaços.

Observe que o comando aceita um intervalo, para que você possa fazer uma seleção visual e, em seguida, apenas :retabas linhas selecionadas.

guillem
fonte
Legal! Funciona rápido e simples!
DenisKolodin
2
Que tal dar um exemplo?
Petr
23

Você pode usar :retab, como indicado, no entanto, isso mudará todas as guias para espaços, não apenas as guias no início da linha

Portanto, este (onde está um caractere de tabulação):

if :; do
⇥echo "⇥hello"
end

é alterado para (onde está um caractere de espaço):

if :; do
␣␣echo "␣␣hello"
end

Isso pode produzir efeitos colaterais inesperados em alguns cenários, e é ainda mais um problema ao alterar espaços para guias!

Então, escrevi uma pequena função para alterar apenas tabulações / espaços no início da linha:

" :retab changes *everything*, not just start of lines
fun! Retab(expandtab)
    let l:spaces = repeat(' ', &tabstop)

    " Replace tabs with spaces
    if a:expandtab
        silent! execute '%substitute#^\%(' . l:spaces . '\)\+#\=repeat("\t", len(submatch(0)) / &tabstop)#e'
    " Replace spaces with tabs
    else
        silent! execute '%substitute#^\%(\t\)\+#\=repeat("' . l:spaces . '", len(submatch(0)))#e'
    endif
endfun

Com esta versão, você deve especificar manualmente expandtabna chamada de função (ou seja, :call Retab(1)alterar guias para espaços), mas também pode modificá-la para obter o valor atual de &expandtab(como já acontece com &tabstop) da mesma forma que :retabfaz. (Eu prefiro especificá-lo manualmente).

Martin Tournoij
fonte
6
Há também uma resposta no SO que abrange a retabitação apenas no início da linha. Vale a pena ligar por causa da clareza dessa explicação.
jalanb
Alguém poderia explicar o que faz carta aem if a:expandtabmédia?
john cj
Além disso, parece que as condições estão invertidas (uma piada: D?). Se você tiver set expandtabno .vimrc e no autocmd BufWritePre * :call Retab(&expandtab)- o recuo será alterado para tabulações, em vez de espaços.
john cj
11

O Vim fornece um !retabcomando que substituirá todas as seqüências <Tab>por novas strings de espaço em branco usando o novo valor tabstop (por exemplo :set tabstop=2) fornecido, mas todas as guias dentro das strings podem ser modificadas (por exemplo, em um programa C, você deve usar \tpara evitar isso)!

Portanto, como alternativa, você pode alterar todas as guias em espaços usando o seguinte comando:

:%s/\t/  /g

ou como sugerido por @Shahbaz :

:%s/^\t\+/ g

Portanto, apenas as guias usadas no recuo são convertidas.

Explicação:

  • %representa todo o buffer / arquivo ( :help :%)
  • ssignifica substituto ( :help sub-replace-special)
  • \t, ou ^Isignifica guia
  • - use quantos espaços você precisar por uma guia
  • g - significa global e converterá várias ocorrências de guias na mesma linha

Em seguida, para corrigir o recuo de todo o arquivo, você pode tentar: gg=G. Verificação: Re-recuando código mal recuado para obter mais detalhes.

Para usar espaços por padrão, em vez de guias, você precisa adicionar as seguintes configurações ao seu .vimrcarquivo:

set tabstop=2     " (ts) width (in spaces) that a <tab> is displayed as
set expandtab     " (et) expand tabs to spaces (use :retab to redo entire file)
set shiftwidth=2  " (sw) width (in spaces) used in each step of autoindent (aswell as << and >>)

Solução alternativa é usar tidy


Relacionado:

kenorb
fonte
1
Eu faria pelo menos %s/^\t\+/ gpara que apenas as guias usadas no recuo sejam convertidas. Além disso, gg=Gpode ser catastrófico com linguagens como python.
Shahbaz
3

Tente usar:

expand -t 4 input_filename output_filename

expandé uma ferramenta de linha de comando para converter guias em espaços, que você pode executar a partir de um shell ou com :!expand.

Está no POSIX, portanto deve estar disponível na maioria dos sistemas. unexpandfará o inverso, a propósito.

Ankit Shah
fonte
2
O que é expand?
Muni
Expandir é um comando de terminal embutido para copiar caracteres de tabulação para espaços. Encontre uma descrição detalhada no link a seguir. computerhope.com/unix/uexpand.htm
Ankit Shah
2
Se estes são comandos externos, você deve mencionar isso.
Muni
Descrição adicional adicionada. Por favor, revise
Ankit Shah
5
Você também pode fazer :%!expand -t 4dentro do vim. Melhor ainda, você também pode usar a opção de largura atual mudança: :exe '%!expand -t ' . &shiftwidth
EvergreenTree
1

Para completar, =também pode ser usado para corrigir recuos, depois de especificar que as guias são substituídas por espaços. No modo normal, você pode fazer isso digitando :set expandtab. Então =poderia ser usado de duas maneiras:

  • No modo Visual, um único =corrigia recuos dos blocos de código selecionados.
  • No modo normal, gg=Gconsertaria o arquivo inteiro, onde ggmove o cursor para o início do arquivo, depois =é aplicado e Gmove o cursor para o final do arquivo.

Referência: link

Samuel Li
fonte
Isso pressupõe que o vim possa recalcular o recuo atual corretamente (pode não ser o caso) - também para arquivos não estruturados ou código gravado em um editor diferente com regras de recuo ligeiramente diferentes.
Ideasman42
Obrigado @ ideasman42; Eu adicionei à resposta para ser mais completo.
Samuel Li