Oh My Posh, prompt esthétique et configurable
Par Maxime Bréhin • Publié le 5 décembre 2022 • 4 min

Utiliser Git dans le terminal sans avoir une invite de commande / un prompt adaptés, c’est un peu comme mettre des chaussettes avec des tongues en hiver, c’est moche et c’est sous-optimal !

Le souci avec les terminaux, c’est qu’il en existe plein ! Comment alors trouver une solution adaptée à chacun ? On avait écrit il y a un bail un article décrivant comment configurer un prompt Git à la mano. Cette méthode est toujours efficace et offre le bénéfice du minimalisme. Par contre pour le design, c’est pas ouf !

Aperçu du prompt configuré à la main

Il y a quelques temps nous étions passés à Powerline, plus sympa, (un peu) portable, et qui propose quelques infos liées à quelques technos (Git, Python, Ruby). Par contre il pour le configurer on pouvait se brosser.

Aperçu de l’invite de commande Powerline

Et puis Oh My Posh est apparu dans nos radars ! Bien plus évoluée, plus facile à installer et à configurer, traitant d’un très large spectre de technos (voir la partie “Segments” de la doc).

Aperçu de l’invite de commande Oh My Posh

On est donc vite tombé sous le charme 😍. À certains égards on peut trouver cette invite de commande trop verbeuse, mais puisqu’on peut la configurer aisément, ça devient vite facile d’en faire une version “light”.

Pour ce qui est de l’installation et de la configuration, je te renvoie directement à sa documentation qui est très bien faite !

Exemple : le mode concis

Je prends ici l’exemple de mon terminal Linux (sous-système sur Windows / WSL2) auquel je passe la configuration au chargement de Oh My Posh dans mon fichier racine .bashrc :

eval "$(oh-my-posh init bash --config ~/.ohmyposh-themes/git.omp.json)"

Le thème se contente de lister le répertoire courant et les statuts Git :

Aperçu de l’invite de commande Oh My Posh en mode "concis"

En définitive on ne gagne pas beaucoup d’espace, on supprime seulement les compléments d’analyse des technos détectées dans le répertoire du projet courant.

