3 คะแนน โดย GN⁺ 2024-11-09 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • Delta เป็นเครื่องมือที่เพิ่มการเน้นไวยากรณ์และฟังก์ชันโปรแกรมดูหน้าให้กับเอาต์พุตของ Git, diff และ grep ช่วยให้อ่าน diff ได้มีประสิทธิภาพและสวยงามขึ้น
  • ใน package manager ส่วนใหญ่ ชื่อแพ็กเกจคือ git-delta แต่ไฟล์รันคือ delta และสามารถตั้งค่า core.pager = delta ใน ~/.gitconfig เพื่อใช้เป็น Git pager ได้
  • ฟีเจอร์หลักได้แก่ ธีมเน้นไวยากรณ์เดียวกับ bat, การเน้น diff ระดับคำโดยอิงอัลกอริทึมอนุมานการแก้ไข Levenshtein, มุมมองเปรียบเทียบซ้าย-ขวา, เลขบรรทัด, การนำทางด้วย n/N และการแสดง merge conflict ที่ปรับปรุงดีขึ้น
  • ยังเน้นไวยากรณ์ให้เอาต์พุตของ git blame, rg, git grep, grep ได้ด้วย และสามารถใช้ --hyperlinks เพื่อทำให้ commit hash อยู่ในรูปแบบลิงก์ของผู้ให้บริการโฮสติ้งอย่าง GitHub, GitLab, SourceHut, Codeberg
  • สามารถคงลักษณะให้ใกล้เคียงกับเอาต์พุต Git/diff พื้นฐาน หรือปรับเลย์เอาต์และสไตล์ได้อย่างมาก ทำให้ปรับแต่งสภาพแวดล้อมการรีวิว diff ภายในเทอร์มินัลได้ละเอียด

Delta ทำอะไร

  • Delta เป็นโปรแกรมดูหน้าแบบเน้นไวยากรณ์สำหรับเอาต์พุต Git, diff และ grep
  • มีเป้าหมายเพื่อทำให้เวลาที่ใช้ในการอ่าน diff มีประสิทธิภาพและเพลิดเพลินขึ้นในสภาพแวดล้อมที่โค้ดเปลี่ยนแปลงตลอดเวลา
  • สามารถปรับ เลย์เอาต์และสไตล์ ของ diff ได้อย่างกว้างขวาง และหากต้องการก็สามารถคงไว้ให้ใกล้เคียงกับเอาต์พุต Git/diff พื้นฐานมาก ๆ ได้

การติดตั้งและการตั้งค่าพื้นฐาน

  • เอกสารการติดตั้งมีอยู่ที่ Install it
  • ใน package manager ส่วนใหญ่ ชื่อแพ็กเกจคือ git-delta และชื่อไฟล์รันคือ delta
  • สามารถเพิ่มการตั้งค่าต่อไปนี้ลงใน ~/.gitconfig เพื่อใช้เป็น Git pager และตัวกรอง diff แบบอินเทอร์แอ็กทีฟได้
[core]
    pager = delta

[interactive]
    diffFilter = delta --color-only

[delta]
    navigate = true  # use n and N to move between diff sections
    dark = true      # or light = true, or omit for auto-detection

[merge]
    conflictStyle = zdiff3
  • การตั้งค่าเดียวกันสามารถใช้ผ่านคำสั่ง git config --global ได้เช่นกัน
git config --global core.pager delta
git config --global interactive.diffFilter 'delta --color-only'
git config --global delta.navigate true
git config --global delta.dark true  # or `delta.light true`, or omit for auto-detection
git config --global merge.conflictStyle zdiff3
  • ดูความช่วยเหลือได้ที่ delta -h, คู่มือฉบับเต็มที่ delta --help และเอกสารออนไลน์ที่ user manual

ฟีเจอร์สำหรับอ่าน diff

  • การเน้นไวยากรณ์ ใช้ธีมเน้นไวยากรณ์เดียวกับ bat
  • การเน้น diff ระดับคำใช้ อัลกอริทึมอนุมานการแก้ไข Levenshtein
  • รองรับมุมมองเปรียบเทียบซ้าย-ขวาและการตัดบรรทัด
  • รองรับการแสดงเลขบรรทัด
  • สามารถใช้ปุ่ม n และ N เพื่อย้ายระหว่างไฟล์ใน diff ขนาดใหญ่ หรือระหว่าง diff ในมุมมอง log -p ได้
    • ฟีเจอร์นี้เปิดใช้งานด้วย --navigate
  • รองรับเอาต์พุต unified diff แบบดั้งเดิมร่วมกับเอาต์พุตของ Git
  • สามารถตรวจจับพื้นหลังเทอร์มินัลแบบสว่าง/มืดได้อัตโนมัติ

