OVH Cloud OVH Cloud

Question (un peu pointue) sur vim et le presse-papier

9 réponses
Avatar
Francois Lafont
Bonjour à tous,

J'ai une question sur vim et le presse-papier. Attention,
c'est une question précise, d'aucuns diraient même
insignifiante, voire carrément chiante :) mais bon... je
n'arrive pas à comprendre correctement le fonctionnement
de vim avec le presse-papier alors peut-être que quelqu'un
pourra m'aider ici.

J'utilise la version de vim packagée sous Debian Jessie,
ie la version 7.4. J'ai bien installé vim-gtk afin que
mon vim soit « connecté » au serveur X et que je puisse
interagir avec le(s) presse-papier(s).

~$ readlink -f /usr/bin/vim
/usr/bin/vim.gtk

~$ vim --version | grep -F '+clipboard'
+clipboard +iconv +path_extra +toolbar

Si j'ai bien compris (surtout merci de me rectifier si
je me trompe), mon vim interagit avec 2 « sélections »
(c'est le nom utilisé dans les documentations pour parler
des presse-papiers de X11) répondant aux doux noms de :

- la PRIMARY sélection qui va contenir a priori
tout ce qui est texte sélectionné avec la souris
et qu'on pourra coller avec un clic sur la molette
de la souris. Ce sont des copies qui se font de
manière automatique sans que l'utilisateur le
demande explicitement.

- la CLIPBOARD sélection qui va contenir a priori
tout ce qui est texte copié via l'environnement
graphique (ie via un clic droit => "Copier"),
autrement dit du texte copié par une action
consciente de l'utilisateur

Il semble que la gestion de PRIMARY et de CLIPBOARD
peut dépendre d'une application à l'autre mais dans
le cas de vim ça semble correspondre à ce qu'il y a
ci-dessus.

Enfin, dans vim, si j'en crois la doc, on a 2 registers
pour interagir avec les sélections PRIMARY et CLIPBOARD
de vim :

- le register + permet d'accéder à la sélection CLIPBORAD
avec "+y pour y copier une sélection de texte
faite avec vim en visual mode, et "+p pour coller
le contenu de CLIPBOARD dans vim.

- le register * permet d'accéder à la sélection PRIMARY
avec "+y pour y copier une sélection de texte
faite avec vim en visual mode, et "+p pour coller
le contenu de PRIMARY dans vim.

J'en viens à ce qui me préoccupe. Je précise que j'ai
fait mes tests avec aucune conf particulière pour vim,
tout par défaut (je n'ai pas de ~/.vimrc - enfin pour
ces tests - ni de répertoire ~/.vim/).

J'ouvre vim dans un terminal (j'utilise terminator) et
je tape le texte :

Salut tout le monde !

