How to make autocomplete for any bash commands
Стащено и криво переведено отсюда, с небольшими добавдениями.
Простой вариант - статический список
Пусть есть команда dothis. Создадим файл dothis-completion.bash:
#/usr/bin/env bash
complete -W "now tomorrow never" dothis
Выполним . ./dothis-completion.bash, теперь по табам будет выдаваться:
$ dothis <tab><tab>
never now tomorrow
$ dothis n<tab><tab>
never now
Ключ -W указывает, что надо брасть список слов. -F func - вызывать функцию
и её вывод брать как список вариантов. -C cmd - аналогично, но выполнять
команду.
-A action - автодополнять вариантами:
-
alias алиасы (=
-a). - arrayvar имена переменных-массивов.
- binding биндинги readline.
-
builtin имена встроенных команд (=
-b). -
command имена команд (=
-c). -
directory каталоги (=
-d). - disabled отключённые встроенные команды.
- enabled включённые встроенные команды.
-
export экспортируемые переменные (=
-e). -
file файлы (=
-f). - function функции.
-
group группы (=
-g). - helptopic темы встроенного help.
- hostname хосты (файл с хостами указывается переменной HOSTFILE).
-
job задачи (jobs) (=
-j). -
keyword ключевые слова shell (=
-k). - running активные звдвчи.
-
service сервисы (?) (=
-s). -
setopt допустимые аргументы опции shell
-oдля установки опций. -
shopt опции для
shopt. - signal сигналы.
- stopped остановленные задачи.
-
user пользователи (логины) (=
-u). - variable переменные.
Пример complete -A directory dothis даст дополнение именами каталогов.
Динамическое дополнение
Поменяем скрипт:
#/usr/bin/env bash
_dothis_completions()
{
COMPREPLY+=("now")
COMPREPLY+=("tomorrow")
COMPREPLY+=("never")
}
complete -F _dothis_completions dothis
Это даст тот же результат, что и изначальный вариант - три варианта дополнения.
При этом если мы напишем dothis ne<tab><tab>, то получим все три варианта
вместо ожидаемого одного never.
Исправим это. В функции, вызываемой для автодополнения, доступны переменные:
- COMP_WORDS массив слов, введённых после имени программы;
- COMP_CWORD индекс слова в предыдущем массиве, на котором сейчас курсор;
- COMP_LINE текущая командная строка.
Кроме того, встроенная функция compgen, принимающая такие же флаги, что и
complete, умеет выдавать список дополнений по началу слова. Например,
compgen -W "now tomorrow never" n выдаст now и never.
Таким образом, получить начальный фугкционал можно например так:
#/usr/bin/env bash
_dothis_completions()
{
COMPREPLY=($(compgen -W "now tomorrow never" "${COMP_WORDS[1]}"))
}
complete -F _dothis_completions dothis
Пример дополнения флага -u именами пользвоателей:
_dothis_completions()
{
local cur prev opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
if [[ ${prev} == -u ]] ; then
COMPREPLY=( $(compgen -u -- ${cur}) )
return 0
fi
}
Все переменные, доступные в автодополнении:
-
COMP_CWORDИндекс текущего слова в ${COMP_WORDS} -
COMP_LINEВся командная строка -
COMP_POINTПозиция курсора относительно начала командерй строки. Если курсор в самом конце, то это равно ${#COMPi_LINE}. -
COMP_WORDBREAKSНабор символов, которые считаются раздедителями слов при автодополнении (не стоит её менять, это глобальная переменная!). -
COMP_WORDSМассив слов из текущей ${COMP_LINE}. -
COMPREPLYМассив слов для автодополнения - результат работы скрипта.