Comment envoyer une commande à tous les volets de tmux?

192

J'aime appeler des :clear-historyvolets avec un énorme défilement. Cependant, je souhaite créer un script pour envoyer cette commande à tous les volets des différentes fenêtres.

Je sais comment envoyer une commande à toutes les fenêtres, grâce à cette question , mais comment envoyer une commande à tous les volets de quelle fenêtre également?

send-keyset synchronize-panesde la page de manuel tmux viennent à l'esprit, mais je ne sais pas comment les marier ensemble. Mais il existe peut-être un moyen plus simple de le faire.

Observations supplémentaires:

En y réfléchissant un peu, tmux list-panes -asemble répertorier tous les volets de la session en cours. Assez utile pour commencer. Où est-ce que je vais d'ici?

Ehtesh Choudhury
la source
Pour ceux qui viennent à cette question dans l'espoir de trouver une solution qui s'applique à chaque volet, dans chaque fenêtre, chaque session: scripter.co/command-to-every-pane-window-session-in-tmux
CHB

Réponses:

356

Avez-vous essayé de suivre dans la fenêtre tmux avec plusieurs volets

Ctrl-B :

setw synchronize-panes on

clear history
garg shailesh
la source
53
Juste pour être complet, à désactiver si vous le feriezCtrl-b :setw synchronize-panes off
Mitch
19
et vous pouvez lier des raccourcis pour cela ~/.tmux.confen ajoutant: bind -n C-x setw synchronize-panes on et bind -n M-x setw synchronize-panes off
guneysus
4
est possible de définir le même raccourci pour basculer?
Arnold Roa
20
@ArnoldRoa oui, l'option basculera si vous partez on/off. Sobind -n C-x setw synchronize-panes
sensation
1
Si j'ajoute sur bind -n C-x setw synchronize-panesquel raccourci dois-je appuyer pour appeler? Est-ce le préfixe + C & x. J'ai essayé beaucoup d'options
Bill Goldberg
29

Un peu tard à la fête, mais je ne voulais pas définir et désactiver les panneaux de synchronisation juste pour envoyer une commande, j'ai donc créé une fonction wrapper autour de tmux et ajouté une fonction personnalisée appelée send-keys-all-panes.

_tmux_send_keys_all_panes_ () {
  for _pane in $(tmux list-panes -F '#P'); do
    tmux send-keys -t ${_pane} "$@"
  done
}

Je crée également un wrapper autour de la commande tmux pour simplifier l'appel de cette fonction (pour plus de commodité). Le wrapper et le code ci-dessus sont tous ici .

Cela me permet d'exécuter tmux send-keys-all-panes <command>ou tmux skap <commandd'envoyer <command>à tous les volets.

Notez que tmux a un alias de ma fonction wrapper tmux_pp.

kshenoy
la source
c'est bash, mais peut-on faire la même chose à partir de l'invite de commande tmux, je veux dire en faisantprefix + :
Rho Phi
Je ne sais pas comment ou si c'est possible. Quel est votre scénario d'utilisation pour lequel vous devez envoyer une commande <prefix>:?
kshenoy
Je recommanderais d'appeler l'extrait de code bash ( : run "yourscript.sh yourargs..."); si votre commande a généré, votre volet actif ou spécifié affichera les résultats jusqu'à ce que vous appuyiez sur q, mais dans ce cas, il ne devrait pas. Bien sûr, vous pouvez alias / lier ceci à votre guise. En passant, les processus internes peuvent interpréter vos frappes ou leurs effets différemment, de sorte qu'une liste blanche ou une liste noire #{pane_current_cmd}peut être nécessaire. J'ai ctrl + k lié pour envoyer ctrl + l et effacer l'historique; cela fonctionne bien pour les shells, mais écrase le tampon de Vim. J'aurais besoin de raffinement avant de pouvoir diffuser mon ctrl + k.
John P
Cela peut être davantage un problème XY; l'invite de commande Tmux est utile, mais il semble que vous l'utilisiez car vous n'avez pas d'autre invite de commande ouverte. Vous pouvez configurer une liaison de clé - sans le préfixe, si vous le souhaitez - pour basculer et focaliser un volet supplémentaire avec votre shell de choix, au lieu d'envoyer <prefix>:avant chaque commande, de perdre la sortie après avoir quitté la commande, et tous les pièges qui viennent avec l'exécution via Tmux. Par exemple, <prefix>:run "man cat"ne fait pas apparaître l'homme dans pidof manou même ps auxf | grep man, ni comme «moins», mon téléavertisseur actuel pour l'homme.
John P
Le lien est mort
Mateusz Piotrowski
10

Mise à jour juin 2019

Illustration rapide de la configuration de votre propre liaison pour la synchronisation des volets .

