web-dev-qa-db-fra.com

Lancez Terminal.app par programme avec une commande spécifiée (et des couleurs personnalisées)

Je peux lancer un xterm depuis la ligne de commande (ou un programme, via un appel système) comme ceci:

/usr/X11/bin/xterm -fg SkyBlue -bg black -e myscript

Cela lancera un xterm avec du texte bleu et un fond noir, et exécutera un script arbitraire à l'intérieur.

Ma question: comment faire l'équivalent avec Terminal.app?

27
dreeves

En supposant que vous ayez déjà les couleurs que vous souhaitez dans l'un de vos profils de terminal, voici ce que j'ai trouvé (avec l'aide de réponse de Juha et de cette réponse Serverfault ).


Mise à jour:

Après réflexion, je pense que cette activité echo est trop compliquée. Il s'avère que vous pouvez utiliser osascript pour créer un fichier exécutable AppleScript avec une ligne Shebang:

#!/usr/bin/osascript                                                                            

on run argv                                                                                     
  if length of argv is equal to 0                                                               
    set command to ""                                                                           
  else                                                                                          
    set command to item 1 of argv                                                               
  end if                                                                                        

  if length of argv is greater than 1                                                           
    set profile to item 2 of argv                                                               
    runWithProfile(command, profile)                                                            
  else                                                                                          
    runSimple(command)                                                                          
  end if                                                                                        
end run                                                                                         

on runSimple(command)                                                                           
  tell application "Terminal"                                                                   
    activate                                                                                    
    set newTab to do script(command)                                                            
  end tell                                                                                      
  return newTab                                                                                 
end runSimple                                                                                   

on runWithProfile(command, profile)                                                             
  set newTab to runSimple(command)                                                              
  tell application "Terminal" to set current settings of newTab to (first settings set whose name is profile)                                                                                      
end runWithProfile

Enregistrez-le sous term.scpt, rendez-le exécutable avec chmod +x, et utilisez-le de la même manière que ci-dessous, par ex. term.scpt "emacs -nw" "Red Sands".


Réponse originale:

En supposant que nous sauvegardions le script ci-dessous sous term.sh...

#!/bin/sh

echo '
on run argv
  if length of argv is equal to 0
    set command to ""
  else
    set command to item 1 of argv
  end if

  if length of argv is greater than 1
    set profile to item 2 of argv
    runWithProfile(command, profile)
  else
    runSimple(command)
  end if
end run

on runSimple(command)
  tell application "Terminal"
    activate
    set newTab to do script(command)
  end tell
  return newTab
end runSimple

on runWithProfile(command, profile)
  set newTab to runSimple(command)
  tell application "Terminal" to set current settings of newTab to (first settings set whose name is profile)
end runWithProfile
' | osascript - "$@" > /dev/null

... il peut être invoqué comme suit:

  • term.sh
    • ouvre une nouvelle fenêtre de terminal, rien de spécial
  • term.sh COMMAND
    • ouvre une nouvelle fenêtre de terminal, exécutant la commande spécifiée. Les commandes avec des arguments peuvent être placées entre guillemets, par ex. term.sh "emacs -nw" pour ouvrir un nouveau terminal et exécuter emacs (sans fenêtre)
  • term.sh COMMAND PROFILE
    • ouvre une nouvelle fenêtre de terminal, exécute la commande spécifiée et la définit sur le profil spécifié. Les profils avec des espaces dans leurs noms peuvent être placés entre guillemets, par ex. term.sh "emacs -nw" "Red Sands" pour ouvrir un nouveau terminal et exécuter emacs (sans fenêtre) avec le profil Red Sands.

Si vous l'appelez avec un mauvais nom de commande, il ouvrira toujours la fenêtre et définira le profil, mais vous obtiendrez le message d'erreur de bash dans la nouvelle fenêtre.

Si vous l'invoquez avec un nom de profil incorrect, la fenêtre s'ouvrira toujours et la commande sera toujours exécutée mais la fenêtre restera avec le profil par défaut et vous obtiendrez un message d'erreur (à stderr où que vous l'avez lancé) du type

525: 601: erreur d'exécution: le terminal a obtenu une erreur: impossible d'obtenir le jeu de paramètres 1 dont le nom = "elvis". Index invalide. (-1719)

