Title: Ma configuration Tmux: raccourcis clavier et gestion des sessions Category: sysadmin Tags: bash, tmux, scripts Date: 2025-05-21 22:04 Cover: assets/backgrounds/tmux-logo-large.png Je suis depuis quelques années fervent utilisateur de [Sway][sway], gestionnaire de fenêtre en mode tiling. J'utilisais donc naturellement ses fonctionnalités pour gérer plusieurs fenêtres de mon émulateur de terminal et les organiser à ma guise. Mais force est de constater que ce fonctionnement montrait ses limites, j'ai donc choisi d'utiliser un multiplexeur de terminal. J'ai d'abord testé [Zellij][zellij] à la mode en ce moment. Il est vrai que c'est un outil rapide à prendre en main mais je n'ai pas accroché: il est pas assez personnalisable à mon goût. J'ai par contre beaucoup apprécié la configuration par défaut des raccourcis clavier. Je me suis donc tourné vers [Tmux][tmux] que j'utilisais il y a maintenant quelques années. C'est un logiciel libre installable facilement sur tout une ribambelle de systèmes d'exploitation. Mais **sa configuration par défaut est un peu rustique**, il faut mettre les mains dans sa configuration pour l'adapter à ses besoins. Je vais détailler certains éléments de ma configuration. Ces morceaux de configurations sont inspirés de beaucoup d'autres trouvées ci et là, que se soit via des articles de blogs, des dépôts de *dotfiles*, forums, etc. [sway]: https://swaywm.org [zellij]: https://zellij.dev/ [tmux]: https://github.com/tmux/tmux/wiki ## Naviguer entre les éléments Pour gérer les raccourci clavier dans le fichier de configuration de *Tmux*, Il faut utiliser la commande `bind`. Par défaut Tmux utilise un raccourci clavier spécial -- appelé *préfixe* -- avant de pouvoir lancer un autre raccourci clavier pour par exemple changer de fenêtre. Si en plus de ne pas être des plus pratique dans sa configuration par défaut (`Ctrl` + `b`), ce préfixe ralenti la navigation entre les éléments. Mais `bind` propose l'option `-n` afin de se passer du préfixe, très pratique pour définir les raccourcis clavier les plus utilisés. ### Les panneaux D'abord je configure les déplacement entre les panneaux d'une fenêtre avec `Alt` et `h`, `j`, `k`, `l`. Pour les redimensionner, j'utilise `Alt` + `Shift` et `h`, `j`, `k`, `l`. Voici la configuration associée: ``` # move to pane bind -n -N "Select pane to the left of the active pane" M-h select-pane -L bind -n -N "Select pane below the active pane" M-j select-pane -D bind -n -N "Select pane above the active pane" M-k select-pane -U bind -n -N "Select pane to the right of the active pane" M-l select-pane -R # resize pane bind -n -r -N "Resize the pane left by 5" M-H resize-pane -L 5 bind -n -r -N "Resize the pane down by 5" M-J resize-pane -D 5 bind -n -r -N "Resize the pane up by 5" M-K resize-pane -U 5 bind -n -r -N "Resize the pane right by 5" M-L resize-pane -R 5 ``` Pour la création d'un nouveau panneau, `Alt` + `n` me permet de découper le panneau courant verticalement et `Alt` + `Shift` + `n` horizontalement: ``` bind -n M-n split-window -h -c "#{pane_current_path}" bind -n M-N split-window -v -c "#{pane_current_path}" ``` L'option `-c` de la commande `split-window` permet de définir le répertoire courant. Cette option utilise le format `#{pane_current_path}` fait référence au répertoire courant du panneau actif au moment de l'activation de la commande. Plus pratique pour ouvrir un shell rapidement. ### Les fenêtres Pour la création de nouvelle fenêtre, j'utilise la configuration par défaut à savoir *préfixe* suivi de `c`. J'ai juste changé la configuration du préfixe par `Ctrl` + `a` plus pratique Pour naviguer entre les fenêtres, j'utilise `Alt` + `1`, `2`, `3`, `4`, `5` sans *préfixe*. Je n'utilise pas plus de 5 fenêtres par session, en règle générale 3 sont même suffisantes. Voici la configuration associée: ``` # change window with Alt+{1..5} bind -n -N "Goto window 1" M-1 select-window -T -t 1 bind -n -N "Goto window 2" M-2 select-window -T -t 2 bind -n -N "Goto window 3" M-3 select-window -T -t 3 bind -n -N "Goto window 4" M-4 select-window -T -t 4 bind -n -N "Goto window 5" M-5 select-window -T -t 5 ``` ## Les sessions Personnellement j'aime bien regrouper les éléments d'un même projet dans une session Tmux. Par exemple j'ai un espace de travail *blog* avec au moins deux fenêtres: * une pour mon éditeur de texte et un terminal afin de réaliser des actions rapidement comme regarder mon historique git ou lancer une capture d'écran * une seconde pour lancer des commandes relatives à mon gestionnaire de contenu comme le serveur de développement local ou le déploiement. J'ouvre aussi d'autres fenêtres aux besoin, comme pour consulter la page de manuel de tmux. ![Capture d'écran de mon terminal utilisant Tmux avec un thème personnel. On y voit mes différentes fenêtres et les panneaux de celle en cours]({attach}./images/tmux.png) ### Me déplacer dans mes dépôts de code locaux Dans mon flux de travail quotidien, j'utilise [ghq][ghq] pour gérer mes dépôts de code locaux. Je l'utilise à la place de la commande `git clone` mais aussi pour me déplacer facilement d'un dépôt local à un autre avec l'aide de [fzf][fzf] et de de l'alias shell suivant: ```zsh alias g="cd '$(ghq list -p | fzf)'"; ``` L'idée est donc d'utiliser ces outils couplés à Tmux pour démarrer des sessions en y ajoutant fenêtres et panneaux automatiquement. ### Un script shell pour lancer une session J'ai donc créé un script Bash qui me permet de créer ou me déplacer facilement dans mes différentes sessions. Ce script est disponible [dans mon dépôt dotfile][eph_nix]. Je peux ainsi créer une session, y ajouter des fenêtres et panneaux, lancer des commandes ou encore changer le dépôt git courant. Il se lance à l'intérieur d'un client Tmux que se soit lancé depuis un shell. ```shell create-tmux-session.sh -n blog -p ephase/blog "run:nvim ." \ vsplit:20 neww:shell hsplit:50 "run:task serve" ``` Si la session `blog` existe, alors elle sera activée sur le client Tmux en cours, sinon elle sera crée avec tous les éléments définis par les commandes -- ici `run`, `vsplit`, `neww`, `hsplit` et `run` -- et sera activée. [eph_nix]:https://git.epha.se/ephase/nix/src/branch/main/modules/home-manager/cli/tmux/files ### Et des raccourcis clavier D'abord je veux pouvoir lancer des sessions Tmux pour des projets non définis à l'avance. Un menu est alors affiché permettant de choisir le projet à ouvrir dans cette session comme le montre la capture d'écran ci-dessous: ![Capture d'écran montrant le menu de sélection des projets pour l'ouverture d'une nouvelle session dans une popup]({attach}./images/tmux_normal_session.png) J'utilise pour cela les raccourcis `Alt` + `F1` à `Alt` + `F4`. Voici la configuration associée: ```text # define sessions with Alt+F{1..4} for general purpose sessions bind -n M-F1 if 'tmux has-session -t 1' {switch-client -t 1} \ {display-popup -E -E 'create-tmux-session -i 1'} bind -n M-F2 if 'tmux has-session -t 2' {switch-client -t 2} \ {display-popup -E -E 'create-tmux-session -i 2'} bind -n M-F3 if 'tmux has-session -t 3' {switch-client -t 3} \ {display-popup -E -E 'create-tmux-session -i 3'} bind -n M-F4 if 'tmux has-session -t 4' {switch-client -t 4} \ {display-popup -E -E 'create-tmux-session -i 4'} ``` Lors de l'activation d'un ce des raccourcis, Tmux vérifie si la session existe (`if 'tmux has-session -t 1'`). Si elle existe alors elle est activée (`switch-client -t 1`), Sinon une fenêtre popup est affichée et mon script de création de session est lancé. Le passage par une popup est nécessaire pour pouvoir afficher le menu `fzf` qui nécessite une session shell interactive. Pour gérer mes projets du quotidien comme par exemple mon installation nix, ou ce blog, j'utilise les raccourcis `Alt` + `F5`-`F10` ```text # Alt+F10 for launching my Nix project bind -n M-F10 run 'create-tmux-session -n config -p nix "run:nvim ." vsplit:20' bind -n M-F9 run 'create-tmux-session -n blog -p xieme-art "run:nvim ." vsplit neww:shell' ``` Ici pas besoin d'interaction avec l'utilisateur, inutile d'utiliser `has-session` et d'utiliser fenêtre popup: le script s'occupe de tout. ## En conclusion Les éléments de configuration que j'ai détaillé ici me permettent de naviguer rapidement dans mes différents espaces de travail. Je gagne aussi en efficacité et garde organisé mes session, fenêtres et panneaux. Bien sûr j'aurais pu utiliser un plugin ou un outils prêt à l'emploi pour gérer mes sessions -- il en existe un nombre conséquent -- mais aucun ne correspondait à mon usage. Pour écrire mon script je me suis d'ailleurs inspirée de [tmuz-sessionizer][tmux_session] par ThePrimeagen. Au final, j'ai un outil correspondant à mes attentes en moins de 220 ligne de Bash (aide intégrée). Cette configuration m'accompagne au quotidien et j'ai déjà des idées pour la faire évoluer. [ghq]:https://github.com/x-motemen/ghq [fzf]:https://junegunn.github.io/fzf/ [tmux_session]:https://github.com/ThePrimeagen/tmux-sessionizer