Jak uzyskać zakończenie bash dla aliasów poleceń?

57

Chcę uzyskać uzupełnianie tabulatorami w moich aliasach wiersza poleceń, na przykład powiedzmy, że zdefiniowałem następujący alias:

alias apt-inst='sudo aptitude install'

Czy istnieje sposób, aby uzyskać uzupełnienia dostarczone przez aptitude po naciśnięciu klawisza Tab? tzn. kiedy piszę „sudo aptitude install gnumer” i wciskam tab, aptitude uzupełnia to do gnumeric, lub jeśli nie było pewności, wyświetla listę wszystkich dostępnych pakietów zaczynających się od gnumer. Jeśli zrobię to, używając mojego aliasu, nic - bez uzupełnienia.

levesque
źródło

Odpowiedzi:

30

Jest świetny wątek na ten temat na forach Ubuntu . Ole J proponuje następującą funkcję definicji zakończenia aliasu:

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"
}

Użyj go, aby zdefiniować funkcję uzupełniania dla swojego aliasu, a następnie określ tę funkcję jako funkcję uzupełniającą dla aliasu:

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

Wolę używać aliasów do dodawania zawsze używanych argumentów do istniejących programów. Na przykład za pomocą grepzawsze chcę pomijać urządzenia i pliki binarne, więc tworzę alias dla grep. Do dodawania nowych poleceń, takich jak grepbin, używam skryptu powłoki w moim ~/binfolderze. Jeśli ten folder znajduje się na twojej ścieżce, zostanie on automatycznie uzupełniony.

Shawn J. Goff
źródło
2
Świetnie, bałem się, że to nie będzie możliwe.
levesque
Uwaga: w tym kodzie występują pewne problemy. Zobacz moją odpowiedź na ich wyjaśnienie i rozwiązanie.
Tom Hale,
Uwaga: Użyłem tej techniki do innego polecenia i musiałem użyć complete -o default -F ...zamiast tego, complete -F ...aby automatyczne uzupełnianie nazw plików działało poprawnie podczas przekazywania argumentów (Bash 4.3.46).
joelittlejohn,
28

Wypróbuj pełny alias , który dokładnie rozwiązuje ten problem.

Po zainstalowaniu możesz użyć jednej funkcji ogólnej, aby uzupełnić wiele aliasów:

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

Możesz chcieć zdobyć plik complete_alias w każdej instancji bash poprzez .bash_profilelub podobnie.

instalacja

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

podanie

source ~/.bash_completion.d/complete_alias

alias container=docker\ container
complete -F _complete_alias container

containermoże być teraz automatycznie _docker()uzupełniany przez oryginalną procedurę obsługi zakończenia;

$ container l<Tab>
logs  ls    

$ container s<Tab>
start  stats  stop   
Cyker
źródło
2
Biorąc pod uwagę, że to oprogramowanie wydaje się być twoje, możesz zrobić to lepiej. Dodaj instrukcje instalacji. Opisz, co robi i jak go używać. W przeciwnym razie jest to tylko spam.
muru
@muru Myślałem o wklejeniu tutaj kodu, ale prawdopodobnie jest on dłuższy niż tutaj zaakceptowany. Zakładam, że ludzie nie mają problemu z odczytaniem sekcji Instaluj w pliku README, w tym przypadku jest to tylko kilka wierszy.
Cyker,
2
chodzi o to, aby móc ocenić, czy warto odwiedzić README, opierając się na odpowiedzi.
muru
To jest odpowiednia odpowiedź i dokładnie rozwiązuje problem.
Ярослав Рахматуллин
1
To doskonała i bardzo kompleksowa odpowiedź, która działa idealnie, dziękuję! Prawdopodobnie został zaktualizowany, ponieważ @muru miał z tym problemy.
Brian Topping
3

2018 odpowiedź

Musisz dodać swój alias do programu jako „kompletny”. W zależności od rodzaju autouzupełniania, które chcesz osiągnąć, musisz użyć -c lub -F.

W przypadku autouzupełniania pakietów:

complete -c name_of_your_alias

W przypadku autouzupełniania poleceń:

complete -F name_of_your_alias

Aby sprawdzić, czy Twój alias został poprawnie dodany:

complete | grep name_of_your_alias

Wreszcie, aby usunąć alias z „kompletnego”:

complete -r name_of_your_alias

W Twoim przypadku:

complete -c apt-inst
Adrian Lopez
źródło
1
Proszę nie kontynuować odpowiedzi w komentarzach. Jeśli masz coś do powiedzenia, edytuj je w odpowiedzi.
G-Man
2
complete -F xxxnie działa na OSX (pokazuje tylko użycie complete: usage: complete [-abcdefgjksuv] [-pr] [-o option] [-A action] [-G globpat] [-W wordlist] [-P prefix] [-S suffix] [-X filterpat] [-F function] [-C command] [name ...]). Czy masz jakiś wskaźnik? Dzięki.
Anthony Kong
Zamiast tego użyj tego: unix.stackexchange.com/questions/224227/…
Rich
2

Oto kod z odpowiedzi Shawna J. Goffa z pewnymi ulepszeniami:

  • Poprawiono błędy składniowe podkreślił shell-check, np pierwszy "od "$@"faktycznie skończyło ciąg definicji funkcji.
  • Usunięto return 0tak, aby zwracana wartość funkcji bazowej mogła zostać zwrócona z powrotem do obiektu wywołującego.

.

# 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
Tom Hale
źródło
Obawiam się, że nie działa w Bash 4.3.46. Shaun Goff J. odpowiedź na nie pracować.
joelittlejohn,
1
„Zakończenie” ciągu definicji funkcji jest celowe; chodzi o włączenie do COMP_WORDStablicy argumentów funkcji zewnętrznej . Jeśli użyjemy make-completion-wrapper _apt_get _apt_get_install apt-get installjako przykładu, po shift 2, $@zawiera apt-get install. Definicja funkcji obejmuje apt-get install(dwa dosłowne słowa) podczas przypisywania COMP_WORDS.
Jeffery do
0

Jako rozszerzenie odpowiedzi @Giles, następująca funkcja wygody automatycznie zmienia nazwy generowanego opakowania, make-completion-wrapperaby umożliwić zdefiniowanie zakończenia w jednym wierszu:

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}
}
użytkownik84207
źródło