Establezca la opción de pegar, pero solo para una inserción

16

Quiero tener una forma rápida de configurar la 'paste'opción Vim , insertar texto y volver al valor anterior de 'paste'.

Un caso de uso típico inserta el contenido del portapapeles del sistema operativo literalmente, independientemente de cualquier reescritura del modo de inserción que pueda estar activa, como la sangría automática, y sin cambiar el estado de Vim. Otro caso de uso sería permitir que una función de macro del sistema operativo inyecte pulsaciones de teclas en Vim y las interprete como texto literal.

Obviamente, esto se generaliza a otras opciones: la idea general es establecer algunas opciones, pero solo durante la duración de un viaje a través del modo de inserción.

Básicamente quiero vincular una secuencia de teclas (por ejemplo _i) a una macro que hace esto

:set paste
i…<Esc>
:set nopaste

donde i…<Esc>quiero decir cambiar al modo de inserción (como con el icomando) y reanudar la macro al regresar al modo de comando, excepto que quiero terminar con el 'paste'todavía activo si estaba activo de antemano. ¿Cómo puedo hacer esto?

Nota: El contenido del portapapeles del sistema operativo se asigna al "*registro . Cuando eso funciona, la 'paste'opción no es muy útil. El escenario motivador para esta pregunta es para aquellos momentos en que "*no se cumplen las condiciones para el soporte de registro: Vim no se compila con la +xterm_clipboardfunción, o se ejecuta en un terminal como Screen o sobre SSH que lo aísla del servidor ambiente X.

Gilles 'SO- deja de ser malvado'
fuente
1
Me gusta tu pregunta (he estado allí muchas veces). Sin embargo, ¿no es más fácil pegar desde +o *registrarse?
yo '
@yo ' Solo cuando trabajan . Lo cual, para mis usos de Vim, a menudo no es el caso.
Gilles 'SO- deja de ser malvado'

Respuestas:

15

Prueba esto:

function! Paste_Func()
    let s:inPaste = &paste
    if !s:inPaste
        set paste
    endif

    echom s:inPaste
    augroup paste_callback
        autocmd!
        autocmd InsertLeave <buffer> call Paste_End()
    augroup END

    startinsert
endfunction

function! Paste_End()
    augroup paste_callback
        autocmd!
    augroup END
    augroup! paste_callback

    if !s:inPaste
        set nopaste
    endif
endfunction

map _i :call Paste_Func()<cr>

Almacena su estado de pegado actual en la variable inPaste y establece pegar si aún no está configurado. Luego configura un autocmd para cuando abandonas el modo de inserción, y luego te pone en modo de inserción.

Cuando abandona el modo de inserción, ejecuta el autocmd, que primero elimina el autocmd (para que no se ejecute cuando abandona el modo de inserción de otra manera), y finalmente establece nopaste si originalmente no estaba en modo de pegado.

Además, si está utilizando vim en un terminal, puede echar un vistazo a vim-bracketed-paste , que utiliza la función de modo de pegado entre corchetes proporcionada por varios emuladores de terminal para detectar si está pegando y configurar el modo automáticamente.

Editar: reparó el guión

Chad
fuente
Esto parece en el camino correcto (en particular, no tenía idea de cómo "poner" un tramo de inserción mediante comandos mundiales normales). Gracias. Sin embargo, no está del todo bien y no veo dónde está el problema: después _i, la pasteopción está desactivada, incluso si estaba activa antes.
Gilles 'SO- deja de ser malvado'
¡Tienes razón! Estoy bastante seguro de haberlo probado, pero debo haber cambiado algo. He actualizado el guión en la publicación, vea si está funcionando para usted ahora.
Chad
4

excepto que quiero terminar con el 'paste'todavía activo si estaba activo de antemano.

'paste'debe estar activo por el menor tiempo posible. Inhabilita muchas funciones (incluidos los mapas), porque su único propósito es evitar malinterpretar el texto que se está pegando. Como tal, creo que el requisito citado no debería ser realmente necesario.

