Aller au contenu principal

FZF + ripgrep : recherche de code interactive avec aperçu en direct

Combinez ripgrep et fzf avec un panneau d'aperçu coloré par bat pour construire une recherche de code interactive — puis ouvrez le résultat directement dans VSCode, à la ligne exacte.

· 10 minutes de lecture
Voir la source
Christophe
Amoureux de Markdown, WSL et Docker ~ Curieux insatiable.
Claude Code
AI Assistant
Cet article existe aussi en anglais — lire la version originale.

Traduction automatique

Cette traduction a été produite par une IA. Elle peut contenir des contresens ou des maladresses, en particulier sur les termes techniques. En cas de doute, consultez l'article de référence en anglais — c'est lui qui fait foi.

Journal des modifications

Dernière
added a Docker-first demo to try before installing

FZF + ripgrep : recherche de code interactive avec aperçu en direct

⚡
TL;DR

grep -r renvoie une liste plate — pas de contexte, pas d'aperçu, aucun moyen de naviguer sans ouvrir le fichier. En envoyant ripgrep dans fzf et en ajoutant un panneau d'aperçu bat, vous obtenez une recherche de code interactive et colorée, qui ressemble à la barre de recherche d'un IDE mais vit entièrement dans votre terminal. Cet article construit une fonction ZSH rgf qui cherche dans votre code, affiche un aperçu en direct du fichier trouvé et saute directement à la bonne ligne dans VSCode quand vous appuyez sur Enter.

Vous cherchez où une variable d'environnement est lue, ou quel fichier contient encore cette URL codée en dur que vous vouliez nettoyer. Vous lancez grep -rn "DB_PASSWORD" . et vous récupérez quarante lignes de noms de fichiers, de numéros de ligne et d'extraits — tout mélangé. Vous en choisissez une, vous ouvrez le fichier, vous défilez jusqu'à la bonne ligne, vous constatez que ce n'est pas celle-là, vous fermez et vous recommencez.

Il y a mieux.

Le panneau d'aperçu en action​

Envoyez ripgrep dans fzf avec un aperçu bat attaché, et voici le résultat — un panneau en direct, avec coloration syntaxique, qui se met à jour au fil de vos déplacements :

Recherche de DB_PASSWORD avec aperçu

Quand vous déplacez le curseur dans la liste des résultats, le panneau de droite se met à jour en direct — il affiche le fichier avec coloration syntaxique, la ligne trouvée surlignée en jaune et quelques lignes de contexte autour.

Pourquoi ripgrep plutôt que grep ?​

grep -r suffit pour un petit projet. ripgrep est conçu pour le monde réel :

  • Il respecte automatiquement .gitignore — fini les résultats venant de node_modules, vendor ou des dossiers de build.
  • Il est nettement plus rapide sur les gros projets, grâce au traitement parallèle et à un parcours de fichiers plus intelligent.
  • Son format de sortie (file:line:content) est pensé pour l'intégration avec d'autres outils.

Une comparaison rapide — recherche de TODO dans un projet Node.js contenant node_modules :

>user@machine: ~/yourproject

La vitesse et la réduction du bruit justifient à elles seules le changement.

Prérequis​

Cet article s'appuie sur fzf, que vous devriez déjà avoir installé. Deux outils supplémentaires sont nécessaires : ripgrep et bat.

ripgrep​

ripgrep est un outil de recherche en ligne de commande rapide qui parcourt récursivement les fichiers à la recherche de motifs de texte, avec les performances de Rust, tout en respectant automatiquement .gitignore et les règles d'exclusion similaires.

Je lui ai consacré un article complet : ripgrep — l'outil de recherche qui a changé mon workflow WSL2.

Prérequis : ripgrep

>user@machine: ~/yourproject

Vérifier :

>user@machine: ~/yourproject

bat​

bat (batcat sur Debian/Ubuntu) est un remplaçant moderne de cat qui affiche les fichiers avec coloration syntaxique, intégration Git, pagination et d'autres fonctionnalités pratiques pour les développeurs. Il sert ici à alimenter le panneau d'aperçu.

Prérequis : bat

>user@machine: ~/yourproject

Vérifier :

>user@machine: ~/yourproject

batcat sur Ubuntu/Debian

Sur certains systèmes Ubuntu/Debian, le binaire s'appelle batcat et non bat. Si c'est votre cas, remplacez simplement bat par batcat dans la suite de cet article.

Essayer avec Docker​

