Czy istnieje sposób na automatyczne wykonanie polecenia otwarcia w terminalu?

16

Często używam open -a polecenia w Terminalu, aby otwierać aplikacje przez ssh. Jak ustawić automatyczne uzupełnianie nazwy aplikacji?

daviesgeek
źródło
Jakiej powłoki używasz?
Daniel Beck
2
Wydaje mi się, że marginalnie szybszym sposobem byłoby wpisanie pełnej ścieżki (po prostu idź ze mną na chwilę tutaj !!), np. open -a /Applications/Textedit.app foo.txt(Zakładam, że to właśnie próbujesz zrobić). Jeśli naciśniesz Tab po /Az /Applications, a następnie ponownie po Tab /Tez /Textedit.apppotem, że obie części powinny uzupełni dla was jak przejść. Przyznaję, że nie jest idealna, ale może lepsza. To było za pomocą Bash.
binarybob
Możesz także postąpić
Lri
@DanielBeck Bash.
daviesgeek

Odpowiedzi:

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

Trzecia wersja, która powinna teraz zarówno rozróżniać wielkość liter, jak i działać w cudzysłowie.

Lri
źródło
Nie mogłem zmusić tego do pracy DVD Player. Jakieś pomysły, co jest nie tak? Wygląda jak tabulator zamiast spacji ...
Daniel Beck
@DanielBeck Brakowało IFS=$'\n'. W każdym razie ponownie zredagowałem odpowiedź.
Lri
Wygląda dobrze. Spóźniony +1 za mdfindpomysł. Niezła praca nad optymalizacją i poprawkami. CoreServicessą jednak prawdopodobnie osobistymi preferencjami. Jaki jest jednak powód nospace? Jeśli jest tylko 1 program, chcę od razu kontynuować otwieranie pliku. Po prostu osobiste preferencje? Masz pomysł na pozostały problem z cytowaniem? AFAICT, to jedyna rzecz, która pozostała do właściwego rozwiązania.
Daniel Beck
@DanielBeck Zawsze umieszczam -aflagę na końcu, więc myślę, że -o nospaceto tylko osobiste preferencje. Może powinniśmy pingować Bretta Terpstry lub coś, co zakończy ten nerdfest ...
Lri,
Dziękuję bardzo!! @DanielBeck you also. Wybrałem wersję Lri ze względu na szybkość. Niestety twój był trochę powolny. Dziękuję bardzo wam obu! Bardzo mi pomogłeś i zwiększyłeś prędkość mojego terminalu.
daviesgeek
7

Dodaj następujące elementy do swojego .bash_profilelub .bashrci uruchom nową sesję:

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

Nie musisz niczego instalować. Działa to od razu po bashwyjęciu z pudełka.


Będzie automatycznie uzupełniał nazwy programów tylko wtedy, gdy poprzednia opcja jest taka, -aa poza tym wykaże zachowanie domyślne, np. Zwróci listę wszystkich plików w bieżącym katalogu lub dokończy bieżący prefiks ścieżki.

Wyniki są generowane z system_profiler SPApplicationsDataType, co jest najprostszym sposobem na uzyskanie wszystkich aplikacji, które można w ten sposób uruchomić w systemie w ten sposób. Lista jest przetwarzana w celu zwrócenia tylko nazw programów, które mogą zawierać spacje i mogą różnić się od nazw pakietów (nawet przy ignorowaniu .appsufiksu)

Sposób użycia: Wpisz open -a, następnie spację, a następnie naciśnij Tablub Esc(dwa razy w moim systemie, nie jestem pewien, czy jest wszędzie).

Przykład pokazujący wszystkie aplikacje pomocnicze dla mojego skanera:

$ 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

Wady i problemy tego rozwiązania:

  • W twoim systemie jest mnóstwo programów, o których możesz nie wiedzieć, jak wszystko w twoim systemie /System/Library/CoreServices. Możesz nie chcieć wymienić wszystkich. OTOH, to naprawdę łatwo zobaczyć i uruchomić np CharacterPalettelub KeyboardViewerw ten sposób. * Skonfiguruj mdfindpołączenia odpowiednio z -onlyinargumentem.

  • To trochę powolne system_profiler SPApplicationsDataType. Być może trzeba poczekać sekundę lub dwie, zanim pojawi się zakończenie. Teraz używa mdfinddo szybkiego pobierania programów. Dzięki @Lri

  • Może obsługiwać spacje w nazwach aplikacji i nazwy programów w cudzysłowie, ale jest raczej hackerski. Wymaga to, aby cytat był pierwszym znakiem: dopóki Scan" to "Pjest ważny bash, ten program go nie wykryje. Uzupełnianie nie działa po spacji lub (np. Scan\ to), W takich przypadkach używaj cudzysłowów ( "Scan to). Pomoc dla zbiegłych przestrzeni jest tylko dobry, aby zakończyć DVDsię DVD\ Player.

Daniel Beck
źródło
Nie mdfind 'kMDItemKind==Application'byłoby szybciej? Jeśli completion-ignore-casejest włączony, grep powinien prawdopodobnie również ignorować wielkość liter.
Lri
@Lri Masz rację. Nie udało się znaleźć przypadku, w którym wyniki te miałyby znaczenie.
Daniel Beck
3

Programowalne autouzupełnianie na ratunek! Potrzebowałem dużo kopiowania ze strony głównej Bash Completion , którą i tak warto zainstalować, aby uzyskać dużo magii autouzupełniania. Jeśli to zrobisz, będziesz potrzebować tylko ostatniej funkcji ( _open) i polecenia inicjalizującego od dołu.

Dodaj następujące elementy .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/
    # [email protected]/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
nohillside
źródło
Postępowałem zgodnie z instrukcjami instalacji i dodałem kod do .bashrc. Teraz, jak mogę uzyskać autouzupełnianie? Co mam wcisnąć, aby autouzupełnianie? (Przepraszam, nie mogę odczytać kodu)
daviesgeek
1
Nie obsługuje nazw programów ze spacjami (jak DVD Player.app). Wyświetla również katalogi /Applications(jak iWork 09osobne wpisy iWorki 09), ale nie zawiera programów w nich zawartych.
Daniel Beck
1

Jest to domyślnie włączone w powłoce Zsh , o ile oczywiście masz włączone uzupełnianie. Zsh jest zawarty w OS X.

Wszystko, co musisz zrobić, to umieścić autoload -Uz compinit; compinitw swoim ~ / .zshrc lub włączyć uzupełnianie poprzez menu konfiguracji pierwszego uruchomienia.

Zsh to właściwie superset Bash, więc nie powinieneś się uczyć niczego nowego. Nawet twoje skrypty prawdopodobnie będą działać!

SilverWolf - Przywróć Monikę
źródło