Migration de alacritty+tmux vers kitty

2022-08-11 10 Min. lecture Shell

Cela fait un long moment que je n’ai plus écrit d’article, ne sachant pas la fréquentation de ce blog, je ne sais pas s’il y a des gens frustrés.

J’utilise tmux depuis plus de 10 ans et Alacritty depuis 2 ou 3 ans lorsque j’ai commencé à programmer un peu en Rust. Comme avec le langage Go, j’aime bien regarder les outils qui sont créés avec les langages que j’utilise, ça donne une bonne idée des possibilités du langage.

Tmux a été mon compagnon indispensable dans mon précédent boulot. J’avais un serveur d’administration avec tmux qui tournait en permanence et le matin quand j’allumais mon PC je me connectais en ssh et je récupérais ma session tmux avec toutes les consoles tels que je les avais laissées la veille.

J’ai maintenant changé de boulot, je n’utilise tmux que sur mon poste, du coup ce n’est plus la solution la plus pertinente. Autre point, avec Alacritty il n’est pas possible d’afficher des emojis en couleur, ce qui me pénalise dans la rédaction de certain document.

J’ai donc regardé du côté de kitty.

1. Présentation

Si vous n’avez jamais entendu parler de kitty, c’est que vous ne passez pas vos vacances à essayer des nouveaux outils et vous avez certainement raison.

kitty est un émulateur de terminal moderne avec accélération GPU (comme alacritty). Il est disponible pour Linux et macOS. Écrit en C et en python, il est extensible grâce à des scripts python. Il prend en charge des plugins appelés kittens, et est livré avec certains plugins par défaut, comme un changeur de thème et un utilitaire ssh.

kitty offre une grande partie des fonctionnalités de tmux - des choses comme la gestion des volets (pane), les raccourcis clavier personnalisés, le contrôle à distance. Mais, à mon avis, kitty a quelques avantages qui lui sont propres. D’abord, kitty est un émulateur de terminal. Tmux n’est qu’un multiplexeur de terminal, et nécessite donc aussi un émulateur de terminal. Je préfère simplifier le nombre d’outils que j’utilise. kitty peut remplacer à la fois tmux et alacritty.

Le truc qui m’épate le plus avec kitty, c’est l’affichage d’image nativement dans le terminal. Je faisais ça avant dans ranger grâce à ueberzug, mais ce n’est pas parfait.

2. Migration

Ce qui me surprend quand je change d’outil, c’est la capacité de notre cerveau à apprendre de nouveaux raccourcis clavier (à moins que ce soit mes doigts qui apprennent). Et quand on fait du vim sous i3/sway tout les jours on connait un paquet de raccourcis clavier.

Pour la période de transition, j’ai tout de même ajouté dans la configuration de kitty quelques commandes avec la syntaxe tmux, mais du coup hors de question de lancer tmux dans kitty.

Lorsque je migre vers un outil, j’essaie de garder au maximum les raccourcis par défaut de l’outil. Quand je suis passé de screen à tmux, je n’ai surtout pas gardé Ctrl-A pour l’appel des commandes (contrairement à certains anciens collègues). Avantage avec kitty, les commandes ne se ressemblent pas du tout, la plus part des appels se font avec Ctrl-shift.

2.1. Vocabulaire

Autre point avant de parler de la configuration, je vais faire deux petits tableaux avec les comparaisons des noms et de quelques commandes entre tmux et kitty.

Table 1. Comparatif des noms
kittytmuxdocument
sessionsessionsession
windowpanepane, volet
tabwindowonglet
Table 2. Comparatif de quelques commandes
kittytmuxcommentaire
kitty @ launch --type=tab .tmux new-windowCréation d’un nouvel onglet
kitty @ ls | jq -r '.[].tabs[].title'tmux list-windowsListe les onglets
kitty @ focus-tab -m "title:test"tmux select-window -t "test"Se déplacer sur l’onglet test
kitty @ ls | jq -r '.[].tabs[] | select(.is_focused==true) | .title'tmux display-message -p '#W'Nom de l’onglet courant
kitty @ launch .tmux split-windowCrée un nouveau pane
kitty @ launch --env "FOO=BAR" vimtmux new-window -e "FOO=BAR" vimLance la commande vim avec la variable d’environnement FOO=BAR

