Difftastic, un outil d’analyse de diff structurel qui comprend la syntaxe
(difftastic.wilfred.me.uk)- Difftastic est un outil CLI de diff qui compare les fichiers non pas ligne par ligne, mais selon la structure syntaxique du code
- En interne, il analyse le code avec tree-sitter, ce qui permet de mieux distinguer les expressions réellement modifiées même lorsque des lignes changent à cause du formatage
- Même lorsqu’un formateur de code répartit des éléments sur plusieurs lignes ou qu’un wrapper est ajouté, il peut séparer les changements de structure du contenu interne inchangé
- Une documentation d’installation et de configuration Git est fournie, et l’outil prend en charge de nombreux langages de programmation ainsi que des formats de texte structurés comme JSON et YAML
- Publié sous licence MIT, il peut être téléchargé, modifié et partagé, et convient bien pour ajouter une comparaison structurelle à un flux de travail diff existant
Comparer la structure syntaxique plutôt que les lignes
- Difftastic est un outil CLI de diff qui compare les fichiers selon leur syntaxe
- Il vise à montrer des résultats qui comprennent la structure du code, plutôt qu’un diff classique ligne par ligne
- Le code est analysé avec tree-sitter
- Même des expressions internes qui peuvent sembler modifiées dans un diff centré sur les lignes peuvent être distinguées selon qu’elles ont réellement changé ou non
- Même lorsqu’un formateur de code répartit le code sur plusieurs lignes, il peut montrer les changements réels
- Lorsqu’un wrapper est ajouté, il fait correspondre les délimiteurs avec précision
- Même si le contenu interne change aussi, il peut indiquer le wrapper ajouté
- Au lieu d’une syntaxe de hunk diff comme
@@ -5,6 +5,7 @@, il affiche les vrais numéros de ligne des fichiers avant et après modification
Langages pris en charge et intégration avec Git
- Les ressources du projet sont disponibles sur GitHub, Manual et Install
- Exemples de langages de programmation pris en charge :
- C++, C#, Clojure, Dart, Erlang, Go, Haskell, Java, JavaScript, Kotlin, Lisp, Lua, OCaml, PHP, Python, R, Ruby, Rust, Scala, TypeScript
- La liste complète est disponible dans le manuel, à la page Supported Languages
- Exemples de formats de fichiers pris en charge :
- HCL, HTML, JSON, YAML
- La liste complète est disponible dans le manuel, à la page structured text formats
- Il peut être utilisé avec Git, et le manuel propose un guide de configuration Git
- Difftastic est publié sous licence MIT, ce qui permet son téléchargement, sa modification et son partage
1 commentaires
Avis Hacker News
Certains le savent peut-être déjà, mais cet outil est construit sur tree-sitter(https://tree-sitter.github.io/tree-sitter/) ; en quelque sorte, il fait pour le parsing ce que LSP a fait pour l’analyse
Il transforme le code en arbre de syntaxe abstraite (AST) et fournit une interface standard permettant à des clients comme des éditeurs ou des outils de diff d’utiliser cet AST
Sans avoir à prendre directement en charge des dizaines de langages, ce type d’outil peut simplement prendre en charge tree-sitter, et fonctionner alors automatiquement avec tous les langages pris en charge par tree-sitter
Si vous développez un nouveau langage, il suffit de créer un parseur tree-sitter, et tous les outils qui savent manipuler tree-sitter pourront alors prendre en charge ce langage
Grâce à ces deux grandes innovations, les améliorations de ce type d’outil explosent. Désormais, éditeurs, outils de diff, etc. peuvent prendre en charge des dizaines, voire des centaines de langages sans répéter le même travail chacun de leur côté, et c’est vraiment impressionnant
Pour contexte, plusieurs membres de notre équipe maintiennent les bindings OCaml de tree-sitter et contribuent souvent aux grammaires dans le cadre de notre travail sur Semgrep. Semgrep utilise tree-sitter pour la recherche de code et pour parser en matchers AST des requêtes qui sont elles-mêmes des fragments de code
Quand on écrit un linter, il faut souvent embarquer aussi le runtime du langage ciblé. Par exemple, si l’on construit un parseur avec le module intégré
astde Python, il faut faire correspondre la version du langage et ses fonctionnalités ; ainsi, Pylint exécuté sous Python 2.7 ne peut pas parser du code Python 3Dès qu’on cible plusieurs langages, cela devient beaucoup plus pénible qu’on ne l’imagine au départ
Avant tree-sitter, le mieux était souvent d’utiliser les outils AST intégrés au langage, parce qu’ils garantissaient de suivre la syntaxe la plus récente
À titre personnel, le génie de tree-sitter tient au fait qu’il a rendu beaucoup plus facile le maintien à jour des parseurs de langage que les approches grammaticales traditionnelles
Si vous voulez en savoir plus sur les choix de conception de tree-sitter, je recommande vivement la présentation Strange Loop de Max Brunsfield : https://www.youtube.com/watch?v=Jes3bD6P0To
Résultat : au-delà de difftastic, de nombreux nouveaux outils comme neovim, Zed, Semgrep ou la recherche de code GitHub ont été construits sur tree-sitter
J’ai écrit une grammaire tree-sitter et un ensemble de requêtes de coloration pour VHDL, et représenter la grammaire VHDL avec tree-sitter m’a posé beaucoup de difficultés
LSP résout réellement le problème des M×N intégrations nécessaires entre M éditeurs et N langages en utilisant une interface standard pour des compilateurs orientés requêtes
tree-sitter ne résout pas vraiment ce problème ; il rend plutôt beaucoup plus facile l’écriture de N intégrations dans un éditeur ou un outil
Common Lisp ne peut pas être parsé sans une implémentation Lisp complète, la syntaxe de Haskell est suffisamment complexe pour que la grammaire soit incomplète, C/C++ est difficile à parser correctement ne serait-ce qu’à cause du préprocesseur, et le parsing de Perl est Turing-complet
Comme cela a été suggéré ailleurs, plutôt que de forcer la réécriture des parseurs dans un nouvel écosystème, il me semblerait plus juste de définir un format que les parseurs existants pourraient produire comme sortie auxiliaire
Difftastic pourrait alors afficher les changements par phrase plutôt que par ligne visuelle
Dans un essai, un diff basé sur les lignes visuelles est étrange. En général, la phrase modifiée commence au milieu d’une ligne visuelle
Si vous l’avez installé avec cargo, voici comment mettre à jour difftastic et les outils associés
cargo install cargo-updatecargo install-update --listcargo install-update --allIl existe aussi des projets Rust intéressants installables avec cargo
https://mise.jdx.dev/ mise-en-place est une alternative rapide et flexible à https://asdf-vm.com/
https://github.com/ajeetdsouza/zoxide est un excellent remplaçant de
cd, qui mémorise les emplacements visités et permet d’aller vers"~/projects/helloworld"avec une correspondance partielle comme"z hel"https://github.com/bootandy/dust est un outil qui complète
duet montre quels répertoires consomment beaucoup d’espace disquelsvisuellement plus agréable, https://github.com/ClementTsang/bottom est unhtopavec des graphes, et https://github.com/sharkdp/bat est uncatavec coloration syntaxiquelsplus jolidu, dua-cli est celui que je préfère. C’est une interface terminal interactive qui clonencduJe l’ai découvert en cherchant une alternative parce que
ncdun’a pas de mode clairncdureste de loin le meilleur remplaçant deduJ’ai du mal à comprendre pourquoi des outils comme git ne proposent pas ça par défaut
J’utilise difft depuis environ un an, et mon principal reproche est qu’il rend difficile le retour à d’autres outils de diff dans les environnements où difft n’est pas disponible
Je me demande s’il existe aussi des recherches sur des outils de diff sémantique. Par exemple des outils qui gèrent les cas où la syntaxe a changé mais où le sens reste le même
Comme problème général, ça paraît ardu, mais pour de petits DSL ou des sous-ensembles de certains langages, ça pourrait être possible ou utile
diffest le bon choix par défautIl est déjà présent sur presque tous les systèmes où l’on voudra exécuter git, il est rapide, petit, et tout le monde connaît son usage de base
Cela dit, c’est bien de pouvoir changer facilement cette valeur par défaut
Ce n’est pas un utilitaire en ligne de commande, mais une extension VS Code et une GitHub App
Si vous voulez savoir comment ça fonctionne et en quoi ça diffère de difftastic, voyez https://semanticdiff.com/blog/semanticdiff-vs-difftastic/
Mais l’une des raisons pour lesquelles je pense que ça ne devrait pas devenir la valeur par défaut, c’est que ça masque les différences d’espaces. Je n’ai pas encore vérifié si c’est configurable
Je suis tout à fait d’accord avec l’explication qui demande si l’on sait lire la syntaxe
@@ -5,6 +5,7 @@, et qui dit que Difftastic affiche les vrais numéros de ligne des fichiers avant et après modificationJe viens de l’installer et de lancer
git diff, et ça marche très bienLe fait que GitHub n’ait pas sorti quelque chose comme ça ressemble à un énorme manque d’innovation produit
Il n’y a même pas de fonctionnalité pour aider quand seule l’indentation change, et c’est généralement affiché comme d’énormes suppressions et ajouts
Le visualiseur de diff de GitHub pourrait, et devrait, être plus intelligent
En pratique, il ne sait même pas distinguer
foo.cpp.indefoo.mk.inN’importe quel
foo.test déclaré comme du Perl, sans moyen de le corriger. Il existe même un ticket vieux de 10 ansEn fait, même les développeurs principaux de TS recommandent de ne pas trop se soucier de l’exactitude des grammaires[1]
Pour GitHub ou des services dans une position similaire, cette contrainte peut sembler rédhibitoire
[1] https://github.com/tree-sitter/tree-sitter/issues/130#issuec...
J’ai essayé de passer à cet outil, mais il appliquait une mise en forme étrange même aux parties inchangées, ce qui m’a paru beaucoup trop bruyant
Je suis finalement revenu à icdiff[0]
[0]: https://github.com/jeffkaufman/icdiff
J’avais découvert Semantic Merge[1] il y a quelque temps, mais ce n’était pas open source
Celui-ci ne fait pas de fusion, seulement du diff, mais au moins il est open source et le diff est bien plus lisible, donc je l’ai déjà mis par défaut
Je me demande s’il est prévu de l’étendre avec des fonctionnalités de fusion
[1] https://docs.plasticscm.com/semanticmerge
La fusion d’AST est un problème difficile, et difftastic ne le traite pas
De plus, le diff d’AST est un processus avec perte du point de vue du diff textuel. Difftastic ignore les espaces qui n’ont pas de signification syntaxique, mais la fusion nécessite de suivre les espaces
À l’époque où je faisais du refactoring désordonné sur un projet C# dans une grande équipe, c’était vraiment un outil salvateur
Discussions précédentes :
https://news.ycombinator.com/item?id=27768861 (297 points | il y a 3 ans | 61 commentaires)
https://news.ycombinator.com/item?id=32746258 (698 points | il y a 2 ans | 90 commentaires)
https://news.ycombinator.com/item?id=30841244 (983 points | il y a 2 ans | 219 commentaires)
Ça a l’air d’être un excellent outil, mais après l’avoir testé sur quelques gros fichiers XML, les lignes modifiées s’affichaient en vert normal et les attributs modifiés en vert gras, ce qui était difficile à distinguer visuellement
Je n’ai pas trouvé dans la documentation comment changer le style du diff ou attribuer une autre couleur aux éléments en gras
Je me demande si quelqu’un sait comment faire
J’ai commenté cette issue[1] pour dire que je soutenais cette fonctionnalité
Si la fonctionnalité que vous voulez relève de la même catégorie, vous pouvez y ajouter votre avis ; si vous pensez qu’elle est suffisamment différente, vous pouvez aussi ouvrir une nouvelle issue
[1]: https://github.com/Wilfred/difftastic/issues/611
Il est intéressant de voir que le paquet Arch Linux fait 7 Mo, mais se décompresse à 80 Mo après installation, et que le binaire
difftà lui seul fait 78 MoSur un dataset ZFS avec la compression LZ4 activée,
duindique 17 MoJe me demande pourquoi quelque chose qui se compresse aussi bien à l’intérieur du binaire n’est pas simplement gardé compressé. Décompressé en RAM, il pourrait même sembler se charger plus vite
Processed 1 file, 614 regular extents (614 refs), 0 inline.Type Perc Disk Usage Uncompressed ReferencedTOTAL 14% 10M 77M 77Mnone 100% 1.1M 1.1M 1.1Mzstd 12% 9.8M 76M 76MTree-sitter semble nécessiter énormément de code, dont une bonne partie paraît redondante ou compressible
Il est mappé en mémoire, et seules les parties réellement utilisées sont chargées à la demande
Donc, si l’on compresse un gros binaire, la pagination à la demande ne fonctionne plus, ce qui le rend au contraire plus lent
J’avais testé il y a quelques années avec un EXE Windows de 280 Mo : il se compressait bien à environ 70 Mo, mais mettait plusieurs secondes de plus à démarrer que l’original
Cela peut avoir du sens dans certains scénarios, par exemple lorsqu’on exécute un binaire à travers le réseau, mais dans la plupart des cas un binaire non compressé démarre plus vite