Bash Completion

導入

[1] freshmeatのページ

READMEの抄訳(未完)

インストール

このソフトウェアをインストールする最も簡単な方法はRed Hat LinuxのRPMや Debian/GNU Linuxの.debパッケージを利用することです.

それらのパッケージを利用しない場合, bash_completionファイルをシステム のどこかに置いて, /tec/bashrcか~/.bashrcで読みこみます.

具体的には, たとえば/etc/bashrcに次のように書くとよいでしょう:

bash=${BASH_VERSION%.*}; bmajor=${bash%.*}; bminor=${bash#*.}
if [ "$PS1" ] && [ $bmajor -eq 2 ] && [ $bminor '>' 04 ] \
   && [ -f /etc/bash_completion ]; then # interactive shell
        # Source completion code
        . /etc/bash_completion
fi
unset bash bmajor bminor
このコードはbashのバージョンが2.04以降であるかどうかをチェックした上で, bash補完コードを読み込みます.

一目見ると大仰のように見えるかもしれませんが, このコードはbash 1.xでも 通ります. 1.xと2.xが混在するシステムでも正常に作動するのが利点です.

もしシステムに/etc/profile.dディレクトリが存在するならば, そのディレク トリにbash_completion.shというスクリプトを追加することも可能です. この コードを追加しておくことで, 次のようにすることができます:

# check for bash
[ -z "$BASH_VERSION" ] && return
この場合, /etc/profile.dにあるすべての*.shがBourne系 シェルにおいて/etc/bashrcで読み込まれます. よって他の(bash以外の)シェ ルが混在するシステムでは注意が必要です.

MacOS Xを使っている場合, /etc/bashrcは読みこまれません. この場合, bash_completionファイルを/sw/etcに置き, 以下のコードを~/.bash_profile に書きます:

if [ -f /sw/etc/bash_completion ]; then
   . /sw/etc/bash_completion
fi
/etc/bash_completion以外の場所に置いた場合, bashに読み込む前に $BASH_COMPLETIONを直しておきましょう. ~/.bashrcで設定するのがいいでしょ う.

トラブルシューティング

If you get errors about 'complete' or 'compgen' not accepting the -g flag, you are probably running bash 2.05 and should either apply the group completion patch, download a prepatched bash binary of 2.05, or upgrade to 2.05a or later.

If you find that some commands, such as 'cd /usr', end with a trailing space instead of appending a /, you are probably running the base version of bash 2.05, which suffers from a bug that causes the '-o filenames' option to the complete built-in to be ignored. You can fix this by applying the following the following official patch from the bash maintainer:

ftp://ftp.cwru.edu/pub/bash/bash-2.05-patches/bash205-006

If you get errors about 'complete' not accepting the -o flag, you are probably running bash 2.04. In this case, you should upgrade to bash

2.05a or later. However, I have endeavoured to make the code detect this version of bash and work around this issue, so please inform me if you still encounter this error.

Copies of the patches and prepatched versions of bash are available from:

http://www.caliban.org/bash/

If you find that a given function is producing errors under certain circumstances when you attempt completion, try running 'set -v' or 'set -x' prior to attempting the completion again. This will produce useful debugging output that will aid me in fixing the problem if you are unable to do so yourself. Turn off the trace output by running either 'set +v' or 'set +x'.

既知の問題

  1. bashについているcdをMakefile内で使うときに問題が生じるようです. Makefile内で/bin/shを実行すると, bashはcdコマンドでディレクトリを変更 できません. 回避策はMakefile内でSHELL=/bin/bashと設定することです. こ れはbash内のバグだと思われます.
  2. The have() function is used to conserve memory by only installing completion functions for those programs that are actually present on your system. The current method of determining whether or not a given binary is present is whether or not it can be found along a certain path of directories. The path that is currently searched is: $PATH:/sbin:/usr/sbin:/usr/local/sbin where $PATH is your user path at the time the bash completion file is sourced.
  3. 補完の際に呼ばれる関数はテキストユーティリティが(grep, sed, awkのよ うな)GNUソフトと仮定しています.

よくある質問 (F.A.Q)

Q.
私の環境では正統な拡張子つきのファイルを補完することができないコ マンドが, bash補完を使っているとでてきます. 補完できるように特定のコマ ンドだけbash補完を不可能にすることができますか?
A.
できません. カーソルの前にファイル名を入れたい場合にはM-/を使っ てください(manページに書いてあります). どんなタイプのファイルでも入力 できます.
Q.
How can I insert my own local completions without having to reinsert them every time you issue a new release?
A.
Put them in ~/.bash_completion, which is parsed at the end of the main completion script.
Q.
I author/maintain package X and would like to maintain my own completion code for this package. Where should I put it to be sure that interactive bash shells will find it and source it?

Put it in the directory pointed to by $BASH_COMPLETION_DIR, which is defined at the beginning of the main completion script. Any scripts placed in this directory will be sourced by interactive bash shells.

Q.
I use CVS in combination with passwordless ssh access to my remote repository. How can I have the cvs command complete on remotely checked-out files where relevant?
A.
Define $COMP_CVS_REMOTE. Setting this to anything will result in the behaviour you would like.
Q.
When I'm running a ./configure script and completion returns a list of long options to me, some of these take a parameter, e.g. --this-option=DESCRIPTION.

<\nowiki> Running ./configure --help lists these descriptions, but everything after the '=' is stripped when returning completions, so I don't know what kind of data is expected as a given option's parameter.

Is there a way of getting ./configure completion to return the entire option string, so that I can see what kind of data is required and then simply delete the descriptive text and add my own data?

A.
Define $COMP_CONFIGURE_HINTS. Setting this to anything will result in the behaviour you would like.
Q.
When doing tar completion on a file within a tar file like this:
   tar tzvf foo.tar.gz <Tab>
   
the pathnames contained in the tar file are not displayed correctly. The slashes are removed and everything looks like it's in a single directory. Why is this?
A.
It's a choice I had to make. bash's programmable completion is limited in how it handles the list of possible completions it returns.

Because the paths returned from within the tar file are likely not existing paths on the file system, '-o dirnames' must be passed to the complete built-in to make it treat them as such. However, then bash will append a space when completing on directories during pathname completion to the tar files themselves.

It's more important to have proper completion of paths to tar files than it is to have completion for their contents, so this sacrifice was made and '-o filenames' is used with complete instead.

If you would rather have correct path completion for tar file contents, define $COMP_TAR_INTERNAL_PATHS before sourcing bash_completion.

Q.
When completing on a symlink to a directory, bash does not append the trailing / and I have to hit again. I don't like this.
A.
This has nothing to do with bash_completion. It's the default for completing symlinks to directories in bash 2.05a, and was added because sometimes you want to operate on the symlink itself, rather than what it points to.

In bash 2.05b and later, you can get the pre-2.05a behaviour back by putting 'set mark-symlinked-directories on' in your /etc/inputrc or ~/.inputrc file.

Q.
Completion goes awry when I try to complete on something that contains a colon.
A.
This is actually a 'feature' of bash. bash recognises a colon as starting a new completion token, which is often what you want when completing something like a PATH variable:
   $ export PATH=/bin:/sbin:/usr<Tab>
   
Without the special treatment of the colon, the above wouldn't work without programmable completion, so it has long been a feature of the shell.

Unfortunately, you don't want the colon to be treated as a special case when doing something like:

   $ man File::B<Tab>
   
Here, the colons make bash think that it's completing the a new token that begins with 'B'.

Unfortunately, there's no way to turn this off. The only thing you can do is escape the colons with a backslash.

Q.
Where did urpmi completion go?
A.
Guillaume Rousse <rousse@ccr.jussieu.fr> now maintains it separately as part of the urpmi RPM package.

CVS: http://cvs.mandrakesoft.com/cgi-bin/cvsweb.cgi/soft/urpmi/ Web: http://urpmi.org/

Q.
Why is rpm completion so slow with -q?
A.
Probably because the database is being queried every time and this uses a lot of memory.

You can make this faster by pregenerating the list of installed packages on the system. Make sure you have a readable file called /var/log/rpmpkgs. It's generated by /etc/cron.daily/rpm on modern Red Hat and Mandrake Linux systems.

If you don't have such a cron job, make one:

   #!/bin/sh
   rpm -qa --qf '%{name}-%{version}-%{release}.%{arch}.rpm\n' 2>&1 \
           | sort > /var/log/rpmpkgs
   
rpm completion will use this flat text file instead of the RPM database, unless it detects that the database has changed since the file was created, in which case it will still use the database to ensure accuracy.
Q.
This code is rubbish/not bad/pretty good/the best thing since sliced bread. How can I show my appreciation?
A.
If you're a registered Freshmeat user, take a moment to rate the project at: http://freshmeat.net/rate/19041/ Of course, writing to me and letting me know how you feel also works. Patches and new completion routines are most welcome, too.
Q.
How can I stay abreast of new releases?
A.
If you're a registered Freshmeat user, you can subscribe to new release announcements at: http://freshmeat.net/subscribe/19041/
Q.
Is bash the be-all-and-end-all of completion as far as shells go?
A.
Absolutely not. zsh has an extremely sophisticated completion system that offers many features absent from the bash implementation. More information can be found at: http://www.zsh.org/