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
la source
Réponses:
:buffer
ouvrira un nouveau fichier temporaire au lieu du tampon actuel. Utilisationwritefile()
fonction à la place. Cela peut également aider à redessiner les problèmes.la source
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.
la source