12 puan yazan GN⁺ 2025-08-13 | 1 yorum | WhatsApp'ta paylaş
  • Bash ve Zsh'de, zaten tamamlanmış sözcükler için bile açıklama gösteren bir sekme otomatik tamamlama özelliğinin nasıl uygulanacağı tanıtılıyor
  • Bash ve Zsh, farklı sekme otomatik tamamlama API'leri kullanır; varsayılan olarak yalnızca Zsh, otomatik tamamlamada açıklama gösterme özelliği sunar
  • Adaylar _generate_foo_completions ile üretilir; Bash'te COMPREPLY, Zsh'te ise compadd ile döndürülen bir yapı kurulur
  • Zsh'nin açıklama özelliğini Bash'te de uygulamak için, aday dizelerine açıklama eklenir ve yalnızca tek aday olduğunda açıklama kaldırılır
  • Tek aday durumunda bile, <TAB> basıldığında açıklamanın gösterilmesi için bilerek belirsizlik eklenerek iyileştirme yapılır
  • Nihai betik, iki kabukta da aynı kullanıcı deneyimini sunar ve kısmi tamamlama, tam tamamlama ve aday açıklamalarını gösterme özelliklerinin tümünü destekler

Sorunun arka planı

  • Sekme otomatik tamamlama (tab-completion), komutları veya bayrakları keşfederken kullanışlıdır; özellikle bir API ya da CLI aracını ilk kez kullanırken yardımcı olur
  • Zsh varsayılan olarak yalnızca birden fazla aday olduğunda açıklama gösterir; Bash'te ise bu ancak ek yapılandırmayla mümkündür
  • Ancak zaten tamamlanmış sözcükler için her iki kabuk da açıklama göstermez
  • Bu yüzden kullanıcıların açıklamayı görmek için şu zahmetli süreci izlemesi gerekir
    • Bazı karakterleri silerek birden fazla adayın eşleşmesini sağlamak
    • Aday listesini görmek için <TAB> tuşuna basmak
    • İstenen açıklamayı görsel olarak bulmak
    • Komutu çalıştırmak için silinen karakterleri yeniden girmek

Çözümün özeti

  • Tek aday olsa bile, bir sahte aday (dummy completion) eklenerek adaylar belirsiz hale getirilir
  • Böylece hem Bash hem de Zsh, açıklamalarla birlikte aday listesini gösterir
  • Ancak açıklama metninin gerçek komuta eklenmemesine dikkat etmek gerekir

Temel kavramlar

  • Sekme otomatik tamamlama, <TAB> girildiğinde mevcut sözcüğü ve imleç konumunu alıp olası adayların listesini döndüren bir yapı ile çalışır
  • Bash: adaylar COMPREPLY dizisine atanır
  • Zsh: adaylar compadd komutuyla kaydedilir
  • _generate_foo_completions işlevi aday dizelerini yazdırır; pratikte bunlar CLI'ın durumuna göre dinamik olarak üretilebilir

Bash ve Zsh'yi aynı anda desteklemek

  • _complete_foo_bash ve _complete_foo_zsh işlevleriyle, her kabuk için ayrı uygulama yapılır
  • Ayırım için if [ -n "${ZSH_VERSION:-}" ]; then ... elif [ -n "${BASH_VERSION:-}" ]; then ... fi kullanılır
  • Kullanıcı, betiği .bashrc ya da .zshrc dosyasına ekledikten sonra etkinleştirir

Zsh'de açıklama gösterme

  • Aday dizelerinde ad: açıklama biçimi kullanılır
  • Zsh: ad ve açıklamayı paralel diziler halinde iletmek için compadd -d raw -- $trimmed kullanılır
  • Bash: yalnızca açıklama kısmı kaldırılmış adaylar COMPREPLY'e verilir (varsayılan olarak açıklama desteği yoktur)

Bash'te açıklama uygulamak

  • Birden fazla aday varsa, açıklama içeren dizeler olduğu gibi gösterilir
  • Yalnızca tek aday varsa açıklama kaldırılır
  • Bash'in yalnızca ortak öneki ekleyen otomatik tamamlama davranışından yararlanılarak, açıklamanın gerçek girdiye eklenmemesi sağlanır

Tek adayda da açıklama göstermek

  • Tamamlanmış bir sözcükte <TAB> basıldığında da açıklamayı göstermek için sahte aday eklenerek bilerek belirsizlik oluşturulur
  • Zsh: hem raw hem de trimmed adlı iki paralel diziye sahte aday eklenir
  • Bash: tek aday durumunda trimmed içine yalnızca ad eklenir

Nihai sonuç

  • Birden fazla aday olduğunda hem ad hem açıklama gösterilir
  • Tek aday olduğunda bile <TAB> ile açıklama görülebilir
  • Hem Bash hem de Zsh aynı deneyimi sunar
  • Uygulama örneği:
    $ foo <TAB>  
    apple: a common fruit banana: starchy and high in potassium  
    apricot: sour fruit... cherry: small and sweet...  
    

