Obtenir que tmux copie un tampon dans le presse-papier

118

J'essaie de trouver un moyen décent de copier ce que j'ai dans un tampon tmux dans mon presse-papiers. J'ai essayé différentes choses comme

bind-key p select-pane -t 2 \; split-window 'xsel -i -b' \; paste-buffer

ce qui me rapproche assez, tout ce que j'ai à faire est d'appuyer sur control-d après avoir préfixé-p.

J'ai essayé de réparer ça en faisant

bind-key p select-pane -t 2 \; split-window 'xsel -i -b << HERE\; tmux paste-buffer\; echo HERE'

Mais ça ne marche pas. En fait, si je compare cela à juste

bind-key p select-pane -t 2 \; split-window 'xsel -i -b << HERE'

cela ne fait rien, donc je suppose que split-window n'aime pas << dans une commande shell.

Des idées?

Edit: Vous pouvez ignorer le select-pane -t 2si vous voulez, ce n'est pas vraiment important. J'utilise simplement une présentation spécifique et le volet 2 est celui que je préfère scinder lorsque je fais autre chose, de sorte que les liaisons impliquant des scissions par défaut sont intégrées.

Pouvoirs numériques
la source
2
Assurez-vous de regarder la réponse de 2014 ci-dessous, qui est plus récente que d'autres. Il recommande le plugin tmux yank qui fonctionne très bien.
Monopoly
Pour une réponse qui est à jour avec Tmux 2.4 (sortie en avril 2017) et la version 2.6, voyez ma réponse
Jason Axelson

Réponses:

26

Ici, les documents ont besoin de nouvelles lignes. Par exemple, dans un script shell, vous pouvez écrire

cat <<EOF >somefile; echo  done
file contents
EOF

Je ne pense pas que tmux vous permette d'y placer des nouvelles lignes, et même si c'était le cas, ce ne serait pas une bonne approche. Que se passe-t-il si les données elles-mêmes ne contiennent que HEREsur une ligne (par exemple parce que vous les copiez .tmux.conf)?

Je suggère d'écrire le contenu du tampon dans un fichier temporaire. Non testé:

bind-key p save-buffer ~/.tmux-buffer \; run-shell "xsel -i -b <~/.tmux-buffer && rm ~/.tmux-buffer"

Il existe une condition de concurrence si vous utilisez cette commande dans deux instances distinctes de tmux. Je ne sais pas comment résoudre ça.

Gilles
la source
Merci fonctionne parfaitement, la condition de course ne me concerne pas, je n'utilise qu'une session.
Pouvoirs numériques
Pour éviter les problèmes de concurrence, je suggérerais d'utiliser mktempce qui est largement disponible
Deuil
@Brief Bonne idée. Dans ce cas, utiliser le PID du processus tmux fonctionnerait également et serait probablement plus facile à organiser ( $PPIDdans un shell lancé par tmux). Mais comment obtenez-vous le nom de fichier variable (quelle que soit sa construction) dans l'argument de save-buffer? Je suppose que, save-buffer - | …comme dans la réponse de Grauwolf , qui supprime complètement un fichier temporaire?
Gilles
Vous avez raison, ma faute, cela ne serait pas possible.
Chagrin
93

Cela devrait fonctionner:

# move x clipboard into tmux paste buffer
bind C-p run "tmux set-buffer \"$(xclip -o)\"; tmux paste-buffer"
# move tmux copy buffer into x clipboard
bind C-y run "tmux save-buffer - | xclip -i"
Grauwolf
la source
1
Alors c'est le cas. C'est beaucoup mieux que d'utiliser un fichier temporaire, merci. Il gère même automatiquement plusieurs sessions simultanées, grâce aux TMUXvariables d'environnement.
Gilles
22
Une meilleure instruction pour le C-pserait: bind C-p run "xclip -o | tmux load-buffer - ; tmux paste-buffer"- pas de problème de citation ni de problème de limite de ligne de commande.
doc what
8
Tmux a-t-il un crochet pour copier la sélection dans le presse-papiers lorsque vous y êtes copy-mode?
Ehtesh Choudhury
1
xclip -ooption n'a pas fonctionné pour moi alors j'ai changé pourbind C-c run "tmux save-buffer - | xclip -selection c"\; display-message "Buffer copied to clipboard"
Pawka
6
À chaque fois que je copie de cette façon, tmux cesse de répondre aux raccourcis clavier. Une solution à cela?
Skrat
41

