Avvio conciso dell'app per Mac OS dalla riga di comando

22

Svolgo una discreta quantità di lavoro nella riga di comando e mi trovo a definire molti alias del modulo:

alias skim='/Applications/Skim.app/Contents/MacOS/Skim'

C'è un modo per aggiungere magia in modo tale che la richiesta di eseguibile "foo" utilizzi automaticamente eseguibile /Applications/Foo.app/Contents/MacOS/Foo? Questo è su OS X 10.6.

(Sono consapevole che potrei fare open foo.pdf , ma Skim non è il lettore PDF predefinito, e mi piacerebbe una soluzione generale - in alcuni casi, non è appropriato impostare l'applicazione in questione come predefinita gestore del file.)

    
posta Reid 22.11.2010 - 21:46
fonte

4 risposte

10

Finalmente l'ho capito: Aggiungi questo al tuo .bash_profile

function foomagick() {
    rm -f ~/.foomagick.tmp
    ls /Applications/ | grep "\.app" | grep -v iWork | while read APP; do
        # clean it up                                                           
        a='echo $APP | sed s/\ //g';
        a='echo $a | sed s/\'//g';
        echo alias ${a%.*}="'open -a \"${APP%.*}\"'" >> ~/.foomagick.tmp
    done
    source ~/.foomagick.tmp
    rm ~/.foomagick.tmp  
}
foomagick()

Ora il seguente lavoro:

Skim # open Skim.app
Skim foo.pdf
FireFox http://google.com
FireFox google.com # ERROR. Looks for local file.

Modifica di Reid:

Ho implementato il precedente come uno script Python che rende gli script wrapper al posto degli alias. Dovrai inserire ~/bin/mankoffmagic nel tuo percorso. Se vuoi che i wrapper vengano aggiornati automaticamente, eseguilo regolarmente da cron o somesuch.

#!/usr/bin/python
#
# This script automagically updates a set of wrapper shell scripts in
# ~/bin/mankoffmagic which call Mac apps installed in /Applications.
#
# Inspired by mankoff's shell alias posted on apple.stackexchange.com; see:
# http://apple.stackexchange.com/questions/4240/concisely-starting-mac-os-apps-from-the-command-line/4257#4257
#
# Notes/Bugs:
#
# 1. Does not follow symlinks (aliases?)
#
# 2. Assumes that application names do not contain double-quotes.
#
# 3. Not very smart about finding the actual binary (it guesses). This is
# wrong sometimes, e.g. Firefox. Probably a deeper understanding of the app
# package structure would fix this.

import copy
import glob
import os
import os.path
import re

BINDIR = os.path.expandvars("$HOME/bin/mankoffmagic")
APP_RE = re.compile(r'(.*)\.app$')
STRIP_RE = re.compile(r'[\W_]+')

def main():
   # We aggressively delete everything already in BINDIR, to save the trouble
   # of analyzing what should stay
   for f in glob.glob("%s/*" % BINDIR):
      os.unlink(f)

   # Walk /Applications and create a wrapper shell script for each .app dir
   for (root, dirs, files) in os.walk("/Applications"):
      dirs_real = copy.copy(dirs)  # so we can manipulate dirs while looping
      for d in dirs_real:
         #print "checking %s" % os.path.join(root, d)
         m = APP_RE.search(d)
         if (m is not None):
            #print "Found " + m.group()
            dirs.remove(d)  # no need to recurse into app
            create_script(root, d, m.group(1))

def create_script(path, appdir, appname):
   # remove non-alphanumerics and downcase it
   wrapper = STRIP_RE.sub('', appname).lower()
   wrapper = os.path.join(BINDIR, wrapper)
   fp = open(wrapper, "w")
   # Twiddle the comments in the script depending on whether you want to
   # invoke the binary or use "open" -- the former lets you use any
   # command-line args, while the latter is more Mac-like (app puts itself in
   # the front, etc.)
   fp.write("""
#!/bin/sh
exec "%s/%s/Contents/MacOS/%s" "$@"
#open -a "%s" "$@"
""" % (path, appdir, appname, appname))
   fp.close()
   os.chmod(wrapper, 0700)


if (__name__ == "__main__"):
   main()
    
risposta data 23.11.2010 - 02:06
fonte
8

Non hai bisogno di niente di sofisticato, hai già la risposta. Prova:

open /Applications/Foo.app bar.pdf

in modifica

Alla luce dei commenti qui sotto, penso che la mia risposta sarebbe ancora relativamente simile ... Io farei una funzione che sovrascrive aperta, fa un pushd a /Applications , chiama /usr/bin/open $appName.app $args , fa un popd e restituisce.

Faccio schifo allo scripting di shell ma qualcosa di simile in basso che copre casi speciali e ti consente di utilizzare praticamente la stessa sintassi di Apple prevista per open. Mi piace mantenere il mio ambiente il più pulito possibile.

Sono sicuro che la sintassi provenga dallo spazio:

function open($appName, $args)
{
    #if we are calling open without a path like /Applications/TextEdit.app AND
    #    $appName ends in '.app'
    if (!hasParent($appName) && isApp($appName))
    {
        pushd /Applications
        /usr/bin/open ${appName}.app $args &
        popd
        return
    }
    #otherwise, use open as normal
    /usr/bin/open $appName $args
    return
}

alla seconda modifica

guardando il commento di @ mankoff sulla domanda originale, la maggior parte delle cose nella funzione sopra sarebbe probabilmente una perdita di tempo dato che potresti semplicemente usare open -a $appName . Quindi mankoff probabilmente ha la soluzione più semplice e dovrebbe cambiare il suo commento in una risposta;)

    
risposta data 23.11.2010 - 04:24
fonte
4

Ci sono due soluzioni che posso pensare:

Il modo più semplice : utilizzando il file Info.plist in ciascuna directory .app Contents , crea un indice del valore per le chiavi CFBundleExecutable. Quindi aggiungi un breve alias che chiami uno script (perl, python, qualsiasi cosa) con il nome di un eseguibile e gli argomenti che desideri passare.

Il tuo indice sarebbe una coppia di nomi eseguibili e percorsi per questi eseguibili. Dovresti scrivere uno script programmato ricorrente per tenerlo aggiornato.

Finirai per essere in grado di chiamare:

f foo file.txt

dove f è un alias di uno script che controlla il tuo indice per un eseguibile chiamato foo .

Tutto sommato, non molto lavoro per ottenere la funzionalità che desideri.

La via più difficile - Estendi la tua shell per integrare la gestione del suo errore command_not_found . In pratica implementeresti una funzionalità in stile method_missing di Ruby all'interno della shell che stai utilizzando. Quando è stato lanciato command_not_found , il tuo metodo controllerebbe i nomi eseguibili delle tue Applicazioni installate.

    
risposta data 23.11.2010 - 15:27
fonte
2

Apripista per il salvataggio:

osascript -e 'tell application "iTunes"' -e "activate" -e 'end tell'

Sostituisci il nome dell'applicazione con l'applicazione che vuoi avviare e il gioco è fatto. Ovviamente puoi renderlo una funzione di shell, se necessario:

function f() {
    osascript <<EOF
tell application "$1"
  activate
end tell
EOF
}

e usalo in questo modo:

f iTunes

Odio il applescript, ma a volte è utile, e credo che sia l'unico modo per indirizzare un'applicazione semplicemente per nome sulla riga di comando. Tutto il resto richiederà un percorso completo.

    
risposta data 23.11.2010 - 17:27
fonte

Leggi altre domande sui tag