L'appel est légèrement hacky et pourrait probablement être amélioré si je prenais le temps d'apprendre getopt (par exemple, quelque chose comme term.sh -p profile -e command serait mieux et vous permettrait, par exemple, d'ouvrir facilement un nouveau terminal dans le profil spécifié sans appeler de commande). Et je ne serais pas non plus surpris s'il existe des moyens de tout gâcher avec des citations complexes. Mais cela fonctionne dans la plupart des cas.

13
David Moles

Vous pouvez également ouvrir une application par identifiant de bundle et donner d'autres paramètres.

S'il y a un script exécutable test.sh dans le répertoire actuel, la commande suivante s'ouvrira et l'exécutera dans Terminal.app

 open -b com.Apple.terminal test.sh 

Le seul inconvénient que je peux trouver est que Terminal ne semble pas hériter de votre environnement actuel, vous devrez donc organiser une autre façon de transmettre les paramètres au script que vous souhaitez exécuter. Je suppose que construire le script à la volée pour intégrer les paramètres serait une approche (en tenant compte des implications de sécurité bien sûr ...)

22
Sam Deane

Presque tous (tous?) Les programmes osx peuvent être lancés à partir de la ligne de commande en utilisant:

appName.app/Contents/MacOS/command

Pour le terminal, la commande est:

/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal

Vous pouvez utiliser la saisie semi-automatique (tabulation) ou ls pour trouver les noms de fichiers corrects. ".app" est essentiellement un dossier.

Pour changer les couleurs et exécuter un script ... Je pense que vous ne pouvez pas le faire avec les scripts Shell car Terminal n'accepte pas les arguments ("Terminal myScript.sh" ne lance pas myScript). Avec iTerm, cela fonctionne.

La solution de contournement consiste à utiliser applescript (enveloppé dans un script Shell):

   #!/bin/sh
   osascript -e '
     tell application "Terminal"
       activate
       tell window 1
          do script "sleep 5; exit"
          set background color to {0, 11111, 11111}
          set win_id to id
       end tell

       set w_ids to (id of every window)

       repeat while w_ids contains win_id
         delay 1
         set w_ids to (id of every window)
       end repeat
    end tell'

Ok, maintenant il devrait se comporter exactement de la même manière que l'exemple xterm. L'inconvénient est l'interrogation constante des identifiants de fenêtre (ce qui est une mauvaise programmation).

edit: Applescript un peu plus élégant utiliserait la propriété 'busy' de Terminal. Je laisserai le code original tel quel pour un programme général (pas seulement un terminal).

tell application "Terminal"
    tell window 1
        do script "sleep 2"
        set background color to {0, 11111, 11111}
        repeat while busy
            delay 1
        end repeat
        close
    end tell
end tell

Aussi pour un programme parfaitement correct, il faut vérifier que le terminal fonctionne ou non. Cela affecte le nombre de fenêtres ouvertes. Donc, cela devrait être exécuté en premier (encore une fois un hack d'aspect méchant, que je modifierai plus tard lorsque je trouverai une solution qui fonctionne).

tell application "System Events"
    if (count (processes whose name is "Terminal")) is 0 then
        tell application "Terminal"
            tell window 1
                close
            end tell
        end tell
    end if
end tell

br,
Juha

13
Juha

Vous pouvez également accéder à l'interface graphique du terminal, configurer complètement les options à votre guise, et les exporter vers un fichier ".terminal", et/ou regrouper les configurations dans un groupe de fenêtres et l'exporter vers un fichier de terminal "myGroup.terminal" . ensuite

ouvrez myGroup.terminal

ouvrira le (s) terminal (s) à la fois, avec tous vos paramètres et commandes de démarrage configurés.

4
jerseyboy

La réponse de @ david-moles ci-dessus fonctionne mais exécutez le terminal et la commande dans ~ plutôt que dans le répertoire de travail actuel où term a été lancé. Cette variante ajoute une commande cd.

#!/usr/bin/env bash
# based on answer by @david-moles in 
# https://stackoverflow.com/questions/4404242/programmatically-launch-terminal-app-with-a-specified-command-and-custom-colors
echo "
on run argv
  if length of argv is equal to 0
    set command to \"\"
  else
    set command to item 1 of argv
  end if
  set command to \"cd '"$PWD"' ;\" & command
  if length of argv is greater than 1
    set profile to item 2 of argv
    runWithProfile(command, profile)
  else
    runSimple(command)
  end if
end run

on runSimple(command)
  tell application \"Terminal\"
    activate
    set newTab to do script(command)
  end tell
  return newTab
end runSimple

on runWithProfile(command, profile)
  set newTab to runSimple(command)
  tell application \"Terminal\" to set current settings of newTab to (first settings set whose name is profile)
end runWithProfile
" | osascript - "$@" > /dev/null

Il peut y avoir un moyen de définir ce paramètre PWD avec applescript.

Remarque: lorsque j'utilise ceci, j'ai parfois deux fenêtres de terminal, une un Shell fonctionnant dans ~ et une seconde qui exécute la commande cd et la commande d'argv [1]. Semble se produire si le terminal n'est pas déjà en cours d'exécution; peut-être qu'il ouvre l'ancien état (même si je n'avais pas de terminaux ouverts lorsque je l'ai fermé).

1
djb

vous pouvez lancer le terminal avec la commande suivante, sans savoir comment spécifier les couleurs:

 open /Applications/Utilities/Terminal.app/
1
jhuebsch