3. Configuration

Mon fichier de configuration $HOME/.config/kitty/kitty.conf est relativement simple.

3.1. Les fonts

Dans un premier temps je spécifie la police de caractères que je souhaite utiliser. Ici j’utilise une police qui contient des emojis (NerdFonts) mais cela n’est pas nécessaire avec kitty. Il est possible de spécifier une police pour un bloque de code utf8.

1
2
3
4
5
6
7
8
9
10
11
12
font_family       JetBrainsMono Nerd Font
bold_font         JetBrains Mono Bold Nerd Font Complete Mono
italic_font       JetBrains Mono Italic Nerd Font Complete Mono
bold_italic_font  JetBrains Mono Bold Italic Nerd Font Complete Mono

modify_font       strikethrough_position 120%
modify_font       strikethrough_thickness 250%
modify_font       underline_position 150%
modify_font       underline_thickness 1.25

font_size         12.0
disable_ligatures cursor

3.2. Mappings

J’ajoute ici les raccourcis clavier :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
map ctrl+shift+enter new_window_with_cwd
map ctrl+shift+alt+t set_tab_title
map ctrl+left        previous_tab
map ctrl+right       next_tab
map alt+left         neighboring_window left
map alt+right        neighboring_window right
map alt+down         neighboring_window down
map alt+up           neighboring_window up
map ctrl+shift+!     launch --location=vsplit
map ctrl+shift+_     launch --location=hsplit
map ctrl+enter       new_tab
map ctrl+alt+right   move_window right
map ctrl+alt+left    move_window left
map ctrl+alt+up      move_window up
map ctrl+alt+down    move_window down
map ctrl+shift+alt+left move_tab_backward
map ctrl+shift+alt+right move_tab_forward
  • ligne 1: Création d’un nouveau pane dans le même répertoire courant
  • ligne 2: Modifier le nom du volet
  • ligne 3: Se déplacer sur l’onglet précédent
  • ligne 4: Se déplacer sur l’onglet suivant
  • ligne 5: Se déplacer sur le pane de gauche
  • ligne 6: Se déplacer sur le pane de droit
  • ligne 7: Se déplacer sur le pane de bas
  • ligne 8: Se déplacer sur le pane de haut
  • ligne 9: Création d’un nouveau pane horizonal (mode split)
  • ligne 10: Création d’un nouveau pane vertical (mode split)
  • ligne 11: Création d’un nouvel onglet
  • ligne 12: Déplacer le pane vers la droit
  • ligne 13: Déplacer le pane vers la gauche
  • ligne 14: Déplacer le pane vers le haut
  • ligne 15: Déplacer le pane vers le bas
  • ligne 16: Déplacer le tab vers la gauche
  • ligne 17: Déplacer le tab vers la droite

3.3. Tmux

Parfois les réflexes ont la vie dure, j’ai donc mis ici les commandes que j’utilisais le plus avec tmux :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
map ctrl+b>c new_tab
map ctrl+b>| launch --location=vsplit
map ctrl+b>_ launch --location=hsplit
map ctrl+b>n next_tab
map ctrl+b>p previous_tab
map ctrl+b>z kitten zoom_toggle.py
map ctrl+b>w select_tab
map ctrl+b>ctrl+b goto_tab 0
map ctrl+b>0 goto_tab 1
map ctrl+b>1 goto_tab 2
map ctrl+b>2 goto_tab 3
map ctrl+b>3 goto_tab 4
map ctrl+b>4 goto_tab 5
map ctrl+b>5 goto_tab 6
map ctrl+b>6 goto_tab 7
map ctrl+b>7 goto_tab 8
map ctrl+b>8 goto_tab 9
map ctrl+b>9 goto_tab 10
  • ligne 1: Création d’un nouvel onglet
  • ligne 2: Création d’un nouveau pane vertical (mode split)
  • ligne 3: Création d’un nouveau pane horizonal (mode split)
  • ligne 4: Se déplacer sur l’onglet suivant
  • ligne 5: Se déplacer sur l’onglet précédent
  • ligne 6: (Dé)Zoom sur le pane courant (mode stack)
  • ligne 7: Liste les onglets pour se déplacer sur l’un d’eux. Contrairement à tmux, kitty n’affiche pas un aperçu de l’onglet avec l’ensemble des panes.
  • ligne 8: Retour sur le tab précédent
  • lignes 9-18: Déplacement sur le tab numéro n-1

