diff --git a/content/articles/2025/bash_tmux_sessions/images/tmux.png b/content/articles/2025/bash_tmux_sessions/images/tmux.png new file mode 100644 index 0000000..08b36ce Binary files /dev/null and b/content/articles/2025/bash_tmux_sessions/images/tmux.png differ diff --git a/content/articles/2025/bash_tmux_sessions/images/tmux_normal_session.png b/content/articles/2025/bash_tmux_sessions/images/tmux_normal_session.png new file mode 100644 index 0000000..47ed5d0 Binary files /dev/null and b/content/articles/2025/bash_tmux_sessions/images/tmux_normal_session.png differ diff --git a/content/articles/2025/bash_tmux_sessions/index.md b/content/articles/2025/bash_tmux_sessions/index.md new file mode 100644 index 0000000..50badce --- /dev/null +++ b/content/articles/2025/bash_tmux_sessions/index.md @@ -0,0 +1,173 @@ +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 diff --git a/content/assets/backgrounds/tmux-logo-large.png b/content/assets/backgrounds/tmux-logo-large.png new file mode 100644 index 0000000..48cd4e8 Binary files /dev/null and b/content/assets/backgrounds/tmux-logo-large.png differ