Une solution plus simple pour Mac OS-X

Cela découle de la réponse d'Alex et utilise des éléments qui n'existaient pas à l'époque.

Si vous utilisez homebrew (et si vous ne l'êtes pas, pourquoi ne l'êtes-vous pas?), Vous pouvez simplement faire ceci:

brew install reattach-to-user-namespace

Puis dans votre ~/.tmux.conf:

set-option -g default-command "reattach-to-user-namespace -l zsh" # or bash...
bind C-c run "tmux save-buffer - | reattach-to-user-namespace pbcopy"
bind C-v run "reattach-to-user-namespace pbpaste | tmux load-buffer - && tmux paste-buffer"

Pour copier le tampon de tmux (vous devriez déjà avoir déjà copié quelque chose avec tmux) dans le pasteboard du Mac, utilisez <tmux-key> Control-c. Il sera maintenant disponible pour Command-voupbpaste

Pour coller quelque chose à partir du presse-papiers Mac, utilisez <tmux-key> Control-v.

doc what
la source
2
Cette réponse est superbe. J'utilisais tmux show-bufferce qui causait des problèmes de retour à la ligne qui le tmux save-buffer -résolvaient.
event_jr
Qu'est-ce que le faire -à la fin tmux save-buffer -?
hekevintran
Emet le save-bufferà la sortie standard. Vous pouvez remplacer le -avec un nom de fichier et le sauvegarder ici. Cela vous évite d'écrire (et de nettoyer) un fichier.
doc what
1
À partir de OS X 10.10, l'espace de nommage rattachez-à-l'utilisateur n'est plus nécessaire. Presque tous les tutoriels et documentations concernant tmux et OS X en font mention, car copier-coller n’était pas possible il y a quelques années. Ces jours-ci, il fonctionne (généralement) hors de la boîte
Rafael Bugajewski
40

La copy-pipecommande a été ajoutée à partir de la version 1.8. Il copie une sélection dans le tampon tmux et la dirige vers une commande. Maintenant, il n'y a pas besoin de liaison de préfixe. Voici un exemple:

bind -t vi-copy y copy-pipe "xclip"

# For OS X users:
bind -t vi-copy y copy-pipe "reattach-to-user-namespace pbcopy"

Maintenant, lorsque vous avez du texte sélectionné dans copy-mode, ycopiez ce texte dans le tampon tmux ainsi que dans le presse-papier du système d'exploitation. Cependant, cela n'aidera pas si vous voulez obtenir du texte du presse-papiers dans la mémoire tampon tmux.

Tyler Holien
la source
1
Fonctionne parfaitement et est la solution la plus simple du groupe.
Naseer
2
Cela ne fonctionne pas pour moi sous Linux, celui-ci cependant: unix.stackexchange.com/a/131074/13601
Sebastian Blask
1
À partir de OS X 10.10, il semble que ce reattach-to-user-namespacen’est plus nécessaire.
Chris
travaille sur el capitan
olleh
2
Cela ne fonctionne plus pour Tmux 2.4 qui a été publié le 20 avril 2017. Au lieu de cela, vous devez utiliser bind-key -T copy-mode-vi y send-keys -X copy-pipe "xclip"et pour OS X:bind-key -T copy-mode-vi y send-keys -X copy-pipe "reattach-to-user-namespace pbcopy"
Jason Axelson
16

Vous voudrez peut-être essayer le plugin tmux-yank . Il permet de copier directement dans le presse-papiers du système (OS X et Linux) et quelques autres choses intéressantes, telles que le retrait de la ligne de shell actuelle.


la source
7
C’est une excellente solution propre et devrait être considérée comme une réponse beaucoup plus récente que les autres. Merci d'avoir partagé!
Monopoly
9

Après avoir essayé différentes solutions, voici ma configuration finale:

# move x clipboard into tmux paste buffer
bind C-p run "xclip -o | tmux load-buffer -
# move tmux copy buffer into x clipboard
bind C-y run "tmux save-buffer - | xclip -i -selection clipboard"

L'utilisation de save-buffer au lieu de show-buffer donne les données réelles sans les données, comme indiqué par les sauts de ligne lorsque vous êtes dans des divisions.

