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


16

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


어떤 쉘을 사용하고 있습니까?
— Daniel Beck

2
나는 조금 더 빠른 방법은 전체 경로를 입력하는 것입니다 (예를 들어 잠시 동안 나와 함께 가십시오! open -a /Applications/Textedit.app foo.txt). 당신이 후 탭을 누르면 /A의 /Applications후 다시 다음과 탭 /Te의 /Textedit.app다음가는대로 그것은 당신을 위해 두 부분을 자동으로 완성한다. 이상적이지는 않지만 인정하지만 어쩌면 더 좋습니다. 이것은 Bash를 사용하고있었습니다.
— binarybob

이 글의 끝 부분에있는 지침을 따라 시도해 볼 수도 있습니다 : brettterpstra.com/grabbing-a-mac-apps-icon-advanced-bash-usage-2
— Lri

@DanielBeck Bash.
— daviesgeek

답변:


9
_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

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


이 작업을 수행 할 수 없었습니다 DVD Player. 어떤 생각이 잘못 되었나요? 공백 대신 탭처럼 보입니다 ...
— Daniel Beck

@DanielBeck 누락되었습니다 IFS=$'\n'. 어쨌든, 나는 대답을 다시 편집했다.
— Lri February

좋아 보인다 mdfind아이디어에 대한 늦은 +1 . 최적화 및 수정 작업이 훌륭합니다. CoreServices아마 개인적인 취향 일 것입니다. 그 이유는 무엇입니까 nospace? 프로그램이 하나 뿐인 경우 파일을 열어서 바로 계속 진행하고 싶습니다. 개인적인 취향 만? 나머지 인용 문제에 대한 아이디어가 있습니까? AFAICT, 그것이 적절한 해결책을 위해 남겨진 유일한 것입니다.
— Daniel Beck

@DanielBeck 나는 항상 -a깃발을 끝에 놓았습니다. 그래서 나는 -o nospace개인적인 취향 일뿐입니다. 어쩌면 우리는 Brett Terpstra 또는 nerdfest를 끝내기 위해 무언가를 핑해야 할 것입니다.
— Lri

정말 고맙습니다!! @DanielBeck도 당신입니다. 속도 때문에 Lri 버전을 선택했습니다. 불행히도, 당신은 조금 느 렸습니다. 정말 고마워요! 당신은 저에게 많은 도움을 주었고 제 터미널 속도를 향상 시켰습니다.
— daviesgeek

7

다음을 추가 .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.


하지 않을까요 mdfind 'kMDItemKind==Application'빠르다? completion-ignore-case설정되어 있으면 grep은 대소 문자도 무시해야합니다.
— Lri February

@Lri 당신이 맞아요. 이러한 결과가 차이를 보인 사례를 찾을 수 없습니다.
— Daniel Beck

3

구조에 프로그램 가능한 자동 완성! 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

그래서 설치 지침에 따라 코드를 추가했습니다 .bashrc. 이제 자동 완성하려면 어떻게해야합니까? 자동 완성으로 무엇을 푸시합니까? (죄송합니다, 코드를 읽을 수 없습니다)
— daviesgeek

1
공백이있는 프로그램 이름 (예 :)을 처리하지 않습니다 DVD Player.app. 디렉토리 /Applications(예 : iWork 09, 개별 항목 iWork및 09)를 나열 하지만 여기에 포함 된 프로그램 은 나열 하지 않습니다.
— Daniel Beck

1

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

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

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.