3 puan yazan GN⁺ 2024-03-22 | 1 yorum | WhatsApp'ta paylaş
  • Difftastic, dosyaları satır bazında değil kodun sözdizimsel yapısını temel alarak karşılaştıran bir CLI diff aracıdır
  • İçeride kodu tree-sitter ile ayrıştırır; bu sayede biçimlendirme nedeniyle satırlar değişse bile gerçekten değişen ifadeleri daha iyi ayırt eder
  • Kod biçimlendiricisinin öğeleri birden çok satıra bölmesi veya wrapper eklenmesi durumunda da, değişen yapıyı ve korunan içeriği birbirinden ayırarak gösterebilir
  • Git ayar rehberi ve kurulum belgeleri sunulur; ayrıca birçok programlama diliyle JSON ve YAML gibi yapılandırılmış metin formatlarını destekler
  • MIT lisansı ile yayımlanır; indirilebilir, değiştirilebilir ve paylaşılabilir, ayrıca mevcut diff akışına yapısal karşılaştırma eklemek için uygundur

Satırları değil, sözdizimsel yapıyı karşılaştırır

  • Difftastic, dosyaları sözdizimine göre karşılaştıran bir CLI diff aracıdır
  • Tipik satır bazlı diff'ten farklı olarak, kod yapısını anlayarak elde edilen sonuçları göstermeye odaklanır
  • Kod tree-sitter ile ayrıştırılır
    • Satır odaklı diff'te değişmiş gibi görünen iç ifadelerin gerçekten değişip değişmediğini ayırt edebilir
  • Kod biçimlendiricisinin kodu birden çok satıra bölmesi durumunda da gerçek değişiklikleri gösterebilir
  • Wrapper eklendiğinde ayraçları doğru şekilde eşleştirir
    • İçerik de birlikte değişse bile eklenen wrapper'ı gösterebilir
  • @@ -5,6 +5,7 @@ gibi diff hunk sözdizimi yerine, değişiklik öncesi ve sonrası dosyaların gerçek satır numaralarını gösterir

Desteklenen diller ve Git entegrasyonu

  • Proje kaynakları GitHub, Manual, Install üzerinden sunulmaktadır
  • Desteklenen programlama dillerine örnekler şunlardır
    • C++, C#, Clojure, Dart, Erlang, Go, Haskell, Java, JavaScript, Kotlin, Lisp, Lua, OCaml, PHP, Python, R, Ruby, Rust, Scala, TypeScript
    • Listenin tamamı kılavuzdaki desteklenen diller listesinde görülebilir
  • Desteklenen dosya biçimlerine örnekler şunlardır
  • Git ile birlikte kullanılabilir ve kılavuzda Git ayarları için rehber bulunur
  • Difftastic, MIT lisansı ile yayımlanır; indirilebilir, değiştirilebilir ve paylaşılabilir