J'utilise aussi cela pour commencer la sélection / copie en mode copie tmux:

bind-key -t vi-copy 'v' begin-selection
bind-key -t vi-copy 'y' copy-selection

J'imagine qu'il pourrait être possible de fusionner la sélection de copie avec la touche 'y' ET de la déplacer dans le presse-papiers x.

Ownatik
la source
J'essayais de fusionner les deux commandes, comme vous l'avez mentionné, sans succès. Des idées sur la façon de le faire?
Rafael Vega
9

Voici une tentative de réponse globale.

D'abord un peu d'histoire

Lorsque cette question a été posée pour la première fois (juin 2011), la copie de texte de Tmux dans le presse-papiers devait se faire en deux étapes: copiez d'abord le texte sélectionné dans la mémoire tampon de Tmux, puis copiez le texte de la mémoire tampon de Tmux dans le presse-papiers du système.

En 1.8 (mars 2013), la copy-pipecommande a été ajoutée pour vous permettre de copier le texte sélectionné directement dans le Presse-papiers du système (ou dans une autre destination).

Puis, dans la version 2.4 (avril 2017), les tableaux de clés ont été modifiés de manière significative, rendant obsolètes de nombreuses réponses sur cette page.

Répondre à la question initiale

Linux :

bind-key C-y run-shell "tmux save-buffer - | xclip -i -r > /dev/null" \; display-message "Copied tmux buffer to selection"
bind-key C-Y run-shell "tmux save-buffer - | xclip -i -r -selection clipboard > /dev/null" \; display-message "Copied tmux buffer to clipboard"
bind-key C-p run-shell "xclip -o | tmux load-buffer - ; tmux paste-buffer"

Mac :

Si vous utilisez homebrew, vous devez l'installer reattach-to-user-namespaceen exécutant la commande suivante dans un terminal:

brew install reattach-to-user-namespace

Puis dans votre ~ / .tmux.conf:

bind-key C-y run-shell "tmux save-buffer - | reattach-to-user-namespace pbcopy" \; display-message "Copied tmux buffer to clipboard"
bind-key C-p run-shell "reattach-to-user-namespace pbpaste | tmux load-buffer - ; tmux paste-buffer"

La méthode la plus courte (copier-coller une sélection directement depuis et vers le presse-papiers pour tmux> 2.4)

Remarque: il existe deux versions pour Linux car Linux possède un presse-papiers principal et secondaire (également appelé sélection).

Linux :

bind-key -T copy-mode-vi y send-keys -X copy-pipe "xclip -r" \; display-message "Copied to selection"
bind-key -T copy-mode-vi Y send-keys -X copy-pipe "xclip -r -selection clipboard" \; display-message "Copied to clipboard"
bind-key C-p run-shell "xclip -o | tmux load-buffer - && tmux paste-buffer"

Mac :

bind-key -T copy-mode-vi y send-keys -X copy-pipe "reattach-to-user-namespace pbcopy" \; display-message "Copied to clipboard"

Personnaliser ces commandes

  • Si vous ne voulez pas que la commande vous dise ce qu'elle a fait dans la ligne d'état, supprimez simplement le display-message(ainsi que le \;précédant).

  • Si vous utilisez le style Emacs copie en mode au lieu de vi puis remplacer une instance de copy-mode-viavec justecopy-mode

  • Si vous utilisez Linux et que vous voulez utiliser xselau lieu de xclipremplacer xclip -rpar xsel -i -pet xclip -oavecxsel -o -p

  • Le -rin xclip -rest facultatif, il supprime la dernière nouvelle ligne. Cela est utile pour copier des commandes. Lorsque vous les collez, elles ne seront pas exécutées immédiatement.

  • Si vous effectuez un tunneling sur SSH, vous devez consulter https://unix.stackexchange.com/a/354581/14252.

Références:

Jason Axelson
la source
Cette commande est bind-key C-p run-shell "xclip -o | tmux load-buffer - ; tmux paste-buffer"-elle toujours valide? pourtmux>2.4
alpha_989
7

Je n'aime pas avoir des touches supplémentaires, alors je voulais quelque chose de plus ambitieux. Passez en mode copie avec [, mettez en surbrillance le texte de droite, puis appuyez sur] pour copier le texte dans le Presse-papiers.

