Comment pourrais-je transmettre le contenu d'un registre Vim à un script externe?

1

En gros, je veux créer un opérateur dans un script Vim qui envoie le texte sélectionné à un script externe (Python). Il devrait se comporter comme on pourrait s'y attendre normalement, que le texte soit sélectionné en mode visuel ou qu'il utilise un mouvement. Cela s’est avéré plus difficile pour moi que je ne le pensais, et une des limites amusantes est que l’opérateur doit travailler sur les versions de Vim de 6.3 à 7.0. J'utilise la version console de Vim plutôt que GVim, car cela facilite mon processus de travail personnel.

Ma motivation: Je veux copier du texte dans le presse-papiers du système à partir de Vim (sans utiliser la souris), afin de pouvoir le coller dans un autre onglet de terminal. Frustrant, sur les systèmes avec lesquels je travaille, Vim a été compilé sans le support du presse-papiers, donc les registres "+ et" * ne m'aideront pas. Il est assez facile de combiner un script Python rapide pour mettre du texte arbitraire dans le presse-papiers, mais le problème est de passer le texte au script depuis Vim.

Ce que j'ai essayé Ma première idée a été d’extraire le texte, de créer un nouveau tampon, d’y insérer le texte, de le sauvegarder en tant que fichier dans / tmp et d’exécuter une commande du type "cat / tmp / stuff | clipboard.py". Plus spécifiquement: j'ai utilisé let scratchFile = system("mktemp") pour créer un fichier temporaire, badd pour ajouter le fichier en tant que tampon, et buffer pour passer au nouveau tampon. Je mets ensuite le texte sur lequel je travaille dans le tampon, l’écris, puis fais silent execute "!cat % | clipboard.py" suivi par bd se débarrasser du tampon. Cela ne marche pas vraiment. (Cela déforme la façon dont Vim dessine le contenu du fichier original à l'écran, de sorte que je dois surligner le fichier en mode visuel pour que le texte réapparaisse. :redraw ne résout pas le problème.)

Existe-t-il une meilleure approche pour résoudre ce problème?

Modifier pour ajouter mon script en cours:

nnoremap <C-y> :set operatorfunc=<SID>CopyClipboard<cr>g@
vnoremap <C-y> :<c-u>call <SID>CopyClipboard(visualmode())<cr>

function! s:CopyClipboard(type)
    let saved_register = @@

    if a:type ==? 'v'
        normal! `<v`>y
        let scratchFile = system("mktemp")
        execute "badd " . scratchFile
        execute "buffer " . scratchFile
        normal! P
        write
        silent execute "!cat % | clipboard.py"
        execute "bd! " . scratchFile
    elseif a:type ==# 'char'
        normal! `[v`]y
    else
        return
    endif

    let @@ = saved_register
endfunction
user108471
la source
Votre écran Vim est-il toujours perturbé si vous commentez temporairement la ligne 'exécution silencieuse "! Cat% | clipboard.py"'?
Heptite
Mis à part la question que je viens de poster, j'ai deux suggestions. Premièrement, je ne pense pas qu'il soit nécessaire d'utiliser à la fois "badd" et "buffer", cela devrait fonctionner uniquement avec "execute" "edit". fichier de travail '. Vous pouvez également utiliser une fenêtre fractionnée (remplacez "edit" par "split"). Deuxièmement, utilisez "bwipe" au lieu de "bdel".
Heptite

Réponses:

1

:buffer ouvrira un nouveau fichier temporaire au lieu du tampon actuel. Utilisation writefile() fonction à la place. Cela peut également aider à redessiner les problèmes.

Martian
la source
0

Je dirais qu'il existe plus d'une "bonne" façon de le faire, mais vos étapes pourraient éventuellement être simplifiées, en fonction de votre mise en œuvre.

Tout d’abord, vous pouvez écrire directement une plage de texte dans un fichier sans avoir à le faire. Si vous avez sélectionné du texte visuellement, appuyez simplement sur: pour insérer automatiquement la plage appropriée. Continuez à taper " w somefile ". Vim écrira dans le fichier (le créant si nécessaire) uniquement les lignes spécifiées par la plage dans ce fichier. Vous pourrez ensuite envoyer le texte à votre programme externe.

Deuxièmement, vous pouvez même écrire du texte directement dans un tuyau, au lieu d'écrire dans un fichier, puis d'appeler une commande, en utilisant " :w !command ". (N'oubliez pas votre portée, le cas échéant.)

Ces deux options, cependant, auront des problèmes avec la gestion par Vim de lignes complètes, plutôt que partielles, dans les plages de la ligne de commande: et des cas d'utilisation implicites, je dirais donc que votre approche initiale peut être plus appropriée. Sans voir votre mise en œuvre réelle, je ne peux pas trouver de raison solide pour déranger l'affichage de Vim - j'ai des idées, mais elles sont plus difficiles à expliquer dans l'abstrait que s'il y avait des exemples à utiliser.

Heptite
la source
Merci pour votre réponse. Oui, c’était la première chose à laquelle je pensais, mais je ne savais pas que vous pouviez écrire directement sur un tuyau de cette façon. Avec des plages de lignes saisissant des lignes entières à la fois, ce n'est pas vraiment approprié pour ce que j'aimerais faire. J'ai ajouté mon script à la question d'origine.
user108471