3 poin oleh GN⁺ 2024-03-22 | 1 komentar | Bagikan ke WhatsApp
  • Difftastic adalah alat diff CLI yang membandingkan file berdasarkan struktur sintaks kode, bukan per baris
  • Secara internal, alat ini mem-parsing kode dengan tree-sitter, sehingga dapat membedakan ekspresi yang benar-benar berubah meskipun barisnya berubah karena pemformatan
  • Bahkan ketika pemformat kode memecah item ke beberapa baris atau pembungkus ditambahkan, alat ini dapat menampilkan secara terpisah struktur yang berubah dan isi internal yang tetap sama
  • Tersedia panduan konfigurasi Git dan dokumentasi instalasi, serta mendukung banyak bahasa pemrograman dan format teks terstruktur seperti JSON dan YAML
  • Dirilis dengan lisensi MIT, sehingga dapat diunduh, dimodifikasi, dan dibagikan, serta cocok untuk menambahkan perbandingan struktural ke alur diff yang sudah ada

Membandingkan struktur sintaks, bukan baris

  • Difftastic adalah alat diff CLI yang membandingkan file berdasarkan sintaks
  • Fokusnya adalah menampilkan hasil yang memahami struktur kode dibanding diff per baris biasa
  • Kode di-parse dengan tree-sitter
    • Bahkan ekspresi internal yang tampak berubah dalam diff berbasis baris dapat dibedakan apakah benar-benar berubah atau tidak
  • Bahkan ketika pemformat kode memecah kode ke beberapa baris, alat ini tetap dapat menampilkan perubahan yang sebenarnya
  • Jika pembungkus ditambahkan, pemisah dapat dicocokkan secara akurat
    • Bahkan jika isi internal ikut berubah, alat ini dapat menandai pembungkus yang ditambahkan
  • Alih-alih sintaks diff hunk seperti @@ -5,6 +5,7 @@, alat ini menampilkan nomor baris sebenarnya dari file sebelum dan sesudah perubahan

Bahasa yang didukung dan integrasi Git

  • Materi proyek tersedia di GitHub, Manual, Install
  • Contoh bahasa pemrograman yang didukung adalah sebagai berikut
    • C++, C#, Clojure, Dart, Erlang, Go, Haskell, Java, JavaScript, Kotlin, Lisp, Lua, OCaml, PHP, Python, R, Ruby, Rust, Scala, TypeScript
    • Daftar lengkapnya dapat dilihat di daftar bahasa yang didukung pada manual
  • Contoh format file yang didukung adalah sebagai berikut
  • Dapat digunakan bersama Git, dan manual menyediakan panduan konfigurasi Git
  • Difftastic dirilis dengan lisensi MIT, sehingga dapat diunduh, dimodifikasi, dan dibagikan