Ajout de ce qui suit dans mon tmux.conf(les commentaires s'appliquent certainement à ma configuration globale):

# synchronize all panes in a window
# don't use control S, too easily confused
# with navigation key sequences in tmux (show sessions)
unbind C-S
bind C-Y set-window-option synchronize-panes

Maintenant, je peux basculer la possibilité de synchroniser les commandes sur plusieurs volets avec <C-a><C-y>.

(Oui, j'ai remappé la touche de liaison sur Ctrl a).

Arcseldon
la source
4

Aucune des réponses ci-dessus n'a fonctionné pour moi (tmux v2.3), mais cela a fonctionné à partir de la ligne de commande bash:

for _pane in $(tmux list-panes -a -F '#{pane_id}'); do \
  tmux clear-history -t ${_pane}  ; done

Un script plus généralisé, pour les commandes tmux autres que 'clear-history', remplacerait simplement cet élément par un paramètre, par exemple. 1 $. Faites attention si vous avez l'intention d'écrire un script pour gérer une série de commandes tmux, car "-t $ {_ pane}" devra être appliqué à chacune.

Notez que le -aparamètre to tmux list-panesest requis pour couvrir tous les volets de toutes les fenêtres de toutes les sessions. Sans cela, seuls les volets de votre fenêtre tmux actuelle seront affectés. Si vous avez plusieurs sessions tmux ouvertes et que vous souhaitez uniquement appliquer la commande aux volets de la session en cours, remplacez -apar -s(Tout est dans la page de manuel tmux).

Je n'ai pas les points de mod pour commenter directement chacune des réponses ci-dessus, alors voici pourquoi ils ne fonctionnaient pas pour moi:

Le problème que j'ai eu avec la réponse de @ shailesh-garg était que la synchronisation n'affectait que les commandes émises dans les volets, pas les commandes tmux émises en utilisant Ctrl-B :qui sont en dehors des volets.

Les trois problèmes que j'ai rencontrés avec la réponse de @kshenoy étaient les suivants:

  1. il envoie des frappes à l'intérieur d'un volet, pas à l'opération tmux de ce volet, donc par exemple, si l'on avait un shell bash en cours d'exécution dans le volet et que l'on utilisait le script pour envoyer "clear-history", ce seraient les frappes qui apparaîtra dans la ligne de commande bash. Une solution de contournement serait d'envoyer "tmux clear-history" ou de prépendre "tmux" à "$ @", mais je n'ai pas édité la réponse à cause de mes autres problèmes avec la réponse;
  2. Je ne pouvais pas comprendre comment envoyer un caractère de nouvelle ligne sans littéralement casser la ligne;
  3. Même quand j'ai fait ça, l'envoi de "tmux clear-history" n'a eu aucun effet.
user1404316
la source
3

ma version tmux est 1.9a, et cela fonctionne pour moi, une touche suffit pour activer et désactiver

bind-key X set-window-option synchronize-panes\; display-message "synchronize-panes is now #{?pane_synchronized,on,off}"
LIU YUE
la source
2
tmux send-keys -t <session id> <command> C-m  

Remplacez «session id» et «command» en conséquence.

RJ
la source
aimerait dire quelque chose sur cette langue extraterrestre
Muhammad Omer Aslam
Quoi? L'anglais n'est pas difficile. Mais si vous avez quelque chose à dire, dites-le.
RJ
4
:Dmec, vous devez ajouter une description à votre réponse car elle contient très peu de texte et pour cette raison, Stackoverflow le détecte comme un spam ou un message de mauvaise qualité, ajoutez simplement des détails pour qu'il n'apparaisse pas en dessous.
Muhammad Omer Aslam
6
C'est drôle, la réponse acceptée n'a pas non plus de description et seulement le code, mais peu importe.
RJ
0

C'est ma fonction utilitaire pour le faire, n'exécutant la commande que lorsqu'il n'y a rien en cours d'exécution dans le volet.

#!/bin/bash

_send_bash_command_to_session() {
    if [[ $# -eq 0 || "$1" = "--help" ]] ; then
        echo 'Usage: _send_bash_command_to_session $session_name what ever command you want: '
        return
    fi
    input_session="$1"
    input_command="${@:2}"
    for _pane in $(tmux list-panes -s -t ${input_session} -F '#{window_index}.#{pane_index}'); do
        # only apply the command in bash or zsh panes.
        _current_command=$(tmux display-message -p -t ${input_session}:${_pane} '#{pane_current_command}')
        if [ ${_current_command} = zsh ] || [ ${_current_command} = bash ] ; then
            tmux send-keys -t ${_pane} "${input_command}" Enter
        fi
    done
}

tmux_set_venv() {
    _current_session=$(tmux display-message -p '#{session_name}')
    _send_bash_command_to_session ${_current_session} workon $1
}

Exemple ciblant une session appelée dev, activant un virtualenv python dans tous les volets qui se trouvent dans bashou zsh, évitant d'exécuter la commande dans les volets avec vim ou tout autre exécutable:

_send_bash_command_to_session dev workon myvirtualenv

ou plus facile à retenir: pour le faire dans la session en cours:

tmux_set_venv myvirtualenv

Trouvez mon fichier de configuration avec cette fonction.

phcerdan
la source