¿Cómo reemplazar las pestañas con espacios?

85

¿Es posible convertir pestañas en espacios, manteniendo la alineación del texto?

Simplemente reemplazar solo funciona de manera útil cuando no hay personajes principales.

ideasman42
fuente
Si ha instalado vim-faq , puede obtener una respuesta sin conexión allí: :h vim-faqy buscar /tab characters. La etiqueta difícil de memorizar es :h faq-14.16.
Hotschke

Respuestas:

98

Puedes usar el :retabcomando. De :help :retab

Reemplace todas las secuencias de espacios en blanco que contengan a <Tab>con nuevas cadenas de espacios en blanco utilizando el nuevo valor de tabulación dado. Si no especifica un nuevo tamaño de tabulación o es cero, Vim usa el valor actual de 'tabstop'. [...] Con 'expandtab'activado, Vim reemplaza todas las pestañas con el número apropiado de espacios.

Tenga en cuenta que el comando acepta un rango, por lo que puede hacer una selección visual y luego solo :retablas líneas seleccionadas.

guillem
fuente
¡Bueno! Funciona rápido y simple!
DenisKolodin el
2
¿qué tal dar un ejemplo?
Petr
23

:retabSin embargo, puede usar , como se indicó, esto cambiará todas las pestañas a espacios, no solo las pestañas al comienzo de la línea

Entonces esto (donde es un carácter de tabulación):

if :; do
⇥echo "⇥hello"
end

se cambia a (donde hay un espacio):

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

¡Esto puede producir efectos secundarios inesperados en algunos escenarios, y es aún más un problema al cambiar los espacios a pestañas!

Entonces, escribí una pequeña función para cambiar solo las pestañas / espacios al comienzo de la línea:

" :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

Con esta versión, debe especificar manualmente expandtaben la llamada de función (es decir, :call Retab(1)para cambiar las pestañas a espacios), pero también puede modificarlo para tomar el valor actual de &expandtab(como ya lo hace con &tabstop) al igual que lo :retabhace. (Prefiero especificarlo manualmente).

Martin Tournoij
fuente
66
También hay una respuesta en SO que cubre la reasignación solo al comienzo de la línea. Vale la pena vincular debido a la claridad de esa explicación.
jalanb
¿Alguien podría explicar qué significa letra aen if a:expandtab?
John CJ
Además, parece que las condiciones se invierten (una broma: ¿D?). Si tiene set expandtaben su .vimrc y luego autocmd BufWritePre * :call Retab(&expandtab), la sangría se cambiará a pestañas, en lugar de espacios.
John CJ
11

¡Vim proporciona un !retabcomando que reemplazará todas las secuencias de <Tab>con nuevas cadenas de espacio en blanco usando el nuevo valor de tabulación (por ejemplo :set tabstop=2) dado, pero todas las pestañas dentro de las cadenas se pueden modificar (por ejemplo, en un programa en C, debe usar \tpara evitar esto)!

De manera alternativa, puede cambiar todas las pestañas a espacios con el siguiente comando:

:%s/\t/  /g

o como lo sugiere @Shahbaz :

:%s/^\t\+/ g

Por lo tanto, solo las pestañas utilizadas en sangría se convierten.

Explicación:

  • %representa todo el búfer / archivo ( :help :%)
  • ssignifica sustituto ( :help sub-replace-special)
  • \t, o ^Isignifica pestaña
  • - use tantos espacios como necesite por una pestaña
  • g - significa global, y convertirá múltiples ocurrencias de pestañas en la misma línea

A continuación, para corregir la sangría de todo el archivo, puede intentar: gg=G. Verificación: Re-sangría de código mal sangrado para más detalles.

Para usar espacios de forma predeterminada en lugar de pestañas, debe agregar la siguiente configuración a su .vimrcarchivo:

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 >>)

La solución alternativa es usar tidy


Relacionado:

kenorb
fuente
1
Al menos lo haría %s/^\t\+/ gpara que solo se conviertan las pestañas utilizadas en la sangría. Además, gg=Gpodría ser catastrófico con lenguajes como Python.
Shahbaz
3

Intenta usar:

expand -t 4 input_filename output_filename

expandes una herramienta de línea de comandos para convertir pestañas en espacios, que puede ejecutar desde un shell o con :!expand.

Está en POSIX, por lo que debería estar disponible en la mayoría de los sistemas. unexpandhará lo contrario, por cierto.

Ankit Shah
fuente
2
¿Qué es expand?
Muru
Expandir es un comando de terminal incorporado para copiar caracteres de tabulación a espacios. Encuentre una descripción detallada en el siguiente enlace. computerhope.com/unix/uexpand.htm
Ankit Shah
2
Si se trata de comandos externos, debe mencionar eso.
Muru
Descripción adicional añadida. Por favor revise
Ankit Shah
55
También podría hacerlo :%!expand -t 4dentro de vim. Mejor aún, también podría usar la opción de ancho de turno actual: :exe '%!expand -t ' . &shiftwidth
EvergreenTree
1

Para completar, =también podría usarse para corregir sangrías, después de que haya especificado que las pestañas se reemplacen con espacios. En modo normal, puede hacerlo escribiendo :set expandtab. Entonces =podría usarse de dos maneras:

  • En el modo Visual, un solo =solucionaría las sangrías de los bloques de código seleccionados.
  • En el modo normal, gg=Garreglaría todo el archivo, donde ggmueve el cursor al comienzo del archivo, luego =se aplica y Gmueve el cursor al final del archivo.

Referencia: enlace

Samuel Li
fuente
Esto supone que vim puede volver a calcular correctamente la sangría actual (puede que no sea el caso) , también para archivos no estructurados o código escrito en un editor diferente con reglas de sangría ligeramente diferentes.
ideasman42
Gracias @ ideasman42; He agregado a la respuesta para ser más completo.
Samuel Li