En outre, tmux aime inclure les nouvelles lignes dans les expressions qui se suivent (et curieusement ces nouvelles lignes se trouvent au mauvais endroit! Elles ne sont pas celles où l'expression est enveloppée à l'écran). Je voulais donc que C-] copie l'expression en supprimant les nouvelles lignes.

Sur tmux 1.6 j'ai essayé ceci:

bind [ copy-mode
bind -t vi-copy ] run "tmux send-keys Enter; tmux show-buffer | xclip -i -selection clipboard;"
bind -t vi-copy C-] run "tmux send-keys Enter; tmux show-buffer | perl -pe 's/\n//' | xclip -i -selection clipboard;"

mais cela n'a pas fonctionné car tmux ne semble pas content de lier des choses complexes à la table vi-copy. Alors j'ai fini par faire ceci à la place:

bind [ copy-mode \;                                                        \
    bind -n ] run                                                          \
    "tmux send-keys Enter;                                                 \
     tmux show-buffer | xclip -i -selection clipboard;                     \
     tmux unbind -n C-];                                                   \
     tmux unbind -n ]" \;                                                  \
    bind -n C-] run                                                        \
    "tmux send-keys Enter;                                                 \
     tmux show-buffer | perl -pe 's/\n//' | xclip -i -selection clipboard; \
     tmux unbind -n C-];                                                   \
     tmux unbind -n ]"

Cela conduit à des choses étranges (] ou C-] agira de manière amusante la prochaine fois que vous les utiliserez, mais seulement une fois) si vous quittez le mode copie d'une autre manière que] ou C-]. Cela pourrait être corrigé avec d'autres liaisons, j'imagine, mais cela fait ce que je veux la plupart du temps.

Leif
la source
stackoverflow.com/a/10954274/69663 note qu'il existe un rapport de bogue sur les limitations de bind-key sur sourceforge.net/tracker/…
unhammer
4

Il existe une solution sur Arch Wiki utilisant xclip:

# move tmux copy buffer into x clipboard
bind-key C-y save-buffer /tmp/tmux-buffer \; run-shell "cat /tmp/tmux-buffer | xclip"

https://wiki.archlinux.org/index.php/Tmux

jasonwryan
la source
2
Tmux crée-t-il le save-bufferfichier de manière sécurisée dans un répertoire partagé? Sinon, le mettre /tmpest un trou de sécurité. Il y a une utilisation inutile de cat, et la suppression du fichier temporaire est manquante. Ensuite, c’est une question de xselvs xclip, qui sont équivalents ici, et vous avez ma solution (écrite de manière indépendante).
Gilles
1
Merci Gilles. Je mettrai à jour le wiki pour refléter vos points.
jasonwryan
4

Une solution pour Mac OS X. Suivez ces 2 étapes:

  1. Utilisez la solution de contournement de Chris Johnsen: https://github.com/ChrisJohnsen/tmux-MacOSX-pasteboard

  2. Ajoutez ce code à votre configuration tmux (~ / .tmux.conf)

# paste clipboard into tmux buffer
bind v run-shell "reattach-to-user-namespace -l zsh -c 'tmux set-buffer \\"$(pbpaste)\\"; tmux paste-buffer'"
# put tmux buffer into x clipboard
bind y run-shell "reattach-to-user-namespace -l zsh -c 'tmux show-buffer | pbcopy'"

Alex Gaudio
la source
4

Une variante légèrement modifiée de la réponse acceptée, que j'ai concoctée.

Je préfère également utiliser le presse-papiers du système (Ctrl-C, Ctrl-V) en plus du primarypresse-papiers par défaut de xclip (celui obtenu avec la sélection de la souris et les clics de souris correspondants). Pour choisir le presse-papiers du système, vous devez passer un -selection clipboardargument à xclip.

Aussi, lors de la copie d'un tampon dans un presse-papiers, j'aime la possibilité de choisir quel tampon je veux copier. Ceci est fait en utilisant choose-bufferpuis en tamponnant l'argument à save-bufferutiliser -b %%.

# Copy into clipboard
bind C-c choose-buffer "run \"tmux save-buffer -b %% - | xclip -i -selection clipboard\""
# Paste from clipboard
bind C-v run "xclip -o -selection clipboard | tmux load-buffer - ; tmux paste-buffer"
# Copy into primary
bind C-y choose-buffer "run \"tmux save-buffer -b %% - | xclip -i \""
# Paste from primary
bind C-p run "xclip -o | tmux load-buffer - ; tmux paste-buffer"

