Titre du volet dans Tmux

88

Sur ma machine locale, j'ai 3 instances node.js exécutées simultanément. Chacun a son propre volet dans une fenêtre tmux appelée «serveurs». Le problème est qu'il n'est pas si facile de déterminer quel nœud s'exécute dans quel volet, car leurs journaux sont similaires.

Ce dont j'ai besoin, c'est d'un titre pour chaque volet. Comme je l'ai compris, tmux lui-même n'a pas la fonctionnalité: il n'a que des titres pour les fenêtres et non pour les volets. Lancer une session tmux distincte dans chaque volet pour chaque instance de node.js ressemble à une exagération.

Alors, y a-t-il un petit programme qui lance une commande, enveloppant sa sortie avec une barre d'état spécifiée?

Merci d'avance

Andrey Lushnikov
la source
1
tmux à partir de la version 2.3 prend en charge les titres de volet, voir stackoverflow.com/a/37602055/266453
Dennis G

Réponses:

80

tmux prend en charge les titres par volet, mais il ne fournit pas d'emplacement par volet pour afficher ces titres.

Vous pouvez définir le titre d'un volet avec la séquence d'échappement ESC ]2;… ESC \(par exemple, voir la section intitulée Noms et titres dans la page de manuel tmux ). Vous pouvez le faire à partir du shell comme ceci:

printf '\033]2;%s\033\\' 'title goes here'

Le titre de chaque volet est par défaut le nom d'hôte du système. Par défaut, le titre du volet actif est affiché sur le côté droit de la ligne d'état de tmux (la valeur globale par défaut de la variable de session status-rightest "#22T" %H:%M %d-%b-%y, qui affiche 22 caractères du titre du volet, l'heure et la date).

Ainsi, tant que vous êtes satisfait de pouvoir voir le titre du volet actif (c'est-à-dire que vous souhaitez changer de volet pour voir le titre d'un volet inactif), vous pouvez vous en tirer avec la fonctionnalité par défaut. Envoyez simplement la séquence d'échappement de réglage de titre appropriée avant de lancer la commande principale pour chaque volet.


Si vous avez absolument besoin d'une ligne dédiée pour afficher certaines informations par volet, les sessions tmux imbriquées peuvent ne pas être autant (inutiles) «exagérées» que vous ne le pensez.

Dans le cas général, pour fournir une ligne d'état inviolable sur un terminal donné, vous aurez besoin d'un (ré) émulateur de terminal complet qui se trouve entre le terminal d'origine et un nouveau terminal (un avec une ligne en moins). Une telle (ré) émulation est nécessaire pour traduire les séquences de contrôle envoyées au terminal interne et les traduire pour le terminal d'origine. Par exemple, pour maintenir une ligne d'état en bas du terminal externe, la commande

Passez à la dernière ligne.

envoyé au terminal interne doit être devenu

Passez à l'avant-dernière ligne.

une fois traduit et envoyé au terminal externe. De même, un LF envoyé au terminal interne doit devenir

Si le curseur est sur l'avant-dernière ligne, faites défiler cette ligne et toutes les lignes au-dessus d'une ligne vers le haut, pour fournir une avant-dernière ligne claire (protégeant la ligne d'état sur la dernière ligne). Sinon, envoyez un LF.

dans le terminal externe.

Des programmes comme tmux et screen ne sont que de tels réémulateurs de terminaux. Bien sûr, il existe de nombreuses autres fonctionnalités intégrées à l'émulateur de terminal, mais vous auriez besoin d'un gros morceau de code d'émulation de terminal juste pour fournir une ligne d'état fiable .


Il existe cependant une solution légère tant que

  1. vos programmes ( instances Node.js ) ont des interactions de terminal limitées avec les volets dans lesquels ils s'exécutent (c'est-à-dire pas de positionnement du curseur), et
  2. vous ne redimensionnez pas les volets pendant l'exécution de vos programmes.

Comme beaucoup d'émulateurs de terminal, tmux prend en charge une commande de contrôle de terminal «définir la région de défilement» dans ses volets. Vous pouvez utiliser cette commande pour limiter la zone de défilement aux N-1 lignes supérieures (ou inférieures) du terminal et écrire une sorte de texte d'identification d'instance dans la ligne sans défilement.

Les restrictions (pas de commandes de déplacement du curseur autorisées, pas de redimensionnement) sont requises car le programme qui génère la sortie (par exemple une instance Node.js ) n'a aucune idée que le défilement a été limité à une région particulière. Si le programme de génération de sortie déplaçait le curseur en dehors de la région de défilement, alors la sortie pourrait devenir brouillée. De même, l'émulateur de terminal réinitialise probablement automatiquement la région de défilement lorsque le terminal est redimensionné (ainsi la «ligne sans défilement» finira probablement par défiler).

J'ai écrit un script qui utilise tputpour générer les séquences de contrôle appropriées, écrire dans la ligne sans défilement et exécuter un programme après avoir déplacé le curseur dans la région de défilement:

#!/bin/sh

# usage: no_scroll_line top|bottom 'non-scrolling line content' command to run with args
#
#     Set up a non-scrolling line at the top (or the bottom) of the
#     terminal, write the given text into it, then (in the scrolling
#     region) run the given command with its arguments. When the
#     command has finished, pause with a prompt and reset the
#     scrolling region.

get_size() {
    set -- $(stty size)
    LINES=$1
    COLUMNS=$2
}
set_nonscrolling_line() {
    get_size
    case "$1" in
        t|to|top)
            non_scroll_line=0
            first_scrolling_line=1
            scroll_region="1 $(($LINES - 1))"
            ;;
        b|bo|bot|bott|botto|bottom)
            first_scrolling_line=0
            scroll_region="0 $(($LINES - 2))"
            non_scroll_line="$(($LINES - 1))"
            ;;
        *)
            echo 'error: first argument must be "top" or "bottom"'
            exit 1
            ;;
    esac
    clear
    tput csr $scroll_region
    tput cup "$non_scroll_line" 0
    printf %s "$2"
    tput cup "$first_scrolling_line" 0
}
reset_scrolling() {
    get_size
    clear
    tput csr 0 $(($LINES - 1))
}

