Articles

Mac

AppleScript: encore plus loin dans le script de fermeture des applis !

Par Didier Pulicani - Publié le

Ce que nous voulons faire...



Ce script a pour but de quitter tout simplement toutes les applications.Seulement nous allons l' enrichir un peu ou ce serait l' affaire de quelques lignes de code et ne nécessiterait pas un article complet.Rajoutons donc un dialogue de confirmation et un système permettant de définir les applications à garder (dont le Finder devra faire partie !)

Le script se composera donc de deux parties, une permettant de définir les options et l' autre quittant les applications.

Nous aurons besoin des Osax "Sändi's Additions", "Dialog Director" et "AkuaSweets" (que je vous invite fortement à utiliser pour vos propres scripts, car il est excellent, soit dit en passant...)

Le Script



Comme le script est relativement long, je vous conseille d'utiliser un format AppleScript coloré pour mieux s'y retrouver.Voici les détails du format:

(police - taille - style - couleur)
texte non compilé: Courier - 10 - normal - noir
texte normal: Geneva - 10 - gras  -noir
mots clés: Geneva - 10 - gras - rouge
terme des applications: Geneva - 10 - normal - bleu clair
commentaires: Geneva - 9 - italique - noir
valeurs: Helvetica - 10 - normal - noir
variables: Geneva - 10 - normal - bleu foncé
références: Geneva - 10 - normal - noir


Et voilà le script :


property Apps_a_garder : {"Finder"}
property AskBeforeQuit : true

on run
	if (CommandIsDown) is true then set AskBeforeQuit to true
	set TheProcesses to (all processes without background only)
	set |app| to ((all processes with currency) as text)
	
	if AskBeforeQuit is true then
		set |Dialog| to {size:{378, 120}, style:standard dialog, default item:3, contents:{¬
			{class:icon, bounds:{16, 8, 48, 40}, contents:1}, ¬
			{class:static text, bounds:{64, 8, 364, 40}, contents:"Êtes-vous sur de vouloir quitter toutes les applications lancées ?"}, ¬
			{class:push button, bounds:{292, 88, 362, 108}, name:"OK"}, ¬
			{class:push button, bounds:{212, 88, 282, 108}, name:"Annuler"}, ¬
			{class:push button, bounds:{50, 88, 202, 108}, name:"Applications à garder"}, ¬
			{class:check box, bounds:{64, 60, 200, 76}, name:"Ne plus afficher", value:false, font:{name:"Geneva", size:10}}}}
		
		dd auto dialog |Dialog| with fonts {name:"Charcoal", size:12} with grayscale
		set {OK, Annuler, DefApps, NoAsk} to (items 3 thru 6 of the result)
		
		if Annuler is true then
			return
			
		else if OK is true then
			if NoAsk is true then set AskBeforeQuit to false
			
		else if DefApps is true then
			--afficher le dialogue de définition des apps à garder
			set theDialog to {size:{303, 182}, style:movable dialog, name:"Applications à garder", default item:7, contents:{¬
				{class:icon, bounds:{16, 8, 48, 40}, contents:1}, ¬
				{class:static text, bounds:{60, 8, 260, 40}, contents:"Ces applications ne seront pas quittées par le script:"}, ¬
				{class:list box, bounds:{48, 60, 180, 135}, contents:Apps_a_garder}, ¬
				{class:push button, bounds:{204, 60, 284, 80}, name:"Ajouter"}, ¬
				{class:push button, bounds:{204, 92, 284, 112}, name:"Supprimer", enabled:3}, ¬
				{class:push button, bounds:{114, 153, 194, 173}, name:"Annuler"}, ¬
				{class:push button, bounds:{204, 153, 284, 173}, name:"OK"}}}
			
			dd install with fonts {name:"Charcoal", size:12} with grayscale
			set d to dd make dialog theDialog
			repeat
				set i to dd interact with user
				
				if i = 4 then
					set PList to collect items of TheProcesses that match |app| with just contents and negation
					set dlog to {size:[220, 220], name:"Ajouter Application", style:movable dialog, contents:{¬
						{class:static text, bounds:{10, 5, 210, 26}, contents:"Applications lancées :"}, ¬
						{class:list box, bounds:[10, 30, 210, 172], contents:PList}, ¬
						{class:push button, bounds:[150, 190, 210, 210], name:"Ajouter", enabled:2}, ¬
						{class:push button, bounds:{20, 190, 140, 210}, name:"Autre application"}}}
					
					set {LApp, Add, CApp} to (items 2 thru 4 of (dd auto dialog dlog with fonts {name:"Charcoal", size:12} with grayscale))
					
					if CApp is true then --on fait choisir une application
						
						repeat
							set LeFile to (choose file with prompt "Choisissez une application :")
							tell application "Finder"
								if LeFile's original item exists then
									set LeFile to LeFile's original item
								end if
								try
									get suggested size of LeFile
									set AppleScript's text item delimiters to ":"
									set theApp to (last text item of (LeFile as text))
									set AppleScript's text item delimiters to " "
									exit repeat
								on error number ErrNumber
									if ErrNumber = -1728 then
										display dialog "Le Fichier choisi n' est pas une application" with icon caution buttons {"OK"} default button 1
									end if
								end try
							end tell
						end repeat
						
					else if Add is true then
						set theApp to item LApp of PList
						
					end if
					
					if theApp is not in Apps_a_garder then
						set Apps_a_garder to Apps_a_garder & theApp
						dd set contents of item 3 of d to Apps_a_garder
					end if
					
				else if i = 5 then
					set theApp to item (dd get value of item 3 of d) of Apps_a_garder
					set Apps_a_garder to (collect items of Apps_a_garder that match theApp with just contents and negation)
					dd set contents of item 3 of d to Apps_a_garder
					
				else if i = 6 then
					return
					
				else if i = 7 then
					exit repeat
					
				end if
			end repeat
			dd delete d
			dd uninstall
		end if
		
	end if
	
	repeat with |process| in TheProcesses
		
		if |process| is not in Apps_a_garder and |process| != |app| then
			
			tell application |process|
				activate
				quit
			end tell
			
		end if
		
	end repeat