UPDATE: D'une manière ou d'une autre, avec tmux 1.8 et deux de mes installations openSUSE 12.2, je vois un blocage quand tmux run-shellest appelé avec une xcliplecture de stdin sur un tuyau. J'ai plutôt décidé d' xselessayer et cela semble fonctionner. Ce sont les raccourcis clavier équivalents qui utilisent xsel. J'avais aussi l'habitude &&d'enchaîner les commandes en pâte pour plus de robustesse.

# Copy into clipboard
bind C-c choose-buffer "run \"tmux save-buffer -b '%%' - | xsel -i -b\""
# Paste from clipboard
bind C-v run "xsel -o -b | tmux load-buffer - && tmux paste-buffer"
# Copy into primary
bind C-y choose-buffer "run \"tmux save-buffer -b '%%' - | xsel -i\""
# Paste from primary
bind C-p run "xsel -o | tmux load-buffer - && tmux paste-buffer"
Tuxdude
la source
4

Voici ma réponse plutôt longue qui devrait résoudre deux problèmes majeurs liés à l'utilisation de xclip pour copier le tampon à partir d'une session tmux distante (ssh):

1. xclip irresponsif

Pour moi, la réponse de @ Grauwolf avec xclipn'a pas fonctionné (rend le volet tmux totalement irresponsable). J'ai découvert pourquoi dans la page Tmux du wiki Arch :

xclip pourrait également être utilisé à cette fin. Contrairement à xsel, il fonctionne mieux pour imprimer du flux binaire brut qui ne correspond pas aux paramètres régionaux actuels. Néanmoins, il est préférable d'utiliser xsel au lieu de xclip, car xclip ne ferme pas STDOUT une fois qu'il a lu le tampon de tmux. En tant que tel, tmux ne sait pas que la tâche de copie est terminée et continue d'attendre la fin de xclip, rendant ainsi tmux inactif. Une solution de contournement consiste à rediriger STDOUT de xclip vers / dev / null

Donc, la liaison devrait être:

bind-key C-y run "tmux save-buffer - | xclip -i -sel clip > /dev/null"

Maintenant, cela fonctionnera si votre session tmux est locale.

2. xclip incapable de se connecter à X

Si vous utilisez tmux sur ssh -X , il y a de grandes chances que cela ne fonctionne pas directement.

C'est parce que la variable shell $DISPLAYdoit être définie correctement.

Solution complète

Donc, pour moi, la solution de travail complète consiste à mettre les lignes suivantes dans mon ~/.tmux.conf:

set-option -g update-environment "DISPLAY"
bind-key C-y run "export DISPLAY=`tmux show-env | sed -n 's/^DISPLAY=//p'`; tmux save-buffer - | xclip -i -selection clipboard >/dev/null"
# Or more concise:
bind-key C-y run "tmux save-buffer - | xclip -i -selection clipboard -d `tmux show-env | sed -n 's/^DISPLAY=//p'` >/dev/null

Pour coller depuis le primaire:

bind-key C-p run "xclip -d `tmux show-env | sed -n s/^DISPLAY=//p` -o | tmux load-buffer - && tmux paste-buffer"

Je ne comprends parfaitement pourquoi $DISPLAYn'est pas correctement en approvisionnement .tmux.conf, donc c'est pourquoi je dois l' extraire avec tmux show-envet sed.

Si vous avez tmux> = 1.8, vous pouvez adapter cette commande avec copy-pipe:

bind-key -t vi-copy y copy-pipe 'xclip -in -selection clipboard -d `tmux show-env | sed -n s/^DISPLAY=//p` >/dev/null'
PlasmaBinturong
la source
/home/linux/.tmux.conf:11: invalid or unknown command: bind-key C-y run "tmux save-buffer - | xclip -i -selection clipboard -d `tmux show-env | sed -n 's[0/0] PLAY=//p'` >/dev/null
utilisateur
@ utilisateur la sedcommande que vous affichez n'est pas la même que celle que j'ai écrite ... Est-ce ce que vous avez écrit dans votre .tmux.conf?
PlasmaBinturong
Je viens de copier et coller votre code.
utilisateur
@ utilisateur, étrange. Il pourrait y avoir beaucoup de sources d'erreurs. Vérifiez d'abord que votre devis est correct. Alors, connaissez-vous sed? La commande doit être: sed -n s/^DISPLAY=//p. Sinon, vous pouvez utiliser cut: tmux show-env DISPLAY | cut -d'=' -f2. Cela pourrait également valoir la peine de vérifier votre version de tmux.
PlasmaBinturong
3