Ensuite, je fais une sélection de ce texte via le mode
visual de vim. À ce moment là, je viens de sélectionner
du texte avec vim, donc mon texte devrait se trouver
dans la sélection PRIMARY. Pour le tester, je vais par
exemple dans une fenêtre de mon client de mails (Thunderbird
en l'occurrence) et je tente un clic de la molette de ma
souris et j'ai bien le texte « Salut tout le monde ! »
qui est collé dans la fenêtre. Donc PRIMARY a bien été
remplie.

Ensuite je retourne dans vim où ma sélection en visual
mode est en cours. Et là je fais, "+y ce qui copie mon
texte dans CLIPBOARD. Je vais le test et retourne sur
ma fenêtre Thunderbird, je fais un clic droit "Coller"
et j'ai bien mon texte qui est collé. Donc jusqu'ici
tout va bien, les sélections PRIMARY et CLIPBOARD ce
sont comportées comme je l'imaginais et à ce moment
là elles contiennent toutes les deux mon texte.

Maintenant, dernier test (c'est là que je pige pas).
Je refais la même procédure que ci-dessus, sauf je vais
tester sur Thunderbird à la fin _après_ le "+y dans vim.
J'ouvre donc vim et je sélectionne du texte en mode visual
puis je fais "+y. À ce stade, je me dis que :

1. comme j'ai fait une sélection de texte, je devrais
avoir PRIMARY qui contient mon texte
2. comme j'ai fait "+y , je dois avoir aussi mon texte
dans CLIPBOARD.

Je teste dans une fenêtre de mon Thunderbird et là j'ai
bien le clic droit "Coller" qui m'affiche mon texte
donc CLIPBOARD est rempli comme il se doit mais par
contre un clic de la molette de la souris ne colle rien,
PRIMARY est vide.

Ma question est pourquoi ? :)

Vous allez me dire « mais c'est parce qu'après ton "+y
la sélection du texte disparaît » (et c'est vrai qu'elle
disparaît cette sélection après le "+y) mais c'est quand
même ma dernière sélection en date, et donc PRIMARY devrait
la contenir, non ?

D'ailleurs, si je fais une sélection d'un texte sous vim
en mode visual et qu'ensuite je fait disparaître cette
sélection avec ECHAP et bien j'ai bien PRIMARY qui contient
encore cette sélection (comme je peux le vérifier avec un
clic de la molette de la souris sur une fenêtre Thunberbird).
Donc, pour moi, la dernière sélection de texte faite par
vim, qu'elle soit en toujours cours ou non, devrait se trouver
dans PRIMARY (et donc devrait pouvoir se coller avec un
clic de la molette de la souris). Et pourtant ce n'est pas
le cas après un enchaînement sous vim « sélection puis "+y ».
Par contre, dans le premier test où j'ai fait un clic-molette
entre le moment de la sélection sous vim et le moment du "+y
là PRIMARY n'est pas vide, même après le "+y.

Je résume :

Test1:
a. sélection d'un texte sous vim en mode visual
b. texte collé avec succès via un clic-molette
c. retour sur vim et au niveau de la sélection
en cours "+y.
d. Je constate ensuite qu'un clic-molette me
retourne toujours le texte, PRIMARY n'est pas
vide.

Test2:
a. sélection d'un texte sous vim en mode visual
b. je reste sous vim et je fais "+y
c. Je constate ensuite qu'un clic-molette
ne me retourne rien, PRIMARY est vide.

Pourquoi PRIMARY est vide dans le test2 ?

Voilà. Si vous avez des éléments pour que je comprenne
le mécanisme, vraiment je suis preneur. En soi, le problème
n'est pas bien grave, on pourrait même dire insignifiant.
Mais bon, vim c'est quand même un peu mon pain quotidien
alors j'aimerais bien comprendre. :)

Si vous m'avez lu jusqu'au bout et bien chapeau, et je
vous en remercie.

Merci d'avance pour votre aide.

--
François Lafont

9 réponses

Avatar
Benoit Izac
Bonjour,
Le 03/09/2017 à 18:46, Francois Lafont a écrit dans le message
<59ac31d6$0$3308$ :
[...]
Si vous m'avez lu jusqu'au bout et bien chapeau, et je
vous en remercie.

Pas de quoi, j'ai lu en diagonale. ;-)
Juste pour dire que tu peux savoir ce qu'il y a réellement dans les
sélections avec xsel :
for sel in primary secondary clipboard; do
printf ' %s: %sn' $sel "$(xsel --$sel --output)"
done
Tu peux aussi les vider avant tes tests avec xsel --$sel --clear.
Un peu de lecture ici <https://www.x.org/docs/ICCCM/icccm.pdf> (2.6.1).
--
Benoit Izac
Avatar
Francois Lafont
Salut,
On 09/03/2017 10:41 PM, Benoit Izac wrote:
Pas de quoi, j'ai lu en diagonale. ;-)

ah ok. :)
Juste pour dire que tu peux savoir ce qu'il y a réellement dans les
sélections avec xsel :
for sel in primary secondary clipboard; do
printf ' %s: %sn' $sel "$(xsel --$sel --output)"
done
Tu peux aussi les vider avant tes tests avec xsel --$sel --clear.

Merci pour l'info mais j'avais vu cette commande et j'avais
aussi fait mes tests avec xsel justement. Ce que j'obtiens
coïncide parfaitement avec ce que je constate en utilisant
le clic-molette et le clic-droit/Coller dans une fenêtre.
Mais c'est vrai qu'on gagne du temps à tester en ligne de
commande, c'est très pratique, sachant donc que :
* xsel --primary --output => revient à faire clic-molette
* xsel --clipboard --ouptput => revient à faire un clic-droit/Coller
Si tu veux, dit en mode ligne de commandes (ce qui est sans
aucun doute plus concis), ce qui m'interroge est la chose suivante.
À chaque fois je pars avec des sélections vides:
# Le contenu est ce qu'il y a dans les crochets.
~$ /tmp/print-xsel.sh
PRIMARY contains ==>[]<= CLIPBOARD contains ==>[]<=
Test1
a. j'ouvre un vim et je sélectionne du texte en mode visual
(le texte est "Salut").
b. Je lance le script « xsel » pour afficher le contenu
de PRIMARY et de CLIPBOARD, ça me donne:
~$ /tmp/print-xsel.sh
PRIMARY contains ==>[Salut]<= CLIPBOARD contains ==>[]<=
c. je retourne dans vim où ma sélection (en mode visual)
est toujours en cours et je fais "+y (pour copier
la sélection dans CLIPBOARD).
d. Je relance le script « xsel » et j'ai ça :
~$ /tmp/print-xsel.sh
PRIMARY contains ==>[Salut]<= CLIPBOARD contains ==>[Salut]<=
Ce test1 me semble parfaitement normal. En revanche, le test2...
Test2
a. j'ouvre un vim et je sélectionne du texte en mode visual
(le texte est à nouveau "Salut" mais je rappelle que je
commence le test avec des sélections vides).
b. je reste dans vim et je fais directement "+y (pour copier
la sélection dans CLIPBOARD).
c. Je lance le script « xsel » et j'ai ça :
~$ /tmp/print-xsel.sh
PRIMARY contains ==>[]<= CLIPBOARD contains ==>[Salut]<=
Je ne comprends pas pourquoi PRIMARY est vide alors que j'ai
sélectionné du texte avec vim juste avant. Ok, certes cette
sélection a disparu suite au « "+y » mais c'est quand même
ma dernière sélection de texte en date. Par exemple j'ai bien
ceci :
Test2bis
a. j'ouvre un vim et je sélectionne du texte en mode visual
(le texte est "Salut").
b. Je fais disparaître ma sélection avec ECHAP
c. Je lance le script « xsel » et j'ai ça :
~$ /tmp/print-xsel.sh
PRIMARY contains ==>[Salut]<= CLIPBOARD contains ==>[]<=
Là, même si ma sélection dans vim a disparu, j'ai bien "Salut"
dans PRIMARY. Je ne comprends définitivement pas pourquoi
PRIMARY est vide à la fin du test2.
Un peu de lecture ici <https://www.x.org/docs/ICCCM/icccm.pdf> (2.6.1).