end run


L' Explication !



Les deux property définissent, pour la première, les applications qui ne seront pas quittées par le script et pour la deuxième, l' affichage ou non du dialogue de confirmation.Si vous ne mettez aucune application dans la première, elles seront toutes quittées puis le Finder sera relançé.

Ensuite, il nous faut un dialogue de confirmation pour éviter de tout quitter par inadvertance, tout en laissant une option pour ne plus afficher le dialogue.Seulement quand on a demandé à ce qu' il ne s' affiche plus et qu' on veut le rafficher,il faut prévoir quelquechose pour qu' il s' affiche quand même (relisez cette phrase lentement si vous n' avez pas tout compris...)
C' est le role du CommandIsDown.Concrétement si vous appuyez sur commande, le dialogue s' affichera (par l' intermédiaire de la variable AskBeforeQuit).

Les deux premières lignes servent à définir deux variables qui serviront pour tout le script, contenant respectivement la liste des applications lancées et le nom du script grace à une commande d' AkuaSweets:

all processes: Check for a running process by name or creator - or get a list of all processes.
	all processes
		[named  string]  -- Filter processes with this name.
		[whose creators are  string]  -- Four letter creator
		[background only  boolean]  -- Include background (default is TRUE). Specify TRUE to get only background apps.
		[pending notifications  boolean]  -- Only return process with a notification pending.
		[as  type class]  -- The kind of result you want. You can use string (names of apps), integer (process numbers), file (paths to the apps), aliases (ditto), applications or Process Infos.
		[currency  boolean]  -- Just return the current process.
	Result:   a list of string  -- A list of processes that match your criteria.

Après vient toute une grosse partie qui sert à afficher le dialogue de confirmation et à définir les applications à garder sans mettre les mains dans le cambouis.Pour y voir plus clair, la structure du script est très simple:

--properties

on run
--3 lignes de commandes vues plus haut

if AskBeforeQuit is true then
--partie de définition des applications
end if

--partie quittant les applications
end run


Entrons dans la grosse partie...



On commence par définir un dialogue avec DialogDirector.Si vous n' êtes pas familier de cet Osax (j' essaierai de faire un article dessus), sachez juste qu' il permet de faire des dialogues complexes et que la variable theDialog est tout simplement un record qui contient les propriétés du dialogue.Je vous laisse aller voir son dictionnaire pour plus de précisions et pour toutes les autres commandes dont nous aurons besoin.
Puis on affiche ce dialogue avec dd auto dialog:

AppleScript: encore plus loin dans le script de fermeture des applis !


Cette commande renvoie une liste comme résultat dans laquelle nous prennons ce qui nous intéresse (Bouton choisi et checkbox cochée ou pas)