1 yorum

 
GN⁺ 2025-08-13
Hacker News görüşü
  • fish'te ilgilendiğiniz program bir man sayfası sağlıyorsa, yalnızca fish_update_completions çalıştırmanız yeterli
    • Bu komut sistemdeki tüm man sayfalarını ayrıştırıp otomatik tamamlama dosyalarını ~/.cache/fish/generated_completions/ içine oluşturur
    • Man sayfası zayıfsa ya da yoksa, kendiniz yazıp upstream'e katkıda bulunabilirsiniz
    • fish'in biçimi basit olduğundan resmi belgelere bakmak yeterlidir
    • Örnek: curl için -L → 'Follow redirects', -O → 'Write output to file named as remote file'
    • Ekran paylaşımı yaparken insanlar zsh ve eklentiler kullandığımı sanıyor, ama aslında yalnızca varsayılan ayarlarla bile hoş görünen fish kullanıyorum
    • Ama car TAB ifadesinin blkdiscard olarak genişlemesine yol açan önek dışı otomatik tamamlama yüzünden, cargo PATH'te olmasa bile yanlış çalışabilmesi keşke iyileştirilse
    • Man sayfası olmayıp yalnızca --help sunan programlarda, fish'te zsh'deki _gnu_generic ya da bash'teki complete -F _longopt benzeri bir özellik olup olmadığını merak ediyorum
    • zsh için de man sayfası tabanlı otomatik tamamlama üreten bir betik var → zsh-manpage-completion-generator
    • OpenSUSE'da zypper search fish-completion yazınca 200'den fazla paket çıkması bana biraz şüpheli gelmişti
  • bash otomatik tamamlaması giderek daha “akıllı” hale geldikçe, imlecin bulunduğu konumda dosya adının uygun olmadığına karar verirse dosya/dizin tamamlamayı engellemesi can sıkıcı
    • Bence bunun yerine her zaman dosya adı tamamlamaya fallback yapması daha iyi olur
    • Bu yüzden tüm tamamlama betiklerini kapatmayı bile düşündüğüm oldu
    • bash'te M-/ kısayoluna bağlı complete-filename gibi, bağlamı yok sayıp yalnızca dosya adını tamamlayan işlevler var
    • Bazı komutlarda dosya tamamlama tamamen bozuluyor; ben de önce ls ile tamamlayıp sonra komutu değiştirerek bunu aşıyorum
    • Dosya adı mevcut ama çalıştırılamıyorsa, “file foo.exe exists but it isn't executable” gibi bir mesaj vermesi daha az kafa karıştırıcı olur
    • complete -r çalıştırdıktan sonra her şeyin istediğim gibi davrandığını görünce, sorunun bash-completion betiklerinde olduğunu düşünüyorum
    • Bu, web formunda e-posta girerken daha ilk harfte “Invalid email!” hatası veren frontend doğrulaması kadar bunaltıcı bir UX'e benziyor
  • Bu yazıyı ben yazdım; başkalarının da ilginç bulmasını umuyorum
    • zsh tamamlama betiklerini her seferinde yüklemek yerine $fpath içine kurarsanız önbelleğe alınır ve başlangıç hızı artar
    • Homebrew ile dağıtırken completions otomatik olarak kurulabilir
    • zsh tamamlama sistemi büyük olduğu için öğrenmesi zor, ama iş yerinde ansible sarmalayıcı betiğine playbook bazlı seçenekler ve etiket tamamlama gibi şeyler ekleyerek giderek geliştiriyorum
  • Son zamanlarda CLI geliştirmede usage kütüphanesini kullanmaya başladım → clap ile entegre oluyor ve completions, argparse, man sayfası üretimi sağlayabiliyor
    • fish betiğindeki argparse bloğunu değiştirmeye değer mi emin değilim ama optparse'tan çok daha iyi
    • Ben de benzer bir CLI belirtim tanımlama aracı yapıyorum ve fish desteğini daha yeni ekledim
  • bash/zsh'te JSON alanı otomatik tamamlama destekleyen fx.wtf tanıtılıyor
    • ijq'dan daha hafif ama duruma göre faydalı olabilir
  • zsh yerleşik işlevleriyle completer yapmayı anlatan bir öğretici → zsh-completions-howto
  • Programların bash betiği yazmak zorunda kalmamasını sağlayacak bir standart bayrak olup olmadığını merak edenler var
    • zsh'te _gnu_generic ile --help tabanlı basit tamamlama yapılabiliyor
    • Rust'ta clap_complete, ripgrep'te --generate seçeneği, PHP Symfony'de çalışma anında tamamlama üretimi gibi örnekler var
    • Ortak ayrıştırıcı kütüphanelerinin otomatik olarak uyguladığı bir --completion standardı olsa güzel olurdu
  • ksh'te yalnızca dizi tanımlayarak basitçe tamamlama uygulanabiliyor
    • Örneğin complete_kill_1 dizisine sinyal adlarını koyarsanız kill komutunun ilk argümanı için tamamlama sağlanır
    • Bunun ksh93 sözdizimi mi olduğu, yoksa oksh'e geri taşınıp taşınmadığı merak ediliyor
  • Benim yaptığım basit bir zsh tamamlama parçacığı örneği: set-java-home işlevinde ~/apps/java/* listesini sürüm olarak tamamlamak için _describe kullanılıyor
    • Neredeyse tek satırlık kadar basit bir yapı
  • LLM'lerin temel işlevi otomatik metin tamamlama olduğu için olsa gerek, GitHub Copilot vscode terminalinde bash ve zsh tamamlamayı oldukça iyi yapıyor