Conclusão da guia bash personalizada mostrando possíveis conclusões, mas não concluindo realmente a entrada

3

Eu tentei arduamente descobrir isso antes de postar aqui, mas não consigo encontrar nenhum outro exemplo de pessoas resolvendo esse problema em particular.

Estou executando o Ubuntu 17.10

Eu escrevi uma função personalizada para manipular a conclusão de tabulação de um dos meus scripts. A intenção é que quando eu digitar o nome do meu script e clicar em [TAB] liste todos os arquivos em / opt / use que terminem em ".use" (sem exibir o ".use" ou o caminho principal) . Parece que fiz esse trabalho até agora.

Os arquivos em / opt / use são os seguintes:

blender-2.79.use
chrome.use
clarisse-3.6.use
unity-2017.3.0p2.use

O código para a função e a conclusão é:

_use () {
    files=( 'compgen -f -X "!*.use" /opt/use/' )
    output=()
    for file in "${files[@]}"; do
        fileBaseName='basename $file .use'
        output+=("$fileBaseName")
    done
    COMPREPLY=( ${output[@]} )
}
complete -F _use use

Por favor, não me julgue severamente, sou um artista gráfico, não um programador. :)

Além disso, meu script "use" é na verdade um alias para o seguinte comando:

source /opt/scripts/use.sh

Agora, quando digito:

use[SPACE][TAB][TAB]

Consegui com sucesso uma lista dos arquivos em / opt / use que terminam em ".use".

Até aí tudo bem. Por exemplo, eu digito "use [SPACE] [TAB] [TAB]", é assim:

bvz@bvz-xps15-linux:~$ use 
blender-2.79      chrome            clarisse-3.6      unity-2017.3.0p2  

Minha primeira pergunta é por que eu tenho que bater [TAB] duas vezes? A primeira vez apenas apita. A segunda vez me mostra minhas opções. Isso não é um problema para mim, eu só me pergunto se é uma pista sobre o meu problema, que é isso:

Se eu digitar letras suficientes para ser completamente exclusivo, a conclusão da tabulação não "conclui" realmente a linha. Ele apenas deixa a entrada exatamente como eu digitei e me mostra novamente a lista de arquivos em / opt / use. Então, por exemplo, se eu digitar:

use clar[TAB][TAB]

em vez de preencher a linha para ler:

use clarisse-3.6

que é o que eu esperaria (e o que eu sou depois) deixa a linha como:

use clar

e me mostra abaixo da lista completa de possíveis conclusões. Aqui está uma amostra:

bvz@bvz-xps15-linux:~$ use clar[TAB][TAB]
blender-2.79      chrome            clarisse-3.6      unity-2017.3.0p2  
bvz@bvz-xps15-linux:~$ use clar

Observe que, na verdade, a linha não foi concluída para ler "clarisse-3.6", embora essa seja a única conclusão possível.

Alguém pode me esclarecer sobre o que eu fiz de errado? Além disso, se esta é uma duplicata, peço desculpas. Eu olhei em volta por vários dias, mas não encontrei nenhum exemplo onde alguém tenha encontrado esse problema, muito menos resolvido.

Obrigado

    
por bvz 01.02.2018 / 04:46

2 respostas

3

Obrigado ao Muru por me indicar a solução.

Aparentemente, meu problema era que toda vez que minha função era chamada, sempre retornava a lista completa de possíveis correspondências. Eu precisava retornar apenas as conclusões possíveis que correspondem ao que o usuário digitou até agora. Quando eu retornar apenas um único item, o bash completará automaticamente o restante da linha.

Esta é a função que funciona. Antes de adicionar cada conclusão possível, eu faço uma verificação rápida para ver se a conclusão começa com a palavra que foi digitada originalmente. Eu faço isso usando expressões regulares. Eu também tive que testar para ver se eles ainda não entraram nada - nesse caso eu sempre devolvo tudo.

Eu também mudei para fazer mais algumas variáveis "locais".

_use () {
    local word="${COMP_WORDS[$COMP_CWORD]}"
    local files=( 'compgen -f -X "!*.use" /opt/use/' )
    local output=()
    for file in "${files[@]}"; do
        fileBaseName='basename $file .use'
        if [[ $fileBaseName =~ ^$word.* ]] || [ "$word" == "" ]; then
            output+=("$fileBaseName")
        fi
    done
    COMPREPLY=( ${output[@]} )
}
    
por 01.02.2018 / 06:17
1

Agora que tive algum tempo para considerar isso, acho que a função de conclusão pode ser simplificada para:

_use () {
    local word="${COMP_WORDS[$COMP_CWORD]}"
    local IFS=$'\n'
    COMPREPLY=( $(find /opt/use/ -type f -name "$word*.use" -exec basename -as .use {} +) )
}

Assumindo que seu basename é novo o suficiente para suportar -a , caso contrário, use -exec basename {} .use \; .

    
por 02.02.2018 / 09:25