Là on arrive dans un grand if qui dépend du bouton choisi.Les deux cas les plus simples sont les premiers:
Si on a choisi "Annuler", on ... annule ! (le script s' arrête donc)
Si on a choisi "OK" et que la checkbox est cochée, on met la variable d' affichage du dialogue à false et on continue.

Si on a choisi "Applications à garder", là c' est plus compliqué, il faut afficher des dialogues:
On définit le dialogue comme tout à l' heure mais on va utiliser une méthode différente pour l' afficher: les trois commandes dd install, dd make dialog et dd interact with user.

La première initialise l' environnement.
La deuxième crée le dialogue (la variable d est la référence à ce dialogue)
La troisième permet à l' utilisateur d' interagir avec le dialogue (i désigne l' action effectuée)

Cette méthode est légèrement différent de dd auto dialog car elle permet plus d' interaction.Voici son résultat:

AppleScript: encore plus loin dans le script de fermeture des applis !


La commande d' interacton nécessite plus d' attention que les autres car elle est plus complexe.Nous allons l' examiner rapidement.

Tout d' abord, il faut l' encapsuler dans un repeat pour pouvoir interagir plusieurs fois !
La variable i contiendra un entier désignant l' élément du dialogue sur lequel on a cliqué (ou autre)
Nous n' allons définir le comportement à suivre que pour les quatres boutons (c' est inutile pour les autres éléments)
Le plus compliqué étant le bouton ajouter (i=4), nous le verrons en dernier.

Si on clique sur "Supprimer" (possible seulement si un élément de la liste est séléctionné grace au enabled:3 dans la description du bouton), il faut enlever l' élément de la liste à la fois sur l' écran et en property.
La commande dd get value permet de savoir quel élément est séléctionné et on le met dans la variable theApp.
Ensuite on va l' enlever de la liste Apps_a_garder grace à une autre commmande d' AkuaSweets: collect items.Cette commande permet d' enlever un élément d' une liste par son contenu ou au contraire de ne garder que lui.Pour la syntaxe exacte, voilà le dictionnaire:


collect items of: Get item offsets and contents that match an expression.
	collect items of  a list of string  -- A list of text items to search.
		that match  string  -- A string (or list of strings to be “OR’d”) that defines what to find.
% Toggles case
$ Toggles early-end-allow
+ Any one character
[c n chars until c
/c Absolute c comparison
(cde) Any of c, d or e
&xcyd Where x & y are one of (>,<,=,#) matches range e.g.
		[in position  small integer]  -- In a list of lists, this causes a search of the specified sublist item.
		[in subfield  anything]  -- The property you wish to search in subrecords.
		[in user property  string]  -- The name of the field you wish to search in subrecords.
		[from  point]  -- The first/last items to be searched. Default is {1, -1}.
		[item contents  boolean]  -- Return a list of {{item Number, item Data}...} instead of just item numbers.
		[just contents  boolean]  -- Return only the item contents, no reference to position.
		[negation  boolean]  -- Return the opposite (the items that don't match).
		[expression evaluation  boolean]  -- I
	Result:   a list of integer  -- List of item numbers that matched.


enfin on affiche la nouvelle liste avec dd set contents.

Si on clique sur "Annuler", comme pour tout à l' heure ça se passe de commentaires...

Si on clique sur "OK", on quitte la boucle repeat car on en a fini avec ce dialogue.

Maintenant examinons le bouton "Ajouter".
Nous allons commencer par proposer un choix avec les applications lancées après avoir enlevé l' application courante de la liste grace à la commande décrite plus haut:

AppleScript: encore plus loin dans le script de fermeture des applis !


Ce dialogue nous renverra trois variables qui contiendront le numéro de l' application séléctionnée, et le bouton choisi pour les deux dernières ce qui nous amène à un if et à un dernier dialogue au cas où on aurait choisi "Autre Application".

Dans ce cas, on choisit l' application avec un choose file basique.Seulement nous devons vérifier que le fichier choisi est bien une application.C' est le rôle du bloc tell "Finder".
Tout d' abord si on a choisi un alias, on prend l' original à sa place.(Vous remarquerez l' emploi du cas possessif)
Ensuite, dans le bloc try, on essaie d' obtenir la mémoire attribuée à l' application.Si on a pas séléctionné une application l' erreur renvoyée est -1728 et on affiche un message d' erreur approprié.
Par contre, si on a bien une application, on extrait son nom du chemin d' accès par la méthode "set AppleScript' s text item delimiters to ...", fort utile, puis on sort du repeat.

Si on a choisi "Ajouter", on définit la variable theApp.

Ensuite, si l' application n' y est pas déjà, on l' ajoute à la liste puis on affiche celle-ci à l' écran.

A la sortie du grand repeat, on efface le dialogue et on désinstalle l' environnement.

Enfin, nous arrivons à la partie qui quitte véritablement les applications et c' est à la fois la plus courte et la plus simple du script:
On utilise un banal repeat dans lequel on quitte l' application après avoir vérifié qu' elle ne fait pas partie des applications à gerder et qu' elle n' est pas l' application courante (c' est à dire le script)

Le mot de la fin...



Et voilà !Vous vous doutez bien que le but de cet article n' était pas de vous apprendre à quitter une application mais de vous faire un aperçu des possibilités offertes par la création de dialogues multiples et complexes...

Si vous avez des questions, vous savez quoi faire...

Article entièrement rédigé par Coco.