Subdiretório de preenchimento automático de formatação para o comando personalizado

2

Eu tentei por horas fazer isso funcionar e sinto que não cheguei perto.

Estou tentando encurtar nosso fluxo de trabalho ao separar os nomes de diretório no terminal do Mac OS X.

Nós temos uma ferramenta interna, vamos chamá-la bob , que executa automaticamente comandos em submódulos git. O que eu gostaria de fazer é preencher automaticamente os nomes dos subdiretórios. O problema é que esses subdiretórios vivem em um local estático.

   project directory
   ->public
     ->submodules
       ->a-module
       ->another-module
       ->other-module
       ->some-module

Os comandos são executados no diretório superior do projeto da seguinte forma:

bob start bugfix anothermodule

Em vez de digitar "outro módulo", que é o que fazemos atualmente, adoraria concluir o preenchimento automático da guia. Usamos esse fluxo de trabalho várias vezes por dia, e descascar segundos dele seria ótimo e evitar erros de digitação.

O objetivo final é:

bob start bugfix an<tab>

seria preenchido automaticamente para

bob start bugfix anothermodule

Eu tentei CDPATH , mas percebi rapidamente que não era isso que eu queria, pois isso não está seguindo o comando cd , apenas meu comando personalizado.

Eu tenho bash_completion instalado, mas não sou muito bom no bash em geral. Mencionar isso, embora no caso, pode ser uma parte da solução!

    
por Gedrick Wilson 16.11.2017 / 21:00

2 respostas

1

Este é um aprimoramento da excelente resposta do Kamil que retira o hífen da parte -module de cada subdiretório nome.

bugfix)
    curdir=$(pwd)
    cd public/submodules/ 2>/dev/null && _filedir -d
    # Strip the hyphen from '-module' in each sub-directory name.
    for ((i=0; i<${#COMPREPLY[@]}; i++)); do
        COMPREPLY[$i]="${COMPREPLY[$i]/-module/module}"
    done
    cd "$curdir"
    ;;

Ainda há espaço para melhorar esta seção: você pode ter que digitar o hífen, isto é, digitar a - Tab para que ele seja complete em amodule em vez de escolher entre amodule e anothermodule (o hífen ainda é removido pela função de conclusão).

    
por 20.11.2017 / 01:26
1

É isso mesmo, bash_completion é uma solução. Eu posso te dizer o que eu tenho no meu Ubuntu. Espero que as coisas sejam pelo menos semelhantes no Mac.

/etc/bash_completion arquivo que origina /usr/share/bash-completion/bash_completion .

Em um diretório /usr/share/bash-completion , há também um subdiretório completions . Este é o lugar para scripts. Vamos ver o script eject :

# bash completion for eject(1)                             -*- shell-script -*-

_eject()
{
    local cur prev words cword
    _init_completion || return

    case $prev in
        -h|--help|-V|--version|-c|--changerslot|-x|--cdspeed)
            return
            ;;
        -a|--auto|-i|--manualeject)
            COMPREPLY=( $( compgen -W 'on off' -- "$cur" ) )
            return
            ;;
    esac

    if [[ $cur == -* ]]; then
        COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "$cur" ) )
        return
    elif [[ $prev == @(-d|--default) ]]; then
        return
    fi

    _cd_devices
    _dvd_devices
} &&
complete -F _eject eject

# ex: ts=4 sw=4 et filetype=sh

Mesmo sem ler a documentação, podemos fazer engenharia reversa e ajustar o seu caso. Para nós, a parte mais importante do código acima é onde ele diz que, depois de -a , --auto -i ou --manualeject , pode haver on ou off . No seu caso, depois de bugfix você precisa de um nome de diretório.

(Ou não. Você tem o diretório another-module , mas você usa o argumento anothermodule . Por enquanto eu suponho que seja um erro de digitação. Caso não seja, A resposta de Anthony apontará na direção certa, eu acho.

Poderíamos de alguma forma extrair esses diretórios que você deseja e substituir 'on off' , mas talvez seja melhor utilizar o código existente. Depois de digitar cd , bash autocomplete os diretórios e ele funciona bem, mesmo se houver espaços ou caracteres especiais. Então, vamos olhar para _cd() function; está em /usr/share/bash-completion/bash_completion , não vou colar aqui. Em seguida, parece que a parte crucial dessa função é _filedir -d invocação. Pouco antes de onde _filedir() está definido, temos:

# This function performs file and directory completion. It's better than
# simply using 'compgen -f', because it honours spaces in filenames.

Bingo.

Então, copiei o script eject com o nome bob e editei na forma de:

# bash completion for bob                             -*- shell-script -*-

_bob()
{
    local cur prev words cword curdir
    _init_completion || return

    case $prev in
        bob)
            COMPREPLY=( $( compgen -W 'start stop foo bar' -- "$cur" ) )
            return
            ;;
        start)
            COMPREPLY=( $( compgen -W 'bugfix' -- "$cur" ) )
            return
            ;;
        bugfix)
            curdir=$(pwd)
            cd public/submodules/ 2>/dev/null && _filedir -d
            cd "$curdir"    
            ;;
    esac

} &&
complete -F _bob bob

As sessões bash existentes não notarão este arquivo, você terá que executar um novo bash para testá-lo.

Sim, é uma programação vodu rápida e suja, desculpe.

Observe que descemos para public/submodules/ e voltamos. Normalmente eu usaria um subshell:

export -f _filedir
( cd … && _filedir -d )

mas parece que _filedir não funciona desta maneira.

    
por 17.11.2017 / 03:51