[apple] 터미널에서 열기 명령을 자동 완성하는 방법이 있습니까?

open -a 터미널 의 명령을 자주 사용하여 ssh를 통해 응용 프로그램을 엽니 다. 응용 프로그램 이름을 자동 완성하려면 어떻게해야합니까?



답변

_complete_open() {
        COMPREPLY=()
        local cur="${COMP_WORDS[$COMP_CWORD]}"
        local prev="${COMP_WORDS[COMP_CWORD-1]}"
        [[ "$cur" == -* || "$prev" != '-a' ]] && return
        apps="$(mdfind kMDItemKind==Application -onlyin /Applications -onlyin ~/Applications -onlyin /Developer -onlyin ~/Developer | grep -v '/.*/.*/.*/.*/' | sed -E 's|.*/||g;s|\.app$||g' | uniq)"$'Finder\nArchive Utility\nCharacterPalette\nKeyboardViewer'
        local IFS=$'\n'
        if [[ "${cur:0:1}" = '"' || "${cur:0:1}" = "'" ]]; then
            quote="${cur:0:1}"
            cur="${cur:1}"
        fi
        local found="$(grep -i "^$cur" <<< "$apps")"
        if [[ "$quote" == '"' ]]; then
            found="$(sed "s|^|\"|g;s|$|\"|g" <<< "$found")"
        elif [[ "$quote" == "'" ]]; then
            found="$(sed "s|^|'|g;s|$|'|g" <<< "$found")"
        else
            found="$(sed 's| |\\ |g' <<< "$found")"
        fi
        COMPREPLY=($found)
}

complete -o default -F _complete_open open

세 번째 버전은 대소 문자를 구분하지 않으며 따옴표 내에서 작동합니다.


답변

다음을 추가 .bash_profile하거나 .bashrc새 세션을 시작 하십시오 .

function _complete_open {
    cur=$2
    COMPREPLY=( );

    [[ "$COMP_WORDS" = "open" ]] || return
    [[ "${COMP_WORDS[ $(( $COMP_CWORD - 1 )) ]}" = "-a" ]] || return

    OLDIFS="$IFS"
    IFS=$'\n'
    local _part="${COMP_WORDS[$COMP_CWORD]}"

    if [[ "${_part:0:1}" = '"' || "${_part:0:1}" = "'" ]] ; then
        COMPREPLY=( $( compgen -W "$( mdfind kMDItemKind==Application | sed -e 's|.*/||g' -e 's|.app$||' | sort -u )" -- $cur ) )
    else
        COMPREPLY=( $( compgen -W "$( mdfind kMDItemKind==Application | sed -e 's|.*/||g' -e 's|.app$||' -e 's| |\\\\ |g' | sort -u )" -- $cur ) )
    fi
    IFS="$OLDIFS"
}

complete -o default -F _complete_open open

아무것도 설치할 필요가 없습니다. 이것은 bash즉시 사용 가능합니다.


이전 옵션이 -a기본 동작 인 경우에만 프로그램 이름을 자동 완성합니다 . 예를 들어 현재 디렉토리의 모든 파일 목록을 반환하거나 현재 경로 접두사를 완성합니다.

결과는 시스템에서 이런 방식으로 system_profiler SPApplicationsDataType시작할 수있는 모든 응용 프로그램 을 얻는 가장 쉬운 방법 인 에서 생성됩니다 . 이 목록은 공백을 포함 할 수 있고 번들 이름과 다를 수있는 프로그램 이름 만 리턴하도록 처리됩니다 ( .app접미 부를 무시하더라도 ).

사용법 : 유형 open -a, 다음에 공백이 눌러 다음 Tab또는 Esc(2 회 내 시스템에, 확실하지가 사방의 경우).

스캐너의 모든 도우미 응용 프로그램을 보여주는 예 :

$ open -a Scan
Scan to E-mail          Scan to Excel           Scan to Folder          Scan to Print           Scan to Searchable PDF  Scan to Word            ScanSnap Manager