{
  "$schema": "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json",
  "blocks": [
    {
      "alignment": "left",
      "segments": [
        {
          "background": "#f1184c",
          "foreground": "#242424",
          "powerline_symbol": "\ue0c4",
          "style": "powerline",
          "template": "\uf0e7",
          "type": "root"
        },
        {
          "background": "#ff479c",
          "foreground": "#ffffff",
          "leading_diamond": "\ue0b6",
          "trailing_diamond": "\ue0b0",
          "powerline_symbol": "\ue0b0",
          "properties": {
            "folder_separator_icon": " \ue0b1 ",
            "home_icon": "~",
            "style": "folder"
          },
          "style": "diamond",
          "template": "\{\{ .Path \}\} ",
          "type": "path"
        },
        {
          "background": "#3a96ff",
          "background_templates": [
            "\{\{ if and (gt .Ahead 0) (gt .Behind 0) \}\}#ff4500\{\{ end \}\}",
            "\{\{ if gt .Ahead 0 \}\}#B388FF\{\{ end \}\}",
            "\{\{ if gt .Behind 0 \}\}#B388FF\{\{ end \}\}"
          ],
          "foreground": "#ffffff",
          "leading_diamond": "\ue0b6",
          "powerline_symbol": "\ue0b0",
          "properties": {
            "branch_max_length": 25,
            "fetch_stash_count": true,
            "fetch_status": true,
            "fetch_upstream_icon": true
          },
          "style": "powerline",
          "template": " \{\{ .UpstreamIcon \}\}\{\{ .HEAD \}\}\{\{ .BranchStatus \}\}",
          "trailing_diamond": "\ue0b4",
          "type": "git"
        },
        {
          "background": "#eafe34",
          "foreground": "#0d1f2d",
          "leading_diamond": "\ue0b6",
          "powerline_symbol": "\ue0b0",
          "properties": {
            "branch_max_length": 25,
            "fetch_stash_count": true,
            "fetch_status": true,
            "fetch_upstream_icon": true
          },
          "style": "powerline",
          "template": "\{\{ if .Working.Untracked \}\} \{\{ .Working.Untracked \}\}? \{\{ end \}\}",
          "trailing_diamond": "\ue0b4",
          "type": "git"
        },
        {
          "background": "#f95656",
          "foreground": "#0d1f2d",
          "leading_diamond": "\ue0b6",
          "powerline_symbol": "\ue0b0",
          "properties": {
            "branch_max_length": 25,
            "fetch_stash_count": true,
            "fetch_status": true,
            "fetch_upstream_icon": true
          },
          "style": "powerline",
          "template": "\{\{ if .Working.Unmerged \}\} \{\{ .Working.Unmerged \}\}\uf044 \{\{ end \}\}",
          "trailing_diamond": "\ue0b4",
          "type": "git"
        },
        {
          "background": "#f95656",
          "foreground": "#0d1f2d",
          "leading_diamond": "\ue0b6",
          "powerline_symbol": "\ue0b0",
          "properties": {
            "branch_max_length": 25,
            "fetch_stash_count": true,
            "fetch_status": true,
            "fetch_upstream_icon": true
          },
          "style": "powerline",
          "template": "\{\{ if .Working.Added \}\} \{\{ .Working.Added \}\}+ \{\{ end \}\}",
          "trailing_diamond": "\ue0b4",
          "type": "git"
        },
        {
          "background": "#f95656",
          "foreground": "#0d1f2d",
          "leading_diamond": "\ue0b6",
          "powerline_symbol": "\ue0b0",
          "properties": {
            "branch_max_length": 25,
            "fetch_stash_count": true,
            "fetch_status": true,
            "fetch_upstream_icon": true
          },
          "style": "powerline",
          "template": "\{\{ if .Working.Deleted \}\} \{\{ .Working.Deleted \}\}\u26cc \{\{ end \}\}",
          "trailing_diamond": "\ue0b4",
          "type": "git"
        },
        {
          "background": "#f95656",
          "foreground": "#0d1f2d",
          "leading_diamond": "\ue0b6",
          "powerline_symbol": "\ue0b0",
          "properties": {
            "branch_max_length": 25,
            "fetch_stash_count": true,
            "fetch_status": true,
            "fetch_upstream_icon": true
          },
          "style": "powerline",
          "template": "\{\{ if .Working.Modified \}\} \{\{ .Working.Modified \}\}\uf044 \{\{ end \}\}",
          "trailing_diamond": "\ue0b4",
          "type": "git"
        },
        {
          "background": "#58d060",
          "foreground": "#0d1f2d",
          "leading_diamond": "\ue0b6",
          "powerline_symbol": "\ue0b0",
          "properties": {
            "branch_max_length": 25,
            "fetch_stash_count": true,
            "fetch_status": true,
            "fetch_upstream_icon": true
          },
          "style": "powerline",
          "template": "\{\{ if .Staging.Changed \}\} \{\{ .Staging.String \}\} \uf046 \{\{ end \}\}",
          "trailing_diamond": "\ue0b4",
          "type": "git"
        },
        {
          "background": "#aeaeae",
          "foreground": "#0d1f2d",
          "leading_diamond": "\ue0b6",
          "powerline_symbol": "\ue0b0",
          "properties": {
            "branch_max_length": 25,
            "fetch_stash_count": true,
            "fetch_status": true,
            "fetch_upstream_icon": true
          },
          "style": "powerline",
          "template": "\{\{ if gt .StashCount 0 \}\} \{\{ .StashCount \}\}\u2691 \{\{ end \}\}",
          "trailing_diamond": "\ue0b4",
          "type": "git"
        },
        {
          "background": "#6CA35E",
          "foreground": "#ffffff",
          "powerline_symbol": "\ue0b0",
          "properties": {
            "fetch_version": true
          },
          "style": "powerline",
          "template": " \uf898 \{\{ if .PackageManagerIcon \}\}\{\{ .PackageManagerIcon \}\} \{\{ end \}\}\{\{ .Full \}\} ",
          "type": "node"
        },
        {
          "background": "#8ED1F7",
          "foreground": "#111111",
          "powerline_symbol": "\ue0b0",
          "properties": {
            "fetch_version": true
          },
          "style": "powerline",
          "template": " \ue626 \{\{ if .Error \}\}\{\{ .Error \}\}\{\{ else \}\}\{\{ .Full \}\}\{\{ end \}\} ",
          "type": "go"
        },
        {
          "background": "#4063D8",
          "foreground": "#111111",
          "powerline_symbol": "\ue0b0",
          "properties": {
            "fetch_version": true
          },
          "style": "powerline",
          "template": " \ue624 \{\{ if .Error \}\}\{\{ .Error \}\}\{\{ else \}\}\{\{ .Full \}\}\{\{ end \}\} ",
          "type": "julia"
        },
        {
          "background": "#FFDE57",
          "foreground": "#111111",
          "powerline_symbol": "\ue0b0",
          "properties": {
            "display_mode": "files",
            "fetch_virtual_env": false
          },
          "style": "powerline",
          "template": " \ue235 \{\{ if .Error \}\}\{\{ .Error \}\}\{\{ else \}\}\{\{ .Full \}\}\{\{ end \}\} ",
          "type": "python"
        },
        {
          "background": "#AE1401",
          "foreground": "#ffffff",
          "powerline_symbol": "\ue0b0",
          "properties": {
            "display_mode": "files",
            "fetch_version": true
          },
          "style": "powerline",
          "template": " \ue791 \{\{ if .Error \}\}\{\{ .Error \}\}\{\{ else \}\}\{\{ .Full \}\}\{\{ end \}\} ",
          "type": "ruby"
        },
        {
          "background": "#FEAC19",
          "foreground": "#ffffff",
          "powerline_symbol": "\ue0b0",
          "properties": {
            "display_mode": "files",
            "fetch_version": false
          },
          "style": "powerline",
          "template": " \uf0e7\{\{ if .Error \}\}\{\{ .Error \}\}\{\{ else \}\}\{\{ .Full \}\}\{\{ end \}\} ",
          "type": "azfunc"
        },
        {
          "background_templates": [
            "\{\{if contains \"default\" .Profile\}\}#FFA400\{\{end\}\}",
            "\{\{if contains \"jan\" .Profile\}\}#f1184c\{\{end\}\}"
          ],
          "foreground": "#ffffff",
          "powerline_symbol": "\ue0b0",
          "properties": {
            "display_default": false
          },
          "style": "powerline",
          "template": " \ue7ad \{\{ .Profile \}\}\{\{ if .Region \}\}@\{\{ .Region \}\}\{\{ end \}\} ",
          "type": "aws"
        },
        {
          "background": "#e91e63",
          "foreground": "#ffffff",
          "properties": {
            "always_enabled": true
          },
          "style": "diamond",
          "template": "\{\{ if gt .Code 0 \}\} \ue23a\{\{ end \}\}",
          "trailing_diamond": "\ue0b4",
          "type": "exit"
        }
      ],
      "type": "prompt"
    }
  ],
  "console_title_template": "\{\{ .Shell \}\} in \{\{ .Folder \}\}",
  "final_space": true,
  "version": 2
}

