Home Blog
en|ru

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 Массив слов для автодополнения - результат работы скрипта.
en|ru
Home Blog
Nickname sergzhum is registered!