Có cách nào để tự động hoàn thành lệnh mở trong Terminal không?


16

Tôi thường xuyên sử dụng open -a lệnh trong Terminal để mở các ứng dụng thông qua ssh. Làm cách nào để tôi tự động hoàn thành tên ứng dụng?


Bạn đang sử dụng vỏ gì?
Daniel Beck

2
Tôi đoán một cách nhanh hơn một chút sẽ là loại ra toàn bộ đường dẫn (chỉ cần đi với tôi một lúc ở đây !!), ví dụ open -a /Applications/Textedit.app foo.txt(tôi cho rằng đó là những gì bạn đang cố gắng làm). Nếu bạn nhấn Tab sau /Acủa /Applicationsvà sau đó Tab một lần nữa sau /Tecủa /Textedit.appsau đó rằng nên tự động hoàn thành cả hai phần cho bạn khi bạn đi. Không lý tưởng, tôi thừa nhận, nhưng có thể một nhưng tốt hơn. Đây là sử dụng Bash.
binarybob

Bạn cũng có thể thử làm theo các hướng dẫn ở cuối bài này: brettterpstra.com/grabbing-a-mac-apps-icon-advified-bash-usage-2
Lri

@DanielBeck Bash.
daviesgeek

Câu trả lời:


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

Phiên bản thứ ba, mà bây giờ cả hai không phân biệt chữ hoa chữ thường và hoạt động trong dấu ngoặc kép.


Tôi không thể làm việc này với DVD Player. Có ý kiến ​​gì sai không? Trông giống như một Tab thay vì một không gian ...
Daniel Beck

@DanielBeck Nó đã mất tích IFS=$'\n'. Dù sao, tôi đã chỉnh sửa câu trả lời một lần nữa.
Lri

Có vẻ tốt. +1 muộn cho mdfindý tưởng. Công việc tốt về tối ưu hóa và sửa lỗi. CoreServicescó lẽ là sở thích cá nhân mặc dù. Lý do cho nospacemặc dù là gì? Nếu chỉ có 1 chương trình, tôi muốn tiếp tục ngay lập tức với filen để mở. Chỉ là sở thích cá nhân? Bất kỳ ý tưởng về vấn đề trích dẫn còn lại? AFAICT, đó là điều duy nhất còn lại cho một giải pháp thích hợp.
Daniel Beck

@DanielBeck Tôi luôn đặt -acờ ở cuối, vì vậy tôi đoán -o nospacechỉ là một sở thích cá nhân. Có lẽ chúng ta nên ping Brett Terpstra hoặc một cái gì đó để hoàn thành nerdfest này ...
Lri

Cảm ơn bạn rất nhiều!! @DanielBeck bạn quá. Tôi chọn phiên bản của Lri vì tốc độ. Thật không may, bạn đã hơi chậm. Cảm ơn cả hai rất nhiều! Bạn đã giúp tôi rất nhiều và làm cho tốc độ thiết bị đầu cuối của tôi tăng lên.
daviesgeek

7

Thêm phần sau vào .bash_profilehoặc .bashrckhởi chạy phiên mới:

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

Không cần cài đặt gì cả. Điều này làm việc với bashra khỏi hộp.


Nó sẽ chỉ tự động hoàn thành tên chương trình nếu tùy chọn trước đó -avà mặt khác hiển thị hành vi mặc định, ví dụ: trả về danh sách tất cả các tệp trong thư mục hiện tại hoặc hoàn thành tiền tố đường dẫn hiện tại.

Các kết quả được tạo từ system_profiler SPApplicationsDataTypeđó, đây là cách dễ nhất để có được tất cả các ứng dụng có thể được khởi chạy theo cách này trên hệ thống của bạn như thế. Danh sách được xử lý để chỉ trả về tên chương trình, có thể chứa khoảng trắng và có thể khác với tên gói (ngay cả khi bỏ qua .apphậu tố)

Cách sử dụng: Nhập open -a, theo sau là khoảng trắng, sau đó nhấn Tabhoặc Esc(hai lần trên hệ thống của tôi, không chắc nó có ở mọi nơi không).

Ví dụ hiển thị tất cả các ứng dụng trợ giúp cho máy quét của tôi:

$ 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

Hạn chế và vấn đề của giải pháp này:

  • Có rất nhiều chương trình trên hệ thống của bạn mà bạn có thể không biết, như mọi thứ trong đó /System/Library/CoreServices. Bạn có thể không muốn liệt kê tất cả chúng. OTOH, thật dễ dàng để xem và khởi chạy, ví dụ CharacterPalettehoặc KeyboardViewertheo cách này. * Định cấu hình mdfind(các) cuộc gọi một cách thích hợp với -onlyinđối số.

  • Đó là loại chậm, do system_profiler SPApplicationsDataType. Bạn có thể phải đợi một hoặc hai giây trước khi hoàn thành xuất hiện. Bây giờ sử dụng mdfindđể nhanh chóng có được các chương trình. Cảm ơn @ Lri

  • Nó có thể xử lý các khoảng trắng trong tên ứng dụng và trích dẫn tên chương trình kèm theo, nhưng nó khá hack. Nó yêu cầu trích dẫn phải là ký tự đầu tiên: Mặc dù Scan" to "Pcó giá trị trong bashnhưng chương trình này sẽ không phát hiện ra nó. Hoàn thành không hoạt động sau khi một không gian thoát (ví dụ Scan\ to), sử dụng dấu ngoặc kép trong các trường hợp như vậy ( "Scan to). Hỗ trợ cho các không gian thoát là chỉ tốt để hoàn thành DVDđến DVD\ Player.


Sẽ không mdfind 'kMDItemKind==Application'nhanh hơn? Nếu completion-ignore-caseđược đặt trên, grep có lẽ cũng nên bỏ qua trường hợp.
Lri

@Lri Bạn nói đúng. Không thể tìm thấy một trường hợp trong đó những kết quả này sẽ tạo ra sự khác biệt.
Daniel Beck

3

Lập trình tự động hoàn thành để giải cứu! Cần rất nhiều bản sao từ Trang chủ Hoàn thành Bash , dù sao cũng đáng để cài đặt cho rất nhiều phép thuật tự động hoàn thành. Nếu bạn làm như vậy, bạn sẽ chỉ cần hàm cuối cùng ( _open) và lệnh khởi tạo từ bên dưới.

Thêm vào như sau .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

Vì vậy, tôi làm theo hướng dẫn cài đặt và thêm mã vào .bashrc. Bây giờ làm thế nào để tôi có thể tự động hoàn thành? Tôi phải làm gì để tự động hoàn thành? (Xin lỗi, tôi không thể đọc mã)
daviesgeek

1
Không xử lý tên chương trình có dấu cách (như DVD Player.app). Liệt kê các thư mục trong /Applications(như iWork 09, như các mục riêng biệt iWork09), nhưng không phải là các chương trình có trong đó.
Daniel Beck

1

Điều này được bật theo mặc định với trình bao Zsh , miễn là bạn đã tự bật hoàn thành. Zsh được bao gồm trong OS X.

Tất cả bạn phải làm là đặt autoload -Uz compinit; compinittrong ~ / .zshrc của bạn hoặc cho phép hoàn thành thông qua menu cấu hình chạy đầu tiên.

Zsh thực sự chủ yếu là siêu nhân của Bash, vì vậy bạn không cần phải học bất cứ điều gì mới. Ngay cả các kịch bản của bạn có thể sẽ làm việc!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.