Existe uma maneira de personalizar a “Conclusão Programável” na sessão atual?

6

Se eu começar a digitar um comando ou nome de arquivo, posso usar a tecla tab para completar automaticamente minha string.

Isso é bem conhecido ...

Existe uma maneira de alterar o comportamento do preenchimento automático para a sessão bash atual para que ele faça certas coisas?

Por exemplo

Ao pressionar Tab Tab na sessão atual, somente os arquivos que contêm *.txt serão exibidos.

Existem determinadas variáveis de ambiente ou algo que poderia fazer isso funcionar?

    
por Questionmark 06.06.2014 / 18:40

1 resposta

8

No mecanismo bash_completion , é a função bash _filedir_xspec() que é responsável pelas conclusões de nome de arquivo e dirname. Esta função pode ser encontrada no script /etc/bash_completion .

Você pode editar essa função e adicionar uma linha que contenha sua regex. Por exemplo, use esta função (é uma cópia da função original):

_filedir_xspec()
{
    local IFS cur xspec

    IFS=$'\n'
    COMPREPLY=()
    _get_comp_words_by_ref cur

    _expand || return 0

    # get first exclusion compspec that matches this command
    xspec=$( awk "/^complete[ \t]+.*[ \t]${1##*/}([ \t]|\$)/ { print \
eval xspec="!*.txt" 
; exit }" \ "$BASH_COMPLETION" ) # prune to leave nothing but the -X spec xspec=${xspec#*-X } xspec=${xspec%% *} local -a toks local tmp toks=( ${toks[@]-} $( compgen -d -- "$(quote_readline "$cur")" | { while read -r tmp; do # see long TODO comment in _filedir() --David printf '%s\n' $tmp done } )) # Munge xspec to contain uppercase version too eval xspec="${xspec}" eval xspec="!*.txt" #<---- HERE add your regex, that's the only line changed local matchop=! if [[ $xspec == !* ]]; then xspec=${xspec#!} matchop=@ fi [[ ${BASH_VERSINFO[0]} -ge 4 ]] && \ xspec="$matchop($xspec|${xspec^^})" || \ xspec="$matchop($xspec|$(printf %s $xspec | tr '[:lower:]' '[:upper:]'))" toks=( ${toks[@]-} $( eval compgen -f -X "!$xspec" -- "\$(quote_readline "\$cur")" | { while read -r tmp; do [ -n $tmp ] && printf '%s\n' $tmp done } )) [ ${#toks[@]} -ne 0 ] && _compopt_o_filenames COMPREPLY=( "${toks[@]}" ) }

Observe a nova parte na linha 32 :

source /path/to/file

Essa instrução é usada posteriormente em compgen para remover todas as entradas que não correspondem à expressão regular. Eu não recomendaria editar o arquivo /etc/bash_completion . Em vez disso, crie um novo arquivo com o conteúdo acima e source do arquivo, se necessário:

_filedir_xspec()
{
    local IFS cur xspec

    IFS=$'\n'
    COMPREPLY=()
    _get_comp_words_by_ref cur

    _expand || return 0

    # get first exclusion compspec that matches this command
    xspec=$( awk "/^complete[ \t]+.*[ \t]${1##*/}([ \t]|\$)/ { print \
eval xspec="!*.txt" 
; exit }" \ "$BASH_COMPLETION" ) # prune to leave nothing but the -X spec xspec=${xspec#*-X } xspec=${xspec%% *} local -a toks local tmp toks=( ${toks[@]-} $( compgen -d -- "$(quote_readline "$cur")" | { while read -r tmp; do # see long TODO comment in _filedir() --David printf '%s\n' $tmp done } )) # Munge xspec to contain uppercase version too eval xspec="${xspec}" eval xspec="!*.txt" #<---- HERE add your regex, that's the only line changed local matchop=! if [[ $xspec == !* ]]; then xspec=${xspec#!} matchop=@ fi [[ ${BASH_VERSINFO[0]} -ge 4 ]] && \ xspec="$matchop($xspec|${xspec^^})" || \ xspec="$matchop($xspec|$(printf %s $xspec | tr '[:lower:]' '[:upper:]'))" toks=( ${toks[@]-} $( eval compgen -f -X "!$xspec" -- "\$(quote_readline "\$cur")" | { while read -r tmp; do [ -n $tmp ] && printf '%s\n' $tmp done } )) [ ${#toks[@]} -ne 0 ] && _compopt_o_filenames COMPREPLY=( "${toks[@]}" ) }

Agora, todos os comandos / aplicativos no shell, que foram concluídos pela função _filedir_xspec() , concluem agora apenas com *.txt nomes de arquivos.

    
por 10.06.2014 / 14:31