bash なんて書いたことない人が補完関数をとりあえず自作する


## 概要

### 手順

おおざっぱな手順になります。

1. 補完のための関数をかく。
2. `complete` コマンドで `コマンド` と `関数` ひもづける。
3. `1`、`2` がかかれたスクリプトを読み込む。

### 例

例えば、 `chrome` と入力して`TAB`×2した時に、 `standard`、`beta`、`dev`、`canary` と候補を表示してくれるスクリプトは以下です。

```bash:~/bash_completion.d/chrome_completion.bash
#!bash

_chrome()
{
  COMPREPLY=( standard beta dev canary )
}

complete -F _chrome chrome
```

## 補完関数

### 候補 -> 補完

上記の例では候補は表示してくれますが補完はしてくれません。そこで以下のようにします。

```bash:~/bash_completion.d/chrome_completion.bash
#!bash

_chrome()
{
  local cur=${COMP_WORDS[COMP_CWORD]}
  COMPREPLY=( $(compgen -W "standard beta dev canary" -- $cur) )
}

complete -F _chrome chrome
```

まず、補完をするためにうちかけているサブコマンドの文字列を取得したいです。それが

```
cur=${COMP_WORDS[COMP_CWORD]}
```

です。`COMP_CWORD` には補完対象の引数の番号が入っていますと言われてもピンとこないと思い人は次の例を見てください。


また、`compgen` という魔法のコマンドを使ってあげるとなんと補完されてしまいます汗すごい。

`--` はオプションの終わりの印です。

### サブコマンドなどによる場合分け

補完はできましたが、今度は `chrome dev` と入力して`TAB`×2した時には、カレントディレクトリのファイルなどを候補に補完してほしいとします。そこで以下のようにします。

```bash:~/bash_completion.d/chrome_completion.bash
#!bash

_chrome()
{
  local cur=${COMP_WORDS[COMP_CWORD]}
  case "$COMP_CWORD" in
  1)
    COMPREPLY=( $(compgen -W "standard beta dev canary" -- $cur) );;
  *)
    COMPREPLY=( $(compgen -W "$(ls)" -- $cur) );;
  esac
}

complete -F _chrome chrome
```

これで、`COMP_CWORD` に入っているものが感覚的にわかるんじゃないかと思います。

また、このように、`-W "$(ls)"`とすることで `ls` コマンドの出力をそのまま補完候補として使えます汗すごい。

`ls` では普通ですが、他のコマンドと組み合わせればいくらでもできそうです。


### 変数

|変数名|値|
|:-:|:-:|
|COMP_CWORD|補完対象の引数の番号|
|COMP_LINE|コマンドライン全体の文字|
|COMP_POINT|カーソルの位置|




### complete と compgen

```
$ help complete
complete: complete [-abcdefgjksuv] [-pr] [-o option] [-A action] [-G globpat] [-W wordlist] [-P prefix] [-S suffix] [-X filterpat] [-F function] [-C command] [name ...]
    For each NAME, specify how arguments are to be completed.
    If the -p option is supplied, or if no options are supplied, existing
    completion specifications are printed in a way that allows them to be
    reused as input.  The -r option removes a completion specification for
    each NAME, or, if no NAMEs are supplied, all completion specifications.
```

```
$ help compgen
compgen: compgen [-abcdefgjksuv] [-o option] [-A action] [-G globpat] [-W wordlist] [-P prefix] [-S suffix] [-X filterpat] [-F function] [-C command] [word]
    Display the possible completions depending on the options.  Intended
    to be used from within a shell function generating possible completions.
    If the optional WORD argument is supplied, matches against WORD are
    generated.
```


## 読み込み

`bash_completion.d` フォルダ下に置く方法と `.bashrc` などに読み込むコードを追記する方法とあります。

前者では、`/etc/bash_completion.d` や `/usr/local/etc/bash_completion.d` や `~/bash_completion.d` があります。

後者では、`source /path/to/chrome_completion.bash` を `.bashrc` などに追記します。


## 参考

もっと詳しくはこちらを見てください。

* [今回のお題 - Bash-Completion で複雑な補完をする](http://www.usupi.org/sysad/236.html)
* [Writing your own Bash Completion Function](http://fahdshariff.blogspot.jp/2011/04/writing-your-own-bash-completion.html)
* [git-flow-completion/git-flow-completion.bash](https://github.com/codegangsta/cli/blob/master/autocomplete/bash_autocomplete)
* [cli/autocomplete/bash_autocomplete](https://github.com/bobthecow/git-flow-completion/blob/master/git-flow-completion.bash)