이 솔루션의 단점과 문제점 :

  • 시스템에는에있는 모든 것과 같이 알지 못하는 수많은 프로그램이 있습니다 /System/Library/CoreServices. 모두 나열하지 않을 수도 있습니다. OTOH, 예를 들어 CharacterPalette또는 KeyboardViewer이런 식으로 정말 쉽게보고 실행할 수 있습니다. * 인수를 사용 하여 mdfind호출을 적절히 구성하십시오 -onlyin.

  • 로 인해 속도가 느립니다 system_profiler SPApplicationsDataType. 완료가 표시되기 전에 1-2 초 정도 기다려야 할 수도 있습니다. 이제 mdfind프로그램을 빨리 얻는 데 사용 합니다. 감사합니다 @Lri

  • 응용 프로그램 이름의 공백과 따옴표로 묶인 프로그램 이름을 처리 할 수 ​​있지만 다소 해킹 적입니다. 따옴표는 첫 번째 문자 여야합니다. Scan" to "P에서 유효 하지만 bash이 프로그램은 따옴표를 감지하지 않습니다. 이스케이프 된 공간 (예 🙂 이후에는 완료가 작동하지 않습니다 (예 : Scan\ to따옴표 "Scan to). 탈출 한 공간에 대한 지원은 완료 DVD하기 만하면 됩니다 DVD\ Player.


답변

구조에 프로그램 가능한 자동 완성! Bash Completion Homepage 에서 많은 사본이 필요 했지만 자동 완성 마법을 많이 사용하려면 설치해야합니다. 그렇게하면 마지막 함수 ( _open)와 아래에서 초기화 명령 만 필요합니다 .

다음에 추가하십시오 .bashrc:

# taken from http://bash-completion.alioth.debian.org/

_compopt_o_filenames()
{
    # We test for compopt availability first because directly invoking it on
    # bash < 4 at this point may cause terminal echo to be turned off for some
    # reason, see https://bugzilla.redhat.com/653669 for more info.
    type compopt &>/dev/null && compopt -o filenames 2>/dev/null || \
        compgen -f /non-existing-dir/ >/dev/null
}

_tilde() {
    local result=0
    # Does $1 start with tilde (~) and doesn't contain slash (/)?
    if [[ ${1:0:1} == "~" && $1 == ${1//\/} ]]; then
        _compopt_o_filenames
        # Try generate username completions
        COMPREPLY=( $( compgen -P '~' -u "${1#\~}" ) )
        result=${#COMPREPLY[@]}
    fi
    return $result
}

_quote_readline_by_ref()
{
    if [[ ${1:0:1} == "'" ]]; then
        if [[ ${BASH_VERSINFO[0]} -ge 4 ]]; then
            # Leave out first character
            printf -v $2 %s "${1:1}"
        else
            # Quote word, leaving out first character
            printf -v $2 %q "${1:1}"
            # Double-quote word (bash-3)
            printf -v $2 %q ${!2}
        fi
    elif [[ ${BASH_VERSINFO[0]} -le 3 && ${1:0:1} == '"' ]]; then
        printf -v $2 %q "${1:1}"
    else
        printf -v $2 %q "$1"
    fi

    # If result becomes quoted like this: $'string', re-evaluate in order to
    # drop the additional quoting.  See also: http://www.mail-archive.com/
    # bash-completion-devel@lists.alioth.debian.org/msg01942.html
    [[ ${!2:0:1} == '$' ]] && eval $2=${!2}
} # _quote_readline_by_ref()

_filedir()
{
    local i IFS=$'\n' xspec

    _tilde "$cur" || return 0

    local -a toks
    local quoted tmp

    _quote_readline_by_ref "$cur" quoted
    toks=( ${toks[@]-} $(
        compgen -d -- "$quoted" | {
            while read -r tmp; do
                printf '%s\n' $tmp
            done
        }
    ))

    if [[ "$1" != -d ]]; then
        # Munge xspec to contain uppercase version too
        [[ ${BASH_VERSINFO[0]} -ge 4 ]] && \
            xspec=${1:+"!*.@($1|${1^^})"} || \
            xspec=${1:+"!*.@($1|$(printf %s $1 | tr '[:lower:]' '[:upper:]'))"}
        toks=( ${toks[@]-} $( compgen -f -X "$xspec" -- $quoted) )
    fi
    [ ${#toks[@]} -ne 0 ] && _compopt_o_filenames

    COMPREPLY=( "${COMPREPLY[@]}" "${toks[@]}" )
} # _filedir()

# only the following is needed if bash-autocompletion is already installed
_open ()
{
    local cur;

    cur=$2;

    COMPREPLY=();
    if [ $COMP_CWORD -eq 2 ]; then
        COMPREPLY=($(compgen -W "$(/bin/ls /Applications)" -- $cur ));
        return 0
    fi

    _filedir
}

complete -F _open open


답변

이 온다 zsh을 쉘 기본적으로 설정 만큼 당신이 자체는 물론, 활성화 완료를 가지고. Zsh는 OS X에 포함되어 있습니다.

당신이해야 할 모든 투입 autoload -Uz compinit; compinit에 ~ / .zshrc, 또는 첫 번째 실행 구성 메뉴를 통해 완료 할 수 있습니다.

Zsh는 실제로 대부분 Bash의 상위 집합이므로 새로운 것을 배울 필요가 없습니다. 심지어 당신의 스크립트도 작동 할 것입니다!


답변