Définissez l'option de collage, mais pour une seule insertion


16

Je veux avoir un moyen rapide de définir l' 'paste'option Vim , d'insérer du texte et de revenir à la valeur précédente de 'paste'.

Un cas d'utilisation typique insère littéralement le contenu du presse-papiers du système d'exploitation, quelle que soit la réécriture du mode d'insertion qui peut être active, comme l'indentation automatique, et sans changer l'état de Vim. Un autre cas d'utilisation serait de permettre à une fonction de macro du système d'exploitation d'injecter des touches dans Vim et de les faire interpréter comme du texte littéral.

Cela se généralise évidemment à d'autres options - l'idée générale est de définir certaines options mais uniquement pour la durée d'un trajet en mode insertion.

Fondamentalement, je veux lier une séquence de touches (disons _i) à une macro qui fait cela

:set paste
i…<Esc>
:set nopaste

i…<Esc>je veux dire passer en mode insertion (comme avec la icommande) et reprendre la macro au retour en mode commande, sauf que je veux finir avec le 'paste'toujours actif s'il était actif auparavant. Comment puis-je faire ceci?

Remarque: Le contenu du presse-papiers du système d'exploitation est mappé sur le "*registre . Lorsque cela fonctionne, l' 'paste'option n'est pas très utile. Le scénario motivant pour cette question est pour les moments où les conditions de "*prise en charge de l'enregistrement ne sont pas remplies - Vim n'est pas compilé avec la +xterm_clipboardfonctionnalité, ou il s'exécute dans un terminal tel que Screen ou sur SSH qui l'isole du serveur X ambiant.


1
J'aime ta question (j'y suis allée plusieurs fois moi-même). Cependant, n'est-il pas plus facile de coller à partir de +ou de vous *inscrire?
yo '

@yo ' Seulement quand ils travaillent . Ce qui, pour mes utilisations de Vim, n'est souvent pas le cas.
Gilles 'SO- arrête d'être méchant'

Réponses:


15

Essayez ceci:

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>

Il stocke votre état de collage actuel dans la variable inPaste et définit le collage s'il n'est pas déjà défini. Ensuite, il configure un autocmd lorsque vous quittez le mode d'insertion, puis vous met en mode d'insertion.

Lorsque vous quittez le mode d'insertion, il exécute l'autocmd, qui supprime d'abord l'autocmd (de sorte qu'il ne s'exécute pas lorsque vous quittez le mode d'insertion d'une autre manière), et définit enfin nopaste si vous n'étiez pas en mode collage à l'origine.

De plus, si vous utilisez vim dans un terminal, vous voudrez peut-être jeter un œil à vim-bracketed-paste , qui utilise la fonction de mode de collage entre crochets fournie par plusieurs émulateurs de terminal pour détecter si vous collez et définir le mode automatiquement.

Edit: correction du script


Cela semble sur la bonne voie (en particulier, je n'avais aucune idée de la façon de "crocheter" un tronçon d'insertion par des commandes universelles normales). Merci. Cependant, ce n'est pas tout à fait raison et je ne vois pas où est le problème: après _i, l' pasteoption est désactivée, même si elle était activée avant.
Gilles 'SO- arrête d'être méchant'

Tu as raison! Je suis presque sûr d'avoir testé cela, mais j'ai dû changer quelque chose. J'ai mis à jour le script dans le message, voyez s'il fonctionne pour vous maintenant.
Chad

4

sauf que je veux finir avec le 'paste'toujours actif s'il était actif au préalable.

'paste'doit être actif aussi longtemps que possible. Il désactive de nombreuses fonctionnalités (y compris les cartes), car son seul but est d'éviter une mauvaise interprétation du texte collé. En tant que tel, je pense que l'exigence citée ne devrait pas vraiment être nécessaire.

Cela étant dit, il est en fait assez facile de coller sans avoir besoin de définir 'paste'. Si vous exécutez gvim ou avez +xterm_clipboarddans la console vim, vous pouvez simplement utiliser "+ppour coller à partir du presse-papiers du système d'exploitation.

