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


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, 개별 항목 iWork09)를 나열 하지만 여기에 포함 된 프로그램 은 나열 하지 않습니다.
Daniel Beck

1

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

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

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

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