Installer zsh et le thème Powerlevel10k avec un module customConfig

Le shell est l'endroit où l'on passe le plus de temps quand on aime la ligne de commande, autant qu'il soit agréable et bien renseigné. Cet article détaille un fichier zsh.nix complet : zsh, oh-my-zsh, le thème Powerlevel10k, les polices qui vont avec, et les quelques pièges qui font perdre une soirée quand on ne les connaît pas.

:information_source: Remarque
Cet article fait partie d'une série sur les modules à importer dans customConfig. Si vous n'avez jamais édité ces fichiers, lisez d'abord Ajouter vos programmes et Configuration personnalisée.


Ce que vous obtenez

  • zsh comme shell de connexion, avec la complétion, les suggestions au fil de la frappe et la coloration syntaxique ;
  • oh-my-zsh et une sélection de greffons ;
  • Powerlevel10k, une invite de commande qui affiche la branche git, le statut du dépôt, la durée de la dernière commande et le reste ;
  • une police Nerd Font, sans laquelle l'invite afficherait des carrés à la place des icônes.

Le fichier

Créez /etc/nixos/customConfig/zsh.nix, en remplaçant nobodyz par votre identifiant :

{ lib, pkgs, ... }:

{
  users.users.nobodyz.shell = pkgs.zsh;
  users.users.root.shell = pkgs.zsh;

  programs.zsh = {
    enable = true;
    enableCompletion = true;
    autosuggestions.enable = true;
    syntaxHighlighting.enable = true;

    ohMyZsh = {
      enable = true;
      theme = "powerlevel10k/powerlevel10k";
      customPkgs = [ pkgs.zsh-powerlevel10k ];
      plugins = [
        "git"
        "z"
        "extract"
        "history"
        "command-not-found"
        "sudo"
      ];
    };

    interactiveShellInit = lib.mkAfter ''
      set -o vi

      [ -f $HOME/.p10k.zsh ] && source $HOME/.p10k.zsh
      [ -f $HOME/.aliasrc ]  && source $HOME/.aliasrc
    '';
  };

  fonts.packages = [ pkgs.nerd-fonts.caskaydia-cove ];

  environment.systemPackages = with pkgs; [
    fzf
    bat
    ripgrep
    fd
  ];
}

Ce que fait chaque ligne

Deux réglages, pas un. programs.zsh.enable installe zsh et lui donne une configuration globale dans /etc/zshrc, mais ne change le shell de personne. C'est users.users.<votre identifiant>.shell qui décide du shell au moment de la connexion. Les deux sont nécessaires, et c'est l'oubli le plus courant : on se demande pourquoi le terminal ouvre toujours bash.

La ligne pour root est facultative. Elle sert quand vous ouvrez un sudo -i et que vous préférez retrouver vos habitudes.

Les trois compagnons. enableCompletion active la complétion par Tab, bien plus riche que celle de bash. autosuggestions propose en gris la fin de la commande d'après votre historique, la flèche droite l'accepte. syntaxHighlighting colore la commande pendant que vous la tapez : en vert si elle existe, en rouge sinon, ce qui évite pas mal de fautes de frappe.

Powerlevel10k et customPkgs. Le thème ne fait pas partie de oh-my-zsh. Sans la ligne customPkgs, vous obtenez un theme not found à chaque ouverture de terminal. customPkgs copie le thème dans le dossier que oh-my-zsh explore, avec l'arborescence exacte qu'il attend.

Les greffons. Chacun ajoute des alias et des fonctions :

Greffon Ce qu'il apporte
git une centaine d'abréviations, de gst pour git status à gco pour git checkout
z z nom vous téléporte dans un dossier que vous visitez souvent, sans taper son chemin
extract x archive.tar.gz décompresse n'importe quel format sans chercher les bonnes options
history h pour l'historique, recherche facilitée
command-not-found suggère le paquet à installer quand une commande n'existe pas
sudo deux appuis sur Échap ajoutent sudo devant la commande en cours

La liste complète se trouve sur le dépôt de oh-my-zsh.

lib.mkAfter, et pourquoi c'est important. Ce bloc est inséré après le chargement de oh-my-zsh. Sans cela, certains greffons redéfinissent vos alias après vous, et vous passez un moment à vous demander pourquoi votre ll ne fait pas ce que vous avez écrit. Avec mkAfter, vous passez en dernier, donc vous gagnez.

set -o vi donne les raccourcis de vim en ligne de commande : Échap pour passer en mode normal, puis w, b, dw et compagnie. Retirez la ligne si vous préférez les raccourcis Emacs, qui sont ceux par défaut.

Les quatre outils. fzf est un sélecteur interactif qui transforme la recherche dans l'historique, bat est un cat avec coloration et numéros de ligne, ripgrep un grep bien plus rapide, fd un find lisible. Ils ne sont pas obligatoires, mais ils vont de pair avec ce genre de configuration.


