У меня есть инструмент командной строки, который принимает аргументы в трехчастной форме:
$ t first_second_third
У меня есть набор допустимых значений для first
, набор допустимых значений для second
и набор допустимых значений для third
. Я хочу использовать полную функциональность Bash для завершения каждой части значения параметра, как в этом примере:
$ t [tab][tab] # shows options for first part
walk run skip bike
$ t w[tab] # completes first part and appends delimiter
$ t walk_[tab][tab] # shows options for second part
home work park
$ t walk_h[tab] # completes second part and appends delimiter
$ t walk_home_[tab][tab] # shows options for second part
morning afternoon evening
$ t walk_home_a[tab] # completes second part and appends space
$ t walk_home_afternoon
У меня есть этот код:
_tool () {
local cur="${COMP_WORDS[COMP_CWORD]}"
local first="walk run skip bike"
local second="home work park"
local third="morning afternoon evening"
case "${cur}" in
*_*_*)
COMPREPLY=( $(compgen -W "${third}" -- "") ); return 0;;
*_*)
COMPREPLY=( $(compgen -W "${second}" -S "_" -- ${cur}) ); compopt -o nospace; return 0;;
*)
COMPREPLY=( $(compgen -W "${first}" -S "_" -- ${cur}) ); compopt -o nospace; return 0;;
esac
}
complete -F _tool t
Первое предложение отлично работает; ничего особенного нет. Но второе предложение не дает мне никаких вариантов или дополнений.
$ t [tab][tab]
bike_ run_ skip_ walk_
$ t b[tab]
$ t bike_[tab][tab] # nothing but bells
Я заменил второе предложение следующим (то есть я заменил ${cur}
пустой строкой в вызове COMPREPLY
):
COMPREPLY=( $(compgen -W "${second}" -S "_" -- "") ); compopt -o nospace; return 0;;
Я получаю список всех параметров в командной строке, но не завершает работу.
$ t bike_[tab][tab]
home_ park_ work_
$ t bike_h[tab][tab]
home_ park_ work_
$ t bike_ho[tab][tab]
home_ park_ work_
Я думал, что может быть плохое взаимодействие с ${cur}
и списком слов COMPREPLY
, поэтому я снова изменил второе предложение, добавив префикс, который соответствует первой части текущего слова:
local prefix=( $(expr "${cur}" : '\(.*_\)') )
COMPREPLY=( $(compgen -W "${second}" -P "${prefix}" -S "_" -- "") ); compopt -o nospace; return 0;;
Это не помогло. Если ${cur}
все еще находится в команде COMPREPLY
, я не получил никаких параметров или дополнений еще раз. Вместо этого вместо пустой строки я получил полную опцию (а не только текущую часть). Но нажатие вкладки стирает то, что набирается.
$ t bike_[tab][tab]
bike_home_ bike_park_ bike_work_
$ t bike_ho[tab]
$ t bike_ # "ho" was erased
Конечно, у меня такая же проблема и с третьей частью.
- Как я могу получить Bash для завершения текущего слова, частично по частям?
- Как я могу получить Bash, чтобы не добавлять разделитель до тех пор, пока не будет выбран параметр?
Это похоже на еще один вопрос Bash, но я не хочу перечислять все возможные перестановки значений, и они не отформатированы как имена файлов (не конечно, если шаблон имени файла имеет значение).
Спасибо за помощь! --ap