Hlavní navigace

Bash-completion: inteligentní doplňování příkazů

Petr Krčmář 20. 8. 2009

Velmi příjemnou vlastností moderních příkazových řádek je automatické doplňování. Za normálních okolností Bash doplňuje pouze příkazy, adresáře a proměnné, což je samo o sobě velmi užitečné. Můžeme jej ale naučit doplňovat podstatně více než jen to. Jeho rozšíření bash-completion umí doplnit cokoliv.

Programovatelné doplňování je součástí Bash shellu už poměrně dlouhou dobu. Přinesla jej verze 2.04, která vyšla na začátku roku 2000. Přesto ale nejsou informace o této extrémně užitečné funkci obecně příliš známé. Abychom to změnili, rozhodli jsme se ukázat vám možnosti funkce nazvané bash-completion.

Co to je?

Běžný shell umí doplnit jen věci, které dokáže přímo rychle zjistit. Obvykle to bývají názvy souborů, názvy adresářů (tedy cesty), systémové proměnné a několik dalších podobných údajů. Existuje ale řada dalších informací, které bychom chtěli doplnit, namátkou třeba:

  • parametry příkazů
  • názvy počítačů (třeba za SSH)
  • názvy balíků za balíčkovacím systémem
  • ovládací příkazy CVS
  • mailové adresy
  • cokoliv dalšího…

Tyto informace ale shell nedokáže nijak rychle vyhledat na disku, a proto je nedokáže také sám od sebe použít. Navíc nám do hry vstupuje kontext, kdy je třeba doplnit to správné na tom správném místě. Do doplňující polévky je tedy třeba zamíchat také kus inteligence.

Tuto funkci právě zajišťuje bash-completion. Ten neobsahuje rozšířené doplňování jako jediný, ale můžete jej najít také v zsh nebo v tcsh (a určitě dalších). My se ovšem budeme zabývat tím, jak to chodí v Bashi.

Chci to nainstalovat!

Instalace je poměrně snadná, stačí nainstalovat balíček bash-completion. Je možné, že ve vašem systému už bude nainstalovaný. Tento balíček není platformně závislý a obsahuje definice doplňování pro ohromné množství běžně používaných příkazů. Jeho velikost po rozbalení je asi 500 KB.

Programovatelné doplňování funguje v principu tak, že shell má k dispozici sadu skriptů, ve kterých je definováno co je třeba hlídat a co je možno na kterou pozici za příkazem doplňovat. Tyto skripty jsou uloženy v adresáři /etc/bash_completion.d/ a běžně dodávaný balík vám jich dodá asi čtyřicet (záleží ale na distribuci).

Pro spuštění pak stačí na řádku napsat

$ . /etc/bash_completion

Pokud chcete mít funkci zapnutou trvale, uložte tento řádek na konec souboru ~/.bashrc svého uživatele nebo do /etc/bashrc pro všechny uživatele. Pak je třeba se přihlásit a odhlásit.

Co to umí?

Můžete si vyzkoušet namátkou některé doplňovací funkce. Například na

$ aptitude in[tab]

vám automaticky Bash doplní install. Můžeme ale pokračovat a zapsat

$ aptitude install seam[tab]

a Bash nabídne k instalaci balíčky seamonkey-browser a seamonkey-mailnews. Vidíte, že funguje i kontextové doplňování. Bash vidí, že chceme instalovat (podle předchozího příkazu) a hledá v databázi dostupných balíčků.

Stejně tak můžeme vyzkoušet doplňování klasických parametrů:

$ mplayer * -shu[tab]

automaticky doplní -shuffle. Možností je samozřejmě daleko více, předpřipravené skriptíky toho umí opravdu hodně.

A co když tohle právě neumí?

Tady bychom mohli pro mnoho čtenářů skončit. Funkční to je a obvyklé (a často i neobvyklé) věci to umí. Nabízí se ale vtíravá otázka: co když chci vlastní doplňování, které standardně v balíku není? Samozřejmě je možné si napsat vlastní skript. Z toho také ostatně velmi dobře pochopíte, jak celá věc funguje.

Vytvoříme si nový skript, který bude obsluhovat virtuální příkaz pokus. Ten bude mít několik různých parametrů, které si necháme doplnit. Pro funkčnost tohoto příkladu není třeba samotný program pokus vytvářet. Kód bude vypadat takto:

_pokus()
{
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    opts="--help --pomoc --pokracuj --hehehe"

    if [[ ${cur} == -* ]] ; then
        COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
        return 0
    fi
}
complete -F _pokus pokus

Pokud tento kód vložíte do souboru /etc/bash_completion.d/pokus a znovu se přihlásíte, můžete si nechat doplnit parametry:

$ pokus --h[tab]
--help --hehehe

