В настоящее время я работаю над скриптом оболочки, который я назвал makeyourself.sh
(ссылка на /usr/bin/mys
), который автоматически устанавливает пакет Debian из исходного кода (через apt-get source -b $1
).
Поэтому я решил добавить функцию автодополнения для имени пакета, которое указывается в качестве первого параметра: sudo mys panth<tab><tab>
затем следует вывести список всех пакетов, начинающихся с panth
— моя попытка была следующей:
complete -C "apt-cache --no-generate pkgnames" mys
Но, похоже, это не работает: когда я нажимаю клавишу Tab, как указано выше, at изменяет параметр на mys
, который возвращает мне sudo mys mys
.
Что я делаю не так? Нужно ли указывать место в команде, куда complete
вставлять строку, которую нужно дополнить, например {}
или $1
?
Я использую ElementaryOS, дистрибутив Linux на основе Ubuntu. Скрипт представляет собой стандартный скрипт оболочки *.sh, который использует стандартный#!/bin/bash
решение1
Как вы подозреваете, команда получает некоторую информацию о том, что нужно выполнить. Это задокументировано в руководстве, но не вдокументация complete
встроенного, вам нужно прочитатьвводный раздел по программируемому завершению.
вызывается любая функция оболочки или команда, указанная с параметрами
-F
и-C
. Когда вызывается команда или функция, переменнымCOMP_LINE
,COMP_POINT
,COMP_KEY
, иCOMP_TYPE
присваиваются значения, как описано выше (см.Переменные Bash). Если вызывается функция оболочки, то также устанавливаются переменныеCOMP_WORDS
иCOMP_CWORD
. Когда вызывается функция или команда, первый аргумент — это имя команды, аргументы которой дополняются, второй аргумент — это дополняемое слово, а третий аргумент — это слово, предшествующее дополняемому слову в текущей командной строке. Фильтрация сгенерированных дополнений по дополняемому слову не выполняется; функция или команда имеет полную свободу в генерации соответствий.
Итак, команда вызывается с тремя параметрами:
- Имя команды — чтобы можно было объединить завершения для похожих команд в одном скрипте.
- Слово, которое необходимо завершить, — таким образом, вы можете ограничить вывод префиксом, который в любом случае будет отфильтрован.
- Предыдущее слово — полезно, например, для завершения вариантов.
Те же параметры передаются в функции завершения ( complete -F somefunction
). Обратите внимание, что независимо от того, используете ли вы функцию или команду, ваша задача — отфильтровать нужные совпадения.
С тем, что вы попробовали, команда, которая в итоге выполняется, — apt-cache --no-generate pkgnames mys '' mys
. Это выводит список имен пакетов, начинающихся с mys
( apt-cache pkgnames
смотрит только первый операнд). Самый длинный общий префикс — mys
, поэтому bash начинает выполнять mys
и ожидает, что вы выберете следующую букву.
Учитывая, что аргументы добавляются к команде (не передаются как позиционные параметры — аргумент -C
разбирается как команда оболочки), нет простого способа их разобрать. Самое простое решение — использовать функцию-обертку.
_mys () {
COMPREPLY=$(apt-cache --no-generate pkgnames "$2")
}
complete -F _mys mys