# Set up the scrolling region and write into the non-scrolling line
set_nonscrolling_line "$1" "$2"
shift 2

# Run something that writes into the scolling region
"$@"
ec=$?

# Reset the scrolling region
printf %s 'Press ENTER to reset scrolling (will clear screen)'
read a_line
reset_scrolling

exit "$ec"

Vous pouvez l'utiliser comme ceci:

tmux split-window '/path/to/no_scroll_line bottom "Node instance foo" node foo.js'
tmux split-window '/path/to/no_scroll_line bottom "Node instance bar" node bar.js'
tmux split-window '/path/to/no_scroll_line bottom "Node instance quux" node quux.js'

Le script doit également fonctionner en dehors de tmux tant que le terminal prend en charge et publie ses capacités csret cupterminfo.

Chris Johnsen
la source
votre script fonctionne exactement comme je m'y attendais; la seule question: que dois-je google pour personnaliser la couleur de la "non_scroll_line"?
Andrey Lushnikov
1
Peut-être «couleur d'arrière-plan de la capacité terminfo» (c'est-à-dire lire la couleur dans la page de manuel terminfo). Vous pouvez utiliser tputpour inclure les séquences de contrôle appropriées dans l'argument «contenu de la ligne». Avec la plupart des terminaux, vous pouvez faire en sorte que la ligne soit «cyan (6) et vert (3) sur magenta (5)» avec no_scroll_line top "$(tput setaf 6; tput setab 5)Node: $(tput setaf 3)foo$(tput op)" node foo.js. setafdéfinit le premier plan, setabdéfinit l'arrière-plan, opréinitialise les couleurs par défaut des terminaux. Les capacités de couleur prennent un nombre compris entre 0–7, 0–15, 0–87 ou 0–255, selon l'émulation de votre terminal.
Chris Johnsen
Nous avons maintenant publié pymux. Cela affiche les barres de titre du volet: github.com/jonathanslenders/pymux
Jonathan Slenders
Il semble que le comportement est que le titre du volet est défini sur la commande exécutée dans le shell. Donc, il ne "collera" que si nous exécutons un processus de longue durée (qui sait également comment sortir la séquence d'échappement de réglage du titre) à l'intérieur.
Steven Lu
4
Veuillez jeter un œil à la réponse ci-dessous: stackoverflow.com/a/37602055/266453 tmux à partir de la version 2.3 prend en charge les titres dans les bordures de volet.
Dennis G
78

Cette fonctionnalité a été ajoutée à tmux dans ce commit . Ce n'est pas dans la version 2.2, mais il semble que ce sera dans la version 2.3.

Pour l'activer:

tmux set -g pane-border-status top

ou si vous préférez:

tmux set -g pane-border-status bottom

Pour définir un texte personnalisé comme ligne d'état de la bordure de votre volet, vous pouvez utiliser pane-border-format, par exemple, comme suit:

tmux set -g pane-border-format "#{pane_index} #{pane_current_command}"
kevmitch
la source
1
Cela montre le numéro du volet et un titre par défaut. Comment changer sa pensée?
adn le
Je ne suis pas sûr des numéros de volet, mais il répond comme un titre de fenêtre xterm aux séquences d'échappement. Par exemple, avec bash, j'ai défini PS1 = '[\ e] 0; \ u @ \ h: \ w \ a] $' pour obtenir "user @ host: working dir /"
kevmitch
Pour autant que je sache, vous définissez cette séquence à l'avance. Mais il n'y a aucun raccourci ou combinaison de touches qui les modifie. Donc, tmuxvous avez besoin d'une commande à l'extérieur tmuxpour le changer. Droite? Ou y a-t-il une séquence à l'intérieur qui peut le mettre à jour?
adn le
Ouais, vous venez de définir la variable dans le shell en cours d'exécution et elle se met à jour lorsque l'invite suivante est dessinée. Pour moi, il semble que tmux est un peu sommaire et ne le met à jour que lorsque vous passez à un autre volet.
kevmitch le
Vous pouvez en fait utiliser pane-border-formatpour définir une chaîne de format personnalisée pour le volet à afficher (le #{...}format habituel ). J'ai modifié votre réponse pour l'inclure.
Dennis G
32

Puisque tmux 2.6vous pouvez faire:

$ tmux select-pane -t {pane} -T {title}

# Examples:
$ tmux select-pane -T title1          # Change title of current pane
$ tmux select-pane -t 1 -T title2     # Change title of pane 1 in current window
$ tmux select-pane -t 2.1 -T title3   # Change title of pane 1 in window 2

Vous pouvez voir le titre par volet dans une barre d'état avec:

$ tmux set pane-border-status bottom      # For current window
$ tmux set -g pane-border-status bottom   # For all windows

Désactivez la barre d'état avec:

$ tmux set pane-border-status off       # For current window
$ tmux set -g pane-border-status off    # For all windows
Eyal Levin
la source
Savez-vous s'il existe un moyen d'empêcher tmux de changer le titre sous vous? Par exemple, si je définis le titre d'un volet, puis que je fais quelque chose dans ce volet, par exemple cd $HOME, le titre prend la valeur de $HOME. (Je vois ceci sur tmux 2.8.)
pdoherty926
1
@ pdoherty926 Peut-être que vous avez déjà la réponse, mais vérifiez set-window-option automatic-rename off.
noname
J'ai set-option -g allow-rename offdans mon .tmux.confdossier.
Eyal Levin le
1
Merci pour les suggestions. J'ai fini par utiliser pane-border-formatet une variable fournie par l'utilisateur (je ne suis pas sûr qu'il existe un nom officiel pour cette fonctionnalité) pour contrôler ce qui est affiché. Voici un exemple.
pdoherty926
14

Je travaille sur la barre d'état du volet pour tmux - ticket. Ma branche de développement peut être trouvée ici sur github: https://github.com/jonathanslenders/tmux

À l'heure actuelle, cela ajoute déjà une commande "titre" du volet de changement de nom . Il y a encore quelques bugs et l'API va s'améliorer. L'idée est de créer une barre d'état par volet, qui peut avoir une certaine mise en forme, comme la barre d'état de session. Comme le reste de tmux, tout devrait devenir scriptable et personnalisable. Une fois terminé et stable, il sera probablement inclus dans le tmux officiel.

Jonathan Slenders
la source
Pendant que vous y êtes, pouvez-vous faire en sorte que le titre du volet devienne le titre de la fenêtre par défaut pendant un volet de rupture?
djsadinoff
Cette branche n'a jamais été fusionnée dans tmux. Mais j'ai créé pymux à la place, qui a des barres de titre de volet: github.com/jonathanslenders/pymux
Jonathan Slenders
Cette commande ne fonctionne pas non plus sur la dernière version (commit a24260).
adn le
14

J'utilise la version 2.3 de tmux, je pense que le style de bordure n'est pas pris en charge dans les versions précédentes. C'est ce qui a fonctionné pour moi:

Pour chaque volet, définissez le titre:

printf '\033]2;My Pane Title\033\\'

Ensuite:

tmux set -g pane-border-format "#{pane_index} #T"
OriG
la source
9
Au moins aussi récent que tmux 2.6, vous pouvez changer le titre du volet dans tmux: select-pane -T "my title"fait ceci. Vous pouvez même configurer une liaison de clé, il vous suffit donc de fournir le titre:bind-key T command-prompt -p "New title:" 'select-pane -T "%%"'
lucasem
3
@lucasem peut-être que je n'ai pas suivi ce fil, mais cela semble être la réponse.
glaçon
@lucasem Je ne suis pas sûr à 100% mais je crois que votre méthode (qui IMO est la meilleure et la plus simple dans tout ce fil, pour les versions récentes de tmux) ne fonctionne que si l' pane-border-statusoption est définie sur quelque chose ( topou bottom).
cjauvin
11

Un gif vaut mille mots. ( source )

tmux-xpanes est un diviseur de terminal basé sur tmux, qui prend en charge l'affichage du titre pour chaque volet via l' -toption nouvellement ajoutée .

navigaide
la source
1
Un gif vaut mille mots, mais si jamais le lien pourrit, il n'en vaut pas la peine.
Fund Monica's Lawsuit
7

Oui , il y a une telle commande: tmux. Donnez un nom à votre session et elle s'affichera dans une barre d'état interne:

TMUX=0 tmux new-session -s my-new-session
event_jr
la source
2
Oui, merci pour votre réponse! Mais donc je vais devoir lancer une nouvelle session tmux dans chaque volet juste pour un titre en bas de celui-ci - un peu exagéré, n'est-ce pas?
Andrey Lushnikov
Je ne sais pas. C'est ça? L'as tu essayé? Combien de mémoire supplémentaire la session supplémentaire utilise-t-elle?
event_jr
ouais, j'utilise des sessions tmux imbriquées jusqu'à aujourd'hui. Je ne suis pas sûr de la consommation de mémoire et des choses comme ça - je n'aime pas le concept lui-même parce qu'il n'est pas pur.
Andrey Lushnikov
0

TL; DR

Ajoutez les configurations suivantes à votre fichier de configuration tmux (dans mon cas est ~/.tmux.conf.local)

# dispaly pane_current_path as the pane title
set -g pane-border-status top
set -g pane-border-format "#{pane_index} #{pane_current_path}"

puis exécutez:

tmux source-file ~/.tmux.con

Profitez-en

Merci à https://stackoverflow.com/a/37602055/5121972

sstruct
la source