1 yorum

 
GN⁺ 2024-03-22
Hacker News yorumları
  • Bilenler vardır ama bu araç tree-sitter(https://tree-sitter.github.io/tree-sitter/) üzerine inşa edilmiş; LSP’nin analiz için yaptığını ayrıştırma için yapıyor sayılır.
    Kodu soyut sözdizimi ağacına (AST) dönüştürüyor ve bu AST’yi editörler veya diff araçları gibi istemcilerin kullanabilmesi için standart bir arayüz sağlıyor.
    Böyle bir aracın onlarca dili doğrudan desteklemesi gerekmiyor; yalnızca tree-sitter’ı desteklemesi yeterli, böylece tree-sitter’ın desteklediği tüm dillerde otomatik olarak çalışabiliyor.
    Yeni bir dil geliştiriyorsanız bir tree-sitter ayrıştırıcısı yazmanız yeterli; bunun sonucunda tree-sitter ile çalışan tüm araçlar o dili destekleyebilir hâle geliyor.
    Bu iki büyük yenilik sayesinde bu tür araç geliştirmelerinde patlama yaşanıyor. Artık editörler, diff araçları vb. aynı işi tekrar tekrar yapmadan onlarca, hatta yüzlerce dili destekleyebiliyor; gerçekten harika.

    • Tamamen katılıyorum; geçen yıl yazdığım bir yorumu tekrar alıntılarsam, tree-sitter’ın bağımlılıksız bir yapıya sahip olması da vurgulanmaya değer.
      Bu arada ekip arkadaşlarımızdan bazıları OCaml tree-sitter bağlamalarını sürdürüyor ve Semgrep çalışmalarının bir parçası olarak gramerlere de sık sık katkıda bulunuyor. Semgrep, kod arama ve bizzat kod parçaları olan sorguları AST eşleyicilerine ayrıştırmak için tree-sitter kullanıyor.
      Bir linter yazarken çoğu zaman hedef dilin çalışma zamanını da beraberinde getirmeniz gerekir. Örneğin Python’da yerleşik ast modülüyle bir ayrıştırıcı yazarsanız dil sürümü ve özelliklerle uyumlu olmanız gerekir; bu yüzden Python 2.7’de çalışan Pylint ile Python 3 kodunu ayrıştıramazsınız.
      Birden fazla dili hedeflediğinizde iş, başta düşündüğünüzden çok daha zahmetli hâle gelir.
      tree-sitter’dan önce, güncel sözdizimini takip ettiğine dair garanti olduğu için çoğu durumda dilin yerleşik AST araçlarını kullanmak en iyi seçenekti.
      Bana göre tree-sitter’ın dehası, geleneksel gramer yaklaşımlarına kıyasla dil ayrıştırıcılarını güncel tutmayı çok daha kolay hâle getirmesinde yatıyor.
      tree-sitter’ın tasarım tercihleri hakkında daha fazla şey öğrenmek istiyorsanız Max Brunsfield’ın Strange Loop sunumunu şiddetle tavsiye ederim: https://www.youtube.com/watch?v=Jes3bD6P0To
      Sonuç olarak difftastic’in yanı sıra neovim, Zed, Semgrep, GitHub kod arama gibi birçok yeni araç tree-sitter üzerine inşa edildi.
    • tree-sitter’ın harika bir araç olduğuna katılıyorum, ancak doğrudan gramer yazmak inanılmaz derecede zor olabiliyor.
      VHDL için bir tree-sitter grameri ve vurgulama sorguları seti yazmayı denedim; VHDL gramerini tree-sitter ile ifade etmekte çok zorlandım.
    • Bu açıklamanın doğru olmadığını düşünüyorum. tree-sitter konuşmak gibi ortak bir arayüz yok; her tree-sitter ayrıştırıcısı standart bir soyut sözdizimi ağacı değil, birbirinden farklı somut sözdizimi ağaçları üretiyor.
      LSP, sorgu odaklı derleyiciler için standart bir arayüz kullanarak M adet editör ile N adet dil arasında gereken M×N entegrasyon sorununu gerçekten çözüyor.
      tree-sitter ise bu sorunu çözmekten ziyade, editörlerde veya araçlarda N adet entegrasyon yazmayı çok daha kolay hâle getiriyor.
    • tree-sitter’da beni en çok düşündüren nokta, ilgilendiğim birçok dilde bu yaklaşımın işlememesi.
      Common Lisp, eksiksiz bir Lisp uygulaması olmadan ayrıştırılamaz; Haskell grameri yeterince karmaşık olduğu için gramer eksik kalıyor; C/C++’ta yalnızca önişlemciye bakmak bile doğru ayrıştırmayı zorlaştırıyor; Perl ayrıştırması ise Turing-tamam.
      Başka yerlerde önerildiği gibi, yeni ekosistemlerde ayrıştırıcıların yeniden yazılmasını istemek yerine, mevcut ayrıştırıcıların ek çıktı olarak üretebileceği bir biçim tanımlamak daha doğru görünüyor.
    • İngilizce gibi doğal diller için tree-sitter grameri oluşturup her cümleyi bir cümle birimi olarak etiketlemek mümkün olur mu?
      O zaman difftastic ile görsel satırlar yerine cümle bazlı değişiklikleri göstermek mümkün olabilir.
      Denemelerde görsel satır bazlı diff tuhaf oluyor; çünkü değişen cümle genellikle görsel satırın ortasında başlıyor.
  • cargo ile kurduysanız difftastic ve ilgili araçları güncellemenin yolu şöyle:
    cargo install cargo-update
    cargo install-update --list
    cargo install-update --all
    cargo ile kurulabilen ilginç Rust projeleri de var.
    https://mise.jdx.dev/ mise-en-place, https://asdf-vm.com/ için hızlı ve esnek bir alternatif.
    https://github.com/ajeetdsouza/zoxide harika bir cd alternatifi; gittiğiniz konumları kaydedip "z hel" gibi kısmi bir eşleşmeyle "~/projects/helloworld" dizinine gidebiliyor.
    https://github.com/bootandy/dust duyu tamamlayan bir araç; hangi dizinlerin disk alanını çok kullandığını gösteriyor.

    • Üç temiz araç daha sayarsak: https://github.com/eza-community/eza görsel olarak daha hoş bir ls, https://github.com/ClementTsang/bottom grafiklere sahip bir htop, https://github.com/sharkdp/bat ise sözdizimi vurgulamalı bir cat.
    • zoxide’u gerçekten seviyorum. Listeye lsd de eklenebilir; daha güzel bir ls.
    • mise-en-place’i kurdum; asdf’nin olmasını istediğim şeyin tam kendisi.
    • Yeni du türleri arasında en çok dua-cli hoşuma gidiyor. ncdu klonu olan etkileşimli bir terminal UI’si.
      ncduda açık tema olmadığı için ararken keşfettim.
    • ncdu açık ara en iyi du alternatifi.
  • git gibi araçların neden böyle bir şeyi varsayılan olarak sunmadığını neredeyse anlayamıyorum
    difft’i yaklaşık 1 yıldır kullanıyorum; en büyük şikâyetim, difft olmayan ortamlarda başka diff araçlarına dönmeyi zorlaştırması
    Anlam tabanlı diff araçları üzerine de araştırma yapılıp yapılmadığını merak ediyorum. Örneğin sözdizimi değişmiş ama anlamı aynı kalan durumları ele alan araçlar
    Genel bir problem olarak bakınca zor görünüyor, ama küçük DSL’lerde ya da bazı dillerin alt kümelerinde mümkün veya faydalı olabilir

    • Varsayılan olarak eski diff kullanmanın doğru olduğunu düşünüyorum
      git çalıştırmak isteyeceğiniz neredeyse her sistemde zaten var; hızlı, küçük ve herkes temel kullanımını biliyor
      Yine de bu varsayılanın kolayca değiştirilebilmesi güzel
    • https://semanticdiff.com/ üzerinde çalışıyorum; ondalık literal’i onaltılıya çevirmek ya da bir JSON nesnesindeki anahtarların sırasını değiştirmek gibi temel anlamsal değişiklikleri algılıyor
      Bir komut satırı aracı değil; VS Code eklentisi ve GitHub App
      Nasıl çalıştığını ve difftastic’ten farklarını merak ediyorsanız https://semanticdiff.com/blog/semanticdiff-vs-difftastic/ adresine bakabilirsiniz
    • Difftastic kullanışlı bir araç, ama deneyimime göre git kadar yaygın kullanılan bir aracın varsayılan seçeneği olmak için fazla yavaş
    • Bunu yapmak istiyorsanız diff aracı fiilen bir derleyiciye dönüşür
    • Şu anda git’e difft bağlayıp deniyorum ve epey hoşuma gitti
      Yine de varsayılan olmaması gerektiğini düşünmemin nedenlerinden biri, boşluk farklarını gizlemesi. Yapılandırılabilir mi henüz kontrol etmedim
  • @@ -5,6 +5,7 @@ sözdizimini okuyup okuyamadığını sormasına ve Difftastic’in değişiklik öncesi/sonrası dosyanın gerçek satır numaralarını gösterdiği açıklamasına tamamen katılıyorum
    Hemen ekleyip git diff denedim; çok iyi çalışıyor

    • O sözdizimini okuyamıyor musun?
  • GitHub’ın böyle bir şey çıkarmamış olması ürün inovasyonunda büyük bir boşluk gibi görünüyor
    Sadece girinti değişse bile yardımcı olan bir özellik yok; genelde devasa bir silme ve ekleme olarak gösteriyor
    GitHub’ın diff görüntüleyicisi daha akıllı olabilir ve olmalı

    • GitHub, anlam tabanlı diff bir yana, sözdizimi farkındalığını bile doğru düzgün yapamıyor
      Gerçekte foo.cpp.in ile foo.mk.in dosyalarının farklı olduğunu bile ayırt edemiyor
      Herhangi bir foo.t Perl olarak bildiriliyor ve bunu düzeltmenin yolu da yok. 10 yıllık bir ticket bile var
    • tree-sitter doğruluktan ziyade editörlerde kullanılmak üzere performans için optimize edilmiş durumda
      Hatta TS çekirdek geliştiricileri de gramer doğruluğu konusunda fazla takılmamayı öneriyor[1]
      GitHub ya da benzer konumdaki servisler için bu kısıt çok kritik olabilir gibi görünüyor
      [1] https://github.com/tree-sitter/tree-sitter/issues/130#issuec...
    • GitHub’da diff’te boşlukları yok sayma seçeneği var
  • Bu araca geçmeyi denedim, ama değişmeyen kısımlara bile tuhaf biçimlendirme uyguladığı için fazla gürültülü geldi
    Sonunda icdiff’e[0] geri döndüm
    [0]: https://github.com/jeffkaufman/icdiff

  • Bir süre önce Semantic Merge’i[1] keşfetmiştim ama açık kaynak değildi
    Bu araç birleştirme yapmıyor, sadece diff yapıyor; ama en azından açık kaynak ve diff’i çok daha okunabilir olduğu için şimdiden varsayılanım yaptım
    Birleştirme işlevi ekleyecek şekilde genişletme planı olup olmadığını merak ediyorum
    [1] https://docs.plasticscm.com/semanticmerge

    • GitHub README’ye göre difftastic birleştirme yapmıyor
      AST birleştirme zor bir problem ve difftastic’in kapsamına girmiyor deniyor
      Ayrıca AST diff, metin diff’i açısından kayıplı bir süreç. difftastic, sözdizimsel olarak anlamsız boşlukları yok sayıyor; ama birleştirme için boşlukların izlenmesi gerekiyor
    • Ben de Semantic Merge’i önerecektim
      Büyük bir ekipte C# projesinde dağınık bir refactoring yaparken gerçekten kurtarıcı bir araçtı
  • Önceki tartışmalar:
    https://news.ycombinator.com/item?id=27768861 (297 puan | 3 yıl önce | 61 yorum)
    https://news.ycombinator.com/item?id=32746258 (698 puan | 2 yıl önce | 90 yorum)
    https://news.ycombinator.com/item?id=30841244 (983 puan | 2 yıl önce | 219 yorum)

  • Harika bir araç gibi görünüyor, ama birkaç büyük XML dosyasıyla kontrol ettiğimde değiştirilmiş satırlar normal yeşil, değiştirilmiş öznitelikler kalın yeşil göründüğü için görsel olarak ayırt etmek zordu
    Belgelerde diff stilini değiştirmeyi ya da kalın olanlar için başka bir renk atamayı sağlayan bir yol bulamadım
    Nasıl yapılacağını bilen var mı merak ediyorum

    • Ne yazık ki henüz renk özelleştirmesi desteklenmiyor gibi görünüyor
      Bu özelliği desteklediğimi bu issue’ya[1] yorum olarak yazdım
      İstediğiniz özellik aynı kapsama giriyorsa oraya görüş ekleyebilirsiniz; yeterince farklı bir özellik olduğunu düşünüyorsanız yeni bir issue açmanız da uygun olur
      [1]: https://github.com/Wilfred/difftastic/issues/611
  • Arch Linux paketi 7 MB, ancak kurulumdan sonra 80 MB’a açılıyor; yalnızca difft ikili dosyasının bile 78 MB olması ilginç
    LZ4 sıkıştırması açık bir ZFS veri kümesinde du çıktısının 17 MB gösterdiği söyleniyor
    İkili dosyanın içinde bu kadar iyi sıkıştırılabilen bir şeyi neden doğrudan sıkıştırılmış tutmadıklarını merak ediyorum. RAM’de açılırsa daha hızlı yüklenebilirmiş gibi görünüyor

    • Sıkıştırma konusu açılmışken merak edip kontrol ettim; btrfs zstd:1 üzerinde yaklaşık 10 MB
      Processed 1 file, 614 regular extents (614 refs), 0 inline.
      Type Perc Disk Usage Uncompressed Referenced
      TOTAL 14% 10M 77M 77M
      none 100% 1.1M 1.1M 1.1M
      zstd 12% 9.8M 76M 76M
    • Nim ayrıştırıcısının birleştirilemeyen 60 MB’lık bir C dosyası olduğuna dair yorumla ilgili olabilir
      Tree-sitter görünüşe göre çok büyük miktarda koda ihtiyaç duyuyor ve bunun önemli bir kısmı tekrarlı ya da sıkıştırılabilir gibi duruyor
    • Çalıştırılabilir dosya, başlamadan önce RAM’e bütünüyle yüklenmez
      Belleğe eşlenir ve yalnızca gerçekten kullanılan kısımlar gerektiğinde yüklenir
      Bu yüzden büyük bir ikili dosyayı sıkıştırmak, demand paging’in çalışmasını engeller ve aksine daha yavaş hale getirir
      Birkaç yıl önce 280 MB’lık bir Windows EXE ile test etmiştim; yaklaşık 70 MB’a sıkıştı ama başlatılması özgün dosyadan birkaç saniye daha uzun sürdü
      İkili dosyayı ağ üzerinden çalıştırmak gibi bazı senaryolarda mantıklı olabilir, ancak çoğu durumda sıkıştırılmamış ikili dosya daha hızlı başlar