¿Hay alguna manera de completar automáticamente el comando de apertura en la Terminal?

16

Con frecuencia uso el open -a comando en la Terminal para abrir aplicaciones a través de ssh. ¿Cómo hago para que se complete automáticamente el nombre de una aplicación?

daviesgeek
fuente
¿Qué caparazón estás usando?
Daniel Beck
2
Supongo que una forma marginalmente más rápida sería escribir el camino completo (¡solo ve conmigo por un tiempo aquí!), Por ejemplo open -a /Applications/Textedit.app foo.txt(supongo que eso es lo que estás tratando de hacer). Si presiona Tab después de /Aof /Applicationsy luego Tab nuevamente después de /Teof, /Textedit.appentonces eso debería completar automáticamente ambas partes a medida que avanza. No es ideal, lo admito, pero tal vez sea mejor. Esto estaba usando Bash.
binarybob
También puede intentar seguir las instrucciones al final de esta publicación: brettterpstra.com/grabbing-a-mac-apps-icon-advanced-bash-usage-2
Lri
@DanielBeck Bash.
daviesgeek

Respuestas:

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

Tercera versión, que ahora debe ser insensible a mayúsculas y minúsculas y trabajar entre comillas.

Lri
fuente
No pude hacer que esto funcione DVD Player. Alguna idea de lo que está mal? Parece una pestaña en lugar de un espacio ...
Daniel Beck
@DanielBeck Faltaba IFS=$'\n'. De todos modos, edité la respuesta nuevamente.
Lri
Se ve bien. Un +1 tardío para la mdfindidea. Buen trabajo en la optimización y correcciones. CoreServicesson probablemente preferencias personales sin embargo. Sin nospaceembargo, ¿ cuál es la razón ? Si solo hay 1 programa, quiero continuar de inmediato con el archivo para abrir. ¿Solo preferencia personal? ¿Alguna idea sobre el problema de cotización restante? AFAICT, eso es lo único que queda para una solución adecuada.
Daniel Beck
@DanielBeck Siempre pongo la -abandera al final, así que supongo que -o nospacees solo una preferencia personal. Tal vez deberíamos hacer ping a Brett Terpstra o algo para terminar este nerdfest ...
Lri
¡¡Muchas gracias!! @DanielBeck también. Elegí la versión de Lri debido a la velocidad. Desafortunadamente, el tuyo fue un poco lento. Muchas gracias a los dos! Me has ayudado mucho y has hecho que aumente la velocidad de mi Terminal.
daviesgeek
7

Agregue lo siguiente a su .bash_profileo .bashrce inicie una nueva sesió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

No es necesario instalar nada. Esto funciona bashfuera de la caja.


Solo completará automáticamente los nombres de los programas si la opción anterior es -ay mostrará el comportamiento predeterminado, por ejemplo, devolverá una lista de todos los archivos en el directorio actual o completará el prefijo de ruta actual.

Los resultados se generan a partir de system_profiler SPApplicationsDataType, que es la forma más fácil de obtener todas las aplicaciones que se pueden iniciar de esta manera en su sistema de esa manera. La lista se procesa para devolver solo los nombres de programa, que pueden contener espacios y pueden ser diferentes de los nombres de paquete (incluso si se ignora el .appsufijo)

Uso: Escriba open -a, seguido de un espacio, seguido de presionar Tabo Esc(dos veces en mi sistema, no estoy seguro si está en todas partes).

Ejemplo que muestra todas las aplicaciones auxiliares para mi escáner:

$ 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

Inconvenientes y problemas de esta solución:

  • Hay toneladas de programas en su sistema que quizás no conozca, como todo lo que contiene /System/Library/CoreServices. Es posible que no desee enumerarlos a todos. OTOH, es realmente fácil de ver y ejecutar, por ejemplo, CharacterPaletteo de KeyboardVieweresta manera. * Configure las mdfindllamadas apropiadamente con el -onlyinargumento.

  • Es un poco lento, debido a system_profiler SPApplicationsDataType. Es posible que deba esperar uno o dos segundos antes de que aparezca la finalización. Ahora se utiliza mdfindpara obtener rápidamente los programas. Gracias @Lri

  • Puede manejar espacios en nombres de aplicaciones y nombres de programas entre comillas, pero es bastante hacky. Requiere que la cita sea el primer carácter: aunque Scan" to "Pes válido bash, este programa no lo detectará. La finalización tampoco funciona después de un espacio escapado (p Scan\ to. Ej. ), Utilice comillas en tales casos ( "Scan to). Soporte para espacios escapado sólo es bueno para completar DVDa DVD\ Player.

Daniel Beck
fuente
¿No mdfind 'kMDItemKind==Application'sería más rápido? Si completion-ignore-caseestá activado, grep probablemente también debería ignorar el caso.
Lri
@Lri Tienes razón. No se pudo encontrar un caso en el que estos resultados hubieran marcado una diferencia.
Daniel Beck
3

¡Autocompletado programable al rescate! Sin embargo, necesitaba mucha copia de la página de inicio de Bash Completion , que vale la pena instalar de todos modos para obtener mucha magia de autocompletado. Si lo hace, solo necesitará la última función ( _open) y el comando de inicialización a continuación.

Agregue lo siguiente 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/
    # [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
fuente
Así que seguí las instrucciones de instalación y agregué el código .bashrc. Ahora, ¿cómo consigo que se complete automáticamente? ¿Qué presiono para autocompletar? (Lo siento, no puedo leer el código)
daviesgeek
1
No maneja nombres de programas con espacios (como DVD Player.app). Enumera también los directorios /Applications(como iWork 09, como entradas separadas iWorky 09), pero no los programas contenidos en ellos.
Daniel Beck
1

Esto viene habilitado de forma predeterminada con el shell Zsh , siempre que tenga la terminación habilitada, por supuesto. Zsh está incluido en OS X.

Todo lo que tiene que hacer es poner autoload -Uz compinit; compinitsu ~ / .zshrc, o habilitar la finalización a través del menú de configuración de la primera ejecución.

Zsh es en realidad un superconjunto de Bash, por lo que no debería tener que aprender nada nuevo. ¡Incluso tus guiones probablemente funcionarán!

SilverWolf - Restablece a Monica
fuente