Как получить завершение bash для псевдонимов команд?

57

Я хочу получить завершение табуляции в моих псевдонимах командной строки, например, сказать, что я определил следующий псевдоним:

alias apt-inst='sudo aptitude install'

Есть ли способ получить дополнения, предоставляемые aptitude, когда я нажимаю клавишу Tab? то есть, когда я пишу 'sudo aptitude install gnumer' и нажимаю клавишу Tab, aptitude завершает это до gnumeric, или, если была неопределенность, перечисляет все доступные пакеты, начиная с gnumer. Если я делаю это, используя свой псевдоним, ничего - нет завершения.

Левек
источник
1
См. Также stackoverflow.com/questions/342969/…
nschum

Ответы:

30

На форумах Ubuntu есть отличная ветка об этом . Ole J предлагает следующую функцию определения завершения псевдонима:

function make-completion-wrapper () {
  local function_name="$2"
  local arg_count=$(($#-3))
  local comp_function_name="$1"
  shift 2
  local function="
    function $function_name {
      ((COMP_CWORD+=$arg_count))
      COMP_WORDS=( "$@" \${COMP_WORDS[@]:1} )
      "$comp_function_name"
      return 0
    }"
  eval "$function"
  echo $function_name
  echo "$function"
}

Используйте его, чтобы определить функцию завершения для вашего псевдонима, затем укажите эту функцию как завершитель для псевдонима:

make-completion-wrapper _apt_get _apt_get_install apt-get install
complete -F _apt_get_install apt-inst

Я предпочитаю использовать псевдонимы для добавления всегда используемых аргументов в существующие программы. Например, grepя всегда хочу пропустить устройства и двоичные файлы, поэтому я создаю псевдоним для grep. Для добавления новых команд, таких как grepbin, я использую сценарий оболочки в своей ~/binпапке. Если эта папка находится на вашем пути, она будет заполнена автоматически.

Шон Дж. Гофф
источник
2
Круто, я боялась, что это невозможно.
Levesque
Обратите внимание, что у этого кода есть некоторые проблемы. Смотрите мой ответ для их объяснения и решения.
Том Хейл,
Примечание: я использовал эту технику для другой команды, и мне пришлось использовать ее complete -o default -F ...вместо complete -F ...правильной работы автозавершения имени файла при передаче аргументов (Bash 4.3.46).
joelittlejohn
28

Попробуйте полный псевдоним , который решает эту проблему точно.

После установки вы можете использовать одну универсальную функцию для завершения множества псевдонимов, например:

complete -F _complete_alias <myalias1>
complete -F _complete_alias <myalias2>
complete -F _complete_alias <myalias3>

Вы можете захотеть использовать файл complete_alias в каждом экземпляре bash .bash_profileили аналогичный.

монтаж

mkdir ~/.bash_completion.d
curl https://raw.githubusercontent.com/cykerway/complete-alias/master/bash_completion.sh \
     > ~/.bash_completion.d/complete_alias

применение

source ~/.bash_completion.d/complete_alias

alias container=docker\ container
complete -F _complete_alias container

containerтеперь может быть автозаполнено оригинальным _docker()обработчиком завершения;

$ container l<Tab>
logs  ls    

$ container s<Tab>
start  stats  stop   
Cyker
источник
2
Учитывая, что это программное обеспечение кажется вашим, вы могли бы добиться большего успеха, чем это. Добавьте инструкции по его установке. Опишите, что он делает и как его использовать. В противном случае это просто спам.
Муру
@muru Я думал вставить здесь какой-то код, но он, вероятно, дольше, чем здесь принято. Я предполагаю, что у людей нет проблем с чтением раздела « Установка » в файле README, и в этом случае это всего несколько строк.
Cyker
2
Дело в том, чтобы суметь оценить, стоит ли посещать указанный README, просто по ответу.
Муру
Это адекватный ответ, и он точно решает проблему.
Ярослав Рахматуллин
1
Это отличный и очень исчерпывающий ответ, который отлично работает, спасибо! Вероятно, оно было обновлено, так как у @muru были проблемы с ним.
Брайан Топпинг
3

Ответ 2018

Вы должны добавить свой псевдоним в программу «завершить». В зависимости от типа автозаполнения, которое вы хотите достичь, вы должны использовать -c или -F.

Для автозаполнения пакета:

complete -c name_of_your_alias

Для автозаполнения команды:

complete -F name_of_your_alias

Чтобы проверить, правильно ли был добавлен ваш псевдоним:

complete | grep name_of_your_alias

Наконец, чтобы удалить псевдоним из 'complete':

complete -r name_of_your_alias

В твоем случае:

complete -c apt-inst
Адриан Лопес
источник
1
Пожалуйста, не продолжайте свой ответ в комментариях. Если вам есть что сказать, отредактируйте их в ответе.
G-Man говорит: «Восстановите Монику»
2
complete -F xxxне работает на OSX (просто показывает использование complete: usage: complete [-abcdefgjksuv] [-pr] [-o option] [-A action] [-G globpat] [-W wordlist] [-P prefix] [-S suffix] [-X filterpat] [-F function] [-C command] [name ...]). У вас есть указатель? Благодарю.
Энтони Конг
Используйте это вместо: unix.stackexchange.com/questions/224227/…
Рич
2

Вот код из ответа Шона Дж. Гоффа с некоторыми улучшениями:

  • Исправлены синтаксические ошибки, выделенные shell-check, например, первым "из "$@"фактически завершенных строк определения функции.
  • Удалено, return 0так что возвращаемое значение базовой функции может быть передано обратно вызывающей стороне.

,

# Wraps a completion function, eg for use with an alias.
# Usage:
# make-completion-wrapper <actual completion function> <name of new func.>
#                         <command name> <list supplied arguments>
# eg.
#   alias agi='apt-get install'
#   make-completion-wrapper _apt_get _apt_get_install apt-get install
#     # defines a function called _apt_get_install (that's $2) that will
#     # complete the 'agi' alias. 
#   complete -F _apt_get_install agi
function make-completion-wrapper {
  local function_name="$2"
  local arg_count=$(( $#-3 ))
  local comp_function_name="$1"
  shift 2
  local function="function $function_name {
      (( COMP_CWORD += $arg_count ))
      COMP_WORDS=( \"\$@\" \${COMP_WORDS[@]:1} )
      \"$comp_function_name\"
    }"
  eval "$function"
  # echo "$function"
}
export -f make-completion-wrapper
Том Хейл
источник
Боюсь, у меня в Bash не работает 4.3.46. Ответ Шон Дж Гоффа делает работу.
joelittlejohn
1
«Завершение» строки определения функции специально; Дело в том, чтобы включить аргументы из внешней функции в COMP_WORDSмассив. Если мы используем make-completion-wrapper _apt_get _apt_get_install apt-get installв качестве примера, после shift 2, $@содержит apt-get install. Определение функции включает в себя apt-get install(два буквальных слова) при назначении COMP_WORDS.
Джеффри До
0

В качестве дополнения к ответу @Giles следующая вспомогательная функция автоматически называет сгенерированную оболочку, make-completion-wrapperчтобы можно было определить завершение в одной строке:

function complete-alias  {
    # uses make-completion-wrapper: https://unix.stackexchange.com/a/4220/50978
    # example usage
    # complete-alias _pass pshow pass show
    # complete-alias _pass pgen pass generate

    EXISTING_COMPLETION_FN=${1} && shift
    ALIAS=${1} && shift
    AUTOGEN_COMPLETION_FN="__autogen_completion_${ALIAS}"
    make-completion-wrapper ${EXISTING_COMPLETION_FN} ${AUTOGEN_COMPLETION_FN} ${*}
    complete -F ${AUTOGEN_COMPLETION_FN} ${ALIAS}
}
user84207
источник