1 komentar

 
GN⁺ 2024-03-22
Komentar Hacker News
  • Sebagian orang mungkin sudah tahu, tetapi tool ini dibuat di atas tree-sitter(https://tree-sitter.github.io/tree-sitter/); bisa dibilang ia melakukan untuk parsing apa yang dilakukan LSP untuk analisis
    Ia mengubah kode menjadi abstract syntax tree (AST), lalu menyediakan antarmuka standar agar AST itu bisa digunakan oleh klien seperti editor atau tool diff
    Tool seperti ini tidak perlu mendukung puluhan bahasa secara langsung; cukup mendukung tree-sitter, maka ia otomatis bisa berjalan di semua bahasa yang didukung tree-sitter
    Jika mengembangkan bahasa baru, Anda cukup membuat parser tree-sitter, dan semua tool yang menangani tree-sitter akan bisa mendukung bahasa tersebut
    Berkat dua inovasi besar ini, peningkatan tool semacam ini melonjak pesat. Sekarang editor, tool diff, dan lainnya bisa mendukung puluhan hingga ratusan bahasa tanpa saling mengulang pekerjaan yang sama; ini benar-benar luar biasa

    • Saya sepenuhnya setuju, dan mengutip lagi komentar yang saya tulis tahun lalu, layak juga ditekankan bahwa tree-sitter memiliki struktur tanpa dependensi
      Sebagai konteks, beberapa anggota tim kami memelihara binding OCaml tree-sitter, dan sebagai bagian dari pekerjaan Semgrep, kami juga sering berkontribusi pada grammar-nya. Semgrep menggunakan tree-sitter untuk pencarian kode dan untuk mem-parse kueri yang merupakan potongan kode itu sendiri menjadi AST matcher
      Saat membuat linter, sering kali Anda harus membawa serta runtime bahasa target. Misalnya, jika membuat parser dengan modul bawaan ast di Python, Anda harus mencocokkan versi dan fitur bahasa, sehingga Pylint yang berjalan di Python 2.7 tidak bisa mem-parse kode Python 3
      Jika menargetkan banyak bahasa, ini menjadi jauh lebih merepotkan daripada yang awalnya dibayangkan
      Sebelum tree-sitter, dalam banyak kasus pilihan terbaik adalah memakai tool AST bawaan bahasa, karena ada jaminan bahwa ia mengikuti sintaks terbaru
      Menurut saya pribadi, kejeniusan tree-sitter ada pada bagaimana ia membuat parser bahasa jauh lebih mudah dijaga tetap mutakhir dibandingkan pendekatan grammar tradisional
      Jika ingin tahu lebih jauh tentang pilihan desain tree-sitter, saya sangat merekomendasikan presentasi Strange Loop dari Max Brunsfield: https://www.youtube.com/watch?v=Jes3bD6P0To
      Hasilnya, selain difftastic, berbagai tool baru seperti neovim, Zed, Semgrep, dan pencarian kode GitHub dibuat di atas tree-sitter
    • Saya setuju bahwa tree-sitter adalah tool yang hebat, tetapi menulis grammar sendiri bisa sangat sulit
      Saya pernah menulis grammar tree-sitter dan set kueri highlighting untuk VHDL, dan ada banyak kesulitan dalam mengekspresikan grammar VHDL dengan tree-sitter
    • Menurut saya penjelasan ini tidak akurat. Tidak ada antarmuka bersama seperti “berbicara tree-sitter”, dan setiap parser tree-sitter mengeluarkan concrete syntax tree yang berbeda-beda, bukan abstract syntax tree standar
      LSP benar-benar menyelesaikan masalah integrasi M×N yang dibutuhkan antara M editor dan N bahasa, dengan menggunakan antarmuka standar untuk compiler berorientasi kueri
      tree-sitter bukan menyelesaikan masalah itu, melainkan membuat pekerjaan menulis N integrasi di editor atau tool menjadi jauh lebih mudah
    • Hal yang paling mengganjal dari tree-sitter adalah pendekatan ini tidak berhasil untuk beberapa bahasa yang saya minati
      Common Lisp tidak bisa di-parse tanpa implementasi Lisp lengkap, grammar Haskell cukup rumit sehingga grammar-nya tidak lengkap, C/C++ sulit di-parse secara akurat bahkan hanya dari preprocessor-nya, dan parsing Perl bersifat Turing-complete
      Seperti usulan yang pernah muncul di tempat lain, rasanya lebih tepat mendefinisikan format yang bisa dihasilkan parser yang sudah ada sebagai keluaran tambahan, alih-alih membuat ekosistem baru menulis ulang parser
    • Bisakah dibuat grammar tree-sitter untuk bahasa alami seperti bahasa Inggris, sehingga setiap kalimat bisa diberi label sebagai satu unit kalimat?
      Dengan begitu, difftastic sepertinya bisa menampilkan perubahan berdasarkan kalimat, bukan baris visual
      Untuk esai, diff berdasarkan baris visual terasa aneh. Biasanya kalimat yang berubah dimulai di tengah baris visual
  • Jika Anda memasangnya lewat cargo, berikut cara memperbarui difftastic dan tool terkait
    cargo install cargo-update
    cargo install-update --list
    cargo install-update --all
    Ada juga beberapa proyek Rust menarik yang bisa dipasang lewat cargo
    https://mise.jdx.dev/ mise-en-place adalah pengganti https://asdf-vm.com/ yang cepat dan fleksibel
    https://github.com/ajeetdsouza/zoxide adalah pengganti cd yang hebat; ia menyimpan lokasi yang pernah dikunjungi lalu bisa berpindah ke "~/projects/helloworld" hanya dengan kecocokan sebagian seperti "z hel"
    https://github.com/bootandy/dust adalah tool pelengkap du yang menunjukkan direktori mana yang memakai banyak ruang disk

    • Tiga tool rapi lainnya: https://github.com/eza-community/eza adalah ls yang tampilannya lebih bagus, https://github.com/ClementTsang/bottom adalah htop dengan grafik, dan https://github.com/sharkdp/bat adalah cat dengan syntax highlighting
    • Saya sangat suka zoxide. lsd juga layak ditambahkan ke daftar. Itu ls yang lebih cantik
    • Saya mencoba memasang mise-en-place, dan inilah persis bentuk yang saya harapkan dari asdf
    • Di antara keluarga du baru, dua-cli adalah yang paling saya suka. Ini UI terminal interaktif yang merupakan klon ncdu
      Saya menemukannya saat mencari karena ncdu tidak punya light mode
    • ncdu jelas merupakan pengganti du terbaik
  • Saya hampir tidak mengerti mengapa alat seperti git tidak menyediakan hal semacam ini secara default
    Saya sudah memakai difft sekitar setahun, dan keluhan terbesar saya adalah difft membuat saya sulit kembali ke alat diff lain di lingkungan yang tidak punya difft
    Saya penasaran apakah ada penelitian tentang alat diff berbasis semantik juga. Misalnya alat yang menangani kasus ketika sintaks berubah tetapi maknanya sama
    Sebagai masalah umum ini tampak sulit, tetapi untuk DSL kecil atau subset dari beberapa bahasa mungkin saja bisa atau berguna

    • Menurut saya memang tepat memakai diff lama sebagai default
      Sudah ada di hampir semua sistem yang ingin menjalankan git, cepat, kecil, dan semua orang tahu cara pakai dasarnya
      Meski begitu, bagus karena default itu bisa diubah dengan mudah
    • Saya sedang membuat https://semanticdiff.com/, yang mendeteksi perubahan semantik dasar seperti mengubah literal desimal menjadi heksadesimal atau mengubah urutan kunci di dalam objek JSON
      Ini bukan utilitas command-line, melainkan ekstensi VS Code dan GitHub App
      Jika penasaran cara kerjanya dan perbedaannya dengan difftastic, lihat https://semanticdiff.com/blog/semanticdiff-vs-difftastic/
    • Difftastic adalah alat yang berguna, tetapi menurut pengalaman saya terlalu lambat untuk dijadikan pilihan default pada alat yang dipakai seluas git
    • Untuk melakukan hal seperti ini, alat diff pada dasarnya menjadi compiler
    • Saya sedang mencoba memakai difft dengan git, dan cukup suka
      Namun salah satu alasan saya merasa ini tidak boleh menjadi default adalah karena ia menyembunyikan perbedaan whitespace. Saya belum mengecek apakah itu bisa dikonfigurasi
  • Saya sangat setuju dengan penjelasan yang menanyakan apakah orang bisa membaca sintaks @@ -5,6 +5,7 @@, dan bahwa Difftastic menunjukkan nomor baris aktual dari file sebelum dan sesudah perubahan
    Saya langsung memasangnya dan mencoba git diff, dan hasilnya sangat baik

    • Memangnya ada yang tidak bisa membaca sintaks itu?
  • Fakta bahwa GitHub belum merilis hal seperti ini tampak seperti celah besar dalam inovasi produk
    Bahkan ketika hanya indentasi yang berubah, tidak ada fitur yang membantu, dan biasanya ditampilkan sebagai penghapusan dan penambahan besar-besaran
    Penampil diff GitHub bisa dan seharusnya lebih pintar

    • GitHub bahkan belum benar-benar punya kesadaran sintaks, apalagi diff berbasis semantik
      Dalam praktiknya, ia bahkan tidak bisa membedakan bahwa foo.cpp.in dan foo.mk.in berbeda
      File foo.t apa pun dinyatakan sebagai Perl dan tidak ada cara memperbaikinya. Bahkan ada tiket yang sudah berumur 10 tahun
    • tree-sitter dioptimalkan untuk performa agar dipakai di editor, bukan untuk akurasi
      Bahkan para pengembang inti TS menyarankan agar tidak terlalu memusingkan akurasi tata bahasanya[1]
      Batasan ini tampaknya bisa menjadi fatal bagi GitHub atau layanan dengan posisi serupa
      [1] https://github.com/tree-sitter/tree-sitter/issues/130#issuec...
    • GitHub punya opsi untuk mengabaikan whitespace di diff
  • Saya mencoba beralih ke alat ini, tetapi terasa terlalu berisik karena memakai format aneh bahkan pada bagian yang tidak berubah
    Akhirnya saya kembali ke icdiff[0]
    [0]: https://github.com/jeffkaufman/icdiff

  • Dulu saya menemukan Semantic Merge[1], tetapi itu bukan open source
    Yang ini tidak melakukan merge dan hanya diff, tetapi setidaknya open source dan diff-nya jauh lebih enak dilihat, jadi saya sudah menjadikannya default
    Saya penasaran apakah ada rencana memperluasnya dengan fitur merge
    [1] https://docs.plasticscm.com/semanticmerge

    • Menurut README GitHub, difftastic tidak melakukan merge
      Merge AST adalah masalah yang sulit dan tidak ditangani oleh difftastic
      Selain itu, diff AST adalah proses yang lossy dari sudut pandang diff teks. difftastic mengabaikan whitespace yang tidak bermakna secara sintaksis, tetapi merge perlu melacak whitespace
    • Saya juga hendak merekomendasikan Semantic Merge
      Saat melakukan refactoring berantakan pada proyek C# di tim besar, alat itu benar-benar seperti penyelamat
  • Diskusi sebelumnya:
    https://news.ycombinator.com/item?id=27768861 (297 poin | 3 tahun lalu | 61 komentar)
    https://news.ycombinator.com/item?id=32746258 (698 poin | 2 tahun lalu | 90 komentar)
    https://news.ycombinator.com/item?id=30841244 (983 poin | 2 tahun lalu | 219 komentar)

  • Tampaknya alat yang bagus, tetapi ketika saya mengeceknya dengan beberapa file XML besar, baris yang dimodifikasi ditampilkan hijau biasa dan atribut yang dimodifikasi hijau tebal, sehingga sulit dibedakan secara visual
    Saya tidak menemukan cara di dokumentasi untuk mengubah gaya diff atau menetapkan warna lain untuk bagian yang tebal
    Saya penasaran apakah ada yang tahu caranya

    • Sayangnya, sepertinya kustomisasi warna belum didukung
      Saya menambahkan komentar pada issue ini[1] untuk mendukung fitur tersebut
      Jika fitur yang Anda inginkan masih dalam kategori yang sama, Anda bisa menambahkan pendapat di sana; jika menurut Anda cukup berbeda, mungkin bisa membuka issue baru
      [1]: https://github.com/Wilfred/difftastic/issues/611
  • Menarik bahwa paket Arch Linux ukurannya 7MB, tetapi setelah dipasang diekstrak menjadi 80MB, dan biner difft saja sudah 78MB
    Pada dataset ZFS dengan kompresi LZ4 diaktifkan, du katanya menunjukkan 17MB
    Saya penasaran mengapa sesuatu di dalam biner yang bisa terkompresi sebaik ini tidak dibiarkan dalam bentuk terkompresi saja. Jika didekompresi di RAM, tampaknya bisa dimuat lebih cepat

    • Karena pembahasan soal kompresi muncul, saya jadi penasaran dan mengeceknya; di btrfs zstd:1 ukurannya sekitar 10MB
      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
    • Ini sepertinya terkait dengan komentar bahwa parser Nim adalah file C 60MB yang tidak bisa digabungkan
      Tree-sitter tampaknya membutuhkan kode dalam jumlah sangat besar, dan sebagian besarnya terlihat duplikatif atau bisa dikompresi
    • Berkas executable tidak dimuat seluruhnya ke RAM lalu baru dimulai
      Ia dipetakan ke memori, dan hanya bagian yang benar-benar digunakan yang dimuat saat diperlukan
      Jadi jika biner besar dikompresi, demand paging tidak akan bekerja dan justru menjadi lebih lambat
      Beberapa tahun lalu saya menguji EXE Windows berukuran 280MB; memang bisa dikompresi menjadi sekitar 70MB, tetapi butuh beberapa detik lebih lama untuk mulai dibandingkan versi aslinya
      Dalam beberapa skenario, seperti menjalankan biner lewat jaringan, ini bisa masuk akal, tetapi dalam kebanyakan kasus biner yang tidak dikompresi mulai lebih cepat