Правильно, bash_completion
- это решение. Я могу рассказать вам, что у меня есть в моей Ubuntu. Я надеюсь, что на Mac все по крайней мере похоже.
Существует файл /etc/bash_completion
который содержит исходники /usr/share/bash-completion/bash_completion
.
В каталоге /usr/share/bash-completion
есть также подкаталог completions
. Это место для сценариев. Давайте посмотрим на скрипт eject
:
# bash completion for eject(1) -*- shell-script -*-
_eject()
{
local cur prev words cword
_init_completion || return
case $prev in
-h|--help|-V|--version|-c|--changerslot|-x|--cdspeed)
return
;;
-a|--auto|-i|--manualeject)
COMPREPLY=( $( compgen -W 'on off' -- "$cur" ) )
return
;;
esac
if [[ $cur == -* ]]; then
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "$cur" ) )
return
elif [[ $prev == @(-d|--default) ]]; then
return
fi
_cd_devices
_dvd_devices
} &&
complete -F _eject eject
# ex: ts=4 sw=4 et filetype=sh
Даже не читая документацию, мы могли бы немного переработать ее и приспособить к вашему случаю. Для нас самая важная часть кода выше, где он говорит , что после -a
--auto
-i
или --manualeject
может быть on
или off
В вашем случае после bugfix
вам нужно имя каталога.
(Или нет. У вас есть каталог another-module
но вы используете аргумент anothermodule
. Сейчас я предполагаю, что это опечатка. Если нет, ответ Энтони , я думаю, укажет вам правильное направление.)
Мы могли бы как-то извлечь эти каталоги, которые вы хотите, и заменить 'on off'
, но может быть лучше использовать существующий код. После того, как я ввожу cd
, bash
автоматически заполняет каталоги, и он работает хорошо, даже если есть пробелы или специальные символы. Итак, давайте посмотрим на _cd()
; он находится в /usr/share/bash-completion/bash_completion
, я не буду вставлять его здесь. Затем кажется, что критически важной частью этой функции является вызов _filedir -d
. Непосредственно перед тем, как _filedir()
определен, мы имеем:
# This function performs file and directory completion. It's better than
# simply using 'compgen -f', because it honours spaces in filenames.
Бинго.
Поэтому я скопировал скрипт eject
под именем bob
и отредактировал в виде:
# bash completion for bob -*- shell-script -*-
_bob()
{
local cur prev words cword curdir
_init_completion || return
case $prev in
bob)
COMPREPLY=( $( compgen -W 'start stop foo bar' -- "$cur" ) )
return
;;
start)
COMPREPLY=( $( compgen -W 'bugfix' -- "$cur" ) )
return
;;
bugfix)
curdir=$(pwd)
cd public/submodules/ 2>/dev/null && _filedir -d
cd "$curdir"
;;
esac
} &&
complete -F _bob bob
Существующие сеансы bash
не заметят этот файл, вам нужно запустить новый bash
чтобы протестировать его.
Да, это быстрое и грязное программирование вуду, извините.
Обратите внимание, что мы спускаемся в public/submodules/
и возвращаемся. Обычно я бы использовал подоболочку:
export -f _filedir
( cd … && _filedir -d )
но похоже, что _filedir
не будет работать таким образом.