Sauf pour le dernier, sinon je pense retirer rapidement ces raccourcis.

3.4. Thème

1
2
3
4
5
6
7
8
9
10
11
12
13
14
background_opacity      0.95
# fade, slant, separator, powerline (slanted, angled, round), custom
tab_bar_style           powerline
tab_powerline_style     angled
active_tab_foreground   #d8dee9
active_tab_background   #1b1e25
inactive_tab_background #2e3440
inactive_tab_foreground #7b7b7b
inactive_tab_font_style italic
active_tab_font_style   bold
tab_bar_min_tabs        2
inactive_text_alpha     0.6

include ./nord.conf
  • ligne 1: Un tout petit peu de transparence
  • ligne 2: Le style powerline avec comme séparateur >
  • ligne 11: On affiche la barre à partir du deuxième tab
  • ligne 12: Diminution de la luminosité du texte des fenêtres inactives

Il est possible de personnaliser la barre d’onglet comme ont le souhaite avec un système de template.

3.5. Bells

J’aime les PC silencieux, donc pas de notification intempestive.

enable_audio_bell    no
window_alert_on_bell no
visual_bell_duration 0.0
visual_bell_color    none

3.6. Les Markers

kitty a la capacité de surligner du texte à l’écran sur la base d’expressions régulières. Cela peut être utile pour mettre en évidence des mots ou des phrases dans les sorties standards de vos programmes, ou dans les commandes que vous saisissez.

J’ai donc ajouté ces raccourcis qui me permettent d’en définir de nouvelles expression régulières à la volé, et d’en avoir 2 prédéfinit que je peux activer si besoin.

map ctrl+m>m create_marker
map ctrl+m>: remove_marker
map ctrl+m>e toggle_marker iregex 1 \\bERROR\\b 2 \\bWARNING\\b
map ctrl+m>h toggle_marker iregex 2 https(s)?://[-a-z0-9.]+ 

3.7. Autres

1
2
3
4
5
6
allow_remote_control yes
enabled_layouts      splits, tall, grid, fat, vertical, stack
listen_on            none
shell_integration    on
scrollback_lines     20000
linux_display_server x11
  • ligne 1: Indispensable pour pouvoir lancer des commandes kitty depuis le shell
  • ligne 2: Liste des layouts utilisables
  • ligne 3: Pas de port ni de socket en écoute
  • ligne 4: Active l’intégration des outils shell (zsh, fish et bash)
  • ligne 5: Possibilité de remonter 20000 lignes
  • ligne 6: Affichage x11 pour pouvoir partager kitty sur Jitsi

4. Fonctionnalités

4.1. Contrôle via scripts

En plus des raccourcis que j’ai décrit rapidement plus haut, kitty permet de piloter les layouts (comme sous tmux). Pour cela il faut activer dans la configuration l’option allow_remote_control yes.

Je vous mets ci-dessous mes scripts qui fonctionnent avec kitty et tmux.

4.1.1. Se déplacer sur un onglet

Ce premier scripts permet de se déplacer sur l’onglet passé en paramètre.

$HOME/.local/bin/tsw
#!/bin/bash

if [[ "$TERM" == "xterm-kitty" ]]; then
 win=$(kitty @ ls | jq -r '.[].tabs[].title' | grep "^$1$" | head -n 1)
  if [ "$win" == "" ]; then
    exit 1 
  else
    kitty @ focus-tab -m "title:$win"
  fi
