2011-09-23 19 views
10

Usar Vim Soy realmente un fan del modo visual que le permite insertar texto antes de una columna.Insertar sangría para columnas en Vim

insertar algunas separación después de las flechas,

> one 
> two 
> three 

se puede hacer a través de <Ctrl-V>jjI <Esc>:

> one 
> two 
> three 
  • ir al modo visual <Ctrl-V>,
  • extienden selección visual jj,
  • inserta algunos espacios I__,
  • propagar el cambio a todas las líneas de selección visual en forma de bloques <Esc>

Ahora tengo un archivo de texto que necesita algo de formato. Esto es lo que parece:

start() -- xxx 
initialize() -- xxx 
go() -- xxx 

Ahora quiero alinear parte de este texto para organizar en columnas como esta:

start()  -- xxx 
initialize() -- xxx 
go()   -- xxx 

El problema que tengo es que no puedo insertar una cantidad diferente de sangría en cada línea y simplemente sangría una cantidad fija de espacios/pestañas es insuficiente. ¿Cómo se puede hacer una sangría donde todo el texto sangrado tendrá que estar alineado en la misma columna?


EDIT: Yo sólo di cuenta de un método bastante detallado y difícil de manejar:

  • encontrar la posición de la cadena de guión a partir de: \--,
  • inserto n (digamos 20) espacios antes de que: 20i <Esc>,
  • eliminar una parte de los espacios de nuevo a una determinada columna (digamos 15): d|15,
  • guardar esos pasos como una macro y repita la macro tantas veces como sea necesario,

... muy feo, sin embargo!

+0