Un peu... y'a 70 pages quand même. :) Mais merci pour le lien, je
tenterai de regarder.
--
François Lafont
Avatar
Benoit Izac
Bonjour,
Le 03/09/2017 à 23:39, Francois Lafont a écrit dans le message
<59ac768e$0$3309$ :
Pas de quoi, j'ai lu en diagonale. ;-)

ah ok. :)
[...]

Cette fois-ci j'ai tout lu mais je ne sais pas quoi te dire. Tout porte
à croire que si tu utilises le PRIMARY il est conservé sinon il
disparaît au profil du CLIPBOARD ; comment vim le sait-il ? As-tu essayé
avec d'autres applications que vim ?
Un peu de lecture ici <https://www.x.org/docs/ICCCM/icccm.pdf> (2.6.1).

Un peu... y'a 70 pages quand même. :) Mais merci pour le lien, je
tenterai de regarder.

Tu n'as pas besoin de lire les 70 pages, seulement le paragraphe 2.6.1
qui fait une page et demie. Maintenant, je ne suis pas certain que ça
t'aide à résoudre ton énigme.
--
Benoit Izac
Avatar
Doug713705
Le 04-09-2017, Benoit Izac nous expliquait dans
fr.comp.os.linux.configuration () :
Cette fois-ci j'ai tout lu mais je ne sais pas quoi te dire. Tout porte
à croire que si tu utilises le PRIMARY il est conservé sinon il
disparaît au profil du CLIPBOARD ; comment vim le sait-il ? As-tu essayé
avec d'autres applications que vim ?

J'ai eu un cas similaire avec vim dans une session tmux distante (ssh).
La solution a consister à quitter la session tmux et faire un reset du
terminal.
Autre chose aussi, il me semble que le terminal joue également un rôle
dans les selections/clipboard et Cie. Mais j'avoue ne jamais y avoir
rien compris.
--
Je ne connaîtrai rien de tes habitudes
Il se peut même que tu sois décédée
Mais j'demanderai ta main pour la couper
-- H.F. Thiéfaine, L'ascenceur de 22H43
Avatar
Francois Lafont
Bonjour,
On 09/04/2017 07:22 AM, Benoit Izac wrote:
Cette fois-ci j'ai tout lu mais je ne sais pas quoi te dire. Tout porte
à croire que si tu utilises le PRIMARY il est conservé sinon il
disparaît au profil du CLIPBOARD ;