J'essaie de trouver un moyen décent de copier ce que j'ai dans un tampon tmux dans mon presse-papiers. J'ai essayé différentes choses comme

Pour les liaisons de style emacs, il existe différentes options. (Le style Vi devrait être similaire?) La liaison typique pour effectuer la "sélection de copie" dans emacs est Mw, il serait donc très pratique d'avoir la même liaison dans tmux.

1 - Serait idéal, mais ne fonctionne pas (en raison de la limitation de tmux?)

unbind-key -t emacs-copy M-w
bind-key -t emacs-copy M-w copy-selection\; \
  run-shell "tmux save-buffer - | xsel --input --clipboard"

2 - Un compromis qui fonctionne bien pour moi : Acceptez l’utilisation d’un raccourci clavier différent pour emacs-copy dans tmux. Utilisez par exemple CMw. (Cette liaison sera définie "globalement" - pas seulement en mode copie - mais utile uniquement en mode copie)

bind-key -n C-M-w send-keys M-w\; \
 run-shell "tmux save-buffer - | xsel --input --clipboard" 
Hugo Heden
la source
3

Beaucoup de ces réponses n'ont pas fonctionné pour mon Ubuntu 14.04 sur zsh tel quel. Je ne sais pas si mon shell a quelque chose à voir avec cela, mais voici ma version de travail d'utilisation de cette stratégie pour la copie et cette stratégie pour le collage

    bind-key -t vi-copy 'v' begin-selection
    bind-key -t vi-copy 'y' copy-pipe "xclip -sel clip -i"
    bind-key ] run-shell "xclip -sel clip -o | tmux load-buffer - ; tmux paste-buffer" 

Quelques notes:

  • pour copier-pipe, je devais spécifier mon presse-papiers avec -sel clip -i. Cette ligne combine le tampon yank to tmux et l’envoie à xclip.
  • pour le coller, il me fallait encore spécifier le presse-papiers avec -sel clip -o

Cela fonctionne très bien maintenant pour ma configuration vim / zsh / tmux.

brianclements
la source
Merci! -sel clip -irésout le problème. Bien que, je ne comprenne pas pourquoi vous devez spécifier à nouveau le Presse-papiers pour le coller (la ]
méthode
1

Et la version améliorée de la réponse @Leif pourrait être:

tmux bind-key '[' run "tmux copy-mode;
tmux bind-key -n ']' run \"tmux send-keys Enter; tmux save-buffer - | xclip -i -selection clipboard;
tmux unbind-key -n ']'\";
tmux bind-key -n q run \"tmux unbind -n ']'; tmux send-keys q\";
tmux bind-key -n C-c run \"tmux unbind -n ']'; tmux send-keys C-c\""

Ainsi, le code ci-dessus est encapsulé dans tundle / tmux- yank, un plugin tmux permettant de copier du texte tmux dans le presse-papiers, il cible tmux> = 1.6 sur OS X et Linux.

Javier López
la source
1

Sous OS-X avec tmux version 2.2 ou ultérieure, ce qui suit fonctionnera:

bind-key -t emacs-copy MouseDragEnd1Pane copy-pipe "pbcopy"
bind-key -t vi-copy MouseDragEnd1Pane copy-pipe "pbcopy"
Kyle Kloepper
la source
1

J'utilise copyqun gestionnaire de presse-papiers multiligne. (Cela fonctionne avec Windows, OSX, Linux.)

  • Ajoutez les lignes suivantes dans ~/.tmux.conf:

    set-window-option -g mode-keys vi
    bind C-y run 'out=`tmux save-buffer - ` && copyq add "$out"'
    
  • cygwindemande l' copyq.exeemplacement dans ~/.bashrc:

    export PATH="$PATH:/cygdrive/c/Program Files (x86)/CopyQ"
    
Oleg Svechkarenko
la source