Régler Powerlevel10k

Le thème se configure avec un assistant, à lancer une fois après la première ouverture de zsh :

p10k configure

Il pose une dizaine de questions : jeu d'icônes, séparateurs, invite sur une ou deux lignes, position de l'heure, densité d'information. À la fin il écrit ~/.p10k.zsh, que la ligne source $HOME/.p10k.zsh de notre module recharge ensuite à chaque ouverture.

Vous pouvez relancer l'assistant autant de fois que vous voulez, il réécrit le fichier.

:warning: Attention
Si ~/.zshrc n'existe pas, zsh lance l'assistant zsh-newuser-install à chaque ouverture de terminal, ce qui est déroutant quand on ne s'y attend pas. La vraie configuration étant chargée depuis /etc/zshrc, un fichier vide suffit à le faire taire :

touch ~/.zshrc

La question des polices

Powerlevel10k affiche des icônes qui n'existent pas dans les polices ordinaires. Elles viennent des Nerd Fonts, des polices classiques auxquelles on a ajouté des milliers de symboles.

Installer la police ne suffit pas : il faut encore la sélectionner dans les préférences de votre terminal. Sans cela vous verrez des carrés ou des points d'interrogation, et vous croirez à tort que le thème est cassé.

Notre module n'installe qu'une police, CaskaydiaCove. Pour tout prendre, au prix de plusieurs gigaoctets :

{
  fonts.packages = builtins.filter lib.isDerivation (builtins.attrValues pkgs.nerd-fonts);
}

Les autres noms suivent la même forme : pkgs.nerd-fonts.jetbrains-mono, pkgs.nerd-fonts.fira-code, pkgs.nerd-fonts.hack.


Activer le module

Dans /etc/nixos/customConfig/default.nix :

{
  imports = [ ./zsh.nix ];

  environment.systemPackages = [
  # Add your stable apps here (exemple: pkgs.btop)

Puis :

glf-update

Le changement de shell ne prend effet qu'à la prochaine connexion. Déconnectez-vous et reconnectez-vous, ou vérifiez tout de suite en lançant zsh à la main.


Les options que vous pouvez changer

  • Un autre thème. theme = "agnoster"; ou theme = "robbyrussell"; sont des classiques qui ne demandent pas de customPkgs, puisqu'ils sont fournis avec oh-my-zsh. Vous pouvez alors retirer la ligne customPkgs et le source de ~/.p10k.zsh.
  • Se passer de oh-my-zsh. Il apporte beaucoup, mais il ralentit aussi le démarrage. Powerlevel10k fonctionne très bien seul :
    programs.zsh.promptInit = "source ${pkgs.zsh-powerlevel10k}/share/zsh-powerlevel10k/powerlevel10k.zsh-theme";
    
  • Vos alias. Plutôt que d'allonger interactiveShellInit, écrivez-les dans ~/.aliasrc, que notre module charge déjà s'il existe. Vous les modifiez alors sans reconstruire le système.
  • Poser vos fichiers depuis Nix. Si vous tenez à ce qu'une réinstallation vous rende exactement le même shell, rangez vos fichiers dans customConfig, exposez-les dans /etc, et copiez-les au premier login sans écraser une personnalisation ultérieure :
    {
      environment.etc."glfos/zsh/p10k.zsh".source = ./p10k.zsh;
    
      system.userActivationScripts.dotfilesZsh.text = ''
        if [ ! -f "$HOME/.p10k.zsh" ]; then
          cp /etc/glfos/zsh/p10k.zsh "$HOME/.p10k.zsh"
          chmod u+w "$HOME/.p10k.zsh"
        fi
      '';
    }
    
    Le test if [ ! -f ... ] est la partie importante : sans lui, chaque mise à jour du système écraserait vos retouches locales.
  • Aller plus loin. Home Manager permet de décrire tout votre dossier personnel de façon déclarative, shell compris. C'est plus cohérent, mais c'est aussi un autre univers à apprendre.

En cas de problème

  • Le terminal ouvre toujours bash. Il manque users.users.<votre identifiant>.shell = pkgs.zsh;, ou vous n'avez pas rouvert la session.
  • theme not found : la ligne customPkgs = [ pkgs.zsh-powerlevel10k ]; est absente.
  • Des carrés à la place des icônes : la police Nerd Font n'est pas sélectionnée dans les préférences du terminal.
  • L'assistant zsh-newuser-install revient sans cesse : touch ~/.zshrc.
  • Un greffon fait échouer le démarrage. Les greffons de niche disparaissent parfois des versions récentes de oh-my-zsh, et le chargement se plaint à chaque ouverture. Retirez le nom fautif de la liste, le message vous le donne.
  • L'invite est lente à s'afficher dans un gros dépôt git : lancez p10k configure et choisissez le mode d'affichage instantané, qui montre l'invite immédiatement puis complète les informations.

Voir aussi