Dicho esto, en realidad es bastante fácil de pegar sin necesidad de configurarlo 'paste'. Si está ejecutando gvim o tiene +xterm_clipboarden la consola vim, simplemente puede usar "+ppara pegar desde el portapapeles del sistema operativo.

El problema de la sangría automática mientras se pega realmente solo ocurre en dos escenarios. Insertar el contenido de un registro mientras está en modo de inserción ( <C-r>+) o pegar con el botón central con el mouse.

En lugar de insertar el contenido de un registro mientras está en modo de inserción, pegar desde el registro en modo normal evitará el problema de formateo.

Si desea hacer clic con el botón central pegar con el mouse, use la 'mouse'opción para permitir que Vim, en lugar del terminal, maneje el clic central. Luego, Vim insertará el contenido literalmente en lugar de interpretar el texto entrante como si estuviera escrito.

jamessan
fuente
2
Nada de esto responde a mi pregunta. ¡Puse requisitos explícitos por una razón! Por 'paste'lo general, de hecho no está activo de antemano, pero no quiero tener que pensar en esto. A menudo trabajo en un Vim que no tiene acceso al portapapeles o mouse X, ya sea porque mi compilación de Vim no tiene la xterm_clipboardfunción o porque estoy trabajando, por ejemplo, en una sesión de pantalla que actualmente está conectada a un X terminal.
Gilles 'SO- deja de ser malvado'
@Gilles Entonces, ¿podrías explicar cómo estás pegando? Esa es información relevante para poder proporcionar una respuesta que pueda envolver esa acción con lo que desea hacer.
jamessan
1
Mi caso de uso básico es pegar con el botón central del mouse o con Shift + Insert. Sin embargo, eso no es realmente relevante: el núcleo de la pregunta es cómo configurar una opción, cambiar al modo de inserción (con i, no estoy preguntando cómo parametrizar esto) y restaurar el valor de la opción al regresar del modo de inserción.
Gilles 'SO- deja de ser malvado'
1
@Gilles El núcleo de su pregunta como se indica en este comentario es mucho más claro para mí que su pregunta original. Gracias.
jamessan
1
@Gilles No es relevante para usted , pero puede serlo para futuros visitantes. Por lo tanto, puede ponerlo en la pregunta en sí ("Sé que puedo usar "*po "+ppegar desde los portapapeles, pero no quiero usar las capacidades de pegado del sistema") y luego esta respuesta es innecesaria. O no, y creo que esta respuesta tiene su lugar aquí.
yo '
4

Personalmente, utilizo la yocombinación de teclas del excelente complemento vim-intacto de Tim Pope exactamente por esta razón. De su documentación:

No se ha proporcionado una alternancia para 'pegar' porque el caso de uso típico de envolver una inserción solitaria es muy derrochador: alternar dos veces, pero solo pegar una vez (YOPO). En su lugar, presione yoo yOpara invocar |o|o |O|con 'pegar' ya configurado. Al salir del modo de inserción, se establece 'nopaste' automáticamente.

Puede ser excesivo instalar el complemento simplemente por su pregunta, pero creo que también proporciona una gran cantidad de otras combinaciones de teclas útiles (más información en el archivo README ).

Andrew Ferrier
fuente
1

Con Vim 8+ en Linux o Mac, ahora puede simplemente usar la pasta nativa del terminal (por ejemplo, el botón central del mouse, ctrl+shift+Ven Gnome, cmd+Ven Mac) si el terminal admite pegado entre corchetes. No presione ipara el Modo Insertar.

Pegará el contenido del portapapeles de su sistema operativo, conservando los espacios y las pestañas sin agregar autoindenting. Es equivalente a la antigua :set paste, i, ctrl+shift+V, esc, :set nopastemétodo.

Ya ni siquiera necesita instalar las funciones +clipboardo +xterm_clipboardvim. Esta característica se llama "pasta entre corchetes". Para obtener más detalles, consulte /programming/2514445/turning-off-auto-indent-when-pasting-text-into-vim/56781763#56781763

wisbucky
fuente