Perso, je vois les choses ainsi (mais je crois que c'est ni plus ni
moins ce que tu veux dire en fait) : au moment où vim copie le contenu
de PRIMARY dans CLIPBOARD (typiquement lors d'un « "+y »), PRIMARY est
vidé _sauf_ si le contenu de PRIMARY a été demandé au moins une fois
par une application entre le moment de la dernière mise à jour de
PRIMARY et le moment de la copie de PRIMARY dans CLIPBOARD.
Comme si vim, dès qu'il est le propriétaire de PRIMARY, avait un
compteur "r" du nombre de fois où PRIMARY a été requêté par une
application GUI et comme si vim remettait à 0 ce compteur à chaque
fois qu'il met à jour PRIMARY. On aurait alors un truc du genre
(en pseudo code) :
def copy_in_clipboard () {
if (r == 0) { clear_primary () }
# fonction de la lib gtk pour copier dans CLIPBOARD
}
Ah, si je pouvais trouver la ligne de code dans vim qui valide cela,
je serai content mais je n'ai pas trouvé (et puis faut dire que je
ne suis pas très calé en C... ou C++). Et puis c'est peut-être pas
dans le code vim que ça se trouve mais dans une lib gtk.
comment vim le sait-il ? As-tu essayé
avec d'autres applications que vim ?

Je viens de tenter gedit (un éditeur graphique de Gnome) et le
comportement est un peu différent et beaucoup simple aussi.
En parfaitement résumé (après divers tests), gedit, lui, quand
il perd la sélection de texte (dit autrement, quand il n'est
plus propriétaire de PRIMARY, il l'efface sans condition (peu
importe le contenu de CLIPBOARD).
Un peu de lecture ici <https://www.x.org/docs/ICCCM/icccm.pdf> (2.6.1).

Un peu... y'a 70 pages quand même. :) Mais merci pour le lien, je
tenterai de regarder.

Tu n'as pas besoin de lire les 70 pages, seulement le paragraphe 2.6.1
qui fait une page et demie. Maintenant, je ne suis pas certain que ça
t'aide à résoudre ton énigme.

Merci pour la précision. Je n'y ai pas trouvé de réponses en effet, mais
c'est pas inintéressant, ça m'a permis de voir ce concept de « l'appli
est propriétaire ou non de PRIMARY ou de CLIPBOARD » (onwership).
--
François Lafont
Avatar
Francois Lafont
Salut,
On 09/04/2017 09:38 AM, Doug713705 wrote:
Cette fois-ci j'ai tout lu mais je ne sais pas quoi te dire. Tout porte
à croire que si tu utilises le PRIMARY il est conservé sinon il
disparaît au profil du CLIPBOARD ; comment vim le sait-il ? As-tu essayé
avec d'autres applications que vim ?

J'ai eu un cas similaire avec vim dans une session tmux distante (ssh).
La solution a consister à quitter la session tmux et faire un reset du
terminal.

Je ne sais pas si on peut dire que c'est un « problème ». Perso le
comportement de vim vis à vis de PRIMARY ne me choque pas. En fait,
mon impression du coup est que le comportement d'une appli vis à
vis de PRIMARY et de CLIPBOARD peut varier d'une appli à l'autre
(la définition de ce comportement semble être à la discrétion du
programmeur de l'appli). En revanche, j'aimerais bien pouvoir valider
ce que j'observe soit par du code ou soit via une doc technique.
Autre chose aussi, il me semble que le terminal joue également un rôle
dans les selections/clipboard et Cie. Mais j'avoue ne jamais y avoir
rien compris.

Faut reconnaître que tout cela semble beaucoup moins simple qu'il
n'y paraît. :)
--
François Lafont
Avatar
Benoit Izac
Bonjour,
Le 04/09/2017 à 12:41, Francois Lafont a écrit dans le message
<59ad2ddb$0$8926$ :
Ah, si je pouvais trouver la ligne de code dans vim qui valide cela,
je serai content mais je n'ai pas trouvé (et puis faut dire que je
ne suis pas très calé en C... ou C++). Et puis c'est peut-être pas
dans le code vim que ça se trouve mais dans une lib gtk.

J'ai regardé vite fait (toujours en diagonale) et je t'invite à jeter un
½il dans src/ops.c et d'y chercher « PRIMARY », il y a plein de
commentaires. Tu en as également dans src/gui_gtk_x11.c pour la version
GTK.
J'ai juste fait un « grep -r PRIMARY src ».
Tu as aussi un peu de lecture dans runtime/doc/gui_x11.txt et
<https://en.wikipedia.org/wiki/X_Window_selection>.
Tiens-nous au courant de ton enquête. ;-)
--
Benoit Izac
Avatar
Francois Lafont
Hello,
On 09/04/2017 06:26 PM, Benoit Izac wrote:
J'ai regardé vite fait (toujours en diagonale) et je t'invite à jeter un
œil dans src/ops.c et d'y chercher « PRIMARY », il y a plein de
commentaires. Tu en as également dans src/gui_gtk_x11.c pour la version
GTK.
J'ai juste fait un « grep -r PRIMARY src ».

