Edited at

自作コマンドラインツールでオートコンプリートする

More than 1 year has passed since last update.

自作のコマンドラインツールでも tab 補完はできないと,ということで,どうやるかを調べてみたら意外と簡単だった.


コマンドの仕様

git みたいなサブコマンドがあるタイプがいいので,ここでは例として,レンタカーを借りる時に使うコマンドとしてこんな感じに car-rental コマンドとしてみる

car-rental  book    car            sedan

mini-van
suv
option navi
booster-sheet
cancel car <reservation_id>
option <option_id>


最初の引数の補完

こんな感じで,スクリプト auto-complete-car-rental を書いて

#!/bin/bash

first="book cancel"

# auto complete function
_auto_complete()
{
local cur=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=( $(compgen -W "$first" -- $cur) )
}

# map the function to the target command - 'car-rental'
complete -F _auto_complete car-rental

読み込む

. auto-complete-car-rental

これで car-rental +<tab>で一つ目の引数の補完ができるようになる

$ car-rental # press <tab> here

book cancel


二番目の引数の補完

$COMP_CWORDに引数が何番目のものなのかを示す番号がはいっているっぽい.引数の順番(番号)に応じて候補を出すために, case 文で分岐する.

#!/bin/bash

first="book cancel"
second="car option"

_auto_complete()
{
local cur=${COMP_WORDS[COMP_CWORD]}

case "$COMP_CWORD" in
1) COMPREPLY=( $(compgen -W "$first" -- $cur) ) ;;
2) COMPREPLY=( $(compgen -W "$second" -- $cur) ) ;;
esac

}
complete -F _auto_complete car-rental


三番目の引数の補完

三番目の引数は,二番目の引数$prevcarなのかoptionなのかで変わるので,その分岐をいれる.

#!/bin/bash

first="book cancel"
second="car option"
third_after_car="sedan mini-van suv"
third_after_option="navi booster-sheet"

_auto_complete()
{
local cur=${COMP_WORDS[COMP_CWORD]}
local prev=${COMP_WORDS[COMP_CWORD-1]} # previous argument

case "$COMP_CWORD" in
1) COMPREPLY=( $(compgen -W "$first" -- $cur) ) ;;
2) COMPREPLY=( $(compgen -W "$second" -- $cur) ) ;;
3)
case $prev in
car)
COMPREPLY=( $(compgen -W "$third_after_car" -- $cur) ) ;;
option)
COMPREPLY=( $(compgen -W "$third_after_option" -- $cur) ) ;;
esac
esac

}
complete -F _auto_complete car-rental

あとは,引数が増えてもこの繰り返しでいけそうな感じ.


参考にしたサイト