Le problème de l'indentation automatique lors du collage ne se produit vraiment que dans deux scénarios. Insérer le contenu d'un registre en mode insertion ( <C-r>+) ou cliquer avec le bouton du milieu avec la souris.

Au lieu d'insérer le contenu d'un registre en mode insertion, le collage à partir du registre en mode normal évitera le problème de reformatage.

Si vous souhaitez cliquer avec le bouton du milieu avec la souris, utilisez l' 'mouse'option pour laisser Vim, au lieu du terminal, gérer le clic du milieu. Vim insérera alors le contenu littéralement au lieu d'interpréter le texte entrant comme étant tapé.


2
Rien de tout cela ne répond à ma question. J'ai mis des exigences explicites pour une raison! Habituellement 'paste'n'est en effet pas actif au préalable, mais je ne veux pas avoir à y penser. Je travaille souvent dans un Vim qui n'a pas accès au presse-papiers ou à la souris X, soit parce que ma build Vim n'a pas la xterm_clipboardfonctionnalité, soit parce que je travaille par exemple dans une session Screen qui est actuellement attachée à un Terminal X.
Gilles 'SO- arrête d'être méchant'

@ Gilles Alors pourriez-vous expliquer comment vous collez? Ce sont des informations pertinentes pour pouvoir fournir une réponse qui peut envelopper cette action avec ce que vous voulez faire.
jamessan

1
Mon cas d'utilisation de base est de coller avec le bouton central de la souris ou avec Shift + Insert. Ce n'est pas vraiment pertinent cependant: le cœur de la question est de savoir comment définir une option, passer en mode insertion (avec i, je ne demande pas comment paramétrer cela), et restaurer la valeur de l'option au retour du mode insertion.
Gilles 'SO- arrête d'être méchant'

1
@Gilles Le cœur de votre question, comme indiqué dans ce commentaire, est beaucoup plus clair pour moi que votre question d'origine. Merci.
jamessan

1
@Gilles Cela ne vous concerne pas , mais il peut l'être pour les futurs visiteurs. Par conséquent, soit vous pouvez le mettre dans la question elle-même ("Je sais que je peux utiliser "*pou "+pcoller à partir des presse-papiers, mais je ne veux pas utiliser les capacités de collage du système"), puis cette réponse est inutile. Ou vous ne le faites pas, et je pense que cette réponse a sa place ici.
yo '

4

Personnellement, j'utilise le yoraccourci clavier de l'excellent plugin vim- unimpaired de Tim Pope pour exactement cette raison. D'après sa documentation:

Une bascule n'a pas été fournie pour la «pâte» car le cas d'utilisation typique de l'emballage d'une insertion solitaire est si inutile: vous basculez deux fois, mais vous ne collez qu'une seule fois (YOPO). Au lieu de cela, appuyez sur yoou yOpour appeler |o|ou |O|avec «coller» déjà défini. Le fait de quitter le mode d'insertion définit automatiquement «nopaste».

Il peut être exagéré d'installer le plugin simplement pour votre question, mais je trouve qu'il fournit également une multitude d'autres raccourcis clavier utiles (plus d'informations dans le fichier README ).


1

Avec Vim 8+ sur Linux ou Mac, vous pouvez maintenant simplement utiliser la pâte native du terminal (par exemple le bouton central de la souris, ctrl+shift+Vdans Gnome, cmd+Vsur Mac) si le terminal prend en charge la pâte entre crochets. N'appuyez pas ipour le mode d'insertion.

Il collera le contenu de votre presse-papiers du système d'exploitation, en préservant les espaces et les tabulations sans ajouter d'indentation automatique. Il est équivalent à l'ancienne :set paste, i, ctrl+shift+V, esc, :set nopasteméthode.

Vous n'avez même plus besoin d'installer les fonctionnalités +clipboardou +xterm_clipboardvim. Cette fonction est appelée "coller entre crochets". Pour plus de détails, voir /programming/2514445/turning-off-auto-indent-when-pasting-text-into-vim/56781763#56781763

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.