¿Puedo unir líneas con una coma (u otro carácter)?

19

Sé que puedo unir líneas en Vim con Jy varias variantes de las mismas ( gJ, etc.); Jserá "Eliminar el guión e insertar hasta dos espacios" .

Pero, ¿hay también una forma directa de insertar otro personaje en lugar de los dos espacios? Por ejemplo, una coma ( ,) o coma y espacio ( ,)?

Dado:

8
9
10
32

Me gustaría terminar con:

8, 9, 10, 32

o:

8,9,10,32
Martin Tournoij
fuente
También le puede gustar github.com/sk1418/Join (no probado).
VanLaser

Respuestas:

5

Escribí un plugin Join, puedo hacer lo que quieras y mucho más.

Excepto por todas las características proporcionadas por el comando incorporado: join, Join puede:

  • Unir líneas con separador (cadena)
  • Unir líneas con o sin recortar los espacios en blanco iniciales / finales
  • Unir líneas con recuento negativo (unir hacia atrás)
  • Unir líneas en reversa
  • Unir líneas y mantener líneas unidas (sin eliminar líneas unidas)
  • Une líneas con cualquier combinación de las opciones anteriores

Más detalles y capturas de pantalla:

https://github.com/sk1418/Join

Kent
fuente
23

Una manera simple es esta: simplemente seleccione sus líneas (todas menos la última), o use %, y ejecute:

:'<,'>s/\n/,/

o

:'<,'>s/\n/, /

(donde, por supuesto, la '<,'>parte ya fue insertada después :por Vim, para apuntar a la selección)


(2º) Actualización:

Sobre la base de lo anterior (y el comentario de Sato Katsura ), aquí hay una posible implementación de "unión interactiva", con conteo y soporte de repetición opcional:

" ================ script ===============================================
" interactive 'J', 'gJ' replacement with optional 'vim-repeat' support
" The last used separator is automatically reused as:
" a. default choice
" b. when repeating (=> non-interactive repeats: same range, same separator)
let g:last_join_separator = " "
function! s:interactiveJoin(use_last_sep,...) range
    if (a:use_last_sep == 0) "interactive, ask for separator to use
        call inputsave()
        echohl Question
        let l:sep = input("Separator:", g:last_join_separator)
        echohl None
        call inputrestore()
        redraw!
        let g:last_join_separator = l:sep "update last separator value
    else "non-interactive (when repeating with '.')
        let l:sep = g:last_join_separator
    endif
    if (a:0 == 0) "with no argument, remove indentation *and trailing spaces*
        let l:subst = 's/\s*\n\+\s*/\=' . "'" . l:sep . "'/"
    else " don't remove indentation or trailing spaces (act like 'gJ')
        let l:subst = 's/\n\+/\=' . "'" . l:sep . "'/"
    endif
    if a:firstline < a:lastline "join given range
        execute a:firstline . ',' . (a:lastline - 1) . l:subst
        let l:count = a:lastline - a:firstline + 1 "default count for repeat
    else "or join only with next line
        execute l:subst
        let l:count = 1 "default count for repeat
    endif
    "make command repeatable
    "(with the tpope/vim-repeat plugin: optional, recommended)
    if (a:0 == 0)
        silent! call repeat#set("\<Plug>(repeatJoin)", l:count)
    else
        silent! call repeat#set("\<Plug>(repeatGJoin)", l:count)
    endif
endfunction

noremap <silent> <Plug>(interactiveJoin)  :call <SID>interactiveJoin(0)<CR>
noremap <silent> <Plug>(interactiveGJoin) :call <SID>interactiveJoin(0,'g')<CR>
noremap <silent> <Plug>(repeatJoin)       :call <SID>interactiveJoin(1)<CR>
noremap <silent> <Plug>(repeatGJoin)      :call <SID>interactiveJoin(1,'g')<CR>

Y un mapeo real:

"================= vimrc ================================================
nmap J <Plug>(interactiveJoin)
xmap J <Plug>(interactiveJoin)
nmap gJ <Plug>(interactiveGJoin)
xmap gJ <Plug>(interactiveGJoin)

Esto es un poco (*) como J, pero interactivo: solicitará la cadena de separación. La cadena predeterminada es un espacio; por ejemplo, para unir líneas sin separador, presione Backspacecuando se le solicite, para eliminar el carácter de espacio predeterminado y Enterpara aceptar el separador vacío (ahora). Contar, por ejemplo 3J, también funciona. Si el tpope/vim-repeatcomplemento está instalado, repita con '.' también funcionará, reutilizando el último separador y (si no se modifica, por ejemplo 10.) el último recuento o rango de línea visual.


(*) Sin embargo, no es exactamente así J: aunque eliminará la sangría, no buscará .!?(fin de la frase) para insertar 2 espacios en lugar de uno, o inserta un espacio solo si falta (es difícil hacer algo como esto, ya que la cadena de separación puede ser cualquier cosa ahora). También eliminará los espacios finales (tiene más sentido).

Creo que esta podría ser una buena manera de sobrecargar el espacio limitado de letras de los operadores :)

Bueno, técnicamente Jno es un operador, pero está cerca de uno, por ejemplo, no se puede hacer Jaw, para unir "una palabra".

(sugerencias son bienvenidas)