Exemple : le mode minimaliste Git

Un dernier exemple de configuration pour ne nous concentrer que sur Git :

Aperçu de l’invite de commande Oh My Posh en mode minimaliste Git

{
  "$schema": "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json",
  "blocks": [
    {
      "alignment": "left",
      "segments": [
        {
          "background": "#242424",
          "foreground": "#3A86FF",
          "leading_diamond": "\ue0b6",
          "trailing_diamond": "\ue0b0",
          "properties": {
            "fetch_stash_count": true,
            "fetch_status": true,
            "fetch_upstream_icon": true
          },
          "style": "diamond",
          "template": "\{\{ .UpstreamIcon \}\}\{\{ .HEAD \}\}\{\{ if .Staging.Changed \}\} \uf046 \{\{ .Staging.String \}\}\{\{ end \}\}\{\{ if and (.Working.Changed) (.Staging.Changed) \}\} |\{\{ end \}\}\{\{ if .Working.Changed \}\} \uf044 \{\{ .Working.String \}\}\{\{ end \}\}\{\{ if gt .StashCount 0 \}\} \uf692 \{\{ .StashCount \}\}\{\{ end \}\} ",
          "type": "git"
        }
      ],
      "type": "prompt"
    }
  ],
  "console_title_template": "\{\{if .Root\}\}(Admin) \{\{end\}\}\{\{.Folder\}\}",
  "version": 2
}

Il ne s’agit ici que d’exemples simples. Tu peux en trouver pléthore d’autres dans la section “Themes” de la doc.

Tu veux aller plus loin et maîtriser pleinement les fondamentaux de Git ou être accompagné pour garantir la qualité de tes projets grâce à une bonne mise en place de Git ? On peut t’aider ou te former, il suffit de nous décrire ton besoin !