Můžete si vyzkoušet, že to funguje. Samozřejmě si vysvětlíme celý princip, který je velmi jednoduchý. Jedná se o jednoduchou Bash funkci, jejímž výstupem je proměnná COMPREPLY. To je pole, ve kterém se Bashi vrací odpověď s informací, které parametry jsou v tuto chvíli přípustné.

Samotné doplňování za nás zajišťuje příkaz compgen, který jednoduše vybírá vhodné možnosti z nabízených a ze vstupu, který mu předáme. Můžete si to vyzkoušet na řádce takříkajíc „nasucho“:

$ compgen -W "--help --pomoc --pokracuj" -- "--po"
--pomoc
--pokracuj

Program porovná sadu nabízených variant se zadaným vstupem ( --po) a vypíše možnosti. Zbytek skriptů je už jasný: načteme vstupní hodnoty od Bashe (co zadal uživatel) z pole COMP_WORDS, které obsahuje slova, která jsou právě napsaná na řádce. My si přečteme poslední slovo – proto konstrukce COMP_CWORD-1  – proměnná obsahuje počet slov napsaných právě na řádce. My si tedy zvolíme poslední (tedy nedopsané) slovo. Compgen za nás vybere příslušné možnosti a ty vrátíme Bashi.

Poslední řádek ve skriptu řekne Bashi, že má svázat naši funkci s konkrétním příkazem. Můžeme samozřejmě jednu funkci použít pro více příkazů, pokud by měly stejné parametry nebo by se jednalo o symbolický link na jeden program.

Toto je jen velmi jednoduchá ukázka funkčního skriptu, podle které jste měli pochopit princip. Samozřejmě je možné přejít k podstatně složitějším akcím, kdy můžeme hledat v databázích, zjišťovat něco na internetu (třeba e-mailové adresy v IMAPu a podobně), záleží jen na vašich nápadech.

Pravdou ovšem je, že ve většině případů si vystačíte s doplňováním parametrů z pevného seznamu, pokud máte vlastní skriptíky, můžete se s nimi pochlubit v diskusi.

Další informace naleznete v man bash, kde je popsána i proměnná COMPREPLY.

Našli jste v článku chybu?

20. 8. 2009 11:40

anca (neregistrovaný)

doplnovanie v ZSH je ovela lepsie, odporucam vyskusat

20. 8. 2009 13:28

Atrament (neregistrovaný)

ovšem stačí příkaz pustit s obráceným lomítkem na začátku – obrácené lomítko potlačuje speciální významy, takže \mplayer pustí mplayer, ale bude ignorovat bash-completion, a nejenom to ale i případné aliasy…

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Root.cz: Vypadl Google a rozbilo se toho hodně

Vypadl Google a rozbilo se toho hodně

120na80.cz: Rakovina oka. Jak ji poznáte?

Rakovina oka. Jak ji poznáte?

Vitalia.cz: Baletky propagují zdravotní superpostel

Baletky propagují zdravotní superpostel

120na80.cz: Stoná vaše dítě často? Upravte mu jídelníček

Stoná vaše dítě často? Upravte mu jídelníček

120na80.cz: 5 přírodních tipů na bolest v krku

5 přírodních tipů na bolest v krku

DigiZone.cz: Flix TV má set-top box s HEVC

Flix TV má set-top box s HEVC

DigiZone.cz: Rádio Šlágr má licenci pro digi vysílání

Rádio Šlágr má licenci pro digi vysílání

Měšec.cz: U levneELEKTRO.cz už reklamaci nevyřídíte

U levneELEKTRO.cz už reklamaci nevyřídíte

Vitalia.cz: Paštiky plné masa ho zatím neuživí

Paštiky plné masa ho zatím neuživí

Podnikatel.cz: 1. den EET? Problémy s pokladnami

1. den EET? Problémy s pokladnami

Root.cz: Certifikáty zadarmo jsou horší než za peníze?

Certifikáty zadarmo jsou horší než za peníze?

120na80.cz: Horní cesty dýchací. Zkuste fytofarmaka

Horní cesty dýchací. Zkuste fytofarmaka

Podnikatel.cz: Babiš: E-shopy z EET možná vyjmeme

Babiš: E-shopy z EET možná vyjmeme

Měšec.cz: Jak vymáhat výživné zadarmo?

Jak vymáhat výživné zadarmo?

Vitalia.cz: Dáte si jahody s plísní?

Dáte si jahody s plísní?

Lupa.cz: Seznam mění vedení. Pavel Zima v čele končí

Seznam mění vedení. Pavel Zima v čele končí

Měšec.cz: Kdy vám stát dá na stěhování 50 000 Kč?

Kdy vám stát dá na stěhování 50 000 Kč?

DigiZone.cz: ČT má dalšího zástupce v EBU

ČT má dalšího zástupce v EBU

Podnikatel.cz: Babiše přesvědčila 89letá podnikatelka?!

Babiše přesvědčila 89letá podnikatelka?!