ingrese la descripción de la imagen aquí

VanLaser
fuente
2
Mejor aún: :'<,'>-1s/\n/, /para líneas marcadas o :1,$-1s/\n/, /para todo el archivo.
Sato Katsura
De hecho, eso es aún mejor :)
VanLaser
@SatoKatsura, ¿puedes explicarme -1?
alxndr
1
@alxndr: se usa para omitir la última línea en el rango / archivo: por ejemplo, en el ejemplo de OP, no desea una coma después de 32, y tampoco desea unirla con la siguiente línea, si existe . Incluso puedes usar '<,'>-s/\n/, /o 1,$-s/\n/, /as -es lo mismo que -1.
VanLaser
1
Si l:sepes un &, entonces su reemplazo funcionará incorrectamente, ya que &es mágico en el reemplazo. Podría ser mejor usar el \=para usar una cadena literal let l:subst = 's/\n\+/\=' . "'" . l:sep . "'/"- en lugar de tratar de manejar el escape.
jamessan
3

Aquí hay un ejemplo usando un comando externo:

:%!paste -sd,

donde %!reemplaza el búfer actual (contenido del archivo) con el comando: paste -sd,(los parámetros -sse utilizan para unir varias líneas y -destablece el carácter delimitador en ,).

kenorb
fuente
3

En caso de que a alguien no le guste escribir Regex y memorizar más comandos Ex Plugin:

Bloque visual Agregar

Visual-block Append está disponible en el modo Visual Block ( <C-v>) y puede hacer un bloque A ppend (y el bloque I nsert para prepend). (ref: :help v_b_A, :help v_b_I)

Y si el último movimiento en el Modo visual de bloque es $, la adición se realizará al final de todas las selecciones; o de lo contrario se insertarán espacios antes del texto que agregó (imagine alinear el cierre )al final de varias llamadas a métodos en el código).

Con el texto de muestra a continuación y el cursor encendido 8:

8
9
10
12

<C-v>}$A,<C-c>. Después de volver al modo normal, podemos ver que ,se agrega a todas las líneas seleccionadas. (Prueba sin $)

Luego haga gvpara volver a seleccionar el área y Jo gJ. Tenemos un rastro ,: 8,9,10,12,y $xhemos terminado.

Use Insertar sin seguimiento ,

Vamos a deshacer nuestro texto (ya sea uu..uelegante :ea 1d<cr>:lat 1) e intentemos Visual Insert:

j<C-v>}I, <C-c>y luego podemos unir las líneas gJsin espacios.

Espera espera espera, falta algo. ¿Cómo volver a seleccionar toda la "matriz"? Esta vez no seleccionamos la primera línea ... así gvque no ayuda.

- O puede ayudar, gvokes volver a seleccionar ( gv), oesquina opuesta y karriba.

PD: Mi meñique no es lo suficientemente rápido y preciso para escribir , /\por /\nlo que me gusta combinar las operaciones y los movimientos integrados de Vim para evitar el uso de Regex. Sin embargo, si hago esto con suficiente frecuencia, usar un mapeo, tal vez los que se mapean a complementos deberían ser mejores.

Sunny Pun
fuente
1

Una forma mucho más simple sin complementos o comandos externos para reasignar join ( J) desde un espacio a cualquier personaje que desee. Por ejemplo, para unirse con una coma y un espacio:

:nmap J :s/\n/, /^M

Para el carácter especial nueva línea al final ( ^M) presione Ctrl-Vy luego Retorno / Entrar. Lo mismo ocurre si desea reemplazar con una pestaña ( ^I), escriba Ctrl-Ientonces Tab.

:nmap J :s/\n/^I/^M

Lo que está haciendo es reemplazar una nueva línea con una pestaña en la línea actual y reasignar ese comportamiento al carácter J.

Esto también funciona con combinaciones, como 4Jpara unir las siguientes 4 líneas.

Wes Modes
fuente
0

Puede grabar una macro para unir líneas con una coma. Esto es útil si es una tarea rara o única, y no puede recordar cómo escribir un comando sustituto y una expresión regular para realizar la tarea, pero sí recuerda cómo grabar y ejecutar una macro.

Para unir líneas con una coma, escriba qjgJi,Escqpara grabar la macro en el registro j. Entonces puede ejecutar la macro con @j. Puede volver a ejecutar la macro con @@, lo que ahorra al escribir al ejecutarla varias veces seguidas; incluso puede mantener presionada la tecla @hasta llegar al final de las líneas que desea unir. También puede usar un prefijo numérico @jo @@repetirlo varias veces. Esto deja el espacio inicial y final intacto, por lo que habrá espacios antes o después de la coma si el texto original tenía espacios allí.

Para unir con una coma y un espacio, inserte Spaceentre ,y Esccuando grabe la macro.

También puede usarlo en Jlugar de gJcuando graba la macro, que generalmente unirá líneas con una coma y un espacio. Sin embargo, si la línea actual tiene espacios en blanco al final, la coma aparecerá después del espacio en blanco sin un espacio a continuación. También, que no incluye el espacio si la siguiente línea comienza con ), y pone dos espacios después de la coma si joinspacesse establece y los extremos de la línea de corriente con ., !o ?. Estas advertencias se describen a continuación :help J.

Lithis
fuente