É possível configurar a maneira como o bash conclui os nomes de diretório?


8

Gostaria de instruir o bash a usar um método especial para executar a conclusão em determinados nomes de diretório. Por exemplo, o bash chamaria um programa meu para executar a conclusão se um caminho iniciar com "$$" e, normalmente, executaria a conclusão normalmente.

Tudo isso é possível? Como você o implementaria?

Recompensa : Eu realmente aprecio uma resposta a essa pergunta. O objetivo é permitir que o salto automático complete caminhos para todos os comandos quando o usuário os inicia com um determinado prefixo. Por exemplo, ao copiar um arquivo de um diretório remoto, você pode digitar:

cp $$patern + <Tab>

e o autojump seria concluído

cp /home/user/CompliCatedDireCTOry/long/path/bla/bla

e você apenas teria que adicionar onde deseja colocar o arquivo. É claro que posso usar o comentário de ott para adicioná-lo a alguns comandos específicos, mas se alguém tiver uma idéia melhor, ficaria muito grato.


Consulte a seção "Conclusão programável" na página de manual do bash.

Se você votar para encerrar minha pergunta, explique o motivo.
Peltier

2
"complete" suporta "-G pattern" para corresponder ao seu $$ e ao início e "-F func" para chamar sua própria função, mas ele precisa de um ou mais nomes de comando para funcionar.

Por que não usar apenas uma variável de ambiente? Por exemplo: cp $ prefix / file / path / to / dest /
Xenoactive 09/09

@ Xenoactive: porque o salto automático é totalmente automatizado e funciona em mais de um caminho. Usar variáveis ​​de ambiente definidas manualmente não ajuda. Ou talvez você tenha uma ideia poderosa que eu não entendo?
Peltier

Respostas:


3

Você pode fazer isso substituindo a ligação padrão para TAB (^ i). Primeiro, você precisa substituir a ligação TAB e, em seguida, criar uma função que chama seu comando; por fim, você precisa pegar a saída desse comando e atualizar a variável que contém a linha de comando atual.

Esta função pega a linha de comando atual e altera os dois últimos caracteres para 'huugs'.

function my_awesome_tab_completion_function () {
  set -- $READLINE_LINE
  command="$1"
  shift
  argument="$*"
  argument_length=$(echo -n $argument | wc -c)
  if echo $argument | grep '^$$' >/dev/null 2>&1; then
    new_argument=$(echo $argument | sed 's/..$/huugs/') # put your autojump here
  else
    new_argument=$(compgen -d $argument)
  fi
  new_argument_length=$(echo -n $new_argument | wc -c)
  READLINE_POINT=$(( $new_argument_length - $argument_length + $READLINE_POINT ))
  READLINE_LINE="$command $new_argument"
}

Para o seu exemplo, você provavelmente desejaria alterar a linha new_argument para ficar assim:

  new_argument=$(autojump $argument)

Agora substitua a ligação ^ i:

$ bind -x '"\C-i"':'my_awesome_tab_completion_function'

Agora teste se funciona:

$ cd /ro<TAB>
changes my command to:
$ cd /root

para que a conclusão normal ainda funcione, você pode testar a parte $$ fazendo cd $$ ... etc.

Se você tiver problemas, ative o modo detalhado:

$ set -x

Ele imprimirá tudo o que a função está fazendo.

Eu testei isso no Ubuntu 11 usando o bash 4.2.8 (1) -release (o padrão).


Parece-me que isso funciona apenas no primeiro parâmetro do comando e também pode fazer coisas estranhas se a guia for usada de maneiras inesperadas (por exemplo, após um $$$ ou após o nome do comando), ou estou errado?
harrymc

Bem, está passando $ * para que 'funcione' mais do que apenas o primeiro parâmetro (eu não sei o salto automático, então não tenho certeza se ele pode receber vários argumentos). Você pode mudar para o final e enviar apenas o último para o salto automático, ou usar READLINE_POINT para determinar onde o cursor está entre os argumentos do comando e enviar apenas essa 'palavra' para o salto automático.
polinômio

Sua solução é interessante, mas você deve admitir que assumir a tecla tab é um pouco extremo. Não há como prever todos os casos possíveis.
harrymc 12/09

Obrigado pela sua resposta, essa é uma boa solução alternativa e aborda a parte "de todos os comandos" da minha pergunta. Eu concordo com a harrymc que é um pouco extremo, no entanto ... Acho que se ninguém encontrar uma solução melhor, vou tentar e ver se é viável.
Peltier

Sim, eu concordo com o harrymc também, mas estava tentando responder à pergunta conforme solicitado. Pessoalmente, eu vincularia isso a outra tecla de controle como ^ G ou algo assim, para deixar a guia em paz, mas ainda usar essa funcionalidade.
polinomial

1

A rotina de conclusão do bash pode ser programada como um script de shell.

Aqui está um exemplo de script de shell que será substituído em qualquer parâmetro $$[Tab]por my replacement string, mas apenas para o comando específico mycommande somente se o parâmetro for exatamente "$$":

_mycomplete()
{
        if [ ${COMP_WORDS[COMP_CWORD]} == \$\$ ]
        then
                COMPREPLY='my replacement string'
        fi
}
complete -o default -o bashdefault -F _mycomplete mycommand

Você deve originar o script para bash via source <file-name>(ou o comando dot) para iniciá-lo funcionando e, em seguida:

mycommand $$[Tab] -> mycommand my replacement string
mycommand $$$[Tab] -> mycommand $$$ (beep)
mycommand whatever[Tab] -> (will complete "whatever" in the normal bash manner)

Para que ele funcione sempre para alguns ou todos os usuários, inclua isso em uma das rotinas do perfil do bash .

O problema com o completecomando é que ele funcionará apenas para um ou mais nomes de comandos especificados como parâmetros. Pode-se simplesmente fornecer a lista de todos os comandos que poderiam ser usados ​​pelos usuários ou, em casos desesperados, expandir-se /bin/* /usr/bin/* ~/bin/*.

Testado no CentOS 5.5.

Esse script simples é baseado nas fontes que listei na minha outra resposta - a que foi excluída pelo moderador studiohack. Se estiver interessado, peça-lhe para cancelar a exclusão.


Obrigado pela sua resposta. Minha pergunta não era realmente sobre isso, já que eu era nova, era possível, mas não conclui todos os comandos. No entanto, acho que, se a solução do polinômio não for aceitável, implementarei algo assim e tentarei direcionar os comandos mais comuns.
Peltier
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.