![É possível configurar a forma como o bash completa os nomes dos diretórios?](https://rvso.com/image/1288703/%C3%89%20poss%C3%ADvel%20configurar%20a%20forma%20como%20o%20bash%20completa%20os%20nomes%20dos%20diret%C3%B3rios%3F.png)
Eu gostaria de instruir o bash a usar um método especial para completar determinados nomes de diretório. Por exemplo, o bash chamaria um programa meu para realizar a conclusão se um caminho começar com "$$" e, caso contrário, executaria a conclusão normalmente.
Tudo isso é possível? Como você implementaria isso?
Recompensa: Eu realmente apreciaria uma resposta a essa pergunta. O objetivo é permitirsalto automáticopara completar 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 distante, você pode digitar:
cp $$patern + <Tab>
e o salto automático 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 do ott para adicioná-lo a alguns comandos específicos, mas se alguém tiver uma ideia melhor, ficaria muito grato.
Responder1
Você pode fazer isso substituindo a ligação padrão para TAB(^i). Primeiro você precisa substituir a ligação TAB, depois construir uma função que chame seu comando e, por último, 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
então a conclusão normal ainda funciona, 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.
Testei isso no Ubuntu 11 usando bash 4.2.8(1)-release (o padrão).
Responder2
A rotina de conclusão do bash pode ser programada como um script de shell.
Aqui está um exemplo de shell-script que substituirá qualquer parâmetro $$[Tab]
por my replacement string
, mas apenas para o comando específico mycommand
e 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 fornecer o script para bash via source <file-name>
(ou o comando dot) para iniciá-lo a funcionar e então:
mycommand $$[Tab] -> mycommand my replacement string
mycommand $$$[Tab] -> mycommand $$$ (beep)
mycommand whatever[Tab] -> (will complete "whatever" in the normal bash manner)
Para que sempre funcione para alguns ou todos os usuários, inclua isso em um dosrotinas de perfil bash.
O problema com o complete
comando é que ele funcionará apenas para um ou mais nomes de comandos, que são especificados como parâmetros. Pode-se simplesmente fornecer a lista de todos os comandos que poderiam ser usados pelos usuários ou, em casos desesperadores, expandir /bin/* /usr/bin/* ~/bin/*
.
Testado no CentOS 5.5.
Este script simples é baseado nas fontes que listei em minha outra resposta - aquela que foi excluída pelo moderador studiohack. Se estiver interessado, basta pedir a ele para desfazer a exclusão.