현재 세션 내에서 "프로그래밍 가능한 완료"를 사용자 정의하는 방법이 있습니까?

현재 세션 내에서 "프로그래밍 가능한 완료"를 사용자 정의하는 방법이 있습니까?

명령이나 파일 이름을 입력하기 시작하면 Tab 키를 사용하여 문자열을 자동 완성할 수 있습니다. 현재 bash 세션의 자동 완성 동작을 변경하는 방법이 있습니까?

예를 들어

Tab Tab현재 세션에서 누르면 *.txt포함된 파일만 표시됩니다.

자동완성은 어떻게 작동하나요? 자동 완성 동작을 변경하기 위해 조정할 수 있는 환경 변수 세트가 있습니까?

답변1

bash_completion메커니즘에서 bash 함수는 _filedir_xspec()파일 및 디렉터리 이름 완성을 담당합니다. 이 기능은 스크립트에서 찾을 수 있습니다 /etc/bash_completion.

함수를 편집하고 정규식을 포함하는 줄을 추가할 수 있습니다. 예를 들어 이 함수(원본 함수의 복사본)를 사용하는 경우는 다음과 같습니다.

_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 \$0; 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[@]}" )
}

새로운 섹션을 참고하세요.32호선:

eval xspec="!*.txt" 

이 문은 나중에 compgen정규식과 일치하지 않는 모든 항목을 제거하는 데 사용됩니다. 이 파일을 편집하는 것을 권장하지 않습니다 /etc/bash_completion. 대신 위의 내용과 파일(필요한 경우)을 사용하여 source새 파일을 만듭니다 .

source /path/to/file

셸의 함수로 완성된 모든 명령/응용 프로그램은 _filedir_xspec()이제 파일 이름만 사용하여 완성됩니다 *.txt.

답변2

특정 프로그램이나 사용자 정의 스크립트 또는 명령에서만 사용할 수도 있습니다.

txt제안에 확장명이 있는 파일 만 표시하려면 source현재 세션에서 쉘 스크립트를 작성하기만 하면 됩니다.

# Autocomplete file /path/to/file/sample-completion.sh
# for the command `sample`
_sample(){
   COMPREPLY=($(compgen -f -X "!.*[.][tT][xX][tT]$" -- "$2"))
}

complete -F _sample sample

다음을 호출하여 가져옵니다.

$ source /path/to/file/sample-completion.sh

이 코드에서는 $2현재 단어가 완성되고 있습니다. 이 -- "$2"부분은compgen현재 완성하고 있는 단어가 포함된 제안만 필터링하여 입력하세요.COMPREPLY. 또한 이 -f옵션은compgen현재 디렉터리에 있는 파일만 찾습니다. 마지막으로 중요한 -X옵션은필터 모드(여기 참조)들어오지 못하게 하다파일 이름 일치. !패턴의 시작 부분 에부정적인그런 행동. 결과적으로 .txt확장명이 있는 파일만 표시됩니다. $정규식 끝에 기호를 사용하면 주어진 패턴으로 끝나는 일치 항목을 찾을 수 있습니다. 즉 [.], 문자뿐만 아니라 문자 그대로의 점도 찾습니다. 이는 정규식에서 점의 기본 의미입니다. 이 [tT][xX][tT]부분에서는 패턴이 "txt, txT, tXt, tXT, Txt, TxT, TXT, TXt"와 같은 모든 경우와 일치한다고 말합니다.

답변3

기대다수락된 답변@chaos에서 왔는데, 이 기능을 제안합니다.수리하다필요한 경우 기존 완성 기능:

patchFDxspec(){
  . <(type _filedir_xspec | sed -e '1d;s/\(eval xspec="\).*$/&\n\1!*.txt";/');
}

이 기능을 실행하면 _filedir_xspec현재 세션이 패치됩니다.

. 이외의 확장자가 필요한 경우 .txt기능을 수정하여 원하는 접미사를 $1.

관련 정보