2009-12-13 17 views
3

Bash vous permet de compléter les noms des commandes et les noms des fichiers dans les arguments avec la touche TAB. Mais pourquoi pas aussi des options communes aux commandes? Pourquoi pas, encore mieux, un système d'achèvement qui vous dit ce qu'une option fait aussi?Bash Achèvement: Que pouvons-nous faire avec, ce qui se trouve dans le futur

J'ai entendu d'achèvement programmable .. mais ne comprends pas où il s'intègre ..

Ma question est: est-il un moyen d'obtenir ce que je demande? D'autres outils pour combiner avec Bash peut-être .. ou quoi que ce soit?

+0

Je suis sur un mac avec OSX 10.6, j'utilise GNUBash version 3.2.48 – luca

Répondre

1

achèvement Bash est très personnalisable et peut afficher des options aux commandes communes. Le fichier de configuration a juste besoin de le spécifier. Dans Debian, bash vient avec un ensemble de fichiers de configuration qui complètent les options pour différentes commandes.

Par exemple:

[email protected]:~$ tar 
A c d r t u x 
2

Sur OS X, vous pouvez facilement installer un ensemble de bash prédéfinies complétions en utilisant MacPorts en suivant les instructions here. En regardant les exemples dans /opt/local/etc/bash_completion.d peut vous donner quelques idées pour en faire d'autres.

5

Si vous voulez encore plus impressionnant, regardez zsh. Il ressemble beaucoup à bash, et prend certaines des bonnes fonctionnalités de ksh, tcsh, etc. Il corrige aussi quelques-uns des bogues bash ennuyeux.

Il peut faire des choses assez cool, y compris remplir des noms de fichiers distants pour scp (si vous avez configuré l'authentification basée sur la clé) et mini-documentation lorsque vous complétez Par exemple, j'ai été agréablement surpris lorsque j'ai tabulé jar » l'autre jour:

[[email protected]:~]% jar <tab> 
0 -- store only without using ZIP compression 
M -- do not create manifest file 
etc... 
0

Je n'aime pas les réponses ici et voudrait contribuer quelques exemples concrets.

J'ai parfois un certain nombre de répertoires avec un préfixe commun et je voulais pouvoir y accéder en finissant simplement en tapant la partie unique du nom du répertoire qui serait au milieu ou à la fin du nom du répertoire.

j'ai pu écrire une fonction d'achèvement pour ce faire:

_cd(){ 
    # Backup old nullglob setting 
    local shoptbakup="`shopt -p nullglob`" 
    shopt -s nullglob 

    local cur opts i opt 
    local IFS=$'\n' 
    cur="${COMP_WORDS[COMP_CWORD]}" 

    # Home directory substitution 
    if [[ "${cur:0:1}" == '~' ]]; then 
     cur="$HOME/${cur:1}" 
    fi 

    if [[ $cur == */* ]]; then 
     opts=(${cur}*/) 
    else 
     opts=(*${cur}*/) 
    fi 

    # Prevent trailing// 
    i=0 
    for opt in "${opts[@]}"; do 
     #opts[$i]=${opt%${opt##*[!/]}} 
     opts[$i]=${opt%/} 
     i=$((i+1)) 
    done 

    # Restore nullglob setting 
    eval "$shoptbakup" 2>/dev/null 

    COMPREPLY=("${opts[@]}") 
} 
complete -o filenames -o bashdefault -o nospace -F _cd cd 

Alors maintenant de mon message, je peux le faire:

$ ls 
test 6/ test 7/ test 8/ test1/ test2/ test3/ test4/ test5/ 
$ cd 7[TAB] 

Et il termine automatiquement:

$ cd test\ 7/ 

Une autre raison pour laquelle vous pourriez vouloir utiliser l'achèvement programmable serait si vous écrivez un script et que vous voulez être en mesure d'énumérer ou de compléter les options pour vous.Cette page a une très bon exemple:

http://fahdshariff.blogspot.com/2011/04/writing-your-own-bash-completion.html

Voici un exemple:

Disons que j'ai un script appelé listanimals. Je peux écrire une fonction d'achèvement pour aider à remplir les options

# complete sendevent 
_listanimals() 
{ 
    local cur=${COMP_WORDS[COMP_CWORD]} 
    local prev=${COMP_WORDS[COMP_CWORD-1]} 

    if [[ $prev == "--sort-direction" ]]; then 
     COMPREPLY=($(compgen -W "horizontal vertical" -- $cur)) 
     return 0 
    elif [[ $prev == "--type" ]];then 
     COMPREPLY=($(compgen -W "mammals reptiles birds fish marsupials insects misc" -- $cur)) 
     return 0 
    elif [[ $prev == "--size" ]]; then 
     COMPREPLY=($(compgen -W "tiny small medium large huge" -- $cur)) 
     return 0 
    fi 


    # completing an option 
    if [[ "$cur" == --* ]] || [[ $cur == "" ]]; then 
     COMPREPLY=($(compgen -W "--sort-direction --type --size" -- $cur)) 
    fi 
} 
complete -F _listanimals listanimals 

Maintenant, je peux le faire:

$ listanimals --[TAB][TAB] 
--size   --sort-direction --type 
$ listanimals --t[TAB] 

qui remplira automatiquement ceci:

$ listanimals --type 

Ensuite, je peux faites ceci:

$ listanimals --type [TAB][TAB] 
birds  fish  insects  mammals  marsupials misc  reptiles 

Et je suis sûr que vous pouvez comprendre le reste. Ceci est un exemple de travail, donc si vous voulez l'essayer, copiez/collez-le dans un fichier (par exemple sample.sh) et sourcez-le dans bash source sample.sh. Vous n'avez pas besoin d'avoir un script nommé listanimals.

J'espère que quelqu'un trouvera cela utile parce que j'ai trouvé que c'était difficile à comprendre.