Avant d'installer ripgrep, fzf et bat sur votre machine, essayez rgf dans un container jetable qui contient déjà les trois, la fonction elle-même branchée via un véritable autoload ZSH, et un petit projet de démo qui correspond à la section « Scénarios concrets » plus bas : un DB_PASSWORD qui fuit, trois marqueurs TODO/FIXME/HACK, un appel à sendEmail, un port codé en dur et une interface TypeScript.

Pourquoi Docker d'abord ?

Le Dockerfile ci-dessous reproduit rgf à l'octet près depuis le Snippet plus bas, plus le câblage fpath/autoload décrit à l'étape 3. Pas besoin de VSCode pour essayer : rgf se replie sur l'affichage de file:line dans le terminal quand code n'est pas dans $PATH, ce qui est exactement le cas dans ce container.

Construisez-le et lancez-le :

>user@machine: ~/rgf-demo

$ docker build -t rgf-demo . [+] Building 32.5s (11/11) FINISHED ✔ exporting to image

$ docker run --rm -it rgf-demo 🐳 root ~/demo #

Essayez maintenant, en direct, les scénarios exacts de la section « Scénarios concrets » ci-dessous :

rgf "DB_PASSWORD" # the leaking secret in config/.env
rgf "TODO|FIXME|HACK" # all three markers across the demo project
rgf "sendEmail" # the call site in notifications.js
rgf -t ts "interface UserProps"

Chacun ouvre le même panneau « liste + aperçu » que la capture d'écran en haut de cet article — naviguez avec ↑/↓, filtrez en tapant, appuyez sur Enter pour sélectionner. Comme il n'y a pas de VSCode dans le container, rgf affiche file:line dans le terminal au lieu d'ouvrir un éditeur — tout le reste se comporte exactement comme sur votre propre machine.

Étape 1 — Brancher ripgrep sur fzf​

La combinaison la plus simple bat déjà grep tout seul :

rg "DB_PASSWORD" | fzf

Recherche de DB_PASSWORD sans aperçu

Vous obtenez une liste interactive et filtrable. Tapez quelques lettres pour affiner les résultats. Appuyez sur Enter pour afficher la ligne sélectionnée. Appuyez sur Esc pour sortir sans rien sélectionner.

Mais cela n'affiche que la ligne trouvée — aucun contexte, aucun aperçu du code autour.

Étape 2 — Ajouter un panneau d'aperçu bat​

C'est là que ça devient intéressant. fzf propose une option --preview qui exécute une commande arbitraire pour chaque ligne surlignée et affiche sa sortie dans un panneau latéral.

rg --color=always --line-number --no-heading --smart-case "DB_PASSWORD" \
| fzf --ansi \
--delimiter=':' \
--preview='bat --color=always --highlight-line {2} -- {1}' \
--preview-window='right:60%:+{2}+3/3:~3'

C'est la commande derrière la capture d'écran en haut de cet article. Voyons ce que fait chaque option :

Référence des options

  • --color=always (rg) — Force une sortie colorée même quand on utilise un pipe. Sans ça, rg détecte le pipe et supprime toutes les couleurs, ne laissant à fzf que du texte brut.
  • --line-number --no-heading (rg) — Formate chaque résultat en filename:linenumber:content sur une seule ligne. C'est le format que fzf va analyser.
  • --smart-case (rg) — Insensible à la casse quand la requête est tout en minuscules, sensible à la casse dès qu'elle contient une majuscule. Le meilleur défaut pour chercher dans du code.
  • --ansi (fzf) — Indique à fzf d'interpréter et d'afficher les codes couleur ANSI de la sortie de rg.
  • --delimiter=':' (fzf) — Découpe chaque ligne sur : de sorte que {1} = nom du fichier, {2} = numéro de ligne, {3} = contenu. Ces champs sont ensuite utilisés dans --preview.
  • --highlight-line {2} (bat) — Surligne la ligne trouvée dans l'aperçu. {2} est résolu par fzf vers le champ du numéro de ligne.
    • -- {1} — Le double tiret sépare les options de bat de l'argument nom de fichier. {1} est résolu vers le nom du fichier.
  • --preview-window='right:60%:+{2}+3/3:~3' — Ouvre l'aperçu à droite, sur 60 % de la largeur du terminal. +{2}+3/3 fait défiler le panneau pour que la ligne trouvée soit visible, centrée avec du contexte. ~3 garde 3 lignes d'en-tête en sticky.

Étape 3 — La fonction rgf​