posible duplicado de [¿Cómo insertar espacios hasta la columna X para alinear elementos en columnas?] (Http://stackoverflow.com/questions/6154306/how-to-insert-spaces-up-to-column- x-to-line-up-things-in-columns) – DocMax

Respuesta

14

Estoy mucho mejor sin ningún complemento de vim. Aquí está mi solución:

<Shift-V>jj:!column -ts --

Luego inserte -- en varias líneas del mismo modo que escribió en la pregunta.


También puede agregar un número de comentarios en el momento de la inserción.

:set virtualedit=all

<Ctrl-V>jjA-- xxx<Esc>

+2

Esta es, por supuesto, la forma en que debería hacerlo en el momento de la inserción. +1. – Benoit

+0

no funcionará en mi caso ... las partes '--- xxx' en cada línea comienzan en columnas diferentes. Por lo tanto, no puede alinear las partes de edición de su selección visual. (El archivo que necesito editar ya tiene esta estructura y necesito volver a formatearlo en consecuencia) – oliver

+1

¿Trabajas en * nix? Si es así, puedes probar el comando 'column' dentro de Vim. ' jj:! Columns -ts --', luego inserte' --' en las líneas múltiples que desee. – ernix

4

Tienes que usar un complemento específico, puedes usar el plugin Tabular o Align en este caso.

Ambos le permiten alinear texto en caracteres específicos, como -- en su ejemplo. Sin embargo, su sintaxis es un poco diferente. Elija el que más le convenga.

+0

acaba de instalar Tabular y funciona correctamente. Agradable ... a pesar de que esperaba que esta pequeña tarea no implique la instalación de un complemento. ¡Gracias por la sugerencia! – oliver

+0

@oliver: es posible resolver esta tarea sin la necesidad de instalar un complemento. La solución no es tan compacta como cuando se usa uno de esos complementos. –

3

Sin plugin y si ya ha entrado en sus comentarios sin solución de emix:

:,+2 s/--/         & 

Esto asegurará todos los comentarios han de ser desplazado leftwise con el fin de alinearlos correctamente.

A continuación, a modo de bloques seleccione la columna a la que desea alinear el texto, y: 100<

+0

Agradable y simple. ¡Gusta! – oliver

+0

Además, considere ':, 2s/\ ze -/\ = repeat ('', 32)'. –

+0

@ib .: esto también es bueno, pero dependiendo de la configuración del teclado, ¡puede ser más lento escribir! – Benoit

3

Una manera fácil de alinear el texto en columnas es utilizar Tabular o Align plugin. Si ninguno de estos está listo, se pueden usar los siguientes comandos un tanto complicados (y un poco engorrosos) pero perfectamente operativos (para el caso en cuestión). 1,2

:let m=0|g/\ze -- /let m=max([m,searchpos(@/,'c')[1]]) 
:%s//\=repeat(' ',m-col('.')) 

El propósito de la primera comando es para determinar el ancho de la columna para la izquierda del separador (que supongo que ser -- aquí). El ancho es calculado como un máximo de las longitudes del texto en la primera columna entre todas las líneas. El comando :global se usa para enumerar las líneas que contienen el separador (las otras líneas no requieren alineación). El átomo \ze ubicado justo después del comienzo del patrón, establece el final de la coincidencia en la misma posición donde se inicia (consulte :help \ze). Cambiar los bordes de la coincidencia no afecta la forma en que funciona el comando :global, el patrón está escrito de tal manera que coincida con las necesidades del siguiente comando de sustitución : dado que estos dos comandos podrían compartir el mismo patrón, ser omitido en el segundo.

El comando que se ejecuta en las líneas coincidentes,

:let m=max([m,searchpos(@/,'c')[1]]) 

llama a la función searchpos() para buscar el patrón utilizado en la matriz :global comando, y para obtener la posición de la columna del partido. El patrón se conoce como @/ utilizando el último registro de patrón de búsqueda (consulte :help "/). Esto aprovecha el hecho de que el comando :global actualiza el registro / tan pronto como comienza a ejecutarse. La bandera c pasado como el segundo argumento en la llamada searchpos() permite que el partido en el primer carácter de una línea (:global posiciones del cursor en el comienzo mismo de la línea para ejecutar un comando en), ya que podría ser que hay no hay texto a la izquierda del separador. La función searchpos() devuelve una lista, el primer elemento es el número de línea de la posición coincidente, y el segundo es la posición de la columna.Si el comando se ejecuta en una línea, la línea coincide con el patrón del comando :global que lo contiene. Como searchpos() es para buscar el mismo patrón, definitivamente hay una coincidencia en esa línea. Por lo tanto, solo la columna que inicia la coincidencia está interesada, por lo que se obtiene extraído de la lista de devolución por el subíndice [1]. Esta misma posición es igual al ancho del texto en la primera columna de la línea, más uno. Por lo tanto, m se establece al máximo de su valor actual y esa posición de columna.

El segundo comando,

:%s//\=repeat(' ',m-col('.')) 

almohadillas de la primera ocurrencia del separador en todas las líneas que contienen que, con el número de espacios que falta para que el texto antes del separador para tomar m caracteres, menos uno. Este comando es un sustitución global de la sustitución de un intervalo vacío justo antes de que el separador (ver el comentario sobre el comando :global arriba) con el resultado de la evaluación de la expresión (ver :help sub-replace-\=)

repeat(' ',m-col('.')) 

Los repeat() repeticiones de funciones su primer argumento (como cadena) el número de veces dado en el segundo argumento. Como en cada sustitución el cursor es movido al inicio de la coincidencia de patrón, m-col('.') es exactamente igual al cantidad de espacios necesarios para desplazar el separador a la derecha para alinear las columnas (col('.') devuelve la posición actual de la columna del cursor).


continuación es una versión de una línea de este par de comandos.

:let m=0|exe'g/\ze -- /let m=max([m,searchpos(@/,"c")[1]])'|%s//\=repeat(' ',m-col('.')) 

En revisiones anteriores de la respuesta de los comandos usados ​​para ser tan sigue.

:let p=[0]|%s/^\ze\(.*\) -- /\=map(p,'max([v:val,len(submatch(1))+1])')[1:0]/ 
:exe'%s/\ze\%<'.p[0].'c -- /\=repeat(" ",'.p[0].'-col("."))' 

Aquellos que estén interesados ​​en estos comandos particulares pueden encontrar Descripción detallada en la historia de las ediciones.

+1

wow ... parece un poco complicado! ¿Te importaría explicar tu solución? – oliver

+0

@oliver: Claro. He agregado una explicación detallada a la respuesta. –

+0

gracias por la explicación detallada! aunque no creo que use esto (NUNCA podría recordar :) en la práctica, realmente disfruté leyendo su respuesta y seguramente aprendí algunas cosas sobre vim ... otra vez! – oliver

0

Esta es una modificación en la respuesta de Benoit que tiene dos pasos.

Primer paso, bloquear la selección de texto buscar y reemplazar - con un montón de espacios.

'<,'>s/--/       --/ 

Ahora todos los comentarios deberían tener un montón de espacios, pero aún así ser desigual.

Segundo paso, bloquee de nuevo el texto y use otra expresión regular para unir todos los caracteres que quiera conservar (digamos los primeros 20 caracteres o más) más todos los espacios siguientes, y reemplácelo con una copia de los primeros 20 caracteres:

'<,'>s/\(.\{20}\)\s*/\1/ 

No es tan fácil como Benoit, pero no pude entender cómo hacer que su segundo paso funcione.

Cuestiones relacionadas