Terminal'de open komutunu otomatik olarak tamamlamanın bir yolu var mı?


16

open -a Uygulamaları ssh aracılığıyla açmak için Terminal'deki komutu sık sık kullanıyorum . Bir uygulamanın adını otomatik olarak tamamlamasını nasıl sağlayabilirim?


Hangi kabuğu kullanıyorsun?
Daniel Beck

2
Marjinal olarak daha hızlı bir yol tam yolu yazmak için olurdu (sadece benimle bir süre burada gitmek !!), örneğin open -a /Applications/Textedit.app foo.txt(thats ne yapmaya çalışıyorum varsayalım). Peşinde Tab tuşuna basarsanız /Aait /Applicationssonra yeniden sonra ve Tab /Teait /Textedit.appo zaman ilerledikçe sizin için her iki bölümü otomatik olarak tamamlayacak gerekir. İdeal değil, itiraf ediyorum, ama belki bir ama daha iyi. Bu Bash kullanıyordu.
binarybob


@DanielBeck Bash.
daviesgeek

Yanıtlar:


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

Şimdi her ikisi de büyük / küçük harfe duyarsız ve tırnak içinde çalışması gereken üçüncü sürüm.


Bunu çalıştıramadım DVD Player. Yanlış olan herhangi bir fikir var mı? Boşluk yerine bir sekme gibi görünüyor ...
Daniel Beck

@DanielBeck Eksikti IFS=$'\n'. Her neyse, cevabı tekrar düzenledim.
Lri

İyi görünüyor. mdfindFikir için geç +1 . Optimizasyon ve düzeltmeler üzerinde güzel bir çalışma. CoreServicesmuhtemelen kişisel tercihtir. Bunun sebebi nospacene? Yalnızca 1 program varsa, dosya açılmaya hemen devam etmek istiyorum. Sadece kişisel tercihiniz mi? Kalan alıntı sorunu hakkında bir fikrin var mı? AFAICT, uygun bir çözüm için geriye kalan tek şey bu.
Daniel Beck

@DanielBeck -aBayrağı her zaman sonuna koydum , bu yüzden sanırım -o nospacesadece kişisel bir tercih. Belki Brett Terpstra ya da bu nerdfest bitirmek için bir şey ping gerekir ...
Lri

Çok teşekkür ederim!! @DanielBeck you you. Hız yüzünden Lri'nin versiyonunu seçtim. Ne yazık ki, seninki biraz yavaştı. İkinize de çok teşekkürler! Bana çok yardımcı oldun ve Terminal hızımı artırdın.
daviesgeek

7

Aşağıdakileri .bash_profileveya .bashrchesabınıza ekleyin ve yeni bir oturum başlatın:

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

Hiçbir şey kurmaya gerek yok. Bu bashkutudan çıkar çıkmaz çalışır .


Program adları yalnızca önceki seçenek olduğunda otomatik olarak tamamlanır -ave başka türlü varsayılan davranış gösterirse, örneğin geçerli dizindeki tüm dosyaların listesini döndürür veya geçerli yol önekini tamamlar.

Sonuçlar bu şekilde sisteminizde bu şekilde başlatılabilen tüm uygulamalarısystem_profiler SPApplicationsDataType almanın en kolay yoludur . Liste, yalnızca boşluk içerebilen ve paket adlarından farklı olabilen program adlarını döndürmek için işlenir ( sonek yoksayılsa bile ).app

Kullanım: yazın open -a, ardından bir boşluk bırakın ve ardından Tabveya tuşuna basın Esc(sistemimde iki kez, her yerde olduğundan emin değilim).

Tarayıcım için tüm yardımcı uygulamaları gösteren örnek:

$ 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

Bu çözümün sakıncaları ve sorunları:

  • Sisteminizde, bilmediğiniz her şey gibi tonlarca program var /System/Library/CoreServices. Hepsini listelemek istemeyebilirsiniz. OTOH, örneğin CharacterPaletteveya KeyboardViewerbu şekilde görmek ve başlatmak gerçekten çok kolay . * mdfindÇağrıları -onlyinbağımsız değişkenle uygun şekilde yapılandırın .

  • Nedeniyle biraz yavaş system_profiler SPApplicationsDataType. Tamamlama görünmeden önce bir iki saniye beklemeniz gerekebilir. Şimdi mdfindprogramları hızlı bir şekilde almak için kullanır . Teşekkürler @Lri

  • Uygulama adlarındaki boşlukları ve tırnak içine alınmış program adlarını işleyebilir, ancak oldukça hileli. Alıntı için ilk karakter olması gerekir: Scan" to "Piçinde geçerli olsa da bash, bu program onu ​​algılamaz. Tamamlanma, kaçan bir alandan sonra da çalışmaz (örneğin Scan\ to), bu gibi durumlarda tırnak işaretleri kullanın ( "Scan to). Kaçan alanlar için destek tamamlamak için sadece iyidir DVDiçin DVD\ Player.


Daha mdfind 'kMDItemKind==Application'hızlı olmaz mıydı ? Eğer completion-ignore-caseaçıksa, grep büyük olasılıkla da durumu görmezden gelmelidir.
Lri

@Lri Haklısın. Bu sonuçların bir fark yaratacağı bir durum bulunamadı.
Daniel Beck

3

Kurtarmaya programlanabilir otomatik tamamlama! Bash Tamamlama Ana Sayfasından bir sürü kopyalamaya ihtiyaç vardı , bu da otomatik tamamlama sihri için yine de yüklemeye değer. Bunu yaparsanız, yalnızca son fonksiyona ( _open) ve aşağıdan başlatma komutuna ihtiyacınız olacaktır .

Aşağıdakileri şuraya ekleyin .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

Bu yüzden kurulum talimatlarını izledim ve kodu ekledim .bashrc. Şimdi bunu otomatik tamamlamaya nasıl getirebilirim? Otomatik tamamlama için ne zorlayabilirim? (Üzgünüz, kodu okuyamıyorum)
daviesgeek

1
Boşluklu program adlarını işlemez (gibi DVD Player.app). Listeler de dizinleri /Applicationsde (gibi iWork 09, ayrı giriş olarak iWorkve 09) değil, programlar burada yer alan.
Daniel Beck

1

Bu gelir Zsh kabuğu ile varsayılan olarak etkin sürece kendisi tabii ki, etkin tamamlanmasını sahip olarak. Zsh, OS X'e dahildir.

Tek yapmanız gereken autoload -Uz compinit; compinit~ / .zshrc'nize koymak veya ilk çalıştırma yapılandırma menüsünden tamamlamayı etkinleştirmektir.

Zsh aslında Bash'in bir süper setidir, bu yüzden yeni bir şey öğrenmek zorunda kalmamalısınız. Senaryonuz bile işe yarayacaktır!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.