else
  # Ancienne commandes pour tmux
  win=$(tmux list-windows | sed 's/(.*$//' | grep "[ ]$1[- *]" |awk -F ':' '{print $1}' | head -n 1)
  if [ "$win" == "" ]; then
    exit 1 
  else
    tmux select-window -t "$win"
  fi
fi

Dans kitty la commande kitty @ ls permet de retourner plein d’informations intéressantes au format json. Ici j’utilise jq et lui demande t’afficher la liste des titles des tabs. Je récupère celui qui correspond parfaitement et je ne garde que le premier.

Ensuite j’appelle la commande kitty @ focus-tab avec l’option -m (match) pour prendre le focus sur l’onglet dont le titre correspond à $win.

4.1.2. Ouvrir un nouvel onglet avec le nom passé en paramètre

Ici je fais appel au premier script pour vérifier que l’onglet n’existe pas déjà. S’il existe la commande tsw place le focus dessus, sinon je crée un nouvel onglet.

$HOME/.local/bin/tnw
#!/bin/bash
win="$1"
if [[ "$TERM" == "xterm-kitty" ]]; then
  tsw "$win" || kitty @ launch --type=tab --tab-title "$win" .
else
  tsw "$win" || tmux new-window -n "$win" "/usr/bin/zsh"
fi

4.1.3. Ouvrir une connexion ssh dans un nouvel onglet

Ce script reprend l’idée du précédent mais ouvre une session ssh dans l’onglet dont le nom est passé en paramètre.

$HOME/.local/bin/tssh
#!/bin/bash
if ! ssh-add -l > /dev/null; then
  ssh-add
fi
win="$1"
if [[ "$TERM" == "xterm-kitty" ]]; then
  tsw "$win" || kitty @launch --type=tab --tab-title "$win" kitty +kitten ssh -A "$win"
else
  tsw "$win" || tmux new-window -n "$win" ssh -A "$win"
fi

Le point intéressant à noter ici est le double appel de kitty. Le premier appel permet de créer l’onglet et le deuxième permet d’activer la fonctionnalité permettant de recopier le contexte complet de l’environnement ssh.

Si dans un premier temps je lance tssh srv1, un nouvel onglet est crée et une connexion ssh sur le serveur srv1 est ouverte dessus. Ensuite si j’appuie sur ctrl-shift-enter un nouveau pane est ouvert sur le serveur srv1 dans le même répertoire que la fenêtre appelante.

4.2. Intégration aux shells

Comme indiqué dans la documentation, kitty permet d’interagir avec les shells zsh, bash et fish.

Voici quelques commandes intéressantes.
  • ctrl-shift-g permet d’afficher dans less le retour de la dernière commande.
  • ctrl-shift-z/ctrl-shift-x permet de remonter ou descendre d’un appel de commande à l’autre.
  • Il est possible de cloner totalement une console avec son environnement complet.
  • Mise à jour de la barre d’onglet automatiquement avec le contexte du shell.

4.3. Extension avec scripts python

Ci dessous un exemple simple d’extension de kitty, que j’appelle avec le raccourcis ctrl+shift+z ou ctrl-b>z comme avec tmux.

from kittens.tui.handler import result_handler


def main(args):
    pass


@result_handler(no_ui=True)
def handle_result(args, answer, target_window_id, boss):
    tab = boss.active_tab
    if tab is not None:
        if tab.current_layout.name == 'stack':
            tab.last_used_layout()
        else:
            try:
                tab.current_layout.must_draw_borders = True
                tab.goto_layout('stack')
            finally:
                tab.current_layout.must_draw_borders = False

Cela permet de zoomer et dézoomer sur le pane courant. Contrairement à tmux, il est possible de basculer sur les autres panes comme s’ils étaient toujours afficher. C’est le comportement du mode stack.

5. Conclusion

Migration terminée, je vais commencer à perdre un peu d’agilité sur tmux et en acquérir avec kitty. La migration de mes scripts est terminée, je laisserai certainement la double gestion tmux/kitty pendant un petit moment.

Voici donc la fin de ce rapide retour d’expérience sur les 2 jours que j’ai passé à tester kitty. Je complèterai cet article si je trouve des nouvelles fonctionnalités.