รูปแบบการแสดงผลและธีม

  • ธีมเน้นไวยากรณ์ ทุกธีมที่ bat มีให้ สามารถใช้ใน Delta ได้เช่นกัน
    • delta --show-syntax-themes --dark
    • delta --show-syntax-themes --light
  • มุมมองเปรียบเทียบซ้าย-ขวามีเอกสารอยู่ใน Side-by-side view user manual
[delta]
    side-by-side = true
  • ค่าเริ่มต้นของมุมมองเปรียบเทียบซ้าย-ขวาเปิดใช้เลขบรรทัด และมีการเน้นไวยากรณ์ทั้งในพาเนลซ้ายและขวา
  • มุมมองเปรียบเทียบซ้าย-ขวาจะตัดบรรทัดยาวโดยอัตโนมัติ
  • ฟีเจอร์เลขบรรทัดมีเอกสารอยู่ใน Line numbers user manual
[delta]
    line-numbers = true

การรองรับตามงานของ Git

  • การแสดง merge conflict มีให้ในรูปแบบที่ปรับปรุงแล้ว และเอกสารที่เกี่ยวข้องอยู่ที่ Merge conflicts user manual
  • เอาต์พุตของ git blame รองรับการเน้นไวยากรณ์ และเมื่อใช้ --hyperlinks จะสามารถทำให้ commit อยู่ในรูปแบบลิงก์ของผู้ให้บริการโฮสติ้งได้
    • ผู้ให้บริการโฮสติ้งที่รองรับ: GitHub, GitLab, SourceHut, Codeberg
    • เอกสารที่เกี่ยวข้อง: Git blame user manual
  • ยังเน้นไวยากรณ์ให้เอาต์พุต grep เช่น rg, git grep, grep ด้วย
  • รองรับฟีเจอร์ --color-moved ของ Git

การจัดสไตล์และโหมดเข้ากันได้

  • สามารถคัดลอกโค้ดจาก diff ได้โดยตรง และเครื่องหมาย -/+ จะถูกลบออกโดยค่าเริ่มต้น
  • มีโหมดจำลอง diff-highlight และ diff-so-fancy
  • commit hash สามารถเชื่อมไปยังหน้าของผู้ให้บริการโฮสติ้งในรูปแบบ hyperlinks ของเทอร์มินัลได้
  • พาธไฟล์ก็สามารถทำให้อยู่ในรูปแบบไฮเปอร์ลิงก์ที่เปิดได้ในระบบปฏิบัติการ
  • สามารถจัดสไตล์ กล่อง/เส้นตกแต่ง ที่ช่วยดึงความสนใจไปยังส่วนหัว commit, ไฟล์ และ hunk ได้
  • รองรับสตริงสไตล์ที่รวมสี foreground, สี background และคุณสมบัติฟอนต์ สำหรับองค์ประกอบที่กำหนดสไตล์ได้มากกว่า 20 รายการ
    • ภาษาในการกำหนดสไตล์ใช้ภาษา color/style แบบเดียวกับ Git

