Como obtenho a conclusão do bash para alias de comando?

57

Estou procurando obter o preenchimento de guias nos meus aliases de linha de comando, por exemplo, digamos que defini o seguinte alias:

alias apt-inst='sudo aptitude install'

Existe uma maneira de obter as conclusões fornecidas pelo aptitude quando eu pressiono a tecla tab? ou seja, quando eu escrevo 'sudo aptitude install gnumer' e clico em tab, o aptitude conclui isso em gnumeric, ou se houver incerteza, liste todos os pacotes disponíveis começando com gnumer. Se eu fizer isso usando meu apelido, nada - nenhuma conclusão.

leve
fonte
11
Veja também stackoverflow.com/questions/342969/…
nschum 17/08/2012

Respostas:

30

um ótimo tópico sobre isso nos fóruns do Ubuntu . Ole J propõe a seguinte função de definição de conclusão de alias:

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

Use-o para definir uma função de conclusão para o seu alias e especifique essa função como um complemento para o alias:

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

Prefiro usar aliases para adicionar argumentos sempre usados ​​aos programas existentes. Por exemplo, com grep, eu sempre quero pular dispositivos e arquivos binários, então eu faço um alias para grep. Para adicionar novos comandos, como grepbin, eu uso um script de shell na minha ~/binpasta. Se essa pasta estiver no seu caminho, ela será preenchida automaticamente.

Shawn J. Goff
fonte
2
Incrível, eu tinha medo que não fosse possível.
Leveque
Observe que este código tem alguns problemas. Veja minha resposta para sua explicação e resolução.
Tom Hale
Nota: Eu estava usando essa técnica para outro comando e tive que usar em complete -o default -F ...vez de complete -F ...fazer com que coisas como a conclusão automática de nome de arquivo funcionassem corretamente ao passar argumentos (Bash 4.3.46).
Joelittlejohn
28

Tente o alias completo , que resolve esse problema exatamente.

Após a instalação, você pode usar uma função genérica para concluir vários aliases como este:

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

Você pode originar o arquivo complete_alias em todas as instâncias do bash .bash_profileou através dele .

instalação

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

inscrição

source ~/.bash_completion.d/complete_alias

alias container=docker\ container
complete -F _complete_alias container

containeragora pode ser preenchido automaticamente pelo _docker()manipulador de conclusão original ;

$ container l<Tab>
logs  ls    

$ container s<Tab>
start  stats  stop   
Cyker
fonte
2
Dado que este software parece ser seu, você poderia fazer melhor que isso. Adicione instruções sobre como instalá-lo. Descreva o que faz e como usá-lo. Caso contrário, isso é apenas spam.
Muru
@ muru Eu estava pensando em colar algum código aqui, mas provavelmente é mais do que aceito aqui. Eu suponho que as pessoas não tenham problemas para ler a seção Instalar em um arquivo LEIA-ME e, neste caso, são apenas várias linhas.
Cyker
2
o objetivo é ser capaz de julgar se vale a pena visitar o README, apenas a partir da resposta.
Muru
Esta é uma resposta adequada e resolve o problema exatamente.
Ярослав Рахматуллин 10/10
11
Esta é uma resposta excelente e muito abrangente que funciona perfeitamente, obrigado !. Provavelmente foi atualizado porque o @muru teve problemas com ele.
Brian Topping
3

2018 resposta

Você deve adicionar seu alias ao programa 'complete'. Dependendo do tipo de preenchimento automático que você deseja obter, você deve usar -c ou -F.

Para preenchimento automático de pacote:

complete -c name_of_your_alias

Para preenchimento automático de comando:

complete -F name_of_your_alias

Para verificar se o seu alias foi adicionado corretamente:

complete | grep name_of_your_alias

Por fim, para remover um alias de 'complete':

complete -r name_of_your_alias

No seu caso:

complete -c apt-inst
Adrian Lopez
fonte
11
Por favor, não continue sua resposta nos comentários. Se você tem algo a dizer, edite -o na resposta.
G-Man diz 'Reinstate Monica'
2
complete -F xxxnão funciona no OSX (apenas mostra o uso complete: usage: complete [-abcdefgjksuv] [-pr] [-o option] [-A action] [-G globpat] [-W wordlist] [-P prefix] [-S suffix] [-X filterpat] [-F function] [-C command] [name ...]). Você tem algum ponteiro? Obrigado.
Anthony Kong
2

Aqui está o código da resposta de Shawn J. Goff com algumas melhorias:

  • Corrigidos erros de sintaxe destacados por shell-check, por exemplo, o primeiro "de "$@"fato terminou a sequência de definição de função.
  • Removido o return 0para que o valor de retorno da função subjacente possa ser passado de volta ao chamador.

.

# 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
fonte
Não funciona para mim no Bash 4.3.46, receio. A resposta de Shaun J. Goff não funcionam.
Joelittlejohn
11
"Finalizar" a cadeia de definição de função é proposital; o objetivo é incluir argumentos da função externa na COMP_WORDSmatriz. Se usarmos make-completion-wrapper _apt_get _apt_get_install apt-get installcomo exemplo, after shift 2, $@contains apt-get install. A definição da função inclui apt-get install(as duas palavras literais) ao atribuir COMP_WORDS.
Jeffery até
0

Como uma extensão da resposta do @Giles, a seguinte função de conveniência nomeia automaticamente o wrapper gerado make-completion-wrapperpara tornar possível definir a conclusão em uma linha:

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
fonte