Merci. J'avais déjà fait ce genre de manips mais sans succès. J'ai
regardé à nouveau les fichiers que tu as indiqués et je vois bien
que ça traite de ces histoires de sélections PRIMARY et CLIPBOARD
mais je n'arrive pas à trouver les lignes qui correspondent à ce
que j'observe. Ceci étant, je regarde peut-être mal. Le nom des
fonctions aide un peu mais c'est pas limpide pour moi.
Tu as aussi un peu de lecture dans runtime/doc/gui_x11.txt et
<https://en.wikipedia.org/wiki/X_Window_selection>.

Merci. Comme souvent, Wikipedia aide à dégrossir un peu un sujet.
Tiens-nous au courant de ton enquête. ;-)

Promis je n'hésiterai pas si j'ai des éléments nouveaux. Mais j'ai
peur de me heurter à mes limites là.
Merci pour ton aide Benoît.
--
François Lafont
Avatar
Benoit Izac
Bonjour,
Le 05/09/2017 à 01:00, Francois Lafont a écrit dans le message
<59addb15$0$3355$ :
J'ai regardé vite fait (toujours en diagonale) et je t'invite à jeter un
½il dans src/ops.c et d'y chercher « PRIMARY », il y a plein de
commentaires. Tu en as également dans src/gui_gtk_x11.c pour la version
GTK.
J'ai juste fait un « grep -r PRIMARY src ».

Merci. J'avais déjà fait ce genre de manips mais sans succès. J'ai
regardé à nouveau les fichiers que tu as indiqués et je vois bien
que ça traite de ces histoires de sélections PRIMARY et CLIPBOARD
mais je n'arrive pas à trouver les lignes qui correspondent à ce
que j'observe. Ceci étant, je regarde peut-être mal. Le nom des
fonctions aide un peu mais c'est pas limpide pour moi.

Pour le fun, j'ai essayé d'aller un peu plus loin :
* j'ai compilé vim en debug
git clone https://github.com/vim/vim.git
cd vim
CFLAGS=-g ./configure
make
cd src
* j'ai lancé le vim fraîchement compilé
./vim
* dans un autre terminal, dans le dossier vim/src j'ai lancé gdb
cd vim/src
gdb vim --pid $(pgrep -f ./vim)
* j'ai posé un breakpoint sur clip_get_selection(VimClipboard *cbd)
b clip_get_selection
Je constate que cette fonction est appelée à chaque fois qu'un
programme demande le contenu de la sélection (xsel dans mon cas) :
// le PRIMARY après la sélection d'une ligne avec « V »
Breakpoint 1, clip_get_selection (cbd=0x55f25ededba0 <clip_star>)
at ops.c:6449
// le CLIPBOARD après un « "+y »
Breakpoint 1, clip_get_selection (cbd=0x55f25ededf40 <clip_plus>)
at ops.c:6449
Si un autre programme prends la main sur le PRIMARY, ou le CLIPBOARD
elle n'est plus appelée.
Avec ce mode opératoire tu devrais arriver à comprendre comment ça
marche même si c'est un peu fastidieux.
Les commandes de base dans gdb :
b nom_de_la_fonction // pose un breakpoint
c // continue l'exécution du programme
n // next pour faire du ligne à ligne
p variable // afficher le contenu de la variable
exemple :
(gdb) b clip_get_selection
Breakpoint 1 at 0x55f25ea2532b: file ops.c, line 6449.
(gdb) c
Continuing.
Breakpoint 1, clip_get_selection (cbd=0x55f25ededba0 <clip_star>) at ops.c:6449
6449 {
(gdb) p cdb
No symbol "cdb" in current context.
(gdb) p cbd
$1 = (VimClipboard *) 0x55f25ededba0 <clip_star>
(gdb) p *cbd
$2 = {available = 1, owned = 1, start = {lnum = 2, col = 0, coladd = 0},
end = {lnum = 3, col = 0, coladd = 0}, vmode = 86, origin_row = 0,
origin_start_col = 0, origin_end_col = 0, word_start_col = 0,
word_end_col = 0, prev = {lnum = 0, col = 0, coladd = 0}, state = 0,
mode = 0, sel_atom = 1, gtk_sel_atom = 0x0}
(gdb) n
6460 if (cbd->owned)
(gdb) n
6462 if ((cbd == &clip_plus && y_regs[PLUS_REGISTER].y_array != NULL)
(gdb) c
Continuing.
Avec ça tu as de quoi t'amuser ; j'arrête là ma curiosité à ce sujet.
--
Benoit Izac