C'è un modo per completare automaticamente il comando open in Terminal?


16

Uso frequentemente il open -a comando in Terminale per aprire applicazioni tramite SSH. Come faccio a completare automaticamente il nome di un'applicazione?


Che shell stai usando?
Daniel Beck,

2
Immagino che un modo leggermente più veloce sarebbe quello di scrivere l'intero percorso (basta venire con me per un po 'qui !!), ad esempio open -a /Applications/Textedit.app foo.txt(suppongo che sia quello che stai cercando di fare). Se premi Tab dopo il /Adi /Applicationse poi Tab nuovamente dopo il /Tedi, /Textedit.appquesto dovrebbe completare automaticamente entrambe le parti mentre procedi. Non è l'ideale, lo ammetto, ma forse un ma migliore. Questo stava usando Bash.
binarybob,

Puoi anche provare a seguire le istruzioni alla fine di questo post: brettterpstra.com/grabbing-a-mac-apps-icon-advanced-bash-usage-2
Lri

@DanielBeck Bash.
daviesgeek,

Risposte:


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

Terza versione, che ora dovrebbe essere sensibile al maiuscolo / minuscolo e funzionare tra virgolette.


Non riuscivo a farlo funzionare DVD Player. Qualche idea di cosa c'è che non va? Sembra una scheda invece di uno spazio ...
Daniel Beck,

@DanielBeck Mancava IFS=$'\n'. Comunque, ho modificato di nuovo la risposta.
Lri,

Sembra buono. Un +1 in ritardo per l' mdfindidea. Bel lavoro sull'ottimizzazione e le correzioni. CoreServicessono probabilmente preferenze personali però. Qual è la ragione per cui nospace? Se c'è solo 1 programma, voglio continuare subito con l'apertura del file. Solo preferenze personali? Qualche idea sul problema di quotazione rimanente? AFAICT, questa è l'unica cosa rimasta per una soluzione adeguata.
Daniel Beck,

@DanielBeck Metto sempre la -abandiera alla fine, quindi immagino -o nospacesia solo una preferenza personale. Forse dovremmo fare un ping a Brett Terpstra o qualcosa del genere per finire questo nerdfest ...
Lri,

Grazie mille!! @DanielBeck anche a te. Ho scelto la versione di Lri per via della velocità. Sfortunatamente, il tuo è stato un po 'lento. Grazie mille a tutti e due! Mi hai aiutato molto e hai aumentato la velocità del mio terminale.
daviesgeek,

7

Aggiungi quanto segue a .bash_profileo .bashrce avvia una nuova sessione:

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

Non è necessario installare nulla. Funziona con bashout of the box.


Completerà automaticamente i nomi dei programmi solo se l'opzione precedente è -ae mostra in altro modo il comportamento predefinito, ad esempio restituisce un elenco di tutti i file nella directory corrente o completa il prefisso del percorso corrente.

I risultati sono generati da system_profiler SPApplicationsDataType, che è il modo più semplice per ottenere tutte le applicazioni che possono essere avviate in questo modo sul proprio sistema in quel modo. L'elenco viene elaborato per restituire solo i nomi dei programmi, che possono contenere spazi e possono essere diversi dai nomi dei pacchetti (anche quando si ignora il .appsuffisso)

Utilizzo: digita open -a, seguito da uno spazio, seguito da premendo Tabo Esc(due volte sul mio sistema, non sono sicuro che sia ovunque).

Esempio che mostra tutte le applicazioni di supporto per il mio scanner:

$ 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

Svantaggi e problemi di questa soluzione:

  • Ci sono tonnellate di programmi sul tuo sistema di cui potresti non essere a conoscenza, come ogni cosa /System/Library/CoreServices. Potresti non voler elencarli tutti. OTOH, è davvero facile vedere e lanciare ad esempio CharacterPaletteo in KeyboardViewerquesto modo. * Configurare le mdfindchiamate in modo appropriato con l' -onlyinargomento.

  • È un po 'lento, a causa di system_profiler SPApplicationsDataType. Potrebbe essere necessario attendere un secondo o due prima che venga visualizzato il completamento. Ora utilizza mdfindper ottenere rapidamente i programmi. Grazie @Lri

  • Può gestire spazi nei nomi delle applicazioni e tra i nomi dei programmi racchiusi tra virgolette, ma è piuttosto confuso. Richiede che la citazione sia il primo carattere: mentre Scan" to "Pè valido in bash, questo programma non lo rileverà. Il completamento non funziona neanche dopo uno spazio di escape (ad es. Scan\ to), Utilizzare le virgolette in questi casi ( "Scan to). Il supporto per gli spazi sfuggiti è buono solo per completare DVDa DVD\ Player.


Non mdfind 'kMDItemKind==Application'sarebbe più veloce? Se completion-ignore-caseimpostato, grep dovrebbe probabilmente ignorare anche il caso.
Lri,

@Lri hai ragione. Impossibile trovare un caso in cui questi risultati avrebbero fatto la differenza.
Daniel Beck,

3

Completamento automatico programmabile in soccorso! Avevo bisogno di molte copie dalla homepage di completamento di Bash , che vale comunque la pena installare per un sacco di magia di completamento automatico. Se lo fai, avrai solo l'ultima funzione ( _open) e il comando di inizializzazione dal basso.

Aggiungi quanto segue a .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

Quindi ho seguito le istruzioni di installazione e ho aggiunto il codice a .bashrc. Ora come ottengo il completamento automatico? Cosa devo spingere per il completamento automatico? (Mi dispiace, non riesco a leggere il codice)
daviesgeek

1
Non gestisce i nomi dei programmi con spazi (come DVD Player.app). Elenca anche le directory /Applications(come iWork 09, come voci separate iWorke 09), ma non i programmi in esse contenuti.
Daniel Beck,

1

Questo viene abilitato di default con la shell Zsh , purché tu abbia il completamento stesso abilitato, ovviamente. Zsh è incluso in OS X.

Tutto quello che devi fare è inserire il autoload -Uz compinit; compinittuo ~ / .zshrc o abilitare il completamento attraverso il menu di configurazione della prima esecuzione.

Zsh è in realtà principalmente un superset di Bash, quindi non dovresti imparare nulla di nuovo. Anche i tuoi script probabilmente funzioneranno!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.