1 ความคิดเห็น

 
GN⁺ 2024-11-09
ความคิดเห็นบน Hacker News
  • Delta เป็นเครื่องมือแบบตั้งค่าครั้งเดียวแล้วลืมไปได้เลย และพักใหญ่แล้วที่ไม่ได้เห็นเอาต์พุต git grep/diff/blame แบบ “ดิบ ๆ”
    ผมใช้มันเสมอกับ diff ทั่วไปนอก Git repository ด้วย และวันนี้เพิ่งรู้ว่าสามารถใช้ร่วมกับ ripgrep ได้ด้วย
    https://dandavison.github.io/delta/grep.html
    bat ที่มีคนพูดถึงไปแล้วก็เป็นเครื่องมือแบบตั้งค่าครั้งเดียวแล้วลืมเหมือนกัน เลยตั้ง alias ให้ cat เป็น bat และแยก /usr/bin/cat ซึ่งเป็น “cat แท้ ๆ” ไว้เป็น alias vcat
    https://github.com/sharkdp/bat

    • ถ้าต้องการกันไม่ให้ alias ขยาย ให้ใช้ \cat
  • ผมยังจำข้อสังเกตดี ๆ ที่เคยเห็นได้อยู่ คือ syntax highlighting ในปัจจุบันกำลังเน้นผิดสิ่ง
    ไวยากรณ์เป็นสิ่งที่มนุษย์แยกแยะได้ดีอยู่แล้ว จึงไม่ควรลงสีที่ไวยากรณ์ แต่ควรเน้น symbol มากกว่า ถ้าให้สีต่างกันกับชื่อตัวแปรและชื่อฟังก์ชันแต่ละตัว เป้าหมายจะไม่ใช่ “นี่คือ symbol” แต่เป็น “แยก symbol ที่แตกต่างกันได้เร็วขึ้น”
    แต่เพราะมันยากกว่าการแต่งไวยากรณ์มาก เครื่องมือต่าง ๆ เลยดูเหมือนจะอยู่กับทางที่ง่ายมากกว่าทางที่มีประโยชน์ syntax highlighting ก็ช่วยได้ไม่น้อยเหมือนกัน แต่ผมอยากเห็นว่าเอนจินจับคู่ symbol ทำงานได้ดีจริงแค่ไหน
    จำไม่ได้ว่าอ่านต้นฉบับที่ไหน เลยอ้างแหล่งที่มาให้ถูกต้องไม่ได้
    ระหว่างค้นหาเจอบทความนี้: https://www.wilfred.me.uk/blog/2014/09/27/the-definitive-gui...

    • ใน KDevelop เขาเรียกสิ่งนี้ว่า semantic highlighting ไม่ใช่ syntax highlighting
      น่าจะมีมาก่อนหน้านี้อีก แต่บทความอธิบายที่เก่าที่สุดเท่าที่หาได้คือบทความปี 2009: https://zwabel.wordpress.com/2009/01/08/c-ide-evolution-from...
    • ผู้เขียนบทความนั้นยังสร้าง difftastic ซึ่งเป็น “diff เชิงโครงสร้างที่เข้าใจไวยากรณ์” โดยใช้ treesitter ด้วย
      https://difftastic.wilfred.me.uk/
      https://github.com/Wilfred/difftastic
    • เห็นด้วยสุด ๆ ตอนแรกดูแปลกตา แต่พอชินแล้วก็ชอบวิธี highlight แบบนี้มากกว่า
      ส่วนตัวใช้ color-identifiers-mode ใน Emacs
      https://github.com/ankurdave/color-identifiers-mode
    • ชื่อตัวแปรก็แยกแยะได้ค่อนข้างดี โดยเฉพาะถ้าไวยากรณ์ถูก highlight อยู่แล้ว ก็จะรู้ชัดเจนว่าควรมองตรงไหนและไม่จำเป็นต้องมองตรงไหน
      ผมยังไม่ได้ถูกตรรกะนั้นโน้มน้าวอย่างสมบูรณ์ แต่ก็แอบสนใจอยู่บ้าง
      บางครั้งผม highlight เองเพื่อตามตัวแปรและตรวจว่ามีจุดใช้งานที่พลาดไปไหม ซึ่งเข้าใจประโยชน์ในกรณีนั้นดี แต่ไม่แน่ใจว่าสีและคอนทราสต์จะพอสำหรับตามหลายตัวแปรพร้อมกันหรือไม่ และหน้าจออาจดูรกได้
      ทางประนีประนอมอาจเป็นการลงสีตัวแปรเองได้สูงสุดประมาณ 3 ตัว แต่กรณีที่ต้องการความช่วยเหลือแบบนั้นก็อาจเป็นสัญญาณตั้งแต่แรกว่าโค้ดอ่านยากอยู่แล้ว แน่นอนว่าการช่วยจัดการ codebase ที่รกก็เป็นการใช้งานที่สมเหตุสมผล
  • ไม่ได้หวือหวา แต่ถ้าต้องการ diff ระดับคำ ที่พอใช้ได้ด้วย git มาตรฐานอย่างเดียว แค่นี้ก็มักจะเพียงพอ
    git diff --color-words --word-diff-regex='\w+|.'

    • ถ้าจะเปิดเป็นค่าเริ่มต้นใน .gitconfig ต้องทำอย่างไร?
  • Delta ทำหน้าที่ของมันได้ดีมาก แต่ผมติดปัญหาที่มันตัดบรรทัดยาว ๆ อยู่เรื่อย ๆ
    พอเห็นบทความนี้เลยลองเช็กว่าสถานการณ์เปลี่ยนไปหรือยัง และมันเปลี่ยนไปจริง ๆ ตอนนี้ถ้าตั้งค่า git config --global --replace-all delta.max-line-length 0 ก็จะไม่ตัดบรรทัดอีกต่อไป
    ไม่ค่อยแน่ใจว่าทำไมค่านี้ถึงไม่ใช่ค่าเริ่มต้น การอภิปรายเรื่องการเปลี่ยนแปลงอยู่ที่ https://github.com/dandavison/delta/pull/290

    • เหตุผลที่ไม่ใช่ค่าเริ่มต้นก็อยู่ใน PR นั้นตามตรงเลย
      เพราะเมื่อทำ syntax highlighting กับบรรทัดที่ยาวมาก เช่นไฟล์ .js ที่ถูก minify ถ้าไม่ตัดอาจช้ามากได้
  • ไหน ๆ ก็พูดถึง diff แล้ว สิ่งที่น่ารำคาญในเอาต์พุต diff ของ Git คือมันแสดง path ของไฟล์โดยเริ่มจากชื่อไฟล์สองชื่อเหมือน Unix diff แบบดั้งเดิม
    --- a/some/path/to/file.c
    +++ b/some/path/to/file.c
    ผมมักใช้ cmd-คลิกใน iTerm เพื่อเปิดไฟล์ใน editor แต่กรณีนี้ใช้ไม่ได้เพราะ prefix a/ และ b/ มีวิธีให้ Git format ชื่อไฟล์ให้ดีกว่านี้ไหม? สองบรรทัดนั้นก็ไม่ได้จำเป็นด้วยซ้ำ

    • git config --global diff.noprefix true
      ตัวเลือกอื่นเกี่ยวกับ prefix ดูได้ในคู่มือ
  • ผมใช้ delta กับ difftastic ผสมกันอยู่ และทั้งคู่ยอดเยี่ยม
    โดยเฉพาะ difftastic เก่งกับ syntax แบบ tree-sitter AST จึงช้านิดหน่อย แต่ diff ที่รู้จัก AST นั้นดีจริง ๆ
    Delta สะอาดตาและเร็วมาก

  • ทิปที่มีประโยชน์สำหรับเปิด/ปิดฟีเจอร์ side-by-side ของ Delta ตามขนาดหน้าต่าง ตัวอย่างนี้อิง bash ส่วน shell อื่น ๆ ก็ประยุกต์ใช้เองได้
    function delta_sidebyside {
    if [[ COLUMNS -ge 120 ]]; then
    DELTA_FEATURES='side-by-side'
    else
    DELTA_FEATURES=''
    fi
    }
    trap delta_sidebyside WINCH

    • ข้างหน้า COLUMNS ขาด $ และน่าจะต้อง export ก่อนตั้งค่า DELTA_FEATURES ด้วย
  • ผมใช้ทั้ง delta และ difftastic และแนะนำเท่าไรก็ไม่พอ
    ถ้าใช้ terminal แม้แต่นิดเดียว ก็ควรติดตั้งไว้

    • Difftastic กับ Delta ไม่ได้ทำงานเฉพาะใน terminal ล้วน ๆ เท่านั้น
      ทั้งคู่รองรับใน Magit ของ Emacs และ Lazygit ก็รองรับด้วย
    • ผมใช้ difftastic มาพักหนึ่งแล้ว สงสัยว่าถ้าจะใช้ทั้งสองตัวร่วมกันต้องใช้อย่างไร
  • tig ก็ควรลองดู: https://jonas.github.io/tig/

  • เพราะใช้ git diff ธรรมดาที่มีสีมาตลอด เลยอยากชอบสิ่งนี้อยู่เหมือนกัน แต่ดู ซับซ้อนเกินไป

    • คุณอาจชอบ diffr ก็ได้: https://github.com/mookid/diffr
      ขอแจ้งว่าเป็นโปรเจกต์ของผมเอง
    • รู้สึกแบบเดียวกันเลย ไม่เคยรู้สึกว่า git diff แบบดั้งเดิมมีปัญหาอะไรเป็นพิเศษ