Taper tout ce pipeline à chaque fois n'est pas pratique. La solution suit le même principe que l'article un workflow ZSH modulaire : un fichier autonome dans ~/.zsh/fns/, chargé à la demande par ZSH — sans toucher à .zshrc.

La fonction vérifie toutes ses dépendances au démarrage, détecte automatiquement bat ou batcat, et ouvre le résultat sélectionné dans VSCode à la ligne exacte quand vous appuyez sur Enter. Si code n'est pas dans $PATH, elle se replie sur l'affichage de file:line dans le terminal.

📦 Mise en place du projet : ~/.zsh/fns
Aide

Besoin d'aide ? Cliquez sur le bouton « Aide » ci-dessus pour les instructions de mise en place.

Pourquoi un fichier temporaire plutôt que $(...)

Lancer selected=$(rg ... | fzf ...) capture la sortie standard de fzf et l'empêche d'afficher son interface en WSL — la commande reste bloquée. Écrire la sortie de fzf dans un fichier temporaire lui permet de tourner au premier plan avec un accès complet au terminal ; la sélection est lue depuis le fichier après la fermeture de fzf.

Si ~/.zsh/fns est déjà dans votre fpath (voir l'article un workflow ZSH modulaire), rechargez ZSH et lancez :

rgf "database"

Naviguez avec ↑ / ↓, filtrez en tapant, appuyez sur Enter pour sauter à la ligne trouvée dans VSCode, Esc pour annuler.

Scénarios concrets​

Voici quatre situations où rgf devient partie intégrante de votre quotidien.

Trouver tous les TODO du projet​

rgf "TODO|FIXME|HACK"

rg gère les regex par défaut. Ceci cherche n'importe lequel des trois marqueurs. Parcourez-les tous, choisissez celui que vous voulez traiter et atterrissez directement dans l'éditeur.

Retrouver où une fonction est appelée​

Vous avez renommé sendEmail en sendNotification mais quelque chose plante encore. Trouvez tous les appels :

rgf "sendEmail"

Chaque résultat montre l'appel dans son contexte. Vous voyez immédiatement s'il s'agit d'un import, d'un appel ou d'un test — sans ouvrir les fichiers un par un.

Localiser une valeur codée en dur​

Votre fichier Docker Compose contenait un port codé en dur. Traîne-t-il encore quelque part dans le code ?

rgf "5432"

L'aperçu montre les lignes autour — vous voyez d'un coup d'œil s'il s'agit d'une valeur par défaut, d'un commentaire ou d'une chaîne de connexion active.

Chercher dans un dossier précis​

rgf passe tous ses arguments directement à rg, donc la limitation à un chemin fonctionne comme prévu :

rgf "useEffect" src/components/

Seuls les fichiers sous src/components/ sont parcourus. Idem pour les filtres par type de fichier :

rgf -t ts "interface UserProps"

L'option -t ts demande à rg de ne chercher que dans les fichiers TypeScript.

Pour aller plus loin​

Associer rgf à un raccourci clavier​

Si vous voulez rgf à une touche de distance, ajoutez un raccourci ZSH. Celui-ci associe CTRL+F au lancement de rgf avec le contenu actuel de la ligne de commande comme requête initiale :

# In ~/.zshrc
rgf-widget() { rgf "$BUFFER"; zle reset-prompt }
zle -N rgf-widget
bindkey '^F' rgf-widget

Combiner avec le navigateur de repos​

Si vous avez la fonction repo de l'article un workflow ZSH modulaire, un enchaînement naturel apparaît : repo pour sauter au projet, rgf pour trouver le code, Enter pour l'ouvrir. Trois frappes pour atteindre n'importe quelle ligne de n'importe quel projet.

Utiliser ripgrep seul​

rg vaut aussi la peine d'être appris pour lui-même — même sans fzf. Les options que vous utiliserez rapidement :

rg -l "pattern" # filenames only, no content
rg -c "pattern" # count of matches per file
rg --type-list # list all supported file types
rg -t py "def connect" # Python files only
rg -g "*.yml" "image:" # glob filter — only YAML files

🦋 Rejoignez la conversation sur BlueskyUn compte Bluesky gratuit est nécessaire pour aimer, repartager ou commenter. Ce bloc interroge l'API publique de Bluesky directement depuis votre navigateur (sans cookie, sans connexion) — votre adresse IP parvient donc aux serveurs de Bluesky dès que cette section se charge.

Chargement des commentaires…

Cet article vous a-t-il été utile ?
Avez-vous suivi les étapes de cet article ?