12 पॉइंट द्वारा GN⁺ 2025-08-13 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • Bash और Zsh में ऐसे tab auto-completion फीचर को लागू करने का तरीका पेश किया गया है जो पहले से complete हुए शब्दों पर भी description दिखाता है
  • Bash और Zsh अलग-अलग tab auto-completion API का उपयोग करते हैं, और डिफ़ॉल्ट रूप से केवल Zsh में auto-completion के साथ description दिखाने की सुविधा होती है
  • _generate_foo_completions से candidates बनाए जाते हैं, और Bash में COMPREPLY, जबकि Zsh में compadd के जरिए उन्हें return करने वाली संरचना लागू की जाती है
  • Zsh की description सुविधा को Bash में भी लागू करने के लिए candidate string में description शामिल किया जाता है, और केवल single candidate होने पर description हटाया जाता है
  • single candidate होने पर भी <TAB> इनपुट पर description दिखाने के लिए जानबूझकर ambiguity जोड़ी जाती है
  • अंतिम script दोनों shells में एक जैसा user experience देता है, और partial completion, full completion, candidate description display तीनों को support करता है

समस्या की पृष्ठभूमि

  • tab auto-completion कमांड या flags को explore करते समय उपयोगी है, खासकर जब कोई API या CLI tool पहली बार इस्तेमाल किया जा रहा हो
  • Zsh डिफ़ॉल्ट रूप से सिर्फ तब description दिखाता है जब कई candidates हों, जबकि Bash में यह अलग configuration के बाद ही संभव है
  • लेकिन पहले से complete हुए शब्द के लिए दोनों shells description नहीं दिखाते
  • इसके कारण user को description देखने के लिए यह झंझट करना पड़ता है
    • कुछ characters हटाने पड़ते हैं ताकि कई candidates match हों
    • candidates की सूची देखने के लिए <TAB> key दबानी पड़ती है
    • मनचाहा description visually ढूँढना पड़ता है
    • फिर हटाए गए characters दोबारा टाइप कर command चलानी पड़ती है

समाधान का अवलोकन

  • single candidate होने पर भी dummy candidate जोड़कर candidates को ambiguous बनाया जाता है
  • इससे Bash और Zsh दोनों candidate list के साथ description output करने लगते हैं
  • लेकिन यह ध्यान रखना ज़रूरी है कि actual command में description text insert न हो

बुनियादी अवधारणा

  • tab auto-completion <TAB> इनपुट पर current word और cursor position लेकर possible candidates की सूची return करता है
  • Bash: candidates को COMPREPLY array में assign किया जाता है
  • Zsh: candidates को compadd command से register किया जाता है
  • _generate_foo_completions function candidate strings output करता है, और व्यवहार में इन्हें CLI की state के आधार पर dynamically generate किया जा सकता है

Bash और Zsh दोनों को support करना

  • _complete_foo_bash और _complete_foo_zsh functions के जरिए हर shell के लिए अलग implementation की जाती है
  • if [ -n "${ZSH_VERSION:-}" ]; then ... elif [ -n "${BASH_VERSION:-}" ]; then ... fi से shell का फर्क किया जाता है
  • user script को .bashrc या .zshrc में register करके apply कर सकता है

Zsh में description दिखाना

  • candidate string के लिए नाम: विवरण फ़ॉर्मेट का उपयोग किया जाता है
  • Zsh: compadd -d raw -- $trimmed से name और description को parallel arrays के रूप में pass किया जाता है
  • Bash: description वाला भाग हटाकर सिर्फ candidate को COMPREPLY में दिया जाता है (डिफ़ॉल्ट रूप से description support नहीं है)

Bash में description लागू करना

  • कई candidates होने पर description शामिल string को वैसे ही expose किया जाता है
  • केवल single candidate होने पर description हटाया जाता है
  • Bash के इस व्यवहार का उपयोग किया जाता है कि auto-completion सिर्फ common prefix insert करता है, ताकि description actual input में शामिल न हो

single candidate पर भी description दिखाना

  • complete हुए शब्द पर <TAB> दबाने पर भी description दिखाने के लिए dummy candidate जोड़कर ambiguity बनाई जाती है
  • Zsh: दोनों parallel arrays (raw, trimmed) में dummy candidate जोड़ा जाता है
  • Bash: single candidate होने पर trimmed में सिर्फ name जोड़ा जाता है

अंतिम परिणाम

  • multiple candidates होने पर name + description दोनों दिखते हैं
  • single candidate होने पर भी <TAB> से description देखा जा सकता है
  • Bash और Zsh दोनों में एक जैसा अनुभव मिलता है
  • लागू होने का उदाहरण:
    $ foo <TAB>  
    apple: a common fruit banana: starchy and high in potassium  
    apricot: sour fruit... cherry: small and sweet...  
    

1 टिप्पणियां

 
GN⁺ 2025-08-13
Hacker News राय
  • fish में अगर किसी रुचिकर प्रोग्राम के लिए man page उपलब्ध है, तो बस fish_update_completions चलाना होता है
    • यह कमांड सिस्टम की सभी man pages को parse करके auto-completion files को ~/.cache/fish/generated_completions/ में बनाता है
    • अगर man page कमजोर हो या मौजूद न हो, तो उसे खुद लिखा जा सकता है और upstream में योगदान दिया जा सकता है
    • fish का format सरल है, इसलिए आधिकारिक docs देखना ही काफी है
    • उदाहरण: curl का -L → 'Follow redirects', -O → 'Write output to file named as remote file'
    • स्क्रीन शेयर करते समय लोग समझते हैं कि मैं zsh और plugins इस्तेमाल कर रहा हूँ, लेकिन वास्तव में मैं सिर्फ default settings के साथ सुंदर fish इस्तेमाल कर रहा हूँ
    • लेकिन car TAB का blkdiscard में expand हो जाना, यानी non-prefix auto-completion, की वजह से cargo के PATH में न होने पर भी गलत व्यवहार होता है; यह बेहतर हो तो अच्छा होगा
    • जिन प्रोग्राम्स में man page नहीं है और सिर्फ --help मिलता है, उनके लिए सोच रहा हूँ कि क्या fish में zsh के _gnu_generic या bash के complete -F _longopt जैसी कोई सुविधा है
    • zsh में भी man page-आधारित auto-completion generate करने वाली script है → zsh-manpage-completion-generator
    • OpenSUSE में zypper search fish-completion चलाने पर 200 से ज्यादा packages दिखे, तो कुछ संदिग्ध-सा लगा
  • bash auto-completion का लगातार “ज़्यादा स्मार्ट” होना असुविधाजनक है, क्योंकि जब उसे लगता है कि मौजूदा cursor position पर filename उपयुक्त नहीं है, तो वह file/directory completion को रोक देता है
    • मुझे लगता है कि कम से कम हमेशा filename completion पर fallback होना चाहिए
    • इसी वजह से कभी-कभी सभी completion scripts बंद कर देने का भी विचार आया
    • bash में M-/ से bind किया गया complete-filename जैसे functions होते हैं, जो context को नज़रअंदाज़ करके सिर्फ filename complete करते हैं
    • कुछ commands में file completion पूरी तरह टूट जाती है, इसलिए पहले ls से complete करके फिर command बदलकर workaround करना पड़ता है
    • अगर filename मौजूद हो लेकिन executable न हो, तो “file foo.exe exists but it isn't executable” जैसा message देना कम भ्रमित करेगा
    • complete -r चलाने के बाद अगर सब कुछ मनचाहे तरीके से काम करता है, तो लगता है कि समस्या bash-completion script में है
    • यह UX कुछ वैसा ही परेशान करने वाला है जैसा web form में email टाइप करते समय, पहला अक्षर डालते ही frontend validation का “Invalid email!” error दिखना
  • यह लेख मैंने लिखा है, और उम्मीद है कि दूसरों ने भी इसे दिलचस्प पाया होगा
    • zsh completion script को हर बार load करने के बजाय अगर उसे $fpath में install किया जाए, तो वह cache हो जाती है और startup speed तेज हो जाती है
    • Homebrew distribution के समय completions को अपने-आप install कराया जा सकता है
    • zsh completions काफी बड़ी और सीखने में कठिन हैं, लेकिन कंपनी में ansible wrapper script के लिए playbook-वार options, tag auto-completion आदि जोड़ते हुए मैं इन्हें धीरे-धीरे बेहतर बना रहा हूँ
  • हाल में CLI development में usage library इस्तेमाल करनी शुरू की है → clap के साथ integrate होती है, और completions·argparse·man page generation कर सकती है
    • fish script के argparse block को बदलना कितना उचित है, इस पर अभी सोच रहा हूँ, लेकिन optparse से तो यह काफी बेहतर है
    • मैं भी इसी तरह का CLI spec definition tool बना रहा हूँ, और अभी-अभी उसमें fish support जोड़ी है
  • bash/zsh में JSON field auto-completion देने वाले fx.wtf का परिचय दिया गया
    • यह ijq से हल्का है, लेकिन स्थिति के अनुसार उपयोगी हो सकता है
  • zsh built-in functions से completer बनाने का tutorial → zsh-completions-howto
  • यह जिज्ञासा है कि क्या कोई standard flag है जिससे प्रोग्राम को bash script लिखने की जरूरत ही न पड़े
    • zsh में _gnu_generic के जरिए --help आधारित सरल completion संभव है
    • Rust के clap_complete, ripgrep के --generate option, और PHP Symfony के runtime completion generation जैसे उदाहरण हैं
    • अच्छा होगा अगर कोई --completion standard हो, जिसे common parser libraries अपने-आप implement करें
  • ksh में सिर्फ array definition से सरल completion implement की जा सकती है
    • उदाहरण: complete_kill_1 array में signal names डालने पर kill command के पहले argument की completion मिलती है
    • यह ksh93 syntax है या oksh में backport किया गया है, यह जानने की जिज्ञासा है
  • मेरे बनाए एक सरल zsh completion snippet का उदाहरण: set-java-home function में ~/apps/java/* सूची को version के रूप में complete कराने के लिए _describe का उपयोग
    • संरचना लगभग one-liner जितनी सरल है
  • शायद LLM का मुख्य काम auto text completion होना भी एक कारण है कि GitHub Copilot, vscode terminal में bash और zsh completion काफी अच्छी तरह कर देता है