Detlef Schulz
AppleScript -
Der automatische Mac
AppleScript – Der automatische Mac Bibliografische Information der Deutschen Bibliothek Die Deutsche Bibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über http://dnb.ddb.de abrufbar. Copyright © 2009 Smart Books Publishing AG ISBN: 978-3-908497-78-3 1. Auflage 2009 Lektorat:
Jeremias Radke
Korrektorat:
Dr. Anja Stiller-Reimpell
Layout und Satz:
Peter Murr
Covergestaltung:
Johanna Voss
Coverfoto:
iStockphoto
Illustrationen:
fotolia, iStockphoto
Druck und Bindung:
Stürtz GmbH, Würzburg
Team Elem ents2
Digital unterschrieben von Team Elements2 DN: cn=Team Elements2, c=DE, ou=Girls Club Datum: 2009.03.04 13:38:50 +01'00'
Umwelthinweis: Dieses Buch wurde auf chlorfrei gebleichtem Papier gedruckt. Die Einschrumpffolie – zum Schutz vor Verschmutzung – ist aus umweltverträglichem und recyclingfähigem PE-Material. Trotz sorgfältigem Lektorat schleichen sich manchmal Fehler ein. Autoren und Verlag sind Ihnen dankbar für Anregungen und Hinweise! Smart Books Publishing AG http://www.smartbooks.ch Aus der Schweiz: Aus Deutschland und Österreich:
Sonnenhof 3, CH-8808 Pfäffikon SZ E-Mail:
[email protected] Tel. 055 420 11 29, Fax 055 420 11 31 Tel. 0041 55 420 11 29, Fax 0041 55 420 11 31
Alle Rechte vorbehalten. Die Verwendung der Texte und Bilder, auch auszugsweise, ist ohne die schriftliche Zustimmung des Verlags urheberrechtswidrig und strafbar. Das gilt insbesondere für die Vervielfältigung, Übersetzung, die Verwendung in Kursunterlagen oder elektronischen Systemen. Der Verlag übernimmt keine Haftung für Folgen, die auf unvollständige oder fehlerhafte Angaben in diesem Buch oder auf die Verwendung der mitgelieferten Software zurückzuführen sind. Nahezu alle in diesem Buch behandelten Hard- und Software-Bezeichnungen sind zugleich eingetragene Warenzeichen oder sollten als solche behandelt werden.
Besuchen Sie uns im Internet!
www.smartbooks.ch www.smartbooks.de
Übersicht Vorwort
23
Kapitel 1
27
Einführung
Kapitel 2 Die Architektur
37
Kapitel 3 Das Handwerkszeug
51
Kapitel 4 Die Sprache
97
Kapitel 5 Die Standarderweiterungen
527
Kapitel 6 Von der Kunst, ein AppleScript zu starten
627
Kapitel 7
699
GUI-Scripting
Kapitel 8 Unix
749
Anhänge
767
Index
817
Inhaltsverzeichnis Vorwort
23
Kapitel 1 Einführung
27
Was ist AppleScript?........................................................................................................ 28 Woher kommt AppleScript?............................................................................................. 29 Wofür AppleScript geeignet ist......................................................................................... 33 Wofür AppleScript weniger geeignet ist............................................................................ 34 Was Sie zum Erlernen von AppleScript brauchen........................................................... 35
Kapitel 2 Die Architektur
37
OSA................................................................................................................................. 38 Sprachkomponenten........................................................................................................40 Skripterweiterungen........................................................................................................42 Funktionsverzeichnisse.................................................................................................... 44 Anwendungen.................................................................................................................. 47 Nicht-skriptbare Anwendungen.......................................................................... 48 Skriptbare Anwendungen................................................................................... 48 Aufzeichnungsfähige Anwendungen................................................................... 48 Anwendungen, die Skripts ausführen können..................................................... 49 Anwendungen, die Skripts erstellen können........................................................ 49 Anwendungen, die es erlauben, Skripts an Programmobjekte anzuhängen........50 Anwendungen, die es erlauben, das Programm selber umzubauen....................50
Kapitel 3 Das Handwerkszeug
51
AppleScript-Editoren....................................................................................................... 52 Der Skripteditor........................................................................................................ 52 Der Editorbereich............................................................................................... 53 Schreiben...................................................................................................... 53 Übersetzen.................................................................................................... 54 Ausführen..................................................................................................... 54 Debugging.................................................................................................... 55 Unterschiedliche Schreibweisen.................................................................... 55 Groß- und Kleinschreibung.......................................................................... 56 Der Skriptassistent........................................................................................ 56 Skriptbausteine im Kontextmenü................................................................. 57 Die Steuerungsleiste...................................................................................... 58
Skripts aufzeichnen...................................................................................... 59 Der Protokollbereich des Skripteditors................................................................ 61 Beschreibung................................................................................................ 61 Ergebnis........................................................................................................ 63 Event-Protokoll............................................................................................ 64 Die Verlaufsfenster.............................................................................................. 65 Die Bibliothek..................................................................................................... 66 Das Funktionsverzeichnis................................................................................... 67 Skripteditor-Einstellungen.................................................................................. 68 Tafel Allgemein............................................................................................. 68 Tafel Bearbeitung.......................................................................................... 68 Tafel Formatierung....................................................................................... 69 Tafel Verlauf.................................................................................................70 Tafel Plugins.................................................................................................70 Sichern und Dateiformate..................................................................................70 Kompilieren und Dekompilieren beim Sichern und Öffnen......................... 71 Ein Wort zu Type- und Creator-Codes und Resource-Forks........................ 72 Dateiformat »Skript«.................................................................................... 74 Dateiformat »Programm«............................................................................ 75 Dateiformat »Skript-Bundle«....................................................................... 76 Dateiformat »Programm-Bundle«............................................................... 78 Dateiformat »Text«......................................................................................80 Bundle-Inhalt.....................................................................................................80 Alternative AppleScript-Editoren.............................................................................. 81 Script Debugger.................................................................................................. 82 SmileLab und Smile............................................................................................ 83 Werkzeuge zur Erstellung grafischer Benutzerschnittstellen...................................... 85 AppleScript Studio.............................................................................................. 85 FaceSpan............................................................................................................. 87 Das AppleScript-Dienstprogramm.................................................................................. 89 Das Skriptmenü............................................................................................................... 92 Computerskripts........................................................................................................ 92 Benutzerskripts......................................................................................................... 93 Programmskripts....................................................................................................... 94 Programmspezifische AppleScript-Integration................................................................ 95
Kapitel 4 Die Sprache
97
Einstieg............................................................................................................................ 98 Zahlen............................................................................................................................. 99 Arithmetische Operatoren......................................................................................... 99 Die Klassen integer und real.................................................................................... 101
Umwandlung von Zahlen.......................................................................................102 Klammern und Berechnungsreihenfolge.................................................................102 Der Befehl round.....................................................................................................104 Der Befehl random number.................................................................................... 106 Kommentare..................................................................................................................108 Kommentare über das Kontextmenü des Skripteditors...........................................110 Das Fortführungszeichen............................................................................................... 111 Variablen.......................................................................................................................112 Bezeichner...............................................................................................................114 Reservierte Wörter.................................................................................................. 115 Zuweisungsoperationen mit dem Befehl set............................................................ 116 Der Befehl get..........................................................................................................120 Die Variable result................................................................................................... 121 Der Befehl log..........................................................................................................122 Textgrundlagen..............................................................................................................124 Der Verknüpfungsoperator &.................................................................................124 Steuerzeichenkonstanten......................................................................................... 125 Escape-Sequenzen................................................................................................... 127 Listengrundlagen...........................................................................................................130 Eine Liste aus Variablen zusammenbauen............................................................. 131 Referenzformen am Beispiel von Listen.........................................................................132 Auswahl eines einzelnen Elements..........................................................................132 first, second, third item…..................................................................................132 item n............................................................................................................... 133 item n of item n.................................................................................................134 Auswahl eines Bereiches.......................................................................................... 135 through............................................................................................................. 135 from … to.........................................................................................................136 some, middle und every...........................................................................................136 Zuweisungsoperationen mit Referenzformen.......................................................... 137 Referenzformen mit Angabe der Klasse.................................................................. 137 Referenzformen mit Klasse und every, some und middle........................................138 Relative Referenzformen mit before und after.........................................................139 Arbeiten in der Liste.......................................................................................................140 Ändern von Werten.................................................................................................140 Hinzufügen von Werten.......................................................................................... 141 Entfernen von Werten............................................................................................. 143 Eigenschaften einer Liste......................................................................................... 143 Massenzuweisungen über Listen............................................................................. 145 Der Befehl count in Listen....................................................................................... 146 Der Unterschied zwischen set und copy................................................................... 147 Umwandlung von Listen.........................................................................................150
Arbeiten mit Text........................................................................................................... 151 Unicode................................................................................................................... 151 id und character id...........................................................................................152 Kombinierte Unicode-Zeichen..........................................................................154 Eigenschaften eines Textes....................................................................................... 155 Elemente eines Textes.............................................................................................. 157 character........................................................................................................... 157 word.................................................................................................................. 157 paragraph.........................................................................................................158 text....................................................................................................................158 text item............................................................................................................159 Referenzformen auf Textelemente..................................................................................159 Auswahl eines Textbereichs......................................................................................160 some, middle und every im Text..............................................................................162 text items und text item delimiters...........................................................................162 Schnelles Suchen und Ersetzen mit text item delimiters.................................... 166 AppleScript's text item delimiters...................................................................... 167 Der Befehl count im Text.........................................................................................168 Umwandlung einer Liste in Text..............................................................................169 Umwandlung von Text in eine Liste........................................................................169 Implizite Umwandlung von Text in Zahlen.............................................................170 Explizite Umwandlung von Text in Zahlen............................................................. 171 Records..........................................................................................................................172 Record-Literale........................................................................................................172 Einen Record zusammenbauen...............................................................................174 Hinzufügen und Entfernen von Werten..................................................................174 Zusammenbau über Massenzuweisung........................................................... 175 Referenzformen in einem Record............................................................................ 176 Auswahl mit some und every............................................................................ 176 Auswahl über die Klasse................................................................................... 177 Umwandlung eines Records.................................................................................... 177 Eigenschaften eines Records....................................................................................178 Missing value...........................................................................................................179 Der Befehl count in Records....................................................................................180 Eigenschaften von Objekten...........................................................................................180 Ändern einer Eigenschaft eines Objekts...................................................................184 Die Datumsklasse..........................................................................................................188 Der Befehl current date...........................................................................................188 Datumsliterale.........................................................................................................189 Rechnen mit date.....................................................................................................190 Eigenschaften von date............................................................................................192 class...................................................................................................................192
day ...................................................................................................................192 weekday............................................................................................................ 193 month............................................................................................................... 195 year................................................................................................................... 197 date string und short date string.......................................................................198 time...................................................................................................................199 hours.................................................................................................................200 minutes.............................................................................................................200 seconds.............................................................................................................. 201 time string......................................................................................................... 201 Datum oder Zeit in vorhandenes Datum einsetzen................................................ 201 Der Befehl time to GMT.........................................................................................202 Der Befehl delay...................................................................................................... 203 Umwandlungen von date........................................................................................204 Vergleichsoperatoren...................................................................................................... 206 Die Klasse boolean.................................................................................................. 207 is equal to................................................................................................................ 207 Verneinungsformen...........................................................................................209 Implizite Typumwandlungen............................................................................209 Zahlen..............................................................................................................210 Listen................................................................................................................ 211 Records.............................................................................................................212 Text................................................................................................................... 213 Datum.............................................................................................................. 215 greater than, less than.............................................................................................. 215 Verneinungsformen........................................................................................... 217 Implizite Typumwandlungen............................................................................218 Zahlen..............................................................................................................219 Listen................................................................................................................220 Records.............................................................................................................220 Text................................................................................................................... 221 Datum.............................................................................................................. 223 contains...................................................................................................................223 Verneinungsformen...........................................................................................224 Implizite Typumwandlungen............................................................................224 Zahlen.............................................................................................................. 225 Listen................................................................................................................ 225 Records............................................................................................................. 226 Text................................................................................................................... 227 Datum..............................................................................................................228 starts with, ends with..............................................................................................229 Verneinungsformen...........................................................................................230
Implizite Typumwandlungen............................................................................230 Zahlen.............................................................................................................. 231 Listen................................................................................................................ 231 Records.............................................................................................................232 Text...................................................................................................................232 Datum.............................................................................................................. 233 and, or.....................................................................................................................234 and....................................................................................................................234 or...................................................................................................................... 235 Klammern........................................................................................................ 236 not........................................................................................................................... 237 Umwandlung von booleschen Werten.....................................................................239 Umwandlung in boolesche Werte............................................................................239 Kontrollstrukturen......................................................................................................... 241 Anreden mit tell....................................................................................................... 241 tell auf einer einzelnen Zeile..............................................................................242 tell als Blockanweisung.....................................................................................242 Das implizite tell und die Schlüsselwörter AppleScript, me und my..................242 Explizite Zielbestimmung mit dem Schlüsselwort it..........................................244 Objekthierarchien............................................................................................. 246 Lesen eines Funktionsverzeichnisses.................................................................. 251 Symbolik der Übersicht.............................................................................. 251 Darstellungsarten der Übersicht.................................................................252 Die Beschreibung........................................................................................252 Hierarchische tell-Beispiele...............................................................................254 tell auf Objekte........................................................................................................ 257 tell auf den index............................................................................................... 257 tell auf den Namen........................................................................................... 257 tell auf eine id....................................................................................................258 tell auf eine Objektreferenz...............................................................................259 tell every............................................................................................................264 tell some, tell middle..........................................................................................264 tell mit relativem Bezug.................................................................................... 265 tell auf einen Bereich......................................................................................... 265 Der Filter whose................................................................................................ 266 Eigenschaften, mit denen whose nicht funktioniert...........................................270 Besonderheiten bei einem tell auf ein Programm.............................................. 271 Vor- und Nachteile bei Verwendung der application id.....................................274 Verzweigungen mit if...............................................................................................274 if auf einer Zeile................................................................................................274 if als Blockanweisung........................................................................................276 if mit else...........................................................................................................276
if mit else if ....................................................................................................... 277 if mit else if und else.......................................................................................... 277 exists.................................................................................................................278 running.............................................................................................................279 Schachtelung von if...........................................................................................280 Schleifen mit repeat................................................................................................. 281 repeat (endlos).................................................................................................. 281 exit repeat.........................................................................................................282 Optimierung durch Referenzen........................................................................ 283 Referenzen und der Operator »a reference to«..................................................284 Rückverweis einer Referenz mit »contents of«................................................... 286 Optimierung durch Reduzierung gesendeter Apple-Events..............................288 return oder try als Abbruchbedingung.............................................................. 291 repeat n times.................................................................................................... 291 repeat until........................................................................................................292 repeat while.......................................................................................................294 repeat with........................................................................................................294 repeat with (in Liste)......................................................................................... 297 Optimierung durch System-Events statt Finder................................................302 Geschachtelte repeat..........................................................................................304 considering/ignoring...............................................................................................306 case...................................................................................................................306 diacriticals........................................................................................................308 expansion..........................................................................................................309 hyphens.............................................................................................................309 punctuation......................................................................................................310 white space........................................................................................................ 311 numeric strings.................................................................................................312 Kombinierte Anweisungen und Schachtelungen............................................... 313 considering/ignoring application responses.............................................................314 using terms from.....................................................................................................316 with timeout............................................................................................................ 317 with transaction......................................................................................................319 error........................................................................................................................320 try............................................................................................................................324 Fehler durchreichen.................................................................................... 327 Fehler filtern...............................................................................................330 Eigene Fehlerdialoge................................................................................... 331 Handler......................................................................................................................... 333 Definition................................................................................................................ 333 Aufrufen..................................................................................................................334 Positionsparameter.................................................................................................. 335
Handlerparameter dokumentieren.........................................................................338 Prüfung und Fehlerbehandlung..............................................................................338 Variablen im Handler sind lokal.............................................................................340 Die Parameterübergabe geschieht per Referenz....................................................... 341 Parametervariablen mit Programmobjekten..........................................................344 Rückgabewerte........................................................................................................ 345 Implizite Rückgabe............................................................................................ 345 Explizite Rückgabe mit return.......................................................................... 347 Rückgabe mehrerer Variablen durch Pattern....................................................349 Aufruf von Handlern mit Parameter-Pattern.........................................................352 Aufruf in Ausdrücken.............................................................................................. 353 Aufruf mit my..........................................................................................................354 Ausdrücke als Parameter beim Aufruf.................................................................... 355 Rekursive Handler................................................................................................... 356 Speicherung von Ergebnissen bei rekursiven Aufrufen...................................... 357 Rekursion über Programmobjekte....................................................................359 Handler sind Objekte.............................................................................................. 361 Benannte Parameter............................................................................................... 363 Benutzer-Parameter.........................................................................................364 Der direkte Parameter....................................................................................... 366 Eigene Benutzer-Parameter mit given.............................................................. 367 with oder without beim Aufruf.........................................................................368 Laden von Bibliotheken mit load script...................................................................370 Laden von Bibliotheken aus dem Bundle des Skripts.............................................. 371 Die Standard-Handler einer Skriptanwendung...................................................... 373 Der run-Handler.............................................................................................. 373 Der quit-Handler.............................................................................................. 376 Der idle-Handler.............................................................................................. 377 Der open-Handler und Droplets.......................................................................379 Vorlage für ein Droplet............................................................................... 381 Der reopen-Handler......................................................................................... 383 Applets sind skriptbar..............................................................................................384 Ordneraktionen...................................................................................................... 387 opening folder...................................................................................................389 closing folder window for..................................................................................394 moving folder window for.................................................................................396 adding folder items to........................................................................................ 397 removing folder items from............................................................................... 401 Skriptobjekte..................................................................................................................403 Bestandteile eines Skriptobjekts............................................................................... 403 Die Eigenschaften eines Skriptobjekts...............................................................404 Variablen und Handler als Elemente eines Skriptobjekts.................................. 406
Selbst definierte Eigenschaften – Propertys....................................................... 407 Definition von Propertys............................................................................ 407 Der richtige Platz für Propertys..................................................................408 Wertezuweisung in properties.....................................................................410 Eine Property-Definition verhält sich wie set............................................. 411 Abfrage der Propertys ................................................................................412 Sichtbarkeit von Propertys.........................................................................413 Persistenz von Propertys.............................................................................414 Skriptobjekte als Element eines Skripts............................................................. 415 Skriptobjekte definieren.............................................................................. 415 Mit Skriptobjekten arbeiten.....................................................................................418 Aufruf von Handlern in Skriptobjekten............................................................418 Zugriff auf Propertys eines Skriptobjekts.......................................................... 421 Skriptobjekte als Werte.....................................................................................424 Die Property name...........................................................................................429 Vergleichen von Skriptobjekten.........................................................................429 Zugriff auf Elemente im übergeordneten Skript................................................ 431 Zugriff auf Elemente im übergeordneten Skriptobjekt......................................432 Zugriff auf Elemente in untergeordneten Skriptobjekten.................................. 433 Initialisierung von Skriptobjekten in Handlern.................................................434 Konstruktoren und Instanzen........................................................................... 436 Konstruktor mit copy.................................................................................. 436 Konstruktor mit dediziertem Handler........................................................439 Vererbung und Delegation....................................................................................... 443 Die Property parent.......................................................................................... 443 Implizite Eltern........................................................................................... 443 Explizite Eltern........................................................................................... 446 Eine Property für alle Kinder............................................................................448 Ein Handler für alle Kinder und implizite Delegation......................................449 Rückgabewerte der Eltern..........................................................................450 Me und my in Skriptobjekten mit explizitem parent.................................. 453 Überschreiben oder »Eigensinnige Kinder«....................................................... 455 Überschreiben von Handlern.....................................................................459 Polymorphismus.........................................................................................460 Delegation an die Eltern und der Befehl continue...................................... 463 Befehle von Skripterweiterungen oder Anwendungen überschreiben......... 466 Ein Programm als parent..................................................................................468 Beliebige Objekte als parent..............................................................................470 Skriptobjekte speichern und laden........................................................................... 471 store script......................................................................................................... 471 Skriptobjekte im Bundle speichern....................................................................474 load script......................................................................................................... 475
run script..........................................................................................................476 run script und der Aufruf des run Handlers mit Parametern....................479 run script mit anderen OSA-Sprachen.......................................................479 Der Gültigkeitsbereich von Variablen und Propertys.................................................... 483 Lokale Variablen..................................................................................................... 485 Einfache Variablen..................................................................................................488 Überschreiben von einfachen Variablen.....................................................490 Propertys................................................................................................................. 491 Überschreiben durch properties..................................................................492 Überschreiben durch globals....................................................................... 493 Überschreiben durch einfache und lokale Variablen.................................. 493 Globale Variablen................................................................................................... 495 Globale Variablen sind persistent............................................................... 496 Ort der Deklaration................................................................................... 496 Reichweite in die Tiefe................................................................................498 Reichweite nach oben und in Laufrichtung des Skripts..............................499 Überschreiben von globalen Variablen.......................................................502 Weitere Klassen..............................................................................................................504 Die Klasse alias.......................................................................................................504 Eigenschaften eines alias............................................................................. 506 Umwandlungsmöglichkeiten...................................................................... 506 Die Klassen file und POSIX file..............................................................................508 Eigenschaften von file und POSIX file........................................................509 Umwandlungsmöglichkeiten......................................................................509 Relative Pfade.............................................................................................510 Steuerung von Anwendungen auf entfernten Rechnern.......................................... 511 Die eppc-URL............................................................................................512 Anwendungen und Benutzer......................................................................514 Keine Dialoge............................................................................................. 517 Die Klasse RGB color.............................................................................................. 517 Die unit types..........................................................................................................519 Umwandlungsmöglichkeiten...................................................................... 521 Rechnen mit unit types............................................................................... 521 XML-RPC und SOAP...................................................................................................522 XML-RPC............................................................................................................... 523 SOAP......................................................................................................................524
Kapitel 5 Die Standarderweiterungen
527
Die Standarderweiterungen..........................................................................................528 User Interaction.............................................................................................................529 beep.........................................................................................................................529
choose application...................................................................................................530 Parameter................................................................................................... 531 Rückgabewert............................................................................................. 531 Beispiel.......................................................................................................532 choose color.............................................................................................................532 Parameter...................................................................................................532 Rückgabewert............................................................................................. 533 Beispiel....................................................................................................... 533 choose file................................................................................................................533 Parameter...................................................................................................534 Rückgabewert............................................................................................. 536 Beispiel....................................................................................................... 536 choose file name...................................................................................................... 537 Parameter................................................................................................... 537 Rückgabewert.............................................................................................538 Beispiel.......................................................................................................538 choose folder............................................................................................................538 Parameter...................................................................................................538 Rückgabewert.............................................................................................540 Beispiel.......................................................................................................540 choose from list........................................................................................................540 Parameter................................................................................................... 541 Rückgabewert............................................................................................. 543 Beispiel....................................................................................................... 543 choose remote application.......................................................................................544 Parameter...................................................................................................544 Rückgabewert............................................................................................. 545 Beispiel....................................................................................................... 545 choose URL.............................................................................................................545 Parameter................................................................................................... 546 Rückgabewert.............................................................................................548 Beispiel.......................................................................................................548 delay........................................................................................................................548 display alert.............................................................................................................549 Parameter...................................................................................................549 Rückgabewert.............................................................................................552 Beispiel....................................................................................................... 553 display dialog...........................................................................................................553 Parameter...................................................................................................554 Rückgabewert.............................................................................................558 Beispiel.......................................................................................................559 say...........................................................................................................................559
Parameter...................................................................................................559 Rückgabewert.............................................................................................562 Beispiel.......................................................................................................562 File Commands.............................................................................................................562 info for.....................................................................................................................563 list disks...................................................................................................................564 list folder..................................................................................................................565 mount volume......................................................................................................... 566 Parameter................................................................................................... 566 path to.....................................................................................................................568 Parameter...................................................................................................568 Rückgabewert............................................................................................. 571 path to resource.......................................................................................................572 Parameter...................................................................................................572 Rückgabewert............................................................................................. 573 Beispiel.......................................................................................................574 String Commands..........................................................................................................574 ASCII character.......................................................................................................574 ASCII number......................................................................................................... 575 localized string.........................................................................................................576 Parameter................................................................................................... 576 Rückgabewert............................................................................................. 577 Beispiel....................................................................................................... 577 offset........................................................................................................................ 581 summarize.............................................................................................................. 581 Parameter................................................................................................... 581 Clipboard Commands...................................................................................................582 set the clipboard to...................................................................................................583 the clipboard...........................................................................................................584 clipboard info..........................................................................................................585 File Read/Write............................................................................................................. 586 open for access.........................................................................................................586 Parameter................................................................................................... 587 Rückgabewert.............................................................................................588 close access...............................................................................................................588 read.........................................................................................................................588 Parameter...................................................................................................589 Rückgabewert.............................................................................................600 write........................................................................................................................600 Parameter................................................................................................... 601 Rückgabewert.............................................................................................604 get eof......................................................................................................................604
set eof.......................................................................................................................605 Scripting Commands..................................................................................................... 606 load script............................................................................................................... 607 store script............................................................................................................... 607 run script.................................................................................................................608 scripting components...............................................................................................609 Miscellaneous Commands.............................................................................................610 current date.............................................................................................................610 do shell script...........................................................................................................610 Parameter................................................................................................... 611 Rückgabewert.............................................................................................614 get volume settings...................................................................................................614 random number......................................................................................................615 round......................................................................................................................616 set volume............................................................................................................... 617 system attribute.......................................................................................................619 system info............................................................................................................... 621 time to GMT........................................................................................................... 621 Folder Actions................................................................................................................622 Internet Suite...........................................................................................................622 open location...........................................................................................................622 handle CGI request.................................................................................................623
Kapitel 6 Von der Kunst, ein AppleScript zu starten
627
Von der Kunst, ein AppleScript zu starten.....................................................................628 AppleScript im Finder....................................................................................................628 Die Symbolleiste......................................................................................................628 Die Seitenleiste........................................................................................................630 Orte..................................................................................................................630 Intelligente Ordner............................................................................................630 Das Dock.................................................................................................................632 Das Dienste-Menü.................................................................................................. 633 AppleScript-Dienste.......................................................................................... 633 Dienst »Als AppleScript ausführen«........................................................... 633 Dienst »Ergebnis aus AppleScript«.............................................................634 Dienst »Neues AppleScript erstellen«......................................................... 635 Eigene Dienste mit AppleScript erstellen........................................................... 635 ThisService.................................................................................................. 636 Das Kontextmenü...................................................................................................638 Kontextmenübefehl für den Finder mit Automator erstellen............................638 OnMyCommand..............................................................................................642
Big Cat.............................................................................................................. 646 OpenMenu X.................................................................................................... 647 Skripts über Tastaturkürzel starten...............................................................................649 Programmeigene Skriptmenüs..........................................................................650 ThisService und OpenMenu X..........................................................................650 Shortcuts...........................................................................................................650 FastScripts......................................................................................................... 653 Weitere Programme..........................................................................................654 Skripts automatisch starten........................................................................................... 655 Zu einer bestimmten Zeit........................................................................................ 655 iCal................................................................................................................... 655 cron................................................................................................................... 657 CronniX............................................................................................................ 657 launchd Einführung..........................................................................................659 launchctl.....................................................................................................664 Weitere Beispiele......................................................................................... 666 SystemStarter....................................................................................................668 Weitere Programme mit Timerfunktion...........................................................668 Einen eigenen Skript-Timer in AppleScript erstellen.........................................669 Skriptwächter als Hintergrundprozess........................................................670 Bei einem Ereignis................................................................................................... 671 Start und Anmeldung....................................................................................... 671 Startobjekte................................................................................................672 launchd beim Start.....................................................................................674 loginwindow und LoginHook....................................................................674 Ausschalten und Abmelden............................................................................... 676 loginwindow und LogoutHook.................................................................. 676 Eigenen Skriptwächter erstellen.................................................................. 676 Ruhezustand..................................................................................................... 677 SnoozeRun................................................................................................. 677 SleepWatcher..............................................................................................678 Bildschirmschoner............................................................................................682 ScriptSaver.................................................................................................682 Mailregeln.........................................................................................................684 Ordneraktionen................................................................................................ 685 launchd und WatchPaths........................................................................... 686 launchd und QueueDirectories.................................................................. 687 Einlegen einer CD oder DVD und das Digital Hub Scripting...........................689 Einbinden eines Laufwerks und launchd..........................................................690 Eigenen Skriptwächter Ereignisse beobachten lassen........................................692 Aktionen im Benutzerinterface.........................................................................694 AppleScript URLs.............................................................................................694
Kapitel 7 GUI-Scripting
699
Grundlagen...................................................................................................................700 Zugriff für Hilfsgeräte.................................................................................700 Tastatur & Maus........................................................................................ 701 Grenzen...................................................................................................... 703 Hilfreiche Software........................................................................................................704 Der UI Element Inspector....................................................................................... 705 Das Fenster »Accessibility Inspector«.......................................................... 706 Das Fenster »Locked on«............................................................................708 Der UI Browser von Prefab.....................................................................................709 Das Fenster »UI Browser Screen Reader«..................................................709 Das Fenster »UI Browser«..........................................................................710 Die Processes Suite der System Events............................................................................712 Prozesse................................................................................................................... 715 Die UI elements....................................................................................................... 717 Die Propertys eines UI elements.......................................................................722 Abfragen mit whose.................................................................................... 726 Abfragen mit entire contents....................................................................... 727 Tricks zum manuellen Ermitteln der Objekthierarchie...............................728 Die AXAttribute..................................................................................................... 731 Die Befehle.............................................................................................................. 733 click................................................................................................................... 733 click an ein UI element...............................................................................733 click an Bildschirmkoordinate.................................................................... 736 select.................................................................................................................738 perform.............................................................................................................739 Die Klasse action........................................................................................739 Beispiele...................................................................................................... 741 keystroke...........................................................................................................742 keystroke und tab.......................................................................................744 key code............................................................................................................ 745
Kapitel 8 Unix
749
Das AppleScript-Shebang..............................................................................................750 Die vier osa-Befehle.......................................................................................................752 Escape- und Anführungszeichen.............................................................................752 osalang....................................................................................................................753 osacompile...............................................................................................................754 osadecompile...........................................................................................................758 osascript..................................................................................................................759
Tipps zu do shell script................................................................................................... 763 Skripts in anderen Sprachen.......................................................................763 Standardeingabe........................................................................................ 765 Werte über mehrere Aufrufe erhalten......................................................... 765 Interaktive und dynamische Befehle........................................................... 765 Nicht auf Antwort warten.......................................................................... 766
Anhänge
767
A - AppleScript Kurzübersicht.......................................................................768 Reservierte Wörter..................................................................................................768 Flusskontrolle..........................................................................................................769 Operatoren..............................................................................................................773 Operatorreihenfolge................................................................................................778 Globale Eigenschaften (Konstanten) von AppleScript und current application......779 Bezugsformen..........................................................................................................780 Befehle.....................................................................................................................784 Basisklassen.............................................................................................................790 Umwandlungen......................................................................................................794 Reichweite von Variablen........................................................................................ 796 Mac OS Roman Kodierung.....................................................................................800 Key Codes................................................................................................................802 AppleScript Fehlermeldungen.................................................................................. 803 Fehlermeldungen des Betriebssystems..................................................................... 805 B - Quellen.................................................................................................... 807 AppleScript bei Apple.............................................................................................. 807 Links auf den Entwicklerseiten von Apple.................................................. 807 Links zu Automator...................................................................................809 Links zu AppleScript Studio.......................................................................809 Links für Entwickler, die ihr Programm skriptbar machen wollen.............809 AppleScript im Internet...........................................................................................810 Deutschsprachige Webseiten.............................................................................810 Internationale Links.......................................................................................... 811 Software von Drittherstellern...........................................................................812 AppleScript-Editoren..................................................................................812 Entwicklungsumgebungen auf der Basis von AppleScript..........................812 GUI............................................................................................................812 Letzte Links zu HyperCard........................................................................812
Entwicklungsumgebungen, die auf HyperCard basieren oder davon inspiriert wurden:.......................................................................................812 OSA-Sprachen...........................................................................................812 AppleScript als CGI.................................................................................... 813 Resource-Editoren...................................................................................... 813 Skriptmenüs, Kontextmenüs, Tastaturkürzel, Skriptstarter und Sonstiges..... 813 Wegen guter AppleScript-Anbindung gelobte Programme:........................ 815
Index
817
Vorwort
SmartBooks
AppleScript
Vorwort Mit diesem Buch habe ich mir einen eigenen Traum verwirklicht. Dies ist das Buch zum Thema AppleScript, welches ich immer besitzen wollte, welches aber nie existierte. Ich habe das Buch nun selbst geschrieben. Seit Mitte der 90er Jahre haben sich bei mir ein gutes halbes Dutzend deutscher AppleScript-Bücher angesammelt und noch einmal so viele in englischer Sprache. Wenn mir bei einem Problem ein Buch nicht weiterhelfen konnte, griff ich halt zum anderen und später, mit zunehmender Informationsdichte im Internet, auch auf selbiges. Jedes dieser Bücher, ebenso wie das Internet, hat seine Stärken und seine Schwächen, und ich habe aus allen viel gelernt. Für mich war aber immer auffällig, dass kein deutschsprachiges Buch dem Thema in dem Umfang gerecht wurde, wie ich es mir gewünscht hätte. Mit zunehmender Kenntnis der Sprache wurden für mich die Lücken in der Literatur zudem immer größer. In das vorliegende Buch habe ich nun alles gepackt, was ich bisher in gedruckter Form vermisst habe und dabei auch intensive Tests und Recherchen nicht gescheut. Dazu wurde jede einzelne Codezeile ausführlich durchgetestet und nicht nur einfach aus der Theorie heraus beschrieben, was dazu führte, dass auch einige Fehler und Mankos der Sprache zu Tage treten, auf die in anderen Quellen nicht immer hingewiesen wird. Herausgekommen ist das umfangreichste Buch über AppleScript, welches es bisher in deutscher Sprache gegeben hat. Durch den ausführlichen tabellarischen Anhang und den Index eignet es sich dabei auch als schnelles Nachschlagewerk. Das Buch behandelt den Sprachumfang mit den Standarderweiterungen vollständig und widmet sich auch ausführlich dem GUI-Scripting und der Integration von AppleScript im Betriebssystem Mac OS X. In dieser Beziehung ist dieses Buch sogar den aktuellen Werken geschätzter englischsprachiger Autoren voraus. Hinzu kommt, dass im Bereich GUI-Scripting nicht einmal das Internet eine große Hilfe darstellt. Apple vernachlässigt hier, wie leider so oft, die Dokumentation sträflich. Dieses Kapitel alleine hat mich daher viele Tests gekostet und viel Zeit verschlungen, um gangbare Wege zu erkunden und Fehler auszumerzen, die Sie damit nicht mehr machen müssen. Gerne hätte ich mich auch noch eingehend den Themen »Automator« und »AppleScript Studio« gewidmet, aber das hätte den Umfang des Buches dann endgültig gesprengt. Die längeren Codebeispiele können Sie übrigens von der Buchwebseite www.skripteditor.de herunterladen, so dass Ihnen langes Abtippen erspart bleibt.
24
Vorwort
Ich hoffe, dass es mir gelingt, Ihnen auch etwas von der Faszination, die mich beim Schreiben geleitet hat, weiterzugeben und wünsche Ihnen, dass Sie viel Nutzen aus diesem Buch ziehen.
Detlef Schulz Apple Certified System Administrator
25
Einführung
1
Was ist AppleScript? Wie ist AppleScript entstanden? Wofür wird AppleScript verwendet und wofür ist es nicht geeignet? Was braucht man, um AppleScript zu erlernen?
SmartBooks
AppleScript
Was ist AppleScript? AppleScript ist eine objektorientierte, schwach typisierte Skriptsprache zur Steuerung von Anwendungen auf dem Mac OS-Betriebssystem. Bei allen Substantiven in der AppleScript-Sprache handelt es sich um Objekte in Form von Klassen. Eigene Objekte können erzeugt werden und von anderen Klassen erben. Eine Mehrfachvererbung ist nicht möglich. An Klassen (Objekten) und Befehlen (Verben) bringt AppleScript nur die grundlegenden mit. Erst durch die Funktionsverzeichnisse (Dictionaries) anderer Programme werden der Sprache anwendungsspezifische Befehle und Elemente hinzugefügt, beziehungsweise die Befehle aus dem Kern der AppleScript-Sprache erhalten weitere, zusätzliche Bedeutungen im Kontext des verwendeten Programms. Daneben kann die Sprache aber auch auf dem klassischen Weg über die Einbindung von zusätzlichen Bibliotheken, den sogenannten Skripterweiterungen (Scripting Additions), unabhängig von den zu steuernden Programmen, erweitert werden. AppleScript ist schwach typisiert, das heißt, Sie können in eine Variable hineinpacken, was Sie wollen und den Inhaltstyp automatisch oder explizit umwandeln lassen. Das macht es auf der einen Seite besonders einfach, mit Variablen zu hantieren, auf der anderen Seite müssen Sie dann aber gut Acht geben, ob der Inhalt der Variablen wirklich noch im erwarteten Typ vorliegt. Ansonsten bringen darauf angewendete Befehle unerwartete Ergebnisse. Obwohl die Stärke von AppleScript in erster Linie darin liegt, andere Programme zu steuern, kann es mit Hilfe von AppleScript Studio oder FaceSpan auch zur Programmierung von Anwendungen mit grafischer Benutzerschnittstelle verwendet werden. Im Programm »Automator«, welches zur vereinfachten Erstellung von Arbeitsabläufen (Workflows) mit verschiedenen Programmen dient, wird AppleScript verwendet, um eigene Aktionen zu schreiben und damit den Funktionsumfang von Automator nach Belieben zu erweitern. Die Stärke von AppleScript liegt darin, dass es gar nicht viel können muss, denn wo immer es eine spezielle Fähigkeit benötigt, kann es ein Programm mit genau dieser Fähigkeit fernsteuern und sich das Ergebnis von diesem Programm zurückgeben lassen. AppleScript wird fast wie normales Englisch geschrieben und ist damit leicht zu schreiben und auch nach Jahren wieder leicht zu lesen und zu verstehen, leichter als in jeder anderen Sprache. Andererseits ist die Sprache dadurch aber auch oft ambivalent und missverständlich.
28
Einführung
Kapitel 1
Aufgrund seines geringen Sprachumfangs und seiner Anlehnung an die natürliche englische Sprache ist AppleScript sicher die am schnellsten erlernbare Skriptsprache. Dafür müssen Sie dann aber auch für jede Anwendung, die gesteuert werden soll, wieder einiges an Zeit aufwenden, um die Objekthierarchie und Befehle dieser Anwendung zu verstehen und anzuwenden. AppleScript selbst ist also nur die Basis, danach müssen Sie noch lernen, wie die zu steuernde Anwendung angesprochen werden muss. Da Objekthierarchien und Befehle aber nicht in jeder Anwendung erneut erfunden werden, gleichen sich die Funktionsverzeichnisse vieler Anwendungen zumindest in den Grundlagen. Wenn man einmal eine beliebige Textverarbeitung mit AppleScript gesteuert hat, so wird man in der Regel auch andere Textverarbeitungen schnell automatisieren können.
Woher kommt AppleScript? AppleScript ist aus HyperTalk hervorgegangen, einer von Dan Winkler bei Apple entwickelten Skriptsprache. An die Öffentlichkeit trat HyperTalk 1987 mit dem von Bill Atkinson entwickelten Programm »HyperCard«, in welchem es die Sprache zur Steuerung des Programms darstellte.
Abb. 1-1 HyperCard bewies erstmals, dass Softwareerstellung für jeden möglich ist und kein jahrelanges Studium erfordert. Auch die einfache, der englischen Sprache nachempfundene Skriptsprache HyperTalk setzte Maßstäbe. HyperCard war eine Multimedia-Entwicklungsumgebung und verwendete den Begriff eines »Kartenstapels« als Metapher für ein damit erstelltes Programm und seine Daten. Mit HyperCard konnten eigene Anwendungen mit grafischer Benutzerschnittstelle erzeugt werden, und zwar auf die typische Macintosh-Art: Man platzierte Knöpfe, Textfelder und andere grafische Elemente mit der Maus auf einer zunächst leeren Karte und verknüpfte die Aktionen dieser Elemente wiederum über Skripts miteinander. Jede Karte stellte dabei üblicherweise einen Datensatz in der Anwendung dar. Alle Karten zusammen bildeten den Stapel (Stack). Dieser grafische Weg zur Erstellung eines Benutzerinterfaces ist heute noch im Interface Builder von Apple oder den RAD-Werkzeugen anderer Entwicklungsumgebungen üblich. HyperCard war damit seiner Zeit weit voraus – einer Zeit, in der man noch mit Texteditor und Kommandozeile programmiert hat – und wurde gerne zur Erstellung von interaktiven Lern- und Multimediaprogrammen, aber auch zur Programmierung von Spielen wie zum Beispiel Myst (1993) verwendet.
29
SmartBooks
AppleScript
Abb. 1.2 HyperCard 1.2 in der Klassikumgebung von Mac OS X 10.4 (Montage verschie dener Fensterelemente). Links der sogenannte »Home«-Stack, Start und Endpunkt von HyperCard. Rechts oben die Eigenschaften eines Knopfes mit dem Namen »Return«. Rechts unten das HyperTalk-Skript eines Knopfes zum Wählen einer Telefonnummer. Jedem sichtbaren oder unsichtbaren Element auf einer Karte konnte dabei ein Skript in der Sprache HyperTalk hinzugefügt werden. Dieses Skript bestimmte, was passierte, wenn dieses Element angeklickt, betreten oder verlassen oder wenn auf andere Art damit interagiert wurde. Besaß das Objekt keine entsprechende Methode im Skript, wurde die Nachricht über die Interaktion an das übergeordnete Objekt, also zum Beispiel das Kartenskript oder das Skript des Kartenhintergrunds, zur Ausführung weitergereicht, ganz so wie in den Klassen einer objektorientierten Programmiersprache üblich. HyperTalk war der englischen Sprache zudem so ähnlich, dass selbst Anfänger ohne Programmierkenntnisse damit schnell eigene kleine Scripte erstellen konnten. HyperCard setzte Maßstäbe und beeinflusste auch die Entwicklung des Betriebssystems Nummer 7. Nach mehreren Jahren Grundlagenarbeit erblickte 1993 mit System 7 Pro (System 7.1.1) AppleScript als Skriptsprache des Macintosh Betriebssystems das Licht der Welt. Die Syntax von AppleScript war dabei fast eins zu eins von HyperTalk übernommen worden.
30
Einführung
Kapitel 1
Abb. 1.3 Die sogenannte xTalk-Sprachfamilie mit einer einfachen, dem Englischen ähnlichen Syntax und ihrem »Urvater« HyperTalk (die Anordnung der Nachkommen ist willkürlich und stellt keine zeitliche Folge dar.) (Quelle u.a.: Wikipedia) Im Gegensatz zu HyperTalk war AppleScript dafür gedacht, nicht nur einem Programm zu sagen, was es tun soll, sondern allen Programmen inklusive dem Finder selber. Voraussetzung dafür war allerdings, dass die Entwickler ihre Programme entsprechend anpassten, damit diese auf die mit AppleScript ausgesandten Befehle, die sogenannten Apple Events, auch reagierten. Zu Beginn waren daher nur der Finder und einige Programme von Apple selber skriptfähig. Das änderte sich erst nach und nach, wurde dann aber schnell zu einem unverzichtbaren Standard auf dem Mac. Die Skriptfähigkeit von Grafik- und Layoutanwendungen war neben der Druckerbeschreibungssprache »Postscript« eine der Hauptgründe, warum Desktop-Publishing so lange ganz auf den Mac als Betriebssystem festgelegt war und warum Windows hier lange Jahre keine ernsthafte Konkurrenz darstellte. Das einzige, was viele Anwender in AppleScript schon immer vermisst haben, war die Möglichkeit, einem Skript eine grafische Benutzerschnittstelle wie in HyperCard zu geben. AppleScript selbst bot nur einige grundlegende Dialoge zur Interaktion mit dem Benutzer. Aus dieser Lücke heraus entwickelten Drittanbieter natürlich sofort Entwicklungsumgebungen mit grafischem Benutzerinterface. Als das prominenteste und langlebigste ist hier FaceSpan (www.latenightsw.com) zu nennen, welches bis auf den heutigen Tag immer noch weiterentwickelt wird und eine professionelle Alternative zu AppleScript Studio darstellt. Aber auch HyperCard selbst inspirierte viele Entwickler und fand direkte Nachfolger und -ahmer in Programmen wie »SuperCard« (www.supercard.us), »MetaCard« (www. metacard.com), »ToolBook« (www.toolbook.com), »Revolution« (www.runrev.com) oder dem kostenlosen »HyperNext« (www.tigabyte.com), von denen jeder wiederum seine eigene, von HyperTalk inspirierte Skriptsprache erfand, wie aus obiger Abbildung ersichtlich wird. Nach Erschaffung von AppleScript wurde selbiges im klassischen Mac OS (bis einschließlich System 9.2) jeweils nur im Rahmen der stetig wachsenden Funktionen des
31
SmartBooks
AppleScript
Betriebssystems erweitert. Ansonsten blieb es von Apple-Seite her sehr ruhig. Die Zeit schien in diesem Bereich stehen geblieben. Mit dem Erscheinen der ersten Version von Mac OS X im Jahre 2001 änderte sich an AppleScript auch erstmal wenig. Man hatte es unter Mac OS X zum Laufen gebracht. Und das war die wesentliche, erleichternde Erkenntnis. Es gab schon Befürchtungen, dass man AppleScript sterben lassen würde. Doch wie sich bald herausstellen sollte, wurde es sogar weiterentwickelt. Dann folgte die Entwicklung Schlag auf Schlag. Mit jeder neuen Version von Mac OS X, also fast jedes Jahr, wird AppleScript verbessert, erweitert und mehr und mehr ins Unix-Betriebssystem integriert und damit mehr und mehr zur »Lingua Franca« von Mac OS X – vieles davon meist unsichtbar unter der »Motorhaube« und oft leider schlecht oder überhaupt nicht dokumentiert. 2002 erscheint mit Mac OS X 10.2 AppleScript Studio. Damit wird es zum ersten Mal möglich, mit Bordmitteln Appleskripts mit Benutzer-Interface zu schreiben. Aus dem Skript heraus wird dabei über das AppleScriptKit Framework direkt auf die Cocoa-Bibliotheken zugegriffen, auf dieselben Programmierbibliotheken also, die auch professionelle Programme verwenden. Dadurch lassen sich mit AppleScript Studio entwickelte Programme auf den ersten Blick nicht mehr von normalen Cocoa-Programmen unterscheiden. Der Nachteil von AppleScript Studio liegt nur in seiner Integration in der Entwicklungsumgebung Project Builder (später Xcode), die vor allem Anfänger mit ihren vielen für Skripter unnötigen Optionen abschreckt und einschüchtert. 2004 wird mit Erscheinen von Mac OS X 10.4 »Tiger« das Programm »Automator« eingeführt. Damit lassen sich Arbeitsabläufe und der Austausch von Informationen zwischen verschiedenen Programmen über eine grafische Schnittstelle automatisieren. Man muss also keine einzige Zeile Code mehr schreiben und kann trotzdem andere Anwendungen steuern, zum Beispiel alle Bilder in einem Ordner automatisch skalieren, umbenennen und auf einen FTP-Server ablegen. Solch ein Ablauf lässt sich mit wenigen Mausklicks in Automator erzeugen und dann immer wieder verwenden. Die Programmhersteller müssen nur sogenannte Aktionen erstellen, die sich dann von jedem Anwender in Automator nutzen lassen. Apple selbst ging mit gutem Beispiel voran und stattete viele seiner Programme mit solchen Aktionen aus. Auf den ersten Blick scheint Automator nichts mit AppleScript zu tun zu haben, unter der Haube beruht Automator aber auf Apple-Events, welche die Basis von AppleScript darstellen. So ist es nicht verwunderlich, dass in Automator auch Appleskripts verwendet werden können. Für den Fall, dass eine Anwendung nicht die passende Aktion bereitstellt, kann man sich so mit einem Appleskript selber helfen. Und in AppleScript Studio kann
32
Einführung
Kapitel 1
sich der kundige Anwender auch eigene Automator-Aktionen erstellen und diese anderen Anwendern zur Verfügung stellen. 2004 war dann aber auch das Jahr des Abschiednehmens. Nach langem Siechtum, das heißt nach lange stagnierender Weiterentwicklung, verschwand HyperCard aus den Verkaufsregalen bei Apple und ward nie mehr gesehen. Zum Leidwesen vieler Fans. Die Idee, dass jeder sein eigener Softwarehersteller sein kann und soll, war wohl zu revolutionär für den Markt oder seiner Zeit einfach zu weit voraus. 2007 erschien Mac OS X 10.5 »Leopard« und brachte auch für AppleScript wieder einige Neuerungen mit. Auf den ersten Blick nichts Spektakuläres, tatsächlich wird jedoch zum ersten Mal Unicode vollständig unterstützt. Dazu kommen, unter anderem, informativere Fehlermeldungen, zusätzliche Programmeigenschaften, Unterstützung für das Lesen und Schreiben von Property Lists und die übliche verbesserte AppleScript-Unterstützung von vielen Anwendungen und den Systemeinstellungen. Ordneraktionen werden unter Leopard jetzt vom Dateisystem ausgelöst und funktionieren damit endlich zuverlässiger. Automator entwickelt sich in Leopard immer mehr zu einer Workflow-Programmierumgebung – in Leopard sind nämlich eine AufnahmeFunktion sowie Workflow-Variablen und Schleifen hinzugekommen. Durch eine neue Scripting Bridge wird es in Leopard für andere Sprachen wie Ruby, Python oder Objective-C leichter, das Betriebssystem und Anwendungen über dieselbe Schnittstelle wie AppleScript zu steuern. Und: AppleScript bekommt seine eigene Shebang-Zeile und kann damit genauso wie Shell-, Perl-, Ruby- oder Pythonskripte als Textdatei vom Terminal automatisch kompiliert und ausgeführt werden. Diese Entwicklungen zeigen, dass AppleScript und die zugrundeliegende OSA-Architektur den Stellenwert einer Schlüsseltechnologie bei Apple einnehmen. Für die Zukunft von AppleScript stehen alle Tore offen.
Wofür AppleScript geeignet ist AppleScript ist zur Steuerung von Programmen gedacht – und darin brilliert es. Immer, wenn Sie sich über stetig wiederholende, wenig erquickende Fließbandarbeit am Macintosh ärgern, gibt es unter Garantie eine Lösung, diese Arbeit von einem Appleskript ausführen zu lassen, während Sie sich einen Kaffee holen. Spätestens wenn diese Arbeit öfters vorkommt, macht sich die Erstellung eines Skripts wirklich bezahlt. Die einfachste Art und Weise ist die, mit Automator einen Workflow zu erstellen. Diese Workflows sind
33
SmartBooks
AppleScript
nichts anderes als eine grafische Benutzeroberfläche zur Erstellung von automatisierten Abläufen. Man könnte so einen Workflow also auch von Hand mit AppleScript erstellen. Für den Nicht-Programmierer ist es aber natürlich einfacher, sich einen AutomatorWorkflow zusammenzuklicken. Trotz des Schwerpunkts auf der Steuerung von Programmen wird AppleScript auf Grund seiner schnell erlernbaren Sprache auch gerne zur Erstellung einfacher Programme verwendet, ob seit Urzeiten mit FaceSpan, oder seit Mac OS X 10.2 mit AppleScript Studio. Nicht für jede Aufgabe ist wirklich eine aufwendig programmierte Lösung in der Programmiersprache Objective-C mit den Cocoa-Bibliotheken nötig. Auch ein Appleskript kann auf Cocoa-Bibliotheken zugreifen, wodurch es von einem normalen Programm kaum noch zu unterscheiden ist. Viele Sharewareprogramme entpuppen sich so, bei näherer Untersuchung, als mit AppleScript Studio erstellte Programme. Vor allem aber ist man bei einfachen Aufgaben mit einem Appleskript viel schneller fertig. AppleScript Studio eignet sich damit auch zum schnellen »Prototyping«, also dem Erstellen eines ersten Entwurfs einer später in Objective-C zu programmierenden Anwendung.
Wofür AppleScript weniger geeignet ist AppleScript ist eine Skriptsprache, und Skriptsprachen zeichnen sich dadurch aus, dass sie interpretiert werden müssen, bevor die Befehle vom Computer ausgeführt werden. Naturgemäß sind sie daher langsamer als ein in Maschinencode übersetztes Programm. Erschwerend kommt hinzu, dass die aufwendige Benachrichtigungstechnik mit AppleEvents, die zwischen den Anwendungen und Objekten hin und her gesendet werden, zusätzliche Zeit benötigt. AppleScript ist damit also langsamer als Perl oder Python. Daraus ergibt sich, dass AppleScript nicht so gut geeignet ist für Anwendungen, die mit großen Datenmengen arbeiten. Möchten Sie zum Beispiel hunderte von Megabyte an Daten bearbeiten, ohne eine dafür spezialisierte Anwendung fernzusteuern, so müssen Sie sich damit abfinden, dass die Geschwindigkeit nicht berauschend ist. Auch das häufige Wechseln zwischen verschiedenen Anwendungen kostet Zeit. So ist es daher besser, nicht für jeden Datensatz von einer Anwendung zur anderen zu wechseln, sondern immer alles in einem Rutsch zu holen und abzuliefern. In der Praxis fällt dieser Nachteil aber erstaunlich selten ins Gewicht. Mit zunehmender Geschwindigkeit der Rechner werden inzwischen ja selbst die ursprünglich als langsam verschrienen Skriptsprachen wie Python zur Erstellung von ganzen Anwendungen verwendet.
34
Einführung
Kapitel 1
Und sollte es doch einmal nötig sein, die Schnelligkeit eines Skripts zu steigern, so lassen sich die zeitkritischen Teile eines Appleskripts auch jederzeit in eine andere Skriptsprache oder in ein C-Programm auslagern. Trotzdem ist AppleScript natürlich keine Programmiersprache zum Erstellen eines 3-D-Grafikspiels oder anderer Anwendungen, bei denen es auf Schnelligkeit ankommt. AppleScript ist eine Sprache, die nur auf dem Macintosh zu Hause ist. Es gibt kein AppleScript unter Windows oder Linux. Programmieren Sie dann besser in Sprachen wie Java oder Python.
Was Sie zum Erlernen von AppleScript brauchen Hier gibt es eine gute Nachricht: Die Software, die Sie für den Start brauchen, ist kostenlos. Sie brauchen sich für dieses Buch keine Software zu kaufen. Im Text wird zwar immer wieder auf kommerzielle Alternativen und deren Möglichkeiten und Vorzüge hingewiesen, deren Besitz ist aber in keinem Fall Vorraussetzung für das Verständnis für den Inhalt dieses Buches. Die Vorraussetzungen für die Arbeit mit diesem Buch lassen sich folgendermaßen zusammenfassen: << Alle Ausführungen beziehen sich auf AppleScript unter Leopard. Sie sollten daher einen Macintosh mit installiertem Mac OS 10.5 besitzen. Sie können den Großteil des Buches zwar auch mit einem Tiger-Betriebssystem (10.4) nachvollziehen, werden jedoch immer wieder auf Beschreibungen stoßen, die erst in Leopard funktionieren. << Sie benötigen den Skripteditor und die anderen Programme im Ordner /Programme/ AppleScript/. << Sie sollten sich im Mac-Betriebssystem auskennen. Sie brauchen kein Experte zu sein, sollten sich jedoch auf dem Mac zu Hause fühlen. Die grundlegende Bedienung eines Macs wird hier nicht erklärt. << Sie sollten über grundlegende Englischkenntnisse verfügen. Nicht weil der Rest des Buches auf Englisch geschrieben wäre, sondern weil AppleScript eine Sprache ist, die sich fast wie normales, natürliches Englisch schreibt und liest. Wenn Sie über einfache Englischkenntnisse verfügen, werden Sie daher allein durch Lesen eines Appleskripts schnell verstehen, was es macht. Durch Erschaffen einfacher englischer Satzkonstruktionen können Sie zudem erste legale AppleScript-Befehle geben. Sollten Sie später einmal die Original-Dokumentation von Apple verwenden, sind fundiertere Englischkenntnisse notwendig, denn die Entwicklerdokumentation liegt nicht in deutscher Übersetzung vor. 35
SmartBooks
AppleScript
<< Spaß am Programmieren ist zwar nicht unbedingt nötig, aber wie bei allen Dingen sehr hilfreich beim Erlernen. << Ach ja, dieses Buch brauchen Sie natürlich auch. Also nicht irgendwo liegen lassen!
36
Die Architektur
2
Dieses Kapitel behandelt die Architektur, die der Sprache AppleScript zugrunde liegt.
SmartBooks
AppleScript
OSA AppleScript beruht auf der Offenen Skriptarchitektur von Apple, auf Englisch Open Scripting Architecture oder abgekürzt OSA. OSA ermöglicht es, beliebige Sprachen zur Steuerung von Anwendungen über AppleEvents zu verwenden. Laut Dokumentation (http://developer.apple.com/documentation/AppleScript/ Conceptual/AppleScriptX/) steht es auf vier Säulen: << Der Apple Event Manager ist die zentrale Schaltstelle für das Senden und Empfangen von Apple-Events und stellt allen Programmen ein Programmierinterface (Application Programming Interface, kurz API) zum Senden und Empfangen von Apple-Events zur Verfügung. Er ist damit auch die Basis zur Erstellung eines skriptbaren Programms. Der Apple-Event-Manager ist auf Dateiebene als AE.framework im CoreServices.framework im Ordner /System/Library/Frameworks/ zu finden (Entwicklerdokumentation: Apple Event Manager Reference und Apple Events Programming Guide). << Das Carbon Framework definiert im HIToolbox.framework (einem Subframework von Carbon.framework) verschiedene Funktionen, die für das Verarbeiten von AppleEvents gebraucht werden (zum Beispiel in der Header-Datei AEInteraction.h). << Das Open Scripting Framework definiert die grundlegenden Datenstrukturen und Funktionen, die für das Erstellen von scripting components zur Unterstützung einer Skriptsrache nötig sind. Es gibt auch einen Befehl scripting components in AppleScript, der Ihnen die installierten Sprachen zurückliefert. Auf einem frisch installierten Mac OS X ist das nur AppleScript, nach Installation des Script Debuggers auch JavaScript und AppleScript Debugger X. Das OpenScripting.framework liegt auf Dateiebene als Sub-Framework im Carbon.framework vor. << Eine Sprache wie AppleScript ist eine Komponente des Open Scripting Frameworks und ruht als AppleScript.component unter /System/Library/Components. Andere Sprachkomponenten wie zum Beispiel JavaScript werden meist unter ~/Library/ Components, also in der Library des Benutzers installiert. Alle installierten Sprachen sind im Open Scripting Framework eingebettet. Für die Kommunikation verwendet OSA die sogenannten Apple-Events. Das sind verschachtelte Datenstrukturen, die jeweils durch vier aufeinander folgende Buchstaben, die »rohen« Apple-Event-Codes, definiert werden. Man bekommt sie manchmal zu sehen, wenn die angesprochene Anwendung nicht vorhanden ist oder wenn eine bestimmte Klasse nicht übersetzt wurde, wie zum Beispiel die Klasse «class utf8» für Text in Unicode-
38
Die Architektur
Kapitel 2
UTF8-Kodierung. Die Struktur der Apple-Events wird im Apple-Events Programming Guide von Apple beschrieben. Skriptbare Anwendungen
Editoren sind teilweise auch selbst wieder skriptbare Anwendungen
Skripteditor
Programm A
Apple Events
Apple Events
Programm B
Programm C
…
Apple Events
Apple Events
Apple Events
Apple Event Manager
AppleScript
JavaScript
…
Smile
Editoren
Script Debugger
Open Scripting Framework
Skripteditor
OSA – Open Scripting Architecture
Abb. 2-1 Die Open Scripting Architecture Wenn Sie sich die Struktur von OSA in der grafischen Übersicht ansehen, so wird klar, dass jede skriptbare Anwendung über den Apple-Event-Manager als Schnittstelle mit jeder beliebigen OSA-Sprache steuerbar ist. Das bedeutet auch, dass selbst wenn sich einzelne Anwendungen untereinander überhaupt nicht verstehen, sie sich doch immer über den Apple-Event-Manager miteinander austauschen können. Wenn gewünscht, kann sich also jedes Programm diese Architektur zunutze machen, um mit jedem anderen Programm zu kommunizieren. Üblicherweise lebt in einer monolithischen Programmlandschaft jedes Programm ein Leben ganz alleine für sich. Der Austausch zu anderen Programmen ist streng auf die Export- und Importformate beschränkt. So stehen in einem Betriebssystem dann eine Menge mehr oder weniger dicker Programmriesen wie Wolkenkratzer nebeneinander, jeder für sich durchaus ein Meisterwerk – meistens –, und doch können sie sich untereinander kaum austauschen, zumal, wenn sie nicht vom selben Hersteller stammen. Aber egal, solange die Anwendung skriptbar ist, können Sie mit einer OSA-Sprache wie AppleScript wie eine Maus in jeden Wolkenkratzer hineinfinden, an alle Schätze dort drinnen gelangen – an die Daten und Befehle – und sich holen oder verwenden, was Sie
39
SmartBooks
AppleScript
möchten, um dann zu einem anderen Programm zur Weiterbearbeitung zu wechseln. Sie sind nicht mehr darauf angewiesen, was Ihnen der Softwarehersteller an Austauschformaten oder Verarbeitungsmöglichkeiten anbietet. Ein AppleScript ist klein wie eine Maus, kommt überall hinein und an alles heran.
Sprachkomponenten Jede Sprache kann sich die modulare Architektur der Open Scripting Architecture zunutze machen. Von Apple selber wird nur AppleScript angeboten. AppleScript ist die Standard-Skriptsprache des Mac OS X Betriebssystems. Wenn nicht explizit eine andere Sprache angegeben wird, so geht das System daher immer davon aus, dass das Skript in der Sprache AppleScript vorliegt. OSA-Sprachen werden im Ordner Components eines Library-Ordners abgelegt und damit auch installiert. Normalerweise ist das der Library-Ordner im Heimverzeichnis des angemeldeten Benutzers. Wenn die Sprache aber mehreren Anwendern auf dem Rechner zur Verfügung stehen soll, kann sie auch unter /Library/Components/ abgelegt werden. Die Sprache AppleScript liegt als Grundbestandteil von Mac OS X im Library-Ordner des Systems /System/Library/Components/. Wenn Sie eine andere OSA-Sprache installieren, sollten Sie sich danach abmelden und neu anmelden. Danach lassen sich die so installierten Sprachen im Skripteditor oder Script Debugger im Einblendmenü der Steuerungsleiste auswählen. Dabei hat es nie viele OSA-Sprachen für den Mac gegeben. Wahrscheinlich deshalb nicht, weil sich nie eine große Notwendigkeit für weitere Sprachen ergeben hat. Zurzeit sind mir folgende OSA-Sprachkomponenten bekannt: << Von Late Night Software gibt es eine Implementation für JavaScript als OSA-Sprache. Diese Komponente kann von der Webseite des Herstellers heruntergeladen und installiert werden. Die Komponente ist für den persönlichen Bedarf kostenlos (http:// www.latenightsw.com/freeware/JavaScriptOSA/index.html). << Die bei weitem umfangreichste Sammlung an OSA-Sprachen bietet Philip Aker mit seinen OSA Components an, zu finden unter http://www.vcn.bc.ca/~philip/osa/. Mit einer einzigen Installation erhalten Sie im Skripteditor Unterstützung für die Sprachen Perl, Python, Ruby, sh und Tcl. Die Komponenten sind ebenfalls für den nichtkommerziellen Einsatz kostenlos. << Für Python ist mir noch PyOSA als Alternative bekannt: http://appscript.sourceforge. net/pyosa/.
40
Die Architektur
Kapitel 2
Abb. 2-2 Verschiedene OSA-Komponenten Wenn Sie solch eine OSA-Sprache installiert haben (in den Ordner ~/Library/Components/), können Sie nach erneutem Anmelden im Skripteditor oder Script Debugger die Sprache in der Steuerungsleiste auswählen, ein Skript in dieser Sprache schreiben und es zum Beispiel als Applet oder Droplet abspeichern – eine einfache Methode, um mit den erwähnten Sprachen auf die Schnelle ein Programm zu erstellen, welches per Doppelklick läuft. Inwieweit diese Sprachkomponenten auch Gebrauch vom Apple-Event-Manager machen und Sie damit Zugriff auf skriptbare Programme erhalten, entnimmt man am besten der Dokumentation der Komponente oder man fragt den Entwickler selbst. Ein anderer Weg, eine Skriptsprache an OSA anzukoppeln, ist die Verwendung spezieller Bibliotheken zum Senden und Empfangen von Apple-Events. Für Perl reicht eine einfache Suche über http://search.cpan.org/ nach den Suchwörtern OSA, Apple Event oder AppleScript aus, und Sie erhalten eine Vielzahl von Modulen, die sich um dieses Thema drehen. Für Python existieren die Macintosh Library Modules mit dem MacPython OSA Module, siehe http://www.python.org/doc/2.5.1/mac/mac.html sowie py-appscript http:// appscript.sourceforge.net. Für Ruby gibt es RubyOSA und rb-appscript, zu finden in der Rubyforge unter http:// rubyosa.rubyforge.org/ und der Sourceforge unter http://appscript.sourceforge.net. Für eine andere Sprache als AppleScript ist die Ankoppelung an den Apple-Event-Manager oder die Einbindung als Komponente in das Open Scripting Framework die einzige Möglichkeit, ebenfalls Zugriff auf die innere Struktur eines Programms zu erhalten – es sei denn, das Programm bietet eine spezielle Schnittstelle für eben diese Skriptsprache an.
41
SmartBooks
AppleScript
Ebenfalls zu erwähnen ist, dass man auch mit einem do shell script (Kapitel 5 und 8) aus einem Appleskript heraus ein Skript einer anderen Sprache aufrufen kann. Die Sprachen lassen sich also auch untereinander mischen, womit jeweils immer die Sprache verwendet werden kann, die für eine Aufgabe am besten geeignet ist oder in der man sich am besten auskennt.
Skripterweiterungen AppleScript kann durch sogenannte Skripterweiterungen (Scripting Additions) in seinem Sprachumfang erweitert werden. Eine Skripterweiterung ist das, was in anderen Sprachen als »Bibliothek« oder »Modul« bezeichnet wird. Eine Skripterweiterung muss jedoch nicht vorher im Skript geladen oder importiert werden, sie steht dem Skript nach der Installation automatisch zur Verfügung. Es ist auch keine Adressangabe nötig, wo dieser Befehl zu finden ist (weder Punktnotation, noch tell, noch irgendeine andere Form der Adressierung), im Gegensatz zu den Befehlen aus dem Funktionsverzeichnis einer Anwendung, wo immer eine Adressierung nötig ist. Einem Befehl aus einer Skripterweiterung kann man also im Code nicht ansehen, dass er nicht zur Stammsyntax von AppleScript gehört. Eine Scripting Addition besteht aus einer einzelnen Datei, meist im Bundle-Format und mit der Endung osax versehen. Eine solche Datei wird im Ordner ScriptingAdditions eines Library-Ordners installiert, meist im Library-Ordner der lokalen Domain (/Library/ScriptingAdditions/), wenn die Erweiterung für alle Benutzer auf dem Rechner zur Verfügung stehen soll, ansonsten in der User-Domain (~/Library/ScriptingAdditions). Beide Ordner sind bei einem frisch installierten Mac OS leer oder nicht vorhanden und müssen daher noch von Hand angelegt werden.
Abb. 2-3 Eine Skripterweiterung hat meist einen stilisierten Baustein mit einer Schriftrolle und einem Pluszeichen als Icon. Im Ordner ScriptingAdditions des Systems (/System/Library/ScriptingAdditions/) sind ab Werk bereits folgende Erweiterungen installiert:
42
Die Architektur
<< ColorSyncScripting.app
Kapitel 2
Befehle zum Skripten von Farbräumen und Farbprofilen
<< Digital Hub Scripting.osax Handler, die beim Einbinden eines Laufwerks aktiv werden (Kap. 6) << FontSyncScripting.app
Skripten von Fontprofilen und der Font-Synchronisierung
<< Keychain Scripting.app
Skript-Interface für den Zugriff auf den Schlüsselbund
<< StandardAdditions.osax
Eine Vielzahl unterschiedlicher Erweiterungen (Kap. 5)
<< URL Access Scripting.app Zwei alte, einsame Befehle zum Down- und Upload von Dateien Apple platziert hier, wie oben zu sehen, auch mehrere Programme mit der Endung app. Wenn Sie Befehle aus diesen Programmen verwenden, müssen Sie ein tell verwenden, da diese keine Skripterweiterungen sind, sondern normale Programme. Warum Apple manche dieser »gesichtslosen« Programme, die nur der Steuerung mit AppleScript dienen, hier platziert und andere (System Events, Image Events, Database Events) im Ordner /System/ Library/CoreServices/, entzieht sich meinem Verständnis. Die Standarderweiterung StandardAdditions.osax ist dabei, wie der Name schon sagt, inzwischen zu einem Standard geworden und wird fast in jedem Skript verwendet. Man kann sich darauf verlassen, dass sie auf jedem System installiert ist. Die anderen Erweiterungen (oder Programme) widmen sich ganz speziellen Themeninhalten. Um eine Erweiterung in einem Skript zu verwenden, muss diese nicht, wie in anderen Sprachen, zuerst importiert oder geladen werden – dadurch, dass sie auf dem Betriebssystem in einem der ScriptingAdditions-Ordner liegt, steht sie sofort zur Verfügung. Beim Kompilieren eines Skripts wird an dieser Stelle im Betriebsystem nach den Bibliotheken gesucht, um die Namen von unbekannten Befehlen und Klassen nachzuschlagen. Vorher kann das Skript nicht kompiliert werden. Namenskonflikte sind bei Skripterweiterungen möglich. Es sind keine getrennten Namensräume vorgesehen. Wenn zwei Erweiterungen denselben Namen für einen Befehl oder eine Klasse verwenden, gibt es Probleme im Skript, und eine der Erweiterungen sollte entfernt werden, oder man bittet den Entwickler einer der Erweiterungen darum, den Namen zu ändern. Manchmal verwenden Skripterweiterungen daher ein Kürzel am Anfang oder Ende eines Begriffs, um solche Konflikte zu vermeiden. Aus diesem Grund und auch aus Gründen des Speichermanagements (jede Erweiterung muss auch in den Speicher geladen werden) sollten nach Möglichkeit keine oder nur so wenig Erweiterungen wie möglich zusätzlich installiert werden. Vergessen Sie daher nicht, eine einmal ausprobierte Erweiterung, die nicht mehr gebraucht wird, aus dem Ordner ScriptingAdditions wieder zu entfernen.
43
SmartBooks
AppleScript
Power User Die Verwendung von nicht ab Werk installierten Erweiterungen hat natürlich auch den Nachteil, dass eine solche Anwendung dann nicht mehr alleine auf anderen Systemen lauffähig ist. Das Skript kann dort erst funktionieren, wenn auch die Erweiterung installiert wurde. Dieses Problem lässt sich nur umgehen, wenn es die Lizenz der Skripterweiterung erlaubt, die Erweiterung mit in das Skript-Bundle oder Programm-Bundle zu packen. Eine Skripterweiterung muss sich dort in einem Ordner Scripting Additions (hier seltsamerweise mit Leerstelle) im Ordner Contents/Resources/ befinden, um erkannt zu werden. Ab sofort können Sie Ihr Skript mit Erweiterung im Bundle auch auf einem anderen Rechner verwenden, ohne dort erst die Erweiterung manuell installieren zu müssen (siehe Kapitel 3 zur Struktur eines Skript-Bundles). Wo findet man nun Erweiterungen? Die bekanntesten sind die von Smile, die fast jeder auf seinem Rechner hat, wenn er Smile einmal ausprobiert hat. Die Befehle darin sollten die erste Anlaufstelle bei der Suche nach weiteren Funktionen sein. Danach ist ein Blick auf das Quellverzeichnis aller OSAXen schlechthin unter http://www.osaxen.com zu empfehlen. Da AppleScript schon sehr alt ist, sollten Sie hier auch immer einen Blick auf das Datum werfen und nachsehen, ob die entsprechende Erweiterung unter OS X funktioniert. Das Funktionsverzeichnis der Erweiterung kann man bereits auf der Webseite einsehen, was einem das unnötige Herunterladen erspart. Generell muss eine OSAX-Datei in einem Bundle-Format vorliegen, wenn sie auf einer Intel-Maschine funktionieren soll. Alte Eine-Datei-OSAXen funktionieren nur noch auf PowerPC-Maschinen. Wie kann man sich die Befehle, die eine Skripterweiterung zur Verfügung stellt, ansehen, nachdem man diese heruntergeladen hat? Einfach die Skripterweiterung mit der Endung osax doppelklicken oder auf den Skripteditor ziehen. Dieser öffnet daraufhin das Funktionsverzeichnis. Die Skripterweiterung muss dafür nicht im ScriptingAdditions-Ordner liegen. Der Umgang mit Funktionsverzeichnissen wird in Kapitel 3 und im praktischen Einsatz in Kapitel 4 erklärt.
Funktionsverzeichnisse Wenn ein Programm skriptbar ist, also mit AppleScript gesteuert werden kann, dann teilt es dieses der Umwelt über ein sogenanntes Funktionsverzeichnis (Dictionary) mit. In diesem Funktionsverzeichnis sind die Objekte und Befehle des Programms dokumentiert. Damit kann ein Skripteditor (genauer die AppleScript-Komponente) dann herausfinden, ob die in einem Skript verwendete Terminologie für dieses Programm überhaupt gültig ist. Das Funktionsverzeichnis gibt damit auch an, welche Teile im Programm skriptbar sind.
44
Die Architektur
Kapitel 2
Die nicht erwähnten Bestandteile sind damit offensichtlich nicht erreichbar. Es liegt also ganz in der Hand des Programms und nicht etwa in der Hand von OSA oder AppleScript, was sich an dem Programm genau steuern lässt! Aber nicht nur Skripteditoren schauen sich dieses Funktionsverzeichnis an, auch der Anwender kann das, schließlich ist er es, der die Befehle in der Sprache des Programms geben muss. Ob eine Tabelle in einem Programm nun als table oder spreadsheet angeredet werden will, das und mehr kann zuvor im Funktionsverzeichnis nachgeschlagen werden. In einem Skripteditor, der auf die Belange eines OSA-Skripts zugeschnitten ist, wie bei den drei Editoren Smile, Script Debugger und Skripteditor (siehe Kapitel 3 für eine Beschreibung dieser Programme), gibt es immer auch einen Menüpunkt im Ablage/File-Menü, mit welchem sich das Funktionsverzeichnis eines Programms einsehen lässt. Es reicht aber auch aus, das Programm auf das Icon des Editors zu ziehen. In der folgenden Abbildung sehen Sie ein Beispiel aus dem Script Debugger.
Abb. 2-4 Das Funktionsverzeichnis des Programms Mail im Script Debugger Solch ein Funktionsverzeichnis kann dabei historisch gewachsen in drei verschiedenen Formaten vorliegen. Für die Betrachtung in einem Skripteditor macht das (fast) keinen Unterschied aus, wohl aber für den Entwickler von skriptbaren Anwendungen.
45
SmartBooks
AppleScript
Als deutscher Anwender muss man sich nur damit abfinden, dass Funktionsverzeichnisse immer nur in englischer Sprache vorliegen. Die folgenden Formate sind also nicht bei der Betrachtung eines Funktionsverzeichnisses in einem Skripteditor erkennbar, sondern erst, wenn man in das Bundle des Programms hineinschaut: << aete – Dies ist das älteste Format für ein Funktionsverzeichnis. Es wird seit Bestehen von AppleScript verwendet und ist auch heute noch in vielen Anwendungen zu finden, die auf Carbon basieren oder ihre Ursprünge dort haben. Der Name aete steht dabei für die Ressource mit dem Namen 'aete'. Solche Ressourcen wurden früher in der Resource-Fork einer Datei abgespeichert, heutzutage im Datenteil. Die Datei mit dem Funktionsverzeichnis liegt üblicherweise im Resource-Ordner des Programm-Bundles. Resource-Dateien haben die Endung rsrc. Die Dokumentation findet sich auf den Developer-Seiten von Apple (http://developer. apple.com) in Inside Macintosh:Interapplication Communication und Resource Manager Reference. Auf Dateiebene benötigt man einen Resource-Editor, um in solch eine Datei hineinzuschauen. Nachdem das Programm ResEdit von Apple nicht für Mac OS X weiterentwickelt wurde, ist der altehrwürdige Resorcerer von http://www.mathemaesthetics. com das einzige professionelle Produkt. Alternativen gibt es noch in ResKnife und Rezilla, beide in der Sourceforge zu finden. Ansonsten erzeugt oder verändert man solch eine Datei direkt durch Aufruf des Resource Managers aus einer Programmiersprache heraus. Damit das aete-Funktionsverzeichnis eines Programms gelesen werden kann, muss das Programm laufen. Wenn also zum Beispiel im Skripteditor das Funktionsverzeichnis eines Programms mit einer aete aufgerufen wird und das Programm noch nicht läuft, wird es vorher automatisch gestartet. Das Programm muss das Funktionsverzeichnis liefern, es kann nicht direkt gelesen werden. << script suite – Dieses Format wird üblicherweise von Cocoa-Programmen verwendet. Es handelt sich hierbei um Property list files (in XML), die für eine strukturierte Ansicht am besten mit dem Programm Property List Editor (Bestandteil der XcodeEntwicklungsumgebung) geöffnet werden. Aber auch mit jedem Texteditor ist der Inhalt einsehbar. Für jede Suite (eine Suite ist eine thematische Gruppe von Befehlen und Klassen) existieren zwei Dateien, eine mit der Endung scriptSuite und eine mit der Endung scriptTerminology. Die erste wird von der Anwendung selber verwendet, die zweite vom Anwender. Wie üblich, so befinden sich diese Dateien im ResourceOrdner des Programm-Bundles. Die Dokumentation findet sich auf den DeveloperSeiten im Cocoa Scripting Guide. Auch bei diesem Format muss das Programm laufen, bevor das Funktionsverzeichnis angezeigt werden kann.
46
Die Architektur
Kapitel 2
<< sdef – Dies ist das neueste Format von Apple und wird seit Mac OS X 10.4 für CocoaProgramme empfohlen. Das Kürzel sdef steht für scripting definition. Das Format ist XML, beinhaltet alle Bestandteile der Formate aete und script suite und ist darüber hinaus erweitert und verbessert worden. Für den Anwender sind vor allem die erweiterten Dokumentationsmöglichkeiten, die ihm beim Betrachten eines Funktionsverzeichnisses in seinem Skripteditor zu Gute kommen können, interessant – wenn denn die Programmierer davon Gebrauch machen und der verwendete Skripteditor diese Informationen auch anzeigt. Eine solche Datei liegt üblicherweise ebenfalls im Resource-Ordner des Programms vor und trägt das Dateikürzel sdef. Sie kann mit jedem XML-Editor oder mit einer Textverarbeitung geöffnet werden. Die Dokumentation liegt als man-page vor, einfach man 5 sdef im Terminal eingeben. Ein sdef-Funktionsverzeichnis kann direkt ausgelesen werden, ohne dass das Programm läuft – was alleine schon einen großen Fortschritt darstellt. Eine Anwendung mit einem sdefFunktionsverzeichnis ist dafür aber erst ab Mac OS X 10.4 skriptbar. Tipp Auch die Sprache AppleScript selbst hat ein Funktionsverzeichnis. Es ist nur leider nicht aus dem Skripteditor heraus einsehbar. Das Funktionsverzeichnis von AppleScript verbirgt sich im Bundle der AppleScript.component unter /System/Library/Components/ (als AppleScript.rsrc) und kann zurzeit nur vom Script Debugger oder Smile angezeigt werden. Im Script Debugger einfach File | Open Dictionary | AppleScript auswählen, in Smile Ablage | Verzeichnis öffnen | AppleScript. Darin finden Sie dann auch noch viele »Altlasten«: alte Klassen, die keine Rolle mehr spielen und nur noch aus Kompatibilitätsgründen enthalten sind, oder Klassen, die nie implementiert wurden. Ein Blick in dieses Funktionsverzeichnis kann daher auch helfen herauszufinden, warum ein Bezeichner, den Sie vielleicht für eine Variable vergeben haben, im Skripteditor in der Farbe eines Schlüsselworts angezeigt wird, obwohl Ihnen der Begriff bisher noch nie in AppleScript begegnet ist. Sehr wahrscheinlich werden Sie diesen Begriff dann entweder im Funktionsverzeichnis von AppleScript oder in dem einer Skripterweiterung finden.
Anwendungen Ein Programm kann sich auf vielfältige Art und Weise an OSA ankoppeln. Die Bandbreite reicht von der nicht-skriptbaren Anwendung bis zur Anwendung, die sich per AppleScript umbauen lässt. Dieser Abschnitt soll Ihnen einen Überblick über die Möglichkeiten geben, so dass Sie wissen, worauf Sie bei einem unbekannten Programm achten können. Bei jeder Anwendung kann die Integration in OSA wieder anders aussehen. Maßgeblich ist daher letztlich immer die Dokumentation der Anwendung selber.
47
SmartBooks
AppleScript
Nicht-skriptbare Anwendungen Eine Anwendung, die nicht skriptbar ist, erkennt man daran, dass sie kein Funktionsverzeichnis hat. Wenn Sie also eine Anwendung auf den Skripteditor ziehen und sich kein Funktionsverzeichnis öffnet, kann diese Anwendung nicht mit AppleScript gesteuert werden. Das bedeutet, dass bei der Programmierung der Anwendung keine Anstrengung darauf verwendet oder dass sie nicht mit dem Carbon- oder Cocoa-Framework erstellt wurde. Trotzdem reagiert aber auch diese Anwendung auf die grundlegenden Befehle wie open, run und quit. Ansonsten kann man nur noch mittels GUI-Scripting (siehe Kapitel 7) auf die Menüs, Knöpfe und Textfelder in diesem Programm zugreifen. Der direkte Zugriff auf die Objektstruktur im Programm bleibt einem verwehrt.
Skriptbare Anwendungen Damit eine Anwendung mit einer OSA-Sprache gesteuert werden kann, muss dies bei der Entwicklung der Software bereits mit ein wenig Mühe eingeplant werden, das gilt für sowohl das Carbon- als auch für das Cocoa-Framework. Aber auch wenn eine Anwendung skriptbar ist, also ein Funktionsverzeichnis besitzt, sagt das noch nichts über die Qualität der Zugriffsmöglichkeiten aus. Eine gut durchdachte Objektstruktur und Zugriffsmöglichkeiten darauf vorausgesetzt, lässt sich in einem Programm wirklich an alles herankommen und alles automatisieren. Es kann aber auch sein, dass das Funktionsverzeichnis zwar einige grundlegende Datentypen wie die Text-Suite von AppleScript übernommen hat, aber ansonsten nichts Eigenes dazu beiträgt. Mit anderen Worten, die Skriptbarkeit lässt stark zu wünschen übrig. Inwieweit ein Programm skriptbar ist, hängt also ganz alleine von den Programmierern des Programms ab. Auch die Terminologie und die Begriffe, die für die Befehle und Objekte verwendet werden, liegen ganz in deren Ermessen. So ist es durchaus normal für einen Appleskripter, dass sich Begriffe für ein und dasselbe Objekt von einer Anwendung zur anderen unterscheiden. Ob ein Rechteck nun rect oder rectangle genannt werden will, liegt im Ermessen des Programmierers. Das stellt dann die einzige große Herausforderung beim Programmieren mit AppleScript dar. Bei jeder Anwendung, die man steuern möchte, muss man sich erst einmal mit dem Funktionsverzeichnis dieser Anwendung vertraut machen. Grundlegende Befehle gleichen sich dabei in fast jeder Anwendung, da sie von AppleScript übernommen werden. Trotzdem kann es immer wieder mal zu Überraschungen und ungewohnten Implementierungen kommen.
Aufzeichnungsfähige Anwendungen Eine Anwendung, die nicht nur mit Apple-Events gesteuert werden kann, sondern deren Aktionen sich sogar aufzeichnen lassen, nennt man aufzeichnungsfähig (recordable). Dies wird einfach dadurch erreicht, dass sich die Anwendung bei jeder Aktion, die sie ausführt, selber ein Apple-Event sendet. Dieses Apple-Event kann dann durch eine AufzeichnenFunktion wie im Skripteditor aufgenommen werden. Die Apple-Events werden dabei anhand des Funktionsverzeichnisses der Anwendung in die Sprache AppleScript übersetzt.
48
Die Architektur
Kapitel 2
Angezeigt wird Ihnen also der fertige AppleScript-Code, den Sie so direkt wieder verwenden können, um die Aktion erneut auszuführen. Diese Fähigkeit ist nur bei sehr wenigen Anwendungen zu finden, darunter dem Finder. Naturgemäß können nur die Aktionen aufgezeichnet werden, in denen sich das Programm selbst ein Apple-Event sendet. Mit anderen Worten: Es wird nicht unbedingt jede Aktion tatsächlich aufgenommen. Wird bei einer Aktion kein Apple- Event gesendet, kann dieser Schritt auch nicht aufgezeichnet werden. Das Aufzeichnen kann Ihnen bei einer unbekannten Anwendung erste Hinweise darauf geben, wie sich diese Anwendung steuern lässt. Es stellt keine Alternative für das Erstellen eines vollwertigen Skripts dar.
Anwendungen, die Skripts ausführen können Eine Anwendung kann einem Skript auch einen Platz in sich einräumen, von dem aus es gestartet werden kann. Am beliebtesten sind Menüs. Diese tragen dann meistens das Symbol der AppleScript-Schriftrolle. Beispielsanwendungen sind RagTime, iTunes, GraphicConverter, BBEdit, TextWrangler und viele andere. Damit ein solches Appleskript in dem entsprechenden Menü auftaucht, muss es üblicherweise an einem bestimmten Ort abgelegt werden. Bei iTunes ist es der Ordner ~/Library/iTunes/Scripts, bei TextWrangler der Ordner ~/Library/Application Support/TextWrangler/Scripts/, beim GraphicConverter /Library/Application Support/GraphicConverter/Scripts/. Bei RagTime, muss das Skript im Dokument oder in den Voreinstellungen des Programms gespeichert sein. Im Zweifelsfall ist hier immer die Programmdokumentation zu fragen – zumal das Skript-Menü oft erst erscheint, wenn der Ordner auch vorhanden ist. Aber nicht nur vom Menü eines Programms können Skripts gestartet werden, auch aus allen möglichen anderen, von den Herstellern des Programms zugewiesenen Plätzen. In FileMaker kann ein Appleskript zum Beispiel als Text im Programm gespeichert werden. Das Appleskript lebt also in der Datenbank und nicht als gesonderte Datei auf der Festplatte. In RagTime kann ein Appleskript im Dokument selbst enthalten sein und dann aus dem Dokument heraus (entweder über Menüauswahl oder durch Drücken eines selbst angelegten Knopfes) ausgeführt werden. Je nach Programm kann es zu ganz eigenen Arten der Ausführung eines Skripts kommen. Die Dokumentation zu diesem Programm ist auch hier immer die erste Anlaufstelle, da Apple auf die Art der Integration keinen direkten Einfluss hat.
Anwendungen, die Skripts erstellen können Bei Programmen, die ein OSA-Skript erstellen können, sind zuallererst einmal die reinen Skripteditoren zu nennen. Das sind der Skripteditor von Apple, der Script Debugger von Late Night Software und Smile von Satimage. Aber auch Automator und AppleScript Studio können ein AppleScript erstellen. Manche dieser Programme sind dabei sogar selber
49
SmartBooks
AppleScript
wieder skriptbare Anwendungen, nehmen also eine Doppelrolle ein. Sie können mit dem Skripteditor zum Beispiel auch ein Skript schreiben, welches den Skripteditor steuert, ein Skript zu schreiben und auszuführen. Das lässt sich dann ausnutzen, um wiederkehrende Abläufe im Skripteditor zu automatisieren oder um Skripts zeitnah am augenblicklichen Bedarf maßgeschneidert automatisch zu erstellen. Aber auch Programme mit gänzlich anderem Schwerpunkt können einen eingebauten Editor besitzen. Das Layoutprogramm RagTime besitzt zum Beispiel einen eingebauten Editor für AppleScript, so dass man in RagTime selbst ein Skript erstellen kann. Das Skript kann dann wahlweise im Dokument oder in den Voreinstellungen des Programms gespeichert werden.
Anwendungen, die es erlauben, Skripts an Programmobjekte anzuhängen Eine weitere Stufe der Skriptbarkeit ist es, wenn ein Programm es erlaubt, ein Skript an ein Objekt dieses Programms anzuhängen (attachable). Beispiele sind die Ordneraktionen im Finder, wo ein Skript an einen Ordner »angehängt« werden kann. Dieses Skript wird dann ausgeführt, wenn eine bestimmte Aktion an diesem Ordner auftritt. In Mail kann ein Skript an eine Mailregel angehängt werden und wird dann mit dieser Regel ausgeführt, und in iCal kann ein Skript ausgeführt werden, wenn ein bestimmter Termin eingetreten ist. Wenige Anwendungen nutzen bisher diese Möglichkeit. In FileMaker und RagTime lässt sich ein Skript an einen Knopf anhängen. Das Skript wird dann ausgeführt, wenn der Knopf gedrückt wird.
Anwendungen, die es erlauben, das Programm selber umzubauen Wenige Programme gehen noch einen Schritt weiter und erlauben es dem Anwender, das Programm per Skript sogar zu modifizieren. Der Skripteditor bietet zum Beispiel die Möglichkeit, den Inhalt des Kontextmenüs zu bestimmen. Weiter geht die Anpassbarkeit hier aber nicht. Smile geht von allen mir bekannten Programmen noch am weitesten. Laut Dokumentation lässt es sich per AppleScript zum Beispiel mit eigenen Werkzeugleisten und Kontextmenüs versehen. Über die darin angehängten Skripts lässt sich nicht nur das äußere Erscheinungsbild von Smile verändern, sondern auch dessen Funktionalität erweitern.
50
Das Handwerkszeug
3
Überblick und Einführung in die Handwerkszeuge und Hilfsmittel zum Erstellen und Verwalten eines Appleskripts.
SmartBooks
AppleScript
AppleScript-Editoren AppleScript wird traditionell immer in einem speziellen Editor erstellt und nicht, wie in anderen Skriptsprachen üblich, in einer einfachen Textdatei. Ein AppleScript existiert immer nur in kompilierter Form. Der Text, den Sie nach dem Öffnen eines Skripts zu sehen bekommen, ist tatsächlich das Produkt einer Dekompilierung (Rückübersetzung), die beim Öffnen des Skripts stattfindet. Beim Sichern eines Appleskripts wird es immer in kompilierter Form gespeichert. Ein AppleScript nur als Text zu schreiben und zu speichern und dann erst bei Bedarf zu übersetzen, ist also normalerweise nicht möglich. Zumindest war das früher so. Mit Mac OS X wurde AppleScript langsam, aber sicher ebenfalls in die Unix-Basis integriert, was zur Folge hat, dass sich AppleScript mehr und mehr wie jede andere Skriptsprache im System verhält. Mit Mac OS X 10.5 ist wieder einer dieser Schritte erfolgt. Ein Appleskript lässt sich nun mit einer sogenannten Shebang-Zeile auch in einfachen Textdateien erstellen. Am komfortabelsten ist und bleibt natürlich die Arbeit in einem Editor, der ganz auf die Belange von AppleScript ausgerichtet ist und die Syntax durch Formatierungen verdeutlicht und schnell auf Fehler aufmerksam macht. Auf jedem Mac OS X-System findet sich dafür der Skripteditor von Apple. Einfach, schlank und für fast alle Fälle ausreichend, können Sie damit direkt loslegen. Daneben gibt es noch zwei kommerzielle Alternativen: SmileLab und Script Debugger. Der ungekrönte König der AppleScript-Editoren ist dabei der Script Debugger von Late Night Software. SmileLab glänzt dafür mit seinen hervorragenden grafischen Fähigkeiten für den wissenschaftlichen Einsatz. Wenn Sie nur ab und zu mal ein Appleskript erstellen, reicht der Skripteditor von Apple vollständig aus, und nur dieser wird in diesem Buch vorausgesetzt.
Der Skripteditor Der Skripteditor liegt im Ordner /Programme/AppleScript/. Die Version des Skripteditors zum Zeitpunkt der Erstellung dieses Buches ist die Version 2.2. Wenn Sie den Skripteditor öffnen, erscheint ein zweigeteiltes Fenster wie in der folgenden Abbildung.
52
Das Handwerkszeug
Kapitel 3
Abb. 3-1 Der Skripteditor Falls die Symbolleiste oder die Steuerleiste ausgeblendet sind, so blenden Sie diese bitte über das Menü Darstellung ein.
Der Editorbereich Der obere Teil des Editors ist der Ort, an dem Sie das Appleskript schreiben. Schreiben Sie dort einmal folgende Zeile hinein: display dialog "Hallo Welt!"
Schreiben Alles, was Sie in den oberen Bereich schreiben, ist erst einmal nur reiner Text. Der Skript editor verhält sich in der Handhabung identisch zu anderen Textverarbeitungen, wie zum Beispiel TextEdit. Ihnen stehen daher fast alle Werkzeuge einer Textverarbeitung zur Verfügung. Obwohl Sie fast alle Formatierungen im Text verwenden können, sollten Sie beim Schreiben jedoch Abstand davon nehmen. Einige der Befehle sind zwar inaktiv, aber nicht alle. Sie könnten zum Beispiel display dialog auch kursiv schreiben oder mit einer anderen Schrift. Diese Formatierungen verschwinden jedoch wieder, wenn das Skript in maschinenlesbare Form übersetzt wird. Das Skript erhält dadurch nämlich eine automatische Formatierung. (Die Formatierungen im Menü Schrift und Format sind deswegen allerdings nicht bedeutungslos. Sie sind für den Reiter Beschreibung im unteren Teil des Editors notwendig.) Schreiben Sie Ihr Skript also immer ohne jegliche Formatierungen, wie es in anderen Programmiersprachen ebenfalls üblich ist.
53
SmartBooks
AppleScript
Übersetzen Der von Ihnen geschriebene Text wird üblicherweise in lila Farbe dargestellt. Damit wird angezeigt, dass es sich um ungeprüften Text handelt und noch nicht um ausführbaren Code. Es handelt sich also um Befehle, von denen Sie annehmen, dass es sich um AppleScript-Befehle handelt. Ob das, was Sie geschrieben haben, wirklich gültiger Code ist, wird Ihnen der Skripteditor sagen, wenn Sie auf den Hammer in der Werkzeugleiste klicken. Wird der Text als gültiges AppleScript erkannt, ändert er darauf seine Formatierung. Damit wird Ihnen angezeigt, dass der Text verstanden und in maschinenlesbare Form übersetzt (kompiliert) wurde. So wird display dialog in blauer Farbe und "Hallo Welt!" in schwarz dargestellt (zumindest solange Sie die Voreinstellungen nicht abgeändert haben). Das Skript ist damit bereit, ausgeführt zu werden. An der Farbe des Textes können Sie also ablesen, welcher Teil des Codes bereits vom Skripteditor verstanden wurde und welcher noch nicht. Vor allem können Sie daran aber erkennen, wie der Skripteditor Ihre Angaben verstanden hat. Eventuell haben Sie sich missverständlich ausgedrückt? Dann können Sie das nach dem Kompilieren überprüfen, wenn der Skripteditor Ihnen den gefärbten Text anzeigt, also das, was er aus Ihrem Text verstanden hat. Unterscheiden Sie bitte beides ganz genau! Was Sie schreiben, geht tatsächlich verloren, wenn Sie auf den Hammer klicken! Das, was Sie nach dem Kompilieren als farbigen Text angezeigt bekommen, ist nicht mehr das, was Sie geschrieben haben, sondern das, was der Skripteditor verstanden hat. Das Skript wird beim Kompilieren in Maschinencode übersetzt. Und dieser Code wird gleich wieder dekompiliert und Ihnen angezeigt. Sie erhalten also immer eine sofortige Rückmeldung, ob soweit alles korrekt verstanden wurde – was allerdings nicht heißt, dass es wirklich keine Missverständnisse mehr geben könnte. Tipp Statt mit der Maus auf den Hammer zu klicken, ist es übrigens angenehmer, die [Enter]Taste zu verwenden. Das hat dieselbe Wirkung und den Vorteil, dass man beim Schreiben des Skripts nicht die Finger von der Tastatur nehmen muss. Die Enter-Taste ist die Taste rechts unten im Nummernblock und nicht die Return-Taste! Die Returntaste (Absatzschalter) fügt nur eine neue Zeile in den Text ein.
Ausführen Klicken Sie nun auf den Knopf Ausführen, um obiges Skript auszuprobieren. Ein Dialog mit dem Text Hallo Welt öffnet sich. Nach einem Klick auf den Knopf OK oder Abbrechen wird das Skript wieder beendet. Ein Klick auf den Knopf Ausführen führt also die Befehle im Skript aus. Bevor das geschieht, wird allerdings vorher noch einmal geprüft, ob es seit dem letzten Übersetzen Änderungen gegeben hat. Wenn ja, wird das Skript zuerst übersetzt, also kompiliert, danach der Text entsprechend neu formatiert und angezeigt und dann erst das Skript ausgeführt.
54
Das Handwerkszeug
Kapitel 3
Tipp Auch hier lohnt es sich, sich das Tastenkürzel zu merken. Mit [Befehl]+[r] führen Sie das Skript aus, ohne die Hand von der Tastatur zu nehmen.
Debugging Schreiben Sie obiges Skript nun einmal bewusst falsch, indem Sie zum Beispiel die Leerstelle zwischen display dialog vergessen, und klicken Sie dann auf Übersetzen. Es erscheint eine Fehlermeldung mit einem mehr oder weniger hilfreichen Text, den Sie nur durch Bestätigung zur Kenntnis nehmen können. Die Einfügemarke springt gleichzeitig an die Stelle, an welcher der Skripteditor etwas nicht verstanden hat, und markiert dabei auch oft den entsprechenden Bereich. Diese Stelle ist aber nur ein grober Hinweis auf den Ort des Fehlers. Oft ist der eigentliche Fehler schon viel früher aufgetreten und fällt erst hier an der markierten Stelle auf. Verlassen Sie sich also nicht zu sehr darauf, dass der Fehler wirklich genau an dieser Stelle liegt. Nachdem Sie den Fehler gefunden und korrigiert haben, ist ein erneutes Klicken auf Kompilieren dann meist erfolgreich oder es wird der nächste gefundene Fehler angezeigt. Fahren Sie dann solange fort, bis alle Fehler beseitigt sind und es keine Fehlermeldung mehr gibt. Programmierer bezeichnen diesen Vorgang als Debugging. Darunter ist also nur die Fehlersuche und -behebung zu verstehen, nichts weiter. Im Laufe des Buches werden Sie noch viele nützliche Tipps dazu erhalten.
Unterschiedliche Schreibweisen Viele Begriffe in AppleScript besitzen mehrere Schreibweisen. So können Sie zum Beispiel Folgendes schreiben: tell app "Finder" make new Finder window end tell Nach dem Kompilieren (Klick auf den Hammer) wird das Wort application für app eingesetzt. Sie erkennen daran auch gleich, dass AppleScript das Wort verstanden hat. In den entsprechenden Kapiteln dieses Buches wird jeweils auf Abkürzungsformen und alternative Schreibweisen hingewiesen. app ist nur eine andere, verkürzte Schreibweise des Wortes application. Beides ist gleichwertig, wobei Ersteres Ihnen natürlich Schreibarbeit erspart.
55
SmartBooks
AppleScript
Was Sie bei der Kompilierung des obigen Skripts noch beobachten können, ist, dass der Skripteditor die mittlere Zeile mit einem linken Einzug versieht. Dies geschieht immer innerhalb von Blöcken, die mit dem Schlüsselwort end enden.
Groß- und Kleinschreibung AppleScript unterscheidet nicht zwischen Groß- und Kleinschreibung! Sie könnten also auch TELL schreiben, das würde keinen Einfluss auf das Skript haben. Nach dem Kompilieren werden die AppleScript-Begriffe automatisch in Kleinbuchstaben umgewandelt. Nur von Ihnen selbst definierte Objekte, Eigenschaften und Variablen behalten die Schreibweise bei, die während der ersten Kompilierung vorlag. Der Skriptassistent Der Skripteditor bietet auch eine automatische Code-Vervollständigung, die bei der Eingabe eine große Hilfe sein kann. Diese muss jedoch zuerst in der Tafel Bearbeitung im Menü Skripteditor | Einstellungen eingeschaltet werden. Setzen Sie dort einen Haken bei Skriptassistenten verwenden. Beenden Sie danach den Skripteditor und starten Sie ihn neu, damit die Änderung wirksam wird. Danach finden Sie im Bearbeiten-Menü den Befehl Vervollständigen mit dem Tastaturkürzel [Alt]+[Esc]. Wenn Sie nun die ersten Buchstaben von display dialog schreiben, erscheint in grauer Farbe das vorgeschlagene Wort mit drei Punkten am Ende oder, solange mehrere Vorschläge existieren, einfach nur … (drei Punkte). Drücken Sie dann [Alt]+[Esc] oder die Taste [F5], um das vorgeschlagene Wort zu übernehmen oder um sich eine Liste möglicher Wörter anzeigen zu lassen. In der Liste können Sie mit den Cursortasten navigieren und mit [Esc], [Enter] oder [F5] eine Auswahl treffen. Falls nichts Passendes dabei ist, tippen Sie einfach weiter. Aufgepasst Die Skripteditor-Hilfe spricht von der [F5]-Taste. Im Menü Bearbeiten steht [Alt]+[Esc]. Bei mir funktioniert auch [Esc] alleine. Hier scheint die Dokumentation hinterherzuhinken oder der eine nichts vom anderen zu wissen. Probieren Sie einfach aus, was bei Ihnen funktioniert. Wirklich hilfreich ist der Skriptassistent jedoch vor allem, weil er sich auch die selbstdefinierten Variablen und Eigenschaften merkt. Was leider nicht funktioniert, ist die Übernahme der Terminologie aus skriptfähigen Programmen. Von daher machen Sie sich darauf gefasst, dass Sie des Öfteren Wörter in der Liste der Vorschläge vermissen werden.
56
Das Handwerkszeug
Kapitel 3
Abb. 3-2 Man schreibt die ersten Buch staben, und nach Drücken der [Esc]-Taste wird die Liste aller in Frage kommenden Wörter angeboten. Das kann eine Menge Tipparbeit ersparen, vor allem, wenn man seinen Variablen aussagekräftige lange Namen gegeben hat. Die kleinen Symbole, die den Worten vorangehen, geben Ihnen zudem noch Auskunft, worum es sich bei dem Namen handelt. Auch hier fehlt leider wieder jegliche Dokumentation. Es ist jedoch erkennbar, dass die Symbole für Folgendes stehen: << Ein grünes L in quadratischer Box steht für selbst definierte Variablen, Propertys und Routinen. << Ein grünes K in quadratischer Box steht für die Basisterminologie von AppleScript. << Ein braunes T in quadratischer Box steht für den ganzen Rest, zum Beispiel für Befehle aus den Standard-Additions, den System-Events und Events von Apple-Programmen.
Skriptbausteine im Kontextmenü Das Kontextmenü, welches Sie im Editor mit der rechten Maustaste oder [ctrl]-Klick erreichen, bietet sinnvolle Hilfen und Bausteine zum Erstellen von Skripts.
Abb. 3-3 Das Kontextmenü im Skripteditor bietet sinn volle Bausteine zum Skript aufbau.
57
SmartBooks
AppleScript
Von Belang ist dabei nur der untere Teil. Im dritten Abschnitt können Sie mit Über diese Skripts das Hilfe-Thema zum Kontextmenü öffnen. Hilfe Der Eintrag Über diese Skripts funktioniert im Skripteditor 2.2 nicht richtig. Die Hilfe wird zwar aufgerufen, aber das Thema wird nicht angezeigt. Also am besten manuell die Skripteditor-Hilfe über das Hilfe-Menü aufrufen und dort das Thema Das Kontextmenü auswählen. Mit dem Befehl Skript-Ordner öffnen öffnet sich der Ordner, in welchem die Kontextmenü-Befehle aus dem unteren Abschnitt liegen. Bei diesen Befehlen handelt es sich übrigens um Appleskripts! Power User Mit anderen Worten: Sie können sich Ihre eigenen Kontextmenü-Befehle erstellen, indem Sie ein AppleScript hier ablegen oder ein bestehendes kopieren und abändern. Tatsächlich wird hier der Ordner Script Editor Scripts des Skriptmenüs geöffnet. Im Gegensatz zum Skriptmenü funktioniert im Kontextmenü jedoch nicht die [Alt]-Taste, um das Skript im Editor zu öffnen, anstatt es auszuführen. Ein Beispiel anhand des bereits bekannten display dialog: Erstellen Sie ein neues, leeres Skript im Skripteditor. 1. Klicken Sie mit der rechten Maustaste in den Editor und wählen Sie aus dem Kontextmenü den Eintrag Dialogs | Dialog – 1 Btn OK aus. Folgender Code wird eingefügt: display dialog "" buttons {"OK"} default button 1 2. Schreiben Sie nun einen beliebigen Text zwischen die noch leeren Anführungszeichen und führen Sie das Skript danach zum Testen aus. Ein Dialog mit einem einzelnen OK-Knopf erscheint. Der Knopf wird dabei als Standardknopf (default button) blau pulsierend angezeigt. Bei manchen Skripts im Kontextmenü, zum Beispiel unter Conditionals, steht in deren Namen <selection>. Das bedeutet, dass ein vorher ausgewählter Text nach Ausführung des Skripts an dieser Stelle des Codes eingefügt wird. Beispiele dazu finden sich im Kapitel zu den Kontrollstrukturen.
Die Steuerungsleiste Die Steuerung befindet sich zwischen Symbolleiste und Arbeitsfläche. Falls sie nicht angezeigt wird, blenden Sie sie über Darstellung | Steuerung einblenden ein.
58
Das Handwerkszeug
Kapitel 3
Abb. 3-4 Die Steuerungsleiste im Skripteditor dient der Auswahl der OSA-Sprache und der Navigation im Skript. Im ersten Einblendmenü können Sie die Sprache festlegen, in welcher Sie ein Skript erstellen wollen. Wie in Kapitel 2 erläutert, beruht AppleScript auf OSA, der »Offenen Skript-Architektur«. Das bedeutet, dass hier prinzipiell auch andere Sprachen gelistet sein können, die sich OSA zunutze machen. Wenn Sie nur den Skripteditor besitzen, werden Sie hier nur einen einzigen Eintrag vorfinden, nämlich AppleScript. Haben Sie jedoch den Script Debugger installiert, und sei es auch nur zum Testen, so werden Sie in diesem Menü zwei weitere Einträge vorfinden, nämlich JavaScript und AppleScript Debugger X. AppleScript Debugger X wird dabei nur intern vom Script Debugger verwendet, wenn Sie jedoch JavaScript auswählen, können Sie auch das zur Steuerung Ihres Macintoshs verwenden! Infos zu JavaScript als OSA-Sprache finden Sie auf der Webseite des Herstellers unter www.latenightsw.com/freeware/JavaScriptOSA. Solange Ihre Skripts klein sind und nicht über mehrere Seiten reichen, werden Sie das zweite Einblendmenü sicher nicht oft verwenden. Sobald Sie aber mehrere Routinen, Eigenschaften oder globale Variablen in Ihrem Skript versammelt haben, können Sie damit schnell von einer Stelle zur anderen springen. Das Menü erleichtert Ihnen also die Navigation, indem es den Namen aller Routinen, Eigenschaften und Globalen Variablen auflistet. Vor allem bei umfangreichen Skripts, die über mehrere Seiten gehen, ist dieses Einblendmenü ungemein hilfreich. Die Einträge darin sind nach Vorkommen sortiert und nicht nach dem ABC.
Skripts aufzeichnen Der Knopf Aufzeichnen in der Symbolleiste dient dazu, Skripts zu erstellen, indem man in der entsprechenden Anwendung einfach die gewünschte Tätigkeit vornimmt. Ist die Anwendung aufzeichnungsfähig (recordable), also fähig, Ihre Aktionen aufnehmen zu lassen, dann werden danach im Skripteditor die vom Programm ausgeführten Aktionen als AppleScript-Befehle erscheinen. Wenn die Anwendung nicht in der Lage ist, Ihre Aktionen aufzuzeichnen, wird der Skripteditor leer bleiben.
59
SmartBooks
AppleScript
Damit Sie nicht Dutzende von Fehlversuchen vornehmen – tatsächlich sind nur sehr wenige Anwendungen dieser Aufzeichnung fähig –, versuchen Sie es am besten direkt mit dem Finder selbst. 1. Klicken Sie in einem neuen, leeren Skript im Skripteditor auf den Knopf Aufzeichnen. 2. Wechseln Sie in den Finder. 3. Betätigen Sie die Tastenkombination [Befehl]+[N], um ein neues Finder-Fenster zu öffnen. 4. Schieben Sie das Fenster in die linke, obere Ecke. 5. Ziehen Sie das Fenster größer, bis es den ganzen Bildschirm bedeckt. 6. Wählen Sie Darstellung | Als Cover Flow im Finder-Menü. 7. Wechseln Sie wieder in den Skripteditor und klicken Sie auf den Knopf Stopp, um die Aufzeichnung zu beenden. Das Ergebnis der Aufzeichnung wird im Skripteditor wie folgt aussehen: tell application "Finder" activate make new Finder window set position of Finder window 1 to {1, 45} set bounds of Finder window 1 to {1, 45, 1680, 1050} set current view of Finder window 1 to flow view end tell Abhängig von Ihrer Bildschirmgröße werden die Werte in den geschweiften Klammern, welche die Position und Größe des Fensters bestimmen, natürlich vom obigen Beispiel abweichen. Damit haben Sie nun herausgefunden, wie in AppleScript die Befehle für das Verschieben und Skalieren eines Finder-Fensters lauten. Wenn Sie die obige Aufzeichnung übersetzen und erneut ausführen, wird jedes Mal ein neues Finderfenster geöffnet und in Maximalgröße am Bildschirm aufgezogen. Wenn Sie mit dem Aufzeichnen ein wenig herumprobieren, werden Sie feststellen, dass nicht alle Aktionen tatsächlich aufgezeichnet werden. Auch wenn eine Anwendung aufzeichnungsfähig ist, heißt das nicht unbedingt, dass sie es wirklich durchgehend ist.
60
Das Handwerkszeug
Kapitel 3
Das Aufzeichnen stellt eine wunderbare Einstiegshilfe dar, um sich gleich in der Praxis anzusehen, wie Befehle an diese Anwendung formuliert werden müssen. In der Regel werden solche Aufzeichnungen von einem Skripter jedoch nur als »Steinbruch« verwendet, um die darin gewonnenen Codezeilen in das eigentliche Skript an entsprechender Stelle einzubauen und entsprechend abzuwandeln.
Der Protokollbereich des Skripteditors Die untere Hälfte des Skripteditors teilt sich in drei Bereiche, die über die Schaltflächen Beschreibung, Ergebnis und Event-Protokoll aufgerufen werden können.
Beschreibung In diesen Bereich können Sie beliebigen Text hineinschreiben. Wofür Sie das Feld verwenden, steht Ihnen frei. Sie könnten sich darin zum Beispiel Notizen zum Skript machen, eine Anleitung für das Skript verfassen oder das Copyright hineinstecken. Hier stehen Ihnen alle Formatierungsoptionen des Skripteditors uneingeschränkt zur Verfügung.
Abb. 3-5 Die Beschreibung zu einem Skript kann vor dessen Start angezeigt werden. Die üblichen Textformatierungen stehen samt Lineal alle zur Verfügung. Über Format | Lineal einblenden erhalten Sie sogar ein Textlineal, wie in obiger Abbildung ersichtlich. Der Text, den Sie hier eingeben, können Sie auch als Begrüßungstext für das Skript verwenden, der einem Anwender nach Start des Skripts als Erstes angezeigt wird. Alles, was Sie dafür machen müssen, ist, das Skript mit Ablage | Sichern unter als Programm abzuspeichern. Wählen Sie dafür im Sichern-Dialog Programm oder Programm-Bundle unter Dateiformat und die Option Startdialog aus. Speichern Sie das Skript.
61
SmartBooks
AppleScript
Die Beschreibung nimmt wie TextEdit auch Bilder auf. Sie könnten also zum Beispiel ein Firmenlogo darin einfügen. Bilder gehen jedoch leider verloren, wenn Sie das Skript als Programm oder Programm-Bundle speichern, wodurch diese Fähigkeit wenig Nutzen hat. Power User Bei der Abspeicherung in einem Bundle-Format wird die Beschreibung als RTFD-Dokument, welches ja ebenfalls ein Bundle ist, mit darin enthaltenen Bildern im Bundle des Skripts als description.rtfd abgelegt. Das Bild ist also schon vorhanden, wird aber vom Startdialog aus unbekannten Gründen ignoriert.
Abb. 3-6 Absichern mit der Option »Startdialog« und dem Dateiformat »Programm« oder »Programm-Bundle« führt zur Anzeige des Beschreibungstextes beim Start des Skripts. Wenn Sie dass Skript nun starten, werden Sie zuerst von Ihrem Text begrüßt.
Abb. 3-7 Ein Programm-Skript zeigt seinen Startdialog. Erst wenn der Anwender danach auf den Knopf Run klickt, wird das Skript ausgeführt. Klickt er stattdessen auf Quit, wird das Skript beendet, ohne ausgeführt zu werden. Wenn Sie deutsch beschriftete Knöpfe brauchen, müssen Sie das Skript als Programm-Bundle abspeichern.
62
Das Handwerkszeug
Kapitel 3
Ergebnis Dieser Bereich dient der Anzeige von Ergebnissen, die während der Ausführung des Skripts auftreten. Angezeigt wird dabei immer nur das letzte Ergebnis! Insofern ist die Nützlichkeit dieses Bereiches ein wenig eingeschränkt, da Sie zum Testen immer darauf achten müssen, dass keine anderen Ergebnisse folgen. Erzeugen Sie daher zum Testen besser ein zweites Skriptfenster, in welchem Sie kleine Codeabschnitte einfügen und testen. Der Inhalt in diesem Bereich kann nicht bearbeitet werden. Er dient nur der Anzeige des Ergebnisses. Power User Für alle, die sich schon ein wenig auskennen: Bei dem Ergebnis, welches hier angezeigt wird, handelt es sich um den Inhalt der AppleScript-Variablen result.
Abb. 3-8 Das Ergebnis einer DisplayDialog-Aktion ist der gedrückte Knopf. Nehmen Sie sich zum Testen einfach mal ein paar Rechenaufgaben vor. Tippen Sie 2*25 in das Skript und klicken Sie dann auf Ausführen. Als Ergebnis wird 50 angezeigt. Das Ergebnis kann alles Mögliche darstellen. Es kann eine einfache Zahl, ein Text, eine Liste, ein Record (Datensatz) oder auch ein Objekt sein, wie zum Beispiel in den folgenden Zeilen: tell application "Finder" activate make new Finder window end tell Das Ergebnis sieht dann in etwa so aus: Finder window id 694 of application "Finder" Hier wird als Ergebnis ein Fenster mit der Identifikationsnummer (id) 694 zurückgeliefert, die Nummer wird bei Ihnen dabei abweichen. Über diese Nummer lässt sich dann auch ein Fenster unter vielen herausfinden und ansprechen. Details dazu finden Sie im Kapitel zu den tell-Kontrollstrukturen.
63
SmartBooks
AppleScript
Nicht jede Aktion liefert übrigens ein Ergebnis! Wenn der Bereich Ergebnis leer bleibt, ist die letzte Aktion ohne Rückgabewert gewesen. Der Befehl activate im obigen Skript, welcher den Finder nach vorne holt (also zum aktiven Programm macht), ist eine solche Aktion ohne Ergebnis. Wenn Sie die Zeile make new Finder window löschen und das Skript erneut ausführen, erhalten Sie also kein Ergebnis mehr.
Event-Protokoll Dieser Bereich ist der wichtigste bei der Arbeit im Skripteditor. Der Bereich Event-Protokoll gibt Ihnen Hinweise, wie AppleScript nun eigentlich Ihren geschriebenen Code ausführt. AppleScript ist zwar fast wie natürliches Englisch zu schreiben, aber dadurch auch, wie jede natürliche Sprache, oft missverständlich. Tritt ein Fehler auf, hilft oft ein genauerer Blick in dieses Event-Protokoll, um ihm auf die Schliche zu kommen.
Abb. 3-9 Das Event-Protokoll einer display dialog-Zeile Wie Sie an obiger Abbildung sehen, wurde im Skript nur die Zeile mit dem display dialog geschrieben. Nach der Ausführung sehen Sie im Event-Protokoll jedoch einige Zeilen mehr, die genau anzeigen, wie diese Zeile tatsächlich verstanden wurde. In diesem Fall wird nämlich dem aktiven Programm (also dem Skripteditor) gesagt, dass es einen Dialog anzeigen soll. Der Skripteditor weiß, dass es sich hierbei um einen Befehl der StandardErweiterungen handelt, und leitet den Befehl entsprechend weiter. Power User Wenn das Skript als Programm gesichert wurde, ist die current application allerdings das Skript selber. Das führt zwar hier zu keinem Unterschied, wohl aber bei der Verwendung von me, it, path to me und path to resource. Nach einem Befehl erscheint im Event-Protokoll dann eingerückt in der nächsten Zeile das Ergebnis dieses Befehls. In obiger Abbildung ist es der gedrückte Knopf OK. Im Gegensatz zum Bereich Ergebnis, wo immer der letzte Wert angezeigt wird, werden hier jedoch nicht alle Ergebnisse protokolliert. Wie später gezeigt werden wird, kann man dem allerdings mit dem log-Befehl nachhelfen.
64
Das Handwerkszeug
Kapitel 3
Die Verlaufsfenster Im Menü Fenster finden Sie noch die zwei Einträge Verlauf der Ergebnisse und Verlauf des Event-Protokolls. Hier werden die Ergebnisse und Events jeder Ausführung gesammelt. Wenn Sie also noch mal zurückblicken wollen, wie der Bereich Ergebnis oder Event-Protokoll vor einer Stunde ausgesehen hatte – bevor Sie diese ach so geniale Änderung im Skript vornahmen –, schauen Sie hier nach.
Abb. 3-10 Das Verlaufsfenster für das Event-Protokoll Wie viele Einträge hier gespeichert werden, legen Sie in den Einstellungen unter Skripteditor | Einstellungen und dort in der Tafel Verlauf fest. Sie erreichen die Einstellungen auch über die Tastenkombination [Befehl]+[,]. Wenn Sie dort auch die Option Nur protokollieren, wenn sichtbar ankreuzen, werden die Event-Protokolle nur gespeichert, wenn der Verlauf geöffnet ist. Durch einen Klick auf den Knopf Skript einblenden können Sie sich das Skript anzeigen lassen, wie es zum Zeitpunkt dieses Events aussah. Dabei wird ein neues Editorfenster mit dem alten Skript als Inhalt geöffnet. Mit anderen Worten, Sie können darüber bequem zu alten Ständen Ihres Skripts zurückkehren. Der Verlauf wird allerdings wieder gelöscht, wenn Sie den Skripteditor beenden. Lassen Sie ihn daher so lange geöffnet wie Sie alte Stände benötigen. Im Zweifelsfall speichern Sie die alten Stände, indem Sie das entsprechende Event auswählen und das Skript dazu öffnen und separat abspeichern. Das Fenster Verlauf des Event-Protokolls enthält zusätzlich in der Symbolleiste noch ein Einblendmenü. Darin können Sie auswählen, ob Sie nur Events, Events und Ergebnisse oder gar nichts protokollieren möchten. Wenn Sie Nichts protokollieren wählen, werden nur die alten Stände des Skripts zum Zeitpunkt der Ausführung aufgehoben, ohne das dazugehörige Event-Protokoll.
65
SmartBooks
AppleScript
Die Bibliothek Im Fenster-Menü des Skripteditors findet sich auch noch der Eintrag Bibliothek. Wenn Sie ihn auswählen, öffnet sich ein kleines Fenster, in welchem verschiedene Programme aufgelistet sind.
Abb. 3-11 Die Bibliothek bietet einen Schnellzugriff auf häufig benötigte Funktionsverzeichnisse. Dieses Fenster bietet einen Schnellzugriff auf das sogenannte Funktionsverzeichnis (Dictionary) häufig verwendeter Programme. Funktionsverzeichnisse stellen eine Beschreibung aller Befehle und Klassen dar, die Sie verwenden können, um das Programm mit AppleScript zu steuern. Sie gehören damit zum »täglichen Brot« eines Skripters und sind die erste Anlaufstelle bei Fragen zur Steuerung einer Anwendung. Sie können sich die Bibliothek ganz nach Ihren Wünschen einrichten, indem Sie oben im Fenster die Programme, die Sie nicht benötigen, durch Klick auf die Schaltfläche mit dem Minuszeichen entfernen und die Programme, die Sie häufig benötigen, über das Plus hinzufügen. Ein Klick auf die Schaltfläche mit den Büchern öffnet das Funktionsverzeichnis des gerade ausgewählten Programms. Ein Doppelklick auf den Programmnamen erfüllt denselben Zweck. Die vierte Schaltfläche in der Symbolleiste zeigt das bekannte Symbol von AppleScript. Wenn Sie darauf klicken, wird ein neues Skript angelegt, in welchem bereits ein sogenannter tell-Block für die ausgewählte Anwendung steht. So können Sie im Skript direkt anfangen, der Anwendung Befehle zu geben. Wenn Sie ein Funktionsverzeichnis durch Doppelklick öffnen, wird übrigens auch das dazugehörige Programm gestartet. Je nach Art des Funktionsverzeichnisses ist das nötig, um selbiges aus dem Programm auslesen zu können. Wundern Sie sich also nicht, warum so viele Programme geöffnet sind, nachdem Sie mehrere Funktionsverzeichnisse geöffnet haben.
66
Das Handwerkszeug
Kapitel 3
Das Funktionsverzeichnis Das Funktionsverzeichnis eines Programms können Sie sich als so etwas wie ein Lexikon oder ein Nachschlageverzeichnis vorstellen, in welchem Sie nachsehen können, welches Vokabular diese Anwendung besitzt. Es ist also eine Art Wörterbuch und wird im Englischen daher folgerichtig Dictionary genannt. Im deutschen Skripteditor verwendet Apple den Begriff Funktionsverzeichnis, den ich daher auch hier im Buch vorrangig verwende. Wenn Sie einer Anwendung etwas befehlen möchten, so schauen Sie in der Regel zuerst in ihrem Funktionsverzeichnis nach, um herauszufinden, wie ein Befehl ausgedrückt werden muss, und vor allem, an wen er gerichtet werden muss, damit die Anwendung macht, was Sie wollen. Nachdem Sie in der Bibliothek das Funktionsverzeichnis eines Programms durch Doppelklick geöffnet haben, erhalten Sie ein Fenster der folgenden Art. Alternativ können Sie ein Funktionsverzeichnis auch über Ablage | Funktionsverzeichnis öffnen und anschließende Auswahl eines Programms öffnen. Dieser Weg ist allerdings etwas für Geduldige, da der Skripteditor hier wirklich alle Anwendungen auf dem Rechner auflistet, und das dauert manchmal etwas.
Abb. 3-12 Das Funktionsverzeichnis des Finders Wie man so ein Funktionsverzeichnis liest und anwendet, darauf wird im Verlaufe des Buches immer wieder eingegangen. Hier nur so viel, dass Sie mit den Schaltflächen in der Symbolleiste »vor und zurück« durch bereits betrachtete Einträge navigieren können. Außerdem lässt sich hier der Text
67
SmartBooks
AppleScript
vergrößern oder verkleinern und es lassen sich verschiedene Ansichten einstellen. Drucken und durchsuchen lässt sich so ein Funktionsverzeichnis natürlich auch.
Skripteditor-Einstellungen Wie alle Programme, so besitzt auch der Skripteditor seine Programmeinstellungen, zu finden im Menü Skripteditor | Einstellungen, die Sie am schnellsten mit der Tastenkombination [Befehl]+[,] erreichen. Auf einige der dort vorzufindenden Einstellungen habe ich bereits auf den vorigen Seiten aufmerksam gemacht. Ein paar wichtige Einstellungen fehlen jedoch noch.
Tafel Allgemein Hier können Sie die Sprache festlegen, in der Sie skripten möchten. Lassen Sie für die Arbeit mit diesem Buch die Einstellung auf AppleScript, auch wenn Sie andere Sprachen zur Auswahl haben. Darunter finden Sie noch die Option »Vererbte Objekte im Funktionsverzeichnis anzeigen«. Die Auswahl dieser Option führt dazu, dass im Funktionsverzeichnis bei einer Klasse darauf hingewiesen wird, wenn es andere Klassen gibt, die davon abstammen. Eine durchaus nützliche Option, die Sie einschalten sollten.
Tafel Bearbeitung Hier können Sie den Zeilenumbruch und die Anzahl der Einrückungen bei Tabulatoren einstellen. Lassen Sie diese Tafel wie unten abgebildet eingestellt.
Abb. 3-13 Bearbeitungsoptionen im Skripteditor Hier können Sie auch den Skriptassistenten aktivieren. Wie sich die Option ganz unten in der Tafel auswirkt, wird im Kapitel zu den Textgrundlagen behandelt.
68
Das Handwerkszeug
Kapitel 3
Tafel Formatierung Wie Sie ja schon gesehen haben, wird nach Klick auf den Knopf Übersetzen der Text im Skript formatiert. Damit liegt das Skript dann in kompilierter Form vor, und Sie wissen, dass AppleScript die Begriffe darin verstanden hat. Falls Ihnen diese Formatierung nicht gefällt, dann ist hier die Stelle, wo Sie darauf Einfluss nehmen können.
Abb. 3-14 Formatierung einzelner Sprachelemente In der linken Spalte sind die Sprachelemente aufgelistet. Rechts daneben wird angezeigt, welche Schrift in welcher Größe dafür verwendet wird. Ganz rechts sehen Sie die Farbe für diesen Text. Möchten Sie etwas davon ändern, doppelklicken Sie auf einen Eintrag. Daraufhin öffnet sich der Standarddialog von Mac OS X zur Auswahl und Formatierung von Schriften. Möchten Sie nur die Farbe der Schrift ändern, doppelklicken Sie auf das Farbfeld ganz rechts. Die Farbpalette von Mac OS X öffnet sich, und Sie können eine beliebige Farbe auswählen. Haben Sie Änderungen vorgenommen, müssen Sie zum Schluss noch auf den Knopf Anwenden klicken, damit die Änderungen übernommen werden. In einem geöffneten Skript wird sich dabei erstmal nichts ändern. Erst wenn Sie das Skript erneut übersetzen, tritt die Änderung in Kraft. Sollte Ihnen also zum Beispiel die Schrift im Skripteditor zu klein oder zu groß sein, stellen Sie hier einfach für alle Elemente eine andere Schriftgröße ein. Gefallen Ihnen die Farben nicht, nur zu, tun Sie sich keinen Zwang an. Achten Sie nur darauf, dass der Text trotz aller Formatierung leicht zu lesen bleibt. Die Formatierung soll das Auge leiten und nicht erschlagen.
69
SmartBooks
AppleScript
Power User Die Einstellungen, die Sie hier vornehmen, sind globaler Natur und gelten für alle Skripts auf Ihrem Rechner. Die Formatierung wird nämlich nicht vom Skripteditor selbst vorgenommen, sondern von der AppleScript-Komponente im Betriebssystem. Nach dem Übersetzen liefert diese nämlich nicht nur das kompilierte Skript zurück, sondern auch gleich den dekompilierten und formatierten Text. Mit anderen Worten: Wenn Sie für die Variablen eine rote Schrift in 14 Punkt Größe auswählen, dann werden danach auch in den Skripteditoren anderer Hersteller alle Variablen in 14 Punkt großer, roter Schrift dargestellt. Sollte Ihnen Ihre Formatierung nicht mehr gefallen, können Sie mit einem Klick auf Standardwerte wieder in den Auslieferungszustand zurückkehren. Der Knopf Letzte Version hilft Ihnen nur, solange Sie nicht den Knopf Anwenden geklickt haben. Er macht die letzten Änderungen an der Formatierung wieder rückgängig.
Tafel Verlauf Auf diese Einstellungen wurde bereits bei den Verlaufsfenstern eingegangen. Die Einträge sind selbsterklärend. Beachten Sie, dass die Anzahl der gespeicherten Einträge immer nur für eine Sitzung des Skripteditors gilt. Beenden Sie den Skripteditor, sind die Einträge weg. Ganz wichtig ist noch der unterste Eintrag Nur protokollieren, wenn sichtbar. Wenn Sie diesen Eintrag ankreuzen, werden die Protokolle nur gespeichert, wenn das Verlaufsfenster geöffnet ist.
Tafel Plugins Der Skripteditor kann mit Hilfe von Modulen erweitert werden. Bisher wird davon kein Gebrauch gemacht – mir ist jedenfalls noch kein Plugin für den Skripteditor in freier Wildbahn begegnet. Die professionellen Entwickler, die dies gebrauchen könnten, verwenden zudem den Script Debugger von Late Night Software, welcher jede Menge zusätzlicher Optionen besitzt, die man im Skripteditor erst mühsam als Plugin nachrüsten müsste. Stören Sie sich daher nicht an dieser Tafel. Sollten Sie einmal über ein Plugin für den Skripteditor stolpern und haben Sie es nach Anweisung installiert, wird es hier zu Ihrer Information aufgelistet.
Sichern und Dateiformate Wenn Sie im Skripteditor ein Skript erstellt haben, muss es spätestens nach Fertigstellung natürlich noch gesichert werden.
70
Das Handwerkszeug
Kapitel 3
Nun ist Skript jedoch nicht gleich Skript. Historisch gewachsen gibt es inzwischen mehrere Dateiformate. Bevor Sie in diesem Kapitel fortfahren, sollten Sie zuerst einmal überprüfen, ob in den Findereinstellungen die Anzeige der Suffixe eingeschaltet ist. Wechseln Sie dafür in den Finder und wählen Sie dann das Menü Finder | Einstellungen. Wählen Sie die Tafel Erweitert, setzen Sie einen Haken bei der Option Alle Suffixe einblenden und schließen Sie die Einstellungen wieder. Nun werden Ihnen die Suffixe der folgenden Dateiformate nicht mehr im Finder vorenthalten. Wenn Sie das erste Mal Sichern oder Sichern unter aus dem Ablage-Menü wählen, werden Ihnen im Einblendmenü Dateiformat die Formate Skript, Programm, Skript-Bundle, Programm-Bundle und Text angeboten.
Abb. 3-15 Die verschiedenen Dateiformate für ein Skript
Kompilieren und Dekompilieren beim Sichern und Öffnen Alle Dateiformate mit Ausnahme von Text liegen in kompilierter, also für den Computer übersetzter Form vor. Beim Öffnen eines kompilierten Skripts mit dem Skripteditor wird es daher dekompiliert, um Ihnen den AppleScript-Code anzeigen zu können. Im Skript angesprochene Anwendungen werden dabei geöffnet, um die korrekten Begriffe aus deren Funktionsverzeichnis im Skript eintragen zu können. Ist die Anwendung auf dem Rechner nicht vorhanden, erscheint ein Dialog, der Sie auffordert, die entsprechende Anwendung auszuwählen. Wenn Sie hier auf Abbrechen klicken, wird das Skript zwar geöffnet, aber überall, wo in einem tell-Block die fehlende Anwendung angesprochen wird, stehen für die unbekannten Befehle und Klassen aus dieser fehlenden Anwendung die rohen AppleEvent-Codes in doppelten eckigen Klammern. Das folgende Skript zum Beispiel steuert das Programm RagTime 6: tell application "RagTime 6" set cell 1 of table "Rechenblatt 1" of document 1 to "A" end tell
71
SmartBooks
AppleScript
Öffnen Sie dieses Skript auf einem Rechner, wo RagTime 6 nicht vorhanden ist, so werden diese Zeilen zu folgendem Text: tell application "RagTime 6" set «class ccel» 1 of «class ctbl» "Rechenblatt 1" of document 1 to "A" end tell (Das Skript schreibt übrigens den Buchstaben »A« in die erste Zelle des Rechenblattes mit dem Namen »Rechenblatt 1«.) Die Werte in den Guillemets sind die rohen AppleEvent-Codes, die nicht übersetzt werden konnten, da das Funktionsverzeichnis dieses Programms auf dem Rechner nicht vorlag. Aus diesem Grund bleiben die RagTime-Begriffe cell und table unübersetzt. Auf diese Weise können Sie also den restlichen Text des Skripts herauslesen, auch wenn die Anwendung nicht vorhanden ist. Nur die Stellen mit den AppleEvent-Codes werden Ihnen nicht viel sagen. Und natürlich lässt sich der Code so nicht ausführen, solange die Originalanwendung fehlt. Wohl lässt sich der Code aber so wieder in kompilierter Form speichern. Diese Eigenart von AppleScript, beim Speichern zu kompilieren und beim Öffnen wieder zu dekompilieren, zeigt, wie wichtig es ist, ein Skript immer auch in Textform aufzubewahren. Erst dadurch ist der Code vor dem ständigen Hin- und Herübersetzen beim Öffnen und Speichern geschützt und kann auch ohne Anwesenheit der zu steuernden Anwendungen studiert werden. Daraus ergibt sich aber auch, dass ein AppleScript in anderen Formaten als Text nur gespeichert werden kann, wenn es kompilierbar ist. Enthält das Skript noch Fehler, lässt es sich nicht übersetzen. Und wenn sich ein Skript nicht übersetzen lässt, kann es nur als Text abgespeichert werden. Speichern Sie alle Ihre Skripte immer auch als Text ab!
Ein Wort zu Type- und Creator-Codes und Resource-Forks In klassischen Zeiten hatten Appleskripts auf dem Macintosh kein Dateikürzel. Stattdessen wurde die Art einer Datei am Type- und Creator-Code erkannt. Beide bestehen aus jeweils vier Buchstaben. Der Type-Code gibt die Inhaltsart an, der Creator-Code sagt aus, welche Anwendung diese Datei erzeugt hat. Dieser Type- und Creator-Code wird direkt in der Verzeichnisstruktur der Festplatte gespeichert, zusammen mit anderen Flags für die Datei. Die Speicherung dieser Type- und Creator-Codes in der Verzeichnisstruktur der Festplatte wird jedoch nur von Festplatten unterstützt, die in HFS formatiert sind. Das heißt,
72
Das Handwerkszeug
Kapitel 3
eine Festplatte unter Windows, die in FAT32 oder NTFS formatiert ist, kann diese Informationen nicht abspeichern. Normalerweise ist das nicht von Belang. Solange ein Skript ein Dateikürzel hat, wird die Art der Datei und sein Erzeugungsprogramm ja immer noch am Dateikürzel erkannt. Type- und Creator-Informationen sind also nicht notwendig. Sollten Sie jedoch einmal einem alten Skript ohne Dateikürzel begegnen (und davon gibt es eine Menge, schließlich ist AppleScript schon 15 Jahre alt) sollten Sie diese immer nur auf einer HFS-formatierten Festplatte lagern oder, besser noch, in einem Archiv oder Disk-Image. Verlieren diese Skripts nämlich ihren Type und Creator, werden sie vom Finder als neutrale Dokumente oder Unix-Dateien dargestellt, da er keinen Anhaltspunkt mehr hat, um was für Dateien es sich handelt. Wenn Sie sich selbst auch nicht sicher sind, ob es sich um Skripts handelt oder nicht, versuchen Sie einfach mal, diese Dateien explizit mit dem Skripteditor zu öffnen oder manuell das Dateikürzel eines Appleskripts an die Datei anzuhängen. Gelingt das Öffnen, handelt es sich bei den unbekannten Dateien tatsächlich um Skripts, ansonsten sind es wahrscheinlich doch andere Dateitypen als erwartet. Eine zweite Besonderheit existiert in der Tatsache, dass Macintosh-Dateien aus zwei Hälften bestehen können, im Englischen als »Fork« (Gabelung) bezeichnet. In der DataFork wurden üblicherweise die Daten selbst gespeichert, mit denen der Benutzer arbeitet. In der Resource-Fork speicherte das Programm zusätzliche Informationen, die es für die Arbeit mit dieser Datei benötigte und die der Anwender normalerweise nie zu Gesicht bekam. Früher wurde nun in der Resource-Fork auch das Skript selbst gespeichert! Sie werden also unter Umständen noch auf Skripts stoßen, die ihren Code in der Resource-Fork stecken haben. Sollte diese verloren gegangen sein, ist das Skript beim Öffnen leer. Resource-Forks werden wie Type- und Creator-Codes nur auf Festplatten mit HFS unterstützt, das Skript in der Resource-Fork kann also verlorengehen, wenn es auf einer Festplatte in einem anderen Format abgelegt wurde. Auch wenn das nur ältere Skripts betrifft und Sie im Skripteditor tatsächlich keine Option mehr haben, Skripts mit ihrem Code in der Resource-Fork zu sichern (wohl aber im Script Debugger), ist es wichtig, darüber Bescheid zu wissen, wenn Sie einmal über ein »leeres« Skript stolpern sollten, welches eigentlich Code enthalten sollte.
73
SmartBooks
AppleScript
Grundlagen Kopieren Sie eine Datei mit einer Resource-Fork von einem Mac aus auf eine Festplatte im FAT-Format, so legt der Finder die Resource-Fork als zweite Datei neben das Skript. Vom Mac aus sieht man nur eine Datei, wie üblich. Von einem Windows-Rechner aus betrachtet (oder dem Terminal im Mac), liegen auf dem FAT-Volume tatsächlich zwei Dateien statt einer. Einmal die Datei selbst und einmal eine Datei mit demselben Namen, aber einem vorangestellten Punkt und Unterstrich. Dateien, die mit einem Punkt beginnen, sind auf dem Mac generell unsichtbar, unter Windows nur, wenn die Anzeige der versteckten Dateien und Ordner ausgeschaltet ist. Folgt dem Punkt ein Unterstrich, zeigt dies, dass es sich um eine Ressource-Fork handelt. Wenn Sie die Datei nun von einem Mac auf den Mac zurückkopieren, wird die Resource-Fork gleich wieder in die Datei eingefügt und alles ist gut. Wenn Sie die Datei aber von einem Windows-Rechner aus weiterverteilen, werden Sie die zweite Datei nicht sehen oder eventuell nicht beachten. Hatte diese zweite Datei wichtige Informationen im Resource-Teil, was glücklicherweise nur noch selten vorkommt, so ist die Datei damit sehr wahrscheinlich zerstört.
Dateiformat »Skript« Wenn Sie ein AppleScript als Skript abspeichern, erhält es das Dateikürzel scpt.
Abb. 3-16 Icon eines Skripts oder Skript-Bundles Dies ist die ursprüngliche Art, ein AppleScript zu speichern. Das Skript wird dabei in kompilierter Form auf die Festplatte geschrieben. Es handelt sich hier um eine Datei und kein Bundle. Wenn Sie die Datei doppelklicken, wird das Skript nicht gestartet, sondern in einem Skript editor zur Bearbeitung geöffnet. Dieses Format eignet sich damit vor allem für Skripts, die noch in Bearbeitung sind oder die häufiger Änderungen bedürfen. Beim Sichern im Format Skript steht Ihnen noch die Option Nur ausführbar zur Verfügung. Wenn Sie diese Option ankreuzen, kann das so gesicherte Skript nur noch gestartet, aber nicht mehr geöffnet und bearbeitet werden. Bewahren Sie daher vorher immer eine Kopie des Skripts auf. Diese Option sollten Sie nur dann ankreuzen, wenn Sie nicht wollen, dass andere in Ihrem Code herumschnüffeln. Geschwindigkeitsvorteile bei der Ausführung bringt diese Option kaum, da beide Varianten in kompilierter Form vorliegen.
74
Das Handwerkszeug
Kapitel 3
Das »nur ausführbare« Skript ist nur etwas kompakter, da zum Beispiel die Kommentare darin fehlen. Die Variablen- und Funktionsnamen bleiben aber in dieser Datei weiterhin im Klartext erkennbar, wenn man das Skript zum Beispiel in einem Texteditor öffnet. Einen absoluten Schutz vor Schnüffelei bietet diese Option also keineswegs. Aufgepasst Achtung! Die Option Nur ausführbar ist der sicherste Weg, um sich auf ewig von seinem Werk auszusperren. Kreuzen Sie diese Option wirklich nur an, wenn Sie das Skript unter anderem Namen sichern. Ansonsten sind unter Umständen viele Stunden an Arbeit für immer verloren. Ein kompiliertes Skript hat den Typ 'osas' und den Creator 'ToyS'.
Dateiformat »Programm« Wenn Sie ein Appleskript als Programm abspeichern, erhält es das Dateikürzel app. Das ist dasselbe Dateikürzel, welches auch andere Programme auf dem Mac besitzen. An der Endung allein kann man also nicht erkennen, dass es sich um ein Skript handelt, wenn da nicht das unterschiedliche Icon wäre. Man bezeichnet solche als Programm gespeicherte Skripts auch als »Applet«.
Abb. 3-17 Icon eines Skripts, welches als Programm oder Programm-Bundle gespeichert wurde Im Unterschied zu einem normalen Mac-Programm handelt es sich bei einem Skript-Programm oder Applet jedoch nicht um ein Bundle (dazu gleich mehr), sondern um eine einzelne Datei. Beim Speichern als Programm wird dem Skript sozusagen eine Hülle mitgegeben, die dafür sorgt, dass es sich bei Doppelklick wie ein Programm verhält. Auffälligstes Merkmal: Das Skript hat eine eigene Menüzeile mit den wichtigsten Menüeinträgen. Wenn Sie das als Programm gesicherte Skript doppelklicken, wird es nicht im Skripteditor geöffnet wie ein kompiliertes Skript, sondern es wird sofort ausgeführt, wobei, je nach eingestellter Startoption, vorher noch der Startbildschirm angezeigt wird. Haben Sie eine Beschreibung für Ihr Skript eingegeben, wird diese dort angezeigt.
75
SmartBooks
AppleScript
Das Dateiformat Programm ist daher gut für alle fertigen Skripts, die sich im Alltag bewähren sollen. Hier wird es in der Regel stören, wenn das Skript immer erst manuell im Skripteditor gestartet werden muss. Möchten Sie ein Applet wieder bearbeiten, so öffnen Sie es aus dem Skripteditor heraus, oder ziehen Sie das Programm-Icon mit der Maus auf den Skripteditor. Wenn das Programm nach Doppelklick seinen Startbildschirm anzeigt oder geöffnet bleibt, können Sie auch im Edit-Menü des Applets den Eintrag Edit Script auswählen. Das Menü liegt übrigens auf deutschen Systemen immer in englischer Sprache vor! Wenn Sie ein Skript als Programm absichern, haben Sie drei Optionen zur Auswahl: << Sie können auch hier wieder Nur ausführbar ankreuzen, mit der bekannten Wirkung, dass Sie und andere das Skript in dem Programm nie wieder bearbeiten können. << Sie können Startdialog ankreuzen, um beim Start des Skripts nicht gleich mit der Ausführung loszulegen, sondern zuerst den Text anzuzeigen, den Sie im Skripteditor im Bereich Beschreibung eingegeben haben. << Sie können die Option Nicht automatisch beenden auswählen. Ist diese Option beim Sichern gewählt worden, bleibt das Skript geöffnet, auch wenn es bereits mit der Ausführung fertig ist. Diese Option ist für normale Skripts uninteressant, aber sehr wichtig für solche, die im Hintergrund auf Ereignisse warten oder Leerlaufzeiten des Rechners für ihre Arbeit nutzen. Ein Skript, als Programm abgespeichert, hat den Type 'APPL' und den Creator 'aplt' oder 'dplt', wenn es sich um ein Droplet handelt.
Dateiformat »Skript-Bundle« Wenn Sie ein Appleskript als Skript-Bundle speichern, wird das Skript als sogenanntes »Bundle« gespeichert und erhält das Dateikürzel scptd. Ein Bundle ist dabei nichts anderes als ein Ordner, nur dass dieser im Finder angezeigt wird, als wäre es eine einzelne Datei. Tipp Das d am Ende des Kürzels scptd steht für directory und ist bei vielen Dateikürzeln ein Indiz für ein Bundle-Format. Dieses Format wurde von Apple als Ersatz für das Wegfallen der Resource-Forks unter Mac OS X eingeführt. Wenn Sie einmal in das Bundle hineinsehen oder den Inhalt bearbeiten möchten, brauchen Sie das Skript-Bundle nur im Finder mit der rechten Maustaste anzuklicken und im Kontextmenü Paketinhalt zeigen auswählen. Enthält das Kontextmenü
76
Das Handwerkszeug
Kapitel 3
diesen Eintrag nicht, handelt es sich bei der Datei auch nicht um ein Bundle. Ein als SkriptBundle gesichertes Skript hat, nachdem man es im Finder mit Paketinhalt zeigen geöffnet hat, eine Struktur wie in folgender Abbildung.
Abb. 3-18 Der Inhalt eines Skript-Bundles Das Skript selbst befindet sich dort im Ordner Contents/Resources/Scripts und heißt main.scpt. Der Name ist wichtig, ändern Sie ihn nicht. Das Skript dieses Namens wird nämlich beim Start im Skripteditor angezeigt. Ein Skript-Bundle wird also beim Starten wie ein Skript nicht gleich ausgeführt, sondern zur Bearbeitung im Skripteditor geöffnet. Im Ordner Contents/Resources/ befindet sich eine Datei mit dem Namen description.rtfd. Diese Datei enthält den eventuell vorhandenen Text der Beschreibung im Skript. Das Kürzel »rtfd« deutet es mit seinem letzten Buchstaben bereits an. Auch diese Datei ist ein Bundle. Wenn Sie sie mit Paketinhalt zeigen öffnen, werden Sie allerdings nur eine einzelne RTF-Datei namens TXT.rtf vorfinden. Dort befindet sich der formatierte Text der Beschreibung. Haben Sie auch Bilder in der Beschreibung des Skripteditors verwendet, finden sich diese ebenfalls hier im Bundle wieder. Aber, wie bereits erwähnt, werden die Bilder in der Beschreibung leider nicht im Startbildschirm angezeigt. Tipp Daraus ergibt sich, dass Sie die Beschreibung für das Skript bei einem Bundle-Format auch bequem in TextEdit erstellen können. Speichern Sie die Datei dann im Format RTFD und unter dem Namen description.rtfd ab und legen Sie sie danach in das Bundle in den Ordner Resources. In der Datei info.plist speichert der Skripteditor verschiedene Einstellungen zum Skript ab, zum Beispiel die Fenstergröße und –position, und sorgt damit dafür, dass sich das Skript wieder in demselben Zustand öffnet, in dem es gesichert wurde. Wenn Sie die Entwicklungsumgebung Xcode von Apple installiert haben, öffnet sich bei einem Doppelklick auf diese Datei das Programm Property List Editor. Wenn Sie Xcode noch nicht installiert haben, so ziehen Sie die Datei einfach auf TextEdit, um hineinzuschauen, ändern Sie aber auf keinen Fall etwas darin, solange Sie sich nicht damit auskennen. Es handelt sich um eine Datei im XML-Format.
77
SmartBooks
AppleScript
Das Skript-Bundle-Format eignet sich gut für Skripts, die auf mehrere Dateien verteilt sind. Alle einzelnen Skripts lassen sich nämlich gesammelt im Bundle ablegen und von dort wieder öffnen und bearbeiten. Mehr dazu ein paar Seiten weiter. Bei diesem Dateiformat haben Sie, wie beim normalen Skript, nur die Option Nur ausführbar beim Sichern zur Verfügung. Wenn Sie diese Option ankreuzen, können Sie das Skript anschließend nicht mehr weiter bearbeiten. Denken Sie also daran, immer eine bearbeitbare Sicherungskopie davon aufzubewahren. Das Bundle-Format wird nur von HFS-formatierten Laufwerken unterstützt! Ein Bundle, welches zum Beispiel auf einen üblicherweise FAT-formatierten USB-Stick abgelegt wird, sieht vom Mac aus zwar immer noch wie eine Datei aus, vom Windows-Rechner aus betrachtet liegt auf dem Stick jedoch ein Ordner. Und das verleitet natürlich zum Herumstöbern, wobei das Skript vielleicht zerstört wird. Sie sollten Bundles daher immer in gutes »Packpapier« einwickeln. Das kann ein einfaches Zip-Archiv sein, welches mit dem Kontextmenü im Finder erzeugt wurde, oder ein Disk-Image im DMG-Format. Ein Skript-Bundle hat keinen Type und Creator.
Dateiformat »Programm-Bundle« Ein Skript, welches als Programm-Bundle gespeichert wird, erhält ebenfalls die Endung app. Allerdings handelt es sich hier nicht um eine einzelne Datei, sondern um einen Ordner, der wie eine einzelne Datei behandelt wird. Wenn Sie ein solchermaßen gespeichertes Skript mit der rechten Maustaste im Finder anklicken und Paketinhalt zeigen auswählen, sieht die Struktur im Bundle-Ordner wie in folgender Abbildung aus.
Abb. 3-19 Der Inhalt eines einfachen Skripts, welches als Programm-Bundle gesichert wurde. Die Grundstruktur ist identisch mit der eines Skript-Bundles, beachten Sie daher auch die Beschreibung dort. Das eigentliche Skript befindet sich wieder im Ordner Contents/ Resources/Scripts und heißt main.scpt. Dieses Skript wird geöffnet, wenn man ein Programm-Bundle explizit im Skripteditor öffnet. Wenn man das Programm-Bundle per Doppelklick startet, wird darin jedoch nicht das Skript, sondern die Startdatei applet im
78
Das Handwerkszeug
Kapitel 3
Ordner Contents/MacOS gestartet. Diese bildet sozusagen eine Hülle um den Code des Skripts und verleiht ihm ein Oberfläche mit grundlegender Menüleiste, wie sie auch andere Programme besitzen. Der restliche Inhalt des Bundles entspricht ebenfalls dem Inhalt eines Bundles eines normalen Macintosh-Programms. Dementsprechend finden sich die Details zu deren Sinn und Organisation in der Developer-Dokumentation von Apple. Wer hier tiefer einsteigen will, sei auf den Bundle Programming Guide von Apple hingewiesen: http://developer.apple.com/documentation/CoreFoundation/ResourceManagementdate.html Für Sie als Skripter ist hauptsächlich eine Eigenschaft des Programm-Bundles interessant, nämlich die, den Ordner Resources für alles, was Sie im Skript brauchen, zu verwenden, seien es Bilder, Texte, andere Appleskripts oder Code in anderen Sprachen. Für den Anfang interessant ist die Möglichkeit, seinem Skript ein eigenes Icon zu geben. Tauschen Sie dafür einfach die Datei applet.icns gegen ein anderes Icon mit gleichem Namen aus. Zum Erstellen von Icons ist das kleine Hilfsprogramm Icon Composer sehr nützlich. Sie finden es im Ordner /Developer/Applications/Utilities, wenn Sie die Xcode-Umgebung von Apple installiert haben. Bei Doppelklick wird ein Programm-Bundle standardmäßig direkt ausgeführt. Um es zur Bearbeitung zu öffnen, muss man es explizit mit dem Skripteditor öffnen. Geöffnet wird dadurch nur das Skript main.scpt und nicht eventuell andere vorhandene Skripts. Auch hier stehen beim Sichern alle drei Sichern-Optionen zur Verfügung: Nur ausführen, welche dafür sorgt, dass das Skript sich nicht mehr bearbeiten lässt, Startdialog, wodurch vor dem Ausführen des Skripts der Startdialog eingeblendet wird, und Nicht automatisch beenden, wodurch das Skript geöffnet bleibt und auf weitere Befehle wartet. Aufgepasst Wenn Sie ein Skript im Format Skript-Bundle mit mehreren Skripts oder anderen Dateien im Resources-Ordner als Programm-Bundle abspeichern, gehen diese zusätzlichen Dateien darin verloren! Sie müssen die zusätzlichen Skripts und Dateien nach dem erstmaligen Speichern als Programm-Bundle manuell hineinlegen. Danach bleiben diese Ressourcen aber erhalten – solange Sie das Format nicht erneut wechseln. Type- und Creator-Code für ein Programm-Bundle sind 'APPL' und 'aplt' und damit identisch zum einfachen Programmformat.
79
SmartBooks
AppleScript
Dateiformat »Text« Text ist das einzige Format, in dem das Skript vor dem Sichern nicht kompiliert wird. Damit stellt dieses Format die einzige Möglichkeit dar, ein fehlerbehaftetes (und damit nicht übersetzbares) Skript zu sichern. Das Dateikürzel ist diesmal ein ungewöhnlich langes, nämlich applescript, welches dafür aber auch keinen Zweifel am Inhalt der Datei lässt.
Abb. 3-20 Icon eines Skripts, welches als Text gespeichert wurde. Die Datei erhält das Dateikürzel »applescript«. Trotz des Dateikürzels handelt es sich um eine ganz normale Textdatei im Unicode-Format (UTF16). Die einzige Option beim Sichern ist die Einstellung für das Zeilenende. Solange Sie auf dem Mac arbeiten, sollten Sie diese auf Unix (LF) belassen. Mac OS X ist ein Unix-System, und damit ist dies die normale Einstellung. Andere Alternativen sind der alte Standard Mac (CR), nützlich, wenn Sie den Text in einem älteren Mac-Programm öffnen wollen, sowie Windows (CRLF) für die Weiterverarbeitung auf einem Windows-Rechner. Wenn Sie auf dem Mac auf eine Text-Datei mit der Endung applescript doppelklicken, wird diese weiterhin im Skripteditor geöffnet. Um den Text in einem anderen Programm zu öffnen, müssen Sie das explizit tun. Type- und Creator-Code für diesen Dateityp sind 'TEXT' und 'ToyS'.
Bundle-Inhalt Wenn Sie im Skripteditor ein Skript-Bundle geöffnet haben, können Sie mit der Schaltfläche Bundle-Inhalt rechts in der Symbolleiste in den Ordner Resources des Bundles hineinschauen. Dabei öffnet sich eine Schublade an der Seite des Skripteditors, die den Inhalt des Ressourcen-Ordners darstellt. Sie können nun in diese Schublade weitere Skripts oder andere Dateien ablegen. Ziehen Sie dafür einfach die benötigten Dateien vom Finder in die Seitenschublade. Das funktioniert nur mit Skript-Bundles, also nicht mit Programm-Bundles! Mit Programm-Bundles funktioniert diese Schublade nur während der Erstellung des Skripts, nicht jedoch beim erneuten Öffnen, was wahrscheinlich ein Bug ist. Achten Sie darauf,
80
Das Handwerkszeug
Kapitel 3
das Skript dann auch weiterhin immer nur im Skript-Bundle-Format zu sichern. Beim Wechsel des Formats sind nämlich alle Ressourcen weg! Sie können den Inhalt des Bundles aber natürlich auch auf die klassische Art und Weise bearbeiten, indem Sie im Finder mit der rechten Maustaste auf das Bundle klicken und Paketinhalt zeigen wählen. Das Hauptskript main.scpt wird in der Schublade übrigens nicht angezeigt. Das Hauptskript ist ja auch schon im Fenster geöffnet.
Abb. 3-21 Die Schublade »Bundle-Inhalt« im Skripteditor
Alternative AppleScript-Editoren Die Welt der AppleScript-Editoren ist (noch) relativ klein und überschaubar. Es gibt bisher nur zwei ernsthafte Alternativen zum Skripteditor von Apple: Da sind zum einen der Script Debugger des kanadischen Entwicklers Mark Alldritt (www.latenightsw.com) und SmileLab von Satimage in Frankreich (www.satimage.fr/software/en/). Diese Editoren werden hier kurz vorgestellt. Grundlagen Theoretisch lässt sich auch Xcode für die Erstellung eines Appleskripts verwenden. Dem stellt sich aber die Tatsache entgegen, das Ihnen Xcode immer gleich die ganzen CocoaBibliotheken inklusive Nib-File für ein Fenster mit hineinpackt, was die Erstellung eines einfachen Skripts ohne Benutzerinterface unnötig behindert.
81
SmartBooks
AppleScript
Script Debugger
Abb. 3-22 Script Debugger Icon Der Script Debugger von Late Night Software ist seit 1995 eine der wenigen professionellen Alternativen zum Skripteditor von Apple. Um nur die entscheidenden Vorzüge gegenüber dem Skripteditor von Apple hervorzuheben, hier eine kleine, nicht vollständige Liste mit den Vorteilen des Script Debuggers gegenüber dem Skripteditor von Apple.
Abb. 3-23 Der Script Debugger (www.latenightsw.com) << Ausgeklügelter Dictionary Browser mit ausführlicheren Informationen als denen des Funktionsverzeichnisses aus dem Skripteditor. Mit Explorer und grafischer Baumansicht der Klassenstruktur << Tell Context Inspector – Ein Inspector, der einem, abhängig von der Stelle im Code, an der man sich befindet, alle Eigenschaften des entsprechenden Objekts mitteilt << Erweiterte Suche in Funktionsverzeichnissen, auch über mehrere Funktionsverzeichnisse hinweg << Anzeige unsichtbarer Zeichen und der Zeilennummerierung
82
Das Handwerkszeug
Kapitel 3
<< Detaillierte Informationen zu den AppleScript-Ergebnissen << Es können mehrere Skripte auf einmal laufen << Stoppen oder Pausieren eines Skripts an jeder beliebigen Stelle im Code << Ausführlichere Fehlermeldungen << Professioneller Debugger mit Breakpoints und Anzeige des Inhalts von Variablen zur Laufzeit << Debuggen von Kontrollstrukturen und Handlern (Step into, Step over, Step out) Der Script Debugger kostet 199 US Dollar und liegt, wie bei so vielen Programmierwerkzeugen, nur in englischer Lokalisierung vor. Wenn Sie den Script Debugger installieren, werden Ihnen auch zwei weitere OSA-Sprachen mitinstalliert, AppleScript Debugger X (wird intern vom Script Debugger verwendet) und JavaScript (um JavaScript, statt AppleScript zur Steuerung anderer Anwendungen zu verwenden). Sollten Sie einmal größere Skripts entwickeln oder so gut wie jeden Tag skripten, ist der Script Debugger jeden seiner Dollar wert.
SmileLab und Smile
Abb. 3-24 Smile Icon SmileLab nimmt eine Sonderstellung ein. Es ist ganz auf die Automatisierung der grafischen Darstellung von Daten für den technischen oder wissenschaftlichen Bereich spezia lisiert. SmileLab kostet 449 US Dollar (Academic $299). Sein kleinerer Bruder Smile ist kostenlos. Natürlich können Sie mit Smile aber auch ein ganz »normales« Appleskript erstellen, ohne die zusätzlichen Möglichkeiten zu nutzen. Smile erfordert etwas mehr Einarbeitungsaufwand, da es sich im Konzept vom Skripteditor und dem Script Debugger unterscheidet. Sowohl im Download selbst als auch auf der Webseite findet sich jedoch umfassendes Material für den Einstieg.
83
SmartBooks
AppleScript
Abb. 3-25 Seine wahre Stärke zeigt Smile erst bei der Visualisierung von Daten. Mit der Steuerelementpalette lassen sich zudem auch eigene Fenster und Dialoge zimmern. Wenn Sie Smile installieren, werden auch drei Erweiterungen in den Ordner /Library/ ScriptingAdditions/ installiert. Es handelt sich um die Erweiterungen Numerics.osax, Satimage.osax und XMLLib.osax. Diese liefern die notwendigen Befehle und Klassen für die Arbeit mit Smile. Die besonderen Leckerbissen von SmileLab: << Erstellen von Benutzerschnittstellen in Aqua oder HTML << Grafikbibliothek zur Erstellung von Vektor- (PDF) oder Bitmapgrafiken (PNG, JPG etc.) << Reguläre Ausdrücke für die Bearbeitung von Text << Arbeiten mit XML-Dokumenten und PropertyLists << Mathematik-Bibliotheken für die Berechnung großer Datenmengen << Unterstützung für serielle (RS232) oder digitale I/O-Schnittstellen
84
Das Handwerkszeug
Kapitel 3
Werkzeuge zur Erstellung grafischer Benutzerschnittstellen Es gibt zurzeit genau zwei Entwicklungsumgebungen, mit denen sich mit AppleScript auch ganze Programme erstellen lassen, die sich kaum mehr von anderen »professionellen« Programmen unterscheiden: AppleScript Studio und FaceSpan. AppleScript Studio kommt von Apple, ist kostenlos und in die Entwicklungsumgebung Xcode integriert. FaceSpan ist ein kommerzielles Produkt, seit über 10 Jahren auf dem Markt und im Gegensatz zu AppleScript Studio ganz auf die Entwicklung in AppleScript ausgerichtet. Aufgepasst Auch mit Smile lassen sich übrigens Fenster und Dialoge erstellen, jedoch keine vollwertige Anwendung. Aus diesem Grund wird Smile in diesem Kapitel nicht aufgeführt. Weitere Alternativen sind Programme wie zum Beispiel Revolution (www.runrev.com) oder Supercard (www.supercard.us), die, von HyperCard inspiriert, dessen Gedanken fortführen. Bei den darin verwendeten Skriptsprachen handelt es sich jedoch nicht um AppleScript, sondern um eigene, auf HyperTalk basierende Weiterentwicklungen.
AppleScript Studio AppleScript Studio hört sich so ganz nach einem Programm dieses Namens an. Sie werden jedoch vergeblich auf Ihrer Festplatte nach diesem Programm suchen. Es ist nicht vorhanden, leider. AppleScript Studio ist nichts anderes als die Entwicklungsumgebung Xcode. Dass man in Xcode auch in AppleScript programmieren und dabei auf die professionellen Programmier-Bibliotheken zugreifen kann, wird von Apple als AppleScript Studio vermarktet. Mit AppleScript Studio können Sie in der Sprache AppleScript Programme schreiben und dabei auf viele der Cocoa-Bibliotheken zugreifen, genauso wie professionelle Entwickler, die ihre Programme in der Programmiersprache Objective-C schreiben. Mit anderen Worten: Ihre darin erstellten Programme können all die grafischen Elemente von Fenstern, Dialogen, Knöpfen, Feldern, Schiebereglern und was es sonst noch alles gibt nutzen. Wenn Sie mehr als ein einfaches display dialog benötigen, dann verwenden Sie AppleScript Studio. Programme, die Sie damit erstellen, können dabei durchaus auch professionell sein, in dem Sinne, dass dafür Geld verlangt werden kann. Wenn man die Programmverzeichnisse für Mac-Software im Internet durchforstet, findet man immer mehr Programme, bei denen der Verdacht naheliegt, dass es sich um mit AppleScript Studio erstellte Programme handelt.
85
SmartBooks
AppleScript
Abb. 3-26 AppleScript Studio ist kein eigen ständiges Programm, sondern in den Ent wicklerwerkzeugen Xcode und Interface Builder integriert. Sie müssen also Xcode von Apple installieren, wenn Sie AppleScript Studio nutzen möchten. Xcode wird bei einer normalen Betriebssystem-Installation nicht automatisch mitinstalliert. Wenn Sie Xcode installiert haben, erkennen Sie es daran, dass auf oberster Ebene der Festplatte ein Ordner namens Developer liegt. Im Unterordner Applications befinden sich dann die benötigten Programme, namentlich das Programm Xcode und der Interface Builder. Wenn Sie diesen Ordner nicht vorfinden, müssen Sie Xcode erst installieren. Schauen Sie dafür einfach mal auf Ihren Betriebssystem-CDs oder der DVD nach. Auf der Original Leopard Mac OS X 10.5.0-DVD finden Sie den Installer im Ordner Optional Installs | Xcode Tools. Starten Sie darin Xcode Tools.mpkg und führen Sie eine Standardinstallation durch. Da die Xcode-Entwicklungsumgebung stetig weiterentwickelt wird, ist inzwischen wahrscheinlich eine aktuellere Version erschienen. Sie können diese bei http://developer.apple. com herunterladen. Aufgepasst Vorsicht! Xcode ist in der aktuellen Version bereits 1,1 Gigabyte groß. Das Herunterladen aus dem Internet ist also nur mit einer schnellen DSL-Leitung zu empfehlen. Für den Zugang zum Downloadbereich benötigen Sie einen Developer-Account bei Apple. Die einfache Version eines Accounts ist dabei kostenlos. Klicken Sie dafür auf der Startseite von developer.apple.com auf den Link zum Einloggen (ADC Member Site) und danach auf Join Now. Nach Eingabe einiger persönlicher Daten haben Sie Zugriff auf viele hilfreiche Tools und Dokumente für Entwickler. Beachten Sie dabei, dass das gesamte Material generell nur in englischer Sprache vorliegt. Wechseln Sie nach dem Einloggen in den Bereich Downloads und dort in die Rubrik Developer Tools. Dort finden Sie das Paket Xcode 3.1. Die Entwicklungsumgebung Xcode ist ein professionelles Werkzeug für Programmierer. Sie enthält das Programm Xcode, in welchem der Code erstellt wird, den Interface Builder,
86
Das Handwerkszeug
Kapitel 3
in welchem Fenster und Dialoge zusammengebaut werden, viele weitere Hilfsprogramme und tonnenweise Dokumentation und Beispiele. Wenn Sie mit Xcode AppleScript-Programme schreiben, benötigen Sie jedoch nur einen kleinen Teil der vorhandenen Möglichkeiten. Sie können in Xcode in fast allen Sprachen programmieren. Aber auch genau darin liegt der Nachteil: Als Anfänger werden Sie von den Möglichkeiten – und damit auch den Möglichkeiten, etwas falsch zu machen – erschlagen. Xcode macht es dem Skripter hier sehr schwer. Programme wie FaceSpan sind da übersichtlicher und einfacher in der Handhabung, ohne weniger professionell zu sein. Trotzdem sollten Sie vor AppleScript Studio nicht zurückschrecken. Es gibt nämlich einen guten Grund, Xcode zu verwenden: Es ist kostenlos!
Abb. 3-27 Xcode und der Interface Builder in Aktion
FaceSpan FaceSpan ist die einzige Alternative zu AppleScript Studio und ein Urgestein in der AppleWelt. Apple selbst hatte vor Mac OS X nie eine Entwicklungsumgebung mit vollem grafischem Support für AppleScript angeboten. In diese Bresche sprang damals FaceSpan. Seit 2006 ist FaceSpan in der Obhut von Mark Alldritt von Late Night Software und wird derzeit von ihm komplett überarbeitet und auf eine neue Codebasis gestellt. Fans weltweit warten bereits gespannt auf die angekündigte Version 5.
87
SmartBooks
AppleScript
FaceSpan hat gegenüber AppleScript Studio den großen Vorteil, dass es ganz auf AppleScript ausgerichtet ist. Es ist also kein Alleskönner wie die Entwicklungsumgebung von Xcode, die eigentlich für professionelle Programmierer und die Entwicklung in Sprachen wie C++ und Objective-C gedacht ist. FaceSpan erinnert mehr an das verstorbene HyperCard, ohne jedoch den Stapelbegriff zu übernehmen. FaceSpan hat alles, was Sie brauchen. Sie können damit alle Arten von Fenstern und Dialogen gestalten, genauso wie Menüs. Kurz: Vom Aussehen her wird man Ihr damit erstelltes Programm nicht von anderen Programmen unterscheiden können.
Abb. 3-28 Von Mark Alldritt veröffentlichtes Bildschirmfoto der in Entwicklung befindlichen Version 5 von FaceSpan (www.latenightsw.com/blog/) Wenn es um Alternativen zu AppleScript Studio geht, ist FaceSpan derzeit die einzige auf dem Markt erhältliche, wenn man nicht auf andere Skriptsprachen ausweichen will.
88
Das Handwerkszeug
Kapitel 3
Das AppleScript-Dienstprogramm Das AppleScript-Dienstprogramm finden Sie im Ordner /Applications/AppleScript/. Es bündelt die wenigen Einstellmöglichkeiten AppleScript betreffend in einer einzigen Anwendung. Wenn Sie es starten, erhalten Sie das Fenster aus der folgenden Abbildung.
Abb. 3-29 Das AppleScript-Dienstprogramm Im Einblendmenü neben Standard-Skripteditor können Sie einen anderen Editor zum Erstellen Ihrer Skripts auswählen. Wenn Sie zum Beispiel Smile oder den Script Debugger bevorzugen, dann wählen Sie es hier aus. Für dieses Buch sollten Sie die Einstellung aber auf dem Skripteditor lassen. Diese Einstellung ändert nicht das Erzeugerprogramm eines bereits erstellten Skripts. Dafür müssen Sie weiterhin den Informationsdialog eines Skripts aufrufen, dort bei Öffnen mit das Programm auswählen und anschließend auf Alle ändern klicken. Bei GUI-Scripting sollten Sie für die Arbeit mit diesem Buch einen Haken setzen. Der Knopf Bedienungshilfen führt Sie zu der gleichnamigen Systemeinstellung. Wenn Sie den Haken bei GUI-Scripting gesetzt haben, wird dort automatisch ein Haken bei Zugriff für Hilfsgeräte aktivieren gesetzt. Ohne diese Einstellung ist kein GUI-Scripting möglich.
89
SmartBooks
AppleScript
Abb. 3-30 Für das GUI-Scripting muss der Zugriff für Hilfsgeräte in den Systemeinstellungen aktiv sein. Der Knopf neben Ordneraktionen führt Sie zu dem kleinen Dienstprogramm Ordneraktionen konfigurieren. Dieses Programm liegt im selben Ordner wie das AppleScript-Dienstprogramm. Dieses Werkzeug wird im Kapitel »Ordneraktionen« beschrieben. Das Programm lässt sich auch aufrufen, indem Sie im Kontextmenü eines Ordners den Eintrag Mehr und dann Ordneraktionen konfigurieren wählen.
Abb. 3-31 Die Verwaltungshilfe für Ordneraktionen
90
Das Handwerkszeug
Kapitel 3
Setzen Sie bei Skriptmenü in der Menüleiste zeigen und bei Computer-Skripts anzeigen einen Haken. Sie erhalten daraufhin in der Menüleiste rechts oben ein kleines Schriftrollen-Symbol. Wenn Sie darauf klicken, öffnet sich das Skriptmenü.
Abb. 3-32 Ein angepasstes Skriptmenü: Im unteren Abschnitt stehen selbst hinzugefügte Ordner oder Skripts, in der Mitte Computerskripts, oben Programmskripts des gerade aktiven Programms (hier von der Layout-Software RagTime).
91
SmartBooks
AppleScript
Das Skriptmenü Das Skriptmenü stellt Ihnen systemweit eine zentrale Zugriffsmöglichkeit auf Ihre Skripts zur Verfügung. Wenn Sie noch keine Anpassungen vorgenommen haben, werden Sie im Gegensatz zu obiger Abbildung nur die Einträge in der Mitte, die Computerskripte, und die obersten beiden Menüeinträge sehen. Mit dem zweiten Menüeintrag von oben, AppleScript-Dienstprogramm öffnen, können Sie selbiges von überall schnell erreichen, ohne erst in den Finder zu wechseln. Über den Menüpunkt Skriptordner öffnen können Sie die verschiedenen Ordner öffnen, an denen die Skripts liegen. Dabei gibt es genau drei Möglichkeiten: << Skriptordner von Programmname öffnen << Skriptordner des Benutzers öffnen << Skriptordner des Computers öffnen Für Programmname müssen Sie dabei den Namen des gerade aktiven, also vorne befindlichen Programms einsetzen. Dieser Teil des Skriptmenüs ist jedoch nur sichtbar, wenn für das entsprechende Programm auch Skripts angelegt wurden. Tipp Wenn Sie eines der Skripts aus dem Skriptmenü öffnen möchten, um es zu studieren oder zu bearbeiten, halten Sie einfach die [Alt]-Taste gedrückt, während Sie es auswählen. Ansonsten werden die Skripts im Skriptmenü sofort ausgeführt, auch wenn sie als Skript oder Skript-Bundle abgespeichert wurden. Nur ein als Text abgespeichertes Skript wird vom Skriptmenü immer im Skripteditor geöffnet. Tipp Wenn Sie die [Umschalt]-Taste gedrückt halten, während Sie ein Skript auswählen, öffnet sich der Ordner, in dem das Skript liegt.
Computerskripts Wenn Sie Skriptordner des Computers öffnen auswählen, öffnet sich das Verzeichnis /Library/Scripts/ Ihres Rechners.
92
Das Handwerkszeug
Kapitel 3
Hier liegen alle sogenannten Computerskripts, die allerdings nur angezeigt werden, wenn Sie im AppleScript-Dienstprogramm auch Computer-Skripts anzeigen ausgewählt haben. Sie können hier auch eigene Ordner anlegen, vorausgesetzt, Sie haben Administratorrechte. Alles, was in diesem Verzeichnis liegt, steht allen Benutzern des Rechners zur Verfügung. Das heißt, dieser Ort eignet sich besonders für Skripts, die von mehreren Benutzern am gleichen Rechner verwendet werden sollen. Hier finden Sie alle möglichen Skripts versammelt, die Apple für besonders nützlich oder lehrreich erachtet. Ein Blick in diese Skripts kann Ihnen bei Ihren eigenen Skripts immer wieder eine große Hilfe sein. Schauen Sie sich die Skripts daher unbedingt immer wieder mal an. Sie müssen das Rad nicht jedes Mal neu erfinden. Bei den Computerskripts finden sich auch die Skripts aus dem Kontextmenü des Skript editors wieder, und zwar im Unterordner Script Editor Scripts. Möchten Sie das Kontextmenü erweitern, brauchen Sie hier nur Ihre eigenen Skripts abzulegen. Ein Blick in die bereits bestehenden Skripts hilft beim Erstellen eigener Kontextmenü-Skripts. Seien Sie vorsichtig damit, bereits bestehende Order oder Skripts in den Computerskripts zu löschen. Es kann nicht ausgeschlossen werden, dass auch andere Apple-Programme für manche ihrer Funktionen auf Skripts in diesem Verzeichnis zugreifen. Legen Sie sich in jedem Fall vorher eine Sicherungskopie dieser Skripts an. Es wäre schade, wenn diese Beispiele verloren gingen.
Benutzerskripts Wenn Sie im Skriptmenü Skriptordner öffnen | Skriptordner des Benutzers öffnen auswählen, öffnet sich der Skriptordner in Ihrem Heimverzeichnis. Das liegt unter /Users/[Benutzername]/Library/Scripts/. Statt Benutzername müssen Sie hier den Namen des gerade angemeldeten Benutzers einfügen. Dieser Ordner ist ursprünglich leer. Alles, was Sie hier ablegen, steht nur Ihnen, also dem angemeldeten Benutzer zur Verfügung und kann aus allen Programmen heraus aufgerufen werden. Dieser Ort ist empfehlenswert für Skripts, die entweder keine oder mehrere Programme zur Ausführung benötigen und die normalerweise nicht direkt aus einem Programm heraus aufgerufen werden. Sie können hier aber auch beliebige andere Dateien und nicht nur Skripts ablegen.
93
SmartBooks
AppleScript
Ein paar Beispiele: << Legen Sie sich einen Ordner mit der gesamten AppleScript-Dokumentation von Apple hier an. Das können auch Aliase sein. So können Sie dann jederzeit über das Skriptmenü auf die Dokumentation zugreifen und schnell etwas nachsehen. << Legen Sie sich einen Ordner mit Ihren ganzen Weblinks zu AppleScript hier an. Ziehen Sie dafür einfach die Links aus der Adresszeile von Safari in diesen Ordner. << Legen Sie sich ein Alias auf die ScriptingAdditions-Ordner in Root-, System- und User-Library an. So können Sie schnell nachsehen, welche Erweiterungen installiert sind. Wenn Sie dann eine davon über das Skriptmenü auswählen, wird deren Funktionsverzeichnis geöffnet. << Sie arbeiten auch mit Perl-, Python-, Ruby- oder Shellskripts? Legen Sie sich einen Ordner für die Skripts an, die Sie gerne von überall aus erreichen möchten, und legen Sie Ihre Skripts dort ab. Sie können diese Skripts aber nicht direkt aus dem Skriptmenü starten! Das Skriptmenü erlaubt das nicht. Halten Sie daher die Alt-Taste gedrückt, während Sie zum Beispiel ein Perl-Skript im Skriptmenü auswählen. Das Skript wird dann in seinem Editor geöffnet, zum Beispiel TextWrangler, von wo es sich dann starten lässt.
Programmskripts Wenn Sie Skriptordner von [Programmname] öffnen auswählen, öffnet sich das Verzeichnis /Users/[Benutzername]/Library/Scripts/Applications/[Programmname]. Es handelt sich also um einen Unterordner der Benutzerskripts. Dieser Unterordner hat es jedoch in sich! Sind Sie zum Beispiel gerade als Benutzer »Karl« angemeldet und ist das Programm TextEdit aktiv, dann lautet das Verzeichnis: /Users/Karl/Library/Scripts/Applications/TextEdit/ Existiert das Verzeichnis Applications/TextEdit oder TextEdit noch nicht, wird es gleich erzeugt, wenn Sie Skriptordner öffnen | Skriptordner von TextEdit öffnen im Skriptmenü auswählen. Jeder Unterordner oder jedes Skript, welches Sie nun in den Ordner TextEdit hineinlegen, wird nur dann im Skriptmenü angezeigt, wenn TextEdit gerade aktiv ist. Diese programmbezogene Einblendung im Menü ist damit besonders hilfreich für Skripts, die aus einem Programm heraus aufgerufen werden müssen, zum Beispiel, weil dort zuvor eine Auswahl getroffen werden muss, auf der das Skript dann arbeitet. Auch für alle Programme, die kein eigenes Skriptmenü besitzen, sind diese Programmskripts wunderbar. Alle Skripts, die das Programm betreffen, sind damit an einem Ort versammelt, werden aber nur angezeigt,
94
Das Handwerkszeug
Kapitel 3
wenn das Programm auch gerade geöffnet und vorne ist. Die Programmskripts überfüllen damit also das Skriptmenü nicht so sehr wie die Computer- oder Benutzerskripts, die ständig angezeigt werden. Ebenfalls empfehlenswert ist es natürlich, programmspezifische Ressourcen hier abzulegen. So könnten Sie hier zum Beispiel einen Unterordner anlegen und darin Dokumentation und Weblinks zu diesem Programm ablegen. Je nachdem, was Sie im AppleScript-Dienstprogramm angekreuzt haben, werden diese Programmskripts oben oder unten im Skriptmenü eingeblendet.
Programmspezifische AppleScript-Integration Bei Anwendungen, die ein eigenes Skriptmenü besitzen, wie zum Beispiel BBEdit und sein kleiner Bruder TextWrangler oder GraphicConverter, ist das systemweite Scriptmenü eigentlich nicht notwendig. Solche Programme bringen ihre Appleskripts meist im Ordner ~/Library/Application Support/[Programmname]/Scripts/ unter oder wie iTunes direkt unter ~/Library/iTunes/Scripts/. Liegt ein solcher Ordner nicht vor, wie zum Beispiel bei iTunes nach einer frischen Systeminstallation, so muss man den Ordner dort erst einmal manuell anlegen. Alle Skripts, die Sie dann darin ablegen, erscheinen in iTunes in einem neuen Menü mit dem AppleScript-Symbol.
Abb. 3-33 Das Skriptmenü von iTunes erscheint erst, wenn unter ~/Library/iTunes/ ein Ordner »Scripts« angelegt wurde (hier mit einigen Appleskripts von http://dougscripts.com/ itunes). iTunes ist anscheinend das letzte Programm von Apple, welches noch ein eigenes Skriptmenü besitzt. Früher fand man dieses Menü auch noch in anderen Programmen wie zum Beispiel Mail oder Adressbuch. Jetzt ist man dafür auf das Skriptmenü angewiesen und muss mailspezifische Skripts, zum Beispiel als Programmskripts, dort unterbringen. Der Trend führt wohl hin zum systemweiten Skriptmenü. Nun, darüber kann man durchaus geteilter Meinung sein, Dezentralisierung hat auch ihre Vorteile. Jedenfalls ist es durch das Skriptmenü einfacher geworden, alle seine Skripts mitzunehmen und auf einem anderen Rechner zu installieren.
95
SmartBooks
AppleScript
Manche Programme treiben die AppleScript-Integration noch weit über ein eigenes Skriptmenü hinaus. Hier hilft dann oft nur ein Blick in die Dokumentation. Zwei Beispiele von vielen: RagTime besitzt ein eigenes Skriptmenü (als Untermenü in Extras | AppleScript). Die Skripts, die dort aufgelistet werden, liegen jedoch nicht extern als Datei auf der Festplatte, sondern werden direkt im Dokument abgespeichert. Wenn man das Dokument mitnimmt, kann das Appleskript also nicht vergessen werden. Skripts, die in einem speziellen Voreinstellungsdokument namens RagTime-6-Hilfsmittel abgespeichert werden, stehen allen Dokumenten zur Verfügung, allerdings nur auf diesem Rechner. Dass Skripts im Dokument gespeichert werden, ist bei RagTime-Dokumenten besonders wichtig, da Appleskripts hier auch auf Knöpfe gelegt werden können. Die würden natürlich nicht mehr funktionieren, wenn vergessen würde, das Skript mitzugeben. Des Weiteren besitzt RagTime einen eigenen eingebauten AppleScript-Editor, der sich zumindest zur Erstellung kleinerer Skripts gut eignet. (Ansonsten ist die Arbeit im Skripteditor wesentlich komfortabler, vor allem beim Debuggen.) So kann man aus RagTime heraus, über das Skriptmenü oder über Schaltflächen, RagTime und andere Anwendungen wunderbar steuern, zum Beispiel, um aktuelle Informationen zu sammeln und im Layout einzufügen. FileMaker besitzt zwar kein eigenes Skriptmenü, allerdings können auch hier Skripts auf Schaltflächen gelegt werden. FileMaker wird dafür seit Urzeiten von Mac-Skriptern inniglich geliebt. So lassen sich oft auf direktem Wege Daten aus wirklich allen möglichen anderen Programmen in FileMaker hineinbekommen und natürlich auch wieder heraus. Die Skripts können dabei extern als Datei vorliegen, als Text in der Datenbank oder sogar erst kurz vor der Verwendung zusammengebaut werden. Wichtig ist es hier, klar zu unterscheiden zwischen den FileMaker-Skripts und den Appleskripts, da sich auch die zu FileMaker gehörende Steuersprache als Skript versteht.
96
Die Sprache
4
Dieses Kapitel führt Sie Schritt für Schritt in alle Elemente der ProgrammierSprache ein. Da AppleScript einen relativ kleinen Sprachumfang hat und sich sehr natürlich »spricht«, geht das viel schneller und leichter als in jeder anderen Skriptsprache, trotzdem gibt es natürlich auch hier einige Regeln zu beachten.
SmartBooks
AppleScript
Einstieg Dieses Kapitel fängt ganz von vorne an und erwartet keinerlei Erfahrung mit Programmiersprachen von Ihnen. Alles, was Sie für die folgenden Seiten brauchen, ist der Skripteditor im Ordner Programme/AppleScript. Schreiben Sie dort einfach alle Skripts, die Ihnen ab jetzt begegnen, hinein und klicken Sie dann auf den Knopf Ausführen, um das Resultat im Ergebnisbereich im unteren Teil des Skripteditors angezeigt zu bekommen. Zuerst einmal sollten Sie aber überprüfen, welche Version von AppleScript und dem Skripteditor bei Ihnen installiert ist. 1. Starten Sie dafür im Skripteditor ein neues Skript über das Menü Ablage | Neu. 2. Wählen Sie unten den Bereich Ergebnis aus. 3. Tippen Sie dann im oberen Bereich: version 4. Klicken Sie dann auf Ausführen. Im Bereich Ergebnis erscheint nun die Versionsnummer von AppleScript. Zum Zeitpunkt der Erstellung des Buches war die Version 2.0.1 aktuell und wird es wohl noch einige Zeit bleiben. Trotzdem weise ich darauf hin, dass, wenn Sie eine ältere Version haben, Beschreibungen, die speziell Leopard betreffen, bei Ihnen dann nicht funktionieren. Des Weiteren können einige Fehler, auf die ich in diesem Buch hinweise, in einer neueren Version inzwischen behoben worden sein. In jedem Fall empfehle ich Ihnen, auch einen Blick auf die Webseite für dieses Buch zu werfen. Unter www.skripteditor.de können Sie sich die längeren Codebeispiele aus dem Buch herunterladen. Das erspart Ihnen unnötiges Abschreiben. Auch der Skripteditor selbst hat natürlich eine Versionsnummer. Und es mag sein, dass eine neuere Version sich in dem einen oder anderen Fall anders verhält. Die Skripts in diesem Buch wurden mit dem Skripteditor in der Version 2.2 und manchmal auch mit dem Script Debugger in der Version 4.0.8 erstellt und getestet. Wenn Sie die Version des Skripteditors feststellen möchten, so machen Sie das als zukünftiger Skripter natürlich ebenfalls mit AppleScript. Tippen Sie dafür: version of application "Script Editor"
98
Die Sprache
Kapitel 4
Nach einem Klick auf Ausführen erscheint im Bereich Ergebnis die Version des Skripteditors.
Zahlen Das Einfachste, was man in AppleScript machen kann, ist, damit zu rechnen. Achten Sie im Folgenden darauf, dass der Reiter Ergebnis im Skripteditor eingeblendet ist, denn dort wird das Ergebnis der letzten Rechenoperation angezeigt.
Arithmetische Operatoren Zahlen, direkt als Zahl geschrieben, werden auch als »Zahlliterale« bezeichnet. Sie werden von der Programmiersprache, hier AppleScript, sozusagen »wörtlich« genommen. Wenn Sie im Skripteditor zum Beispiel 5+2 schreiben und dann auf Ausführen klicken, wird unten eine 7 als Ergebnis angezeigt. Alternativ können Sie auch die Tastenkombination [Befehl]+[R] verwenden.
Abb. 4-1 Rechnen im Skripteditor Auch die anderen Grundrechenarten stehen natürlich zur Verfügung.
99
SmartBooks
AppleScript
Probieren Sie einmal die folgenden Berechnungen nacheinander aus. Sie müssen dafür übrigens nicht jedes Mal alles bereits Geschriebene löschen, da im Bereich Ergebnis immer nur das Resultat der letzten Berechnung angezeigt wird. Schreiben Sie die Beispiele daher einfach immer auf der nächsten Zeile weiter. 5-2 5*2 5/2 Weitere Operatoren sind div, mod und ^ (den kursiven Text in Klammern bitte nicht mit eingeben, er dient nur der Erklärung): 5 div 2 (ergibt 2, ganzzahlige Division, nur der Betrag vor dem Komma zählt) 5 mod 2 (ergibt 1, Modulo, Restdivision, der unteilbare Rest) 5 ^ 2 (ergibt 25.0, Exponent) Damit haben Sie bereits alle arithmetischen Operatoren von AppleScript kennengelernt. Beachten Sie das Ergebnis bei der Division 5 / 2. Sie erhalten hier als Ergebnis 2.5 und nicht 2,5. Das heißt, in AppleScript wird für Zahlen der Punkt und nicht das Komma als Dezimalzeichen verwendet. Das ist im englischsprachigen Raum und bei Programmiersprachen üblich. Wenn Sie also mit Kommazahlen rechnen wollen, dann müssen Sie den Punkt verwenden und nicht das Komma, wie in folgendem Beispiel: 10.5 - 2.75 (ergibt 7.75) Ist bei einer Berechnung eine Zahl mit Dezimalpunkt oder der Operator / beteiligt, dann ist das Ergebnis immer eine Dezimalzahl, auch wenn es glatt aufgeht und die Nachkommastelle nur null ergibt. (Text in Klammern nicht eingeben) 5.0 5.0 5.0 5.0
+ – * /
2 2 2 5
(= 7.0) (= 3.0) (= 10.0) (= 1.0) alternativ auch: 5.0 ÷ 5
Es gibt in AppleScript nur diese beiden Klassen von Zahlen, entweder es handelt sich um eine Ganzzahl ohne Komma (Integer genannt) oder um eine Dezimalzahl (Real genannt).
100
Die Sprache
Kapitel 4
Tipp Wenn Sie aus dem technischen oder wissenschaftlichen Bereich kommen, werden Sie zu Recht einige weitere fundamentale Operatoren und höhere Funktionen vermissen. AppleScript ist wie bereits erwähnt bewusst klein gehalten. Weitergehende Funktionen können in AppleScript aber leicht von anderen Programmen berechnet werden, die von AppleScript aus gesteuert werden, oder Sie lassen sich durch Erweiterungen nachrüsten. Die Erweiterungen von Satimage, die beim Installieren von Smile mitgebracht werden, bringen solche Funktionen im Übermaß mit.
Die Klassen integer und real Grundlagen Falls Sie weitere Typen wie zum Beispiel Byte, Short, Long und Double suchen, wie sie in anderen Programmiersprachen üblich sind, werden Sie bei AppleScript nicht fündig. Entweder eine Zahl hat ein Komma oder nicht, so einfach ist das. Dabei entsprechen die Integer nicht ganz einem Long und Dezimalzahlen (Real) entsprechen einem Double. Wie groß oder klein kann eine Integerzahl in AppleScript sein? Genau ± 536870911, also grob 537 Millionen, plus oder minus. Alles, was diese Grenze überschreitet, wird automatisch in eine Dezimalzahl umgewandelt. Dezimalzahlen können in AppleScript bis in den Bereich von 1.797693e±308 verarbeitet werden. Beachten Sie, dass ein Integer automatisch in eine Dezimalzahl umgewandelt wird, wenn irgendwo in der Berechnung eine Division vorkommt. Bei den anderen Operatoren erhalten Sie nur dann eine Dezimalzahl, wenn eine der beteiligten Zahlen eine Dezimalzahl war. Der Operator div ist der einzige Operator, der immer eine Integerzahl als Ergebnis zurückliefert, auch wenn die Operanden Dezimalzahlen sind. Wenn Sie später mit Variablen arbeiten, werden Sie nicht mehr unbedingt sagen können, ob eine Variable nun ein Integer oder ein Real enthält. Hier ist es hilfreich, die Klasse mit class of abzufragen: class of 1.25 ergibt real als Ergebnis.
101
SmartBooks
AppleScript
class of 3 ergibt integer als Ergebnis.
Umwandlung von Zahlen Wenn Sie eine Dezimalzahl in eine Ganzzahl umwandeln wollen, so können Sie das in AppleScript mit dem Operator as erledigen. 3.15 as integer ergibt 3. Aufgepasst Die Nachkommastellen werde dabei gerundet, und zwar nach den Regeln von round to nearest. (Das wird ein paar Seiten weiter beschrieben.) Wenn man das nicht will, sollte man auf die Umwandlung mit as integer verzichten und besser gleich den Befehl round mit anderen Parametern verwenden. Umgekehrt können Sie auch eine Ganzzahl in eine Dezimalzahl verwandeln: 3 as real ergibt 3.0. Der Operator as dient ganz allgemein der Umwandlung einer Werteklasse in eine andere. Sie werden diesem daher noch häufiger begegnen. Wichtig ist, dass dem as immer der Name der Klasse folgen muss, in welche der Wert vor dem as umgewandelt werden soll.
Klammern und Berechnungsreihenfolge Möchten Sie mehrere Berechnungen hintereinander fügen, so müssen Sie beachten, dass in AppleScript die übliche Punkt-vor-Strichrechnung gilt. Das heißt, Multiplikation und Division werden zuerst berechnet und dann erst Addition und Subtraktion. Bei Gleichwertigkeit immer von links nach rechts (außer dem Operator ^, der von rechts nach links ausgewertet wird). 5 + 30 / 5 * 3 Diese Zeile ergibt 23.0. Division und Multiplikation sind gleichwertig, daher wird von links nach rechts berechnet, zuerst wird also 30 durch 5 geteilt, das ergibt 6. Diese 6 wird mit 3 multipliziert. Das Ergibt 18. Und zu dieser 18 wird am Schluss 5 hinzugefügt, macht 23.0. Das Ergebnis ist eine Dezimalzahl, weil in der Berechnung eine Division stattgefunden hat, und bei einer Division werden Ganzahlen (Integer) immer zu Dezimalzahlen.
102
Die Sprache
Kapitel 4
Wenn Sie eine andere Reihenfolge benötigen, so können Sie solche Berechnungen jederzeit klammern. Bei Klammern tritt die Regel in Kraft, dass der Ausdruck in der innersten Klammer immer zuerst berechnet wird, vor allen anderen Operatoren. 5 + 30 / (5 * 3) Hier erhalten Sie 7.0 als Ergebnis, denn zuerst wird die Klammer berechnet. 5 mal 3 ergibt dabei 15. Dann wird 30 durch diese 15 geteilt, ergibt 2. Und ganz zum Schluss wird die 5 dazu addiert, macht 7.0. Wenn Sie sich der Regeln nicht sicher sind oder wenn Sie sich die Regeln auch im Code verbildlichen möchten, so verwenden Sie ruhig so viele Klammern wie nötig. Es schadet nichts, wenn man zuviel klammert, solange man den Überblick bewahrt. Eine Tabelle mit allen Operatoren und ihrer Reihenfolge untereinander finden Sie am Ende des Buches im Anhang. Mit einer zweiten Klammer lässt sich im obigen Beispiel noch verdeutlichen, das die 5 wirklich erst ganz am Schluss zum Zuge kommt. 5 + (30 / (5 * 3)) Mit dieser zweiten Klammer, obwohl unnötig, machen Sie sich die Berechnungsreihenfolge auf den ersten Blick sichtbar. Die Klammern werden von innen nach außen aufgelöst. Solche zusätzlichen Klammern können bei langen Codezeilen sehr hilfreich sein, um den Überblick zu bewahren. Es ist also keinesfalls ein Zeichen von Schwäche, Klammern zu verwenden, obwohl diese nicht unbedingt notwendig sind. Haben Sie sehr große oder sehr kleine Zahlen, können Sie diese auch in exponentieller Schreibweise schreiben und damit rechnen. Statt der Zahl 230000 können Sie auch 2.3E+5 und statt der Zahl 0,000023 2.3E-5 schreiben.
103
SmartBooks
AppleScript
Der Befehl round Wenn Sie mit Dezimalzahlen arbeiten und diese runden wollen, so gibt es dafür in AppleScript den Befehl round mit den verschiedensten Parametern, die alle der zu rundenden Zahl folgen. Verwenden Sie zum Aufrunden auf die nächste Ganzzahl rounding up: round 2.4 rounding up ergibt 3. Zum Abrunden auf die nächste Ganzzahl: round 2.5 rounding down ergibt 2. Um alle Nachkommastellen zu entfernen (was denselben Effekt hat wie ein einfaches rounding down): round 2.5 rounding toward zero Ergebnis: 2 Zum kaufmännischen Auf- oder Abrunden (wenn die letzte Stelle nicht größer als eine 4 ist, wird abgerundet, alles darüber wird aufgerundet): round 2.4 rounding as taught in school ergibt: 2 round 2.5 rounding as taught in school ergibt 3. AppleScript ist sicher die einzige Programmiersprache, die solch einfallsreich bezeichnete Befehlsparameter wie as taught in school kennt. Daneben gibt es noch die Rundungsmöglichkeit to nearest, die eine unverzerrte mathematische Rundung (round to even) vornimmt, die vor allem für Statistiker, Wissenschaftler und Ingenieure interessant ist, da mit der kaufmännischen Rundung immer eine leichte Verfälschung nach oben stattfindet, weil die 5 immer aufgerundet wird. Bei der unverzerrten mathematischen Rundung mit to nearest wird die 5 immer zur nächsten geraden Zahl gerundet. Das heißt, dass die 5 einmal nach oben und einmal nach unten gerundet wird, wodurch die Rundungsfehler statistisch im Mittel bleiben.
104
Die Sprache
Kapitel 4
round 2.5 rounding to nearest ergibt 2, da 2 die nächste gerade Zahl ist. round 3.5 rounding to nearest ergibt jedoch 4, da die 4 die nächste gerade Zahl ist. Aufgepasst Wenn Sie round ohne jegliche Parameter verwenden, wird standardmäßig to nearest verwendet: round 2.5 ergibt 2 round 3.5 ergibt 4 Achten Sie daher darauf, immer explizit den gewünschten Rundungsparameter anzugeben. Bei allen Währungsberechnungen ist die kaufmännische Rundung as taught in school sicher die richtige Wahl. Wie rundet man nun aber in der Praxis einen Wert auf eine bestimmte Anzahl an Nachkommastellen auf oder ab? Für diesen Fall müssen Sie den zu rundenden Wert vorher durch den entsprechenden Faktor teilen und nach der Rundung das Ergebnis damit wieder malnehmen. Hier ein Beispiel für eine Währungsrundung auf zwei Nachkommastellen: (round 2.555 / 0.01 rounding as taught in school) * 0.01 ergibt 2.56. (round 2.554 / 0.01 rounding as taught in school) * 0.01 ergibt 2.55 Umgekehrt, wenn Sie auf eine Stelle vor dem Komma runden wollen, zum Beispiel auf die Hunderterstelle: (round 2540 / 100 rounding as taught in school) * 100 ergibt 2500. (round 2550 / 100 rounding as taught in school) * 100 ergibt 2600
105
SmartBooks
AppleScript
Ein weiteres Beispiel, besonders nützlich für die Schweizer: Für die kaufmännische Rappenrundung (Rundung auf jeweils 5 Rappen) können Sie folgende Formel verwenden: (round 1.024 * 20 rounding as taught in school) / 20 ergibt 1.0 (round 1.025 * 20 rounding as taught in school) / 20 ergibt 1.05 (round 1.074 * 20 rounding as taught in school) / 20 ergibt 1.05 (round 1.075 * 20 rounding as taught in school) / 20 ergibt 1.1
Der Befehl random number Ein weiterer nützlicher in AppleScript eingebauter Befehl, der sich nur mit Zahlen befasst, ist der Befehl random number. Damit können Sie beliebige Zufallszahlen erzeugen. Diese Zufallszahlen sind für die meisten Zwecke völlig ausreichend, nicht jedoch für höhere Ansprüche wie für die Kryptographie. Wenn Sie random number einfach so in den Skripteditor eingeben und ausführen, erhalten Sie eine Kommazahl zwischen 0 und 1. random number ergibt z. B: 0.853332103491. Der Befehl hat jedoch auch noch einige optionale Parameter, mit denen Sie bestimmen können, in welchem Bereich die Zufallszahlen liegen sollen. Dieser Bereich wird mit from und to näher definiert und kann eine Ganzzahl oder eine Kommazahl darstellen. Der angegebene Bereich gilt inklusive der Grenzzahlen. random number from 1 to 6 Hier erhalten Sie immer eine Zahl zwischen 1 und 6 als Zufallszahl, und zwar Ganzzahlen, weil beide Bereichszahlen als Integer angegeben wurden! Geben Sie stattdessen Dezimalzahlen an, erhalten Sie als Ergebnis ebenfalls Dezimalzahlen: random number from 1.0 to 6.0 106
Die Sprache
Kapitel 4
ergibt zum Beispiel: 5.420802808955. Sie können die Zahl für from oder to auch weglassen, dann wird der Standard dafür verwendet, nämlich 0.0 für from oder 1.0 für to. random number from 0.5 ergibt eine Zufallszahl zwischen 0,5 und 1,0. random number to 99 ergibt eine Zufallszahl zwischen 0 und 99 als Ganzzahl. Sie können diese Zufallszahlen auch noch mit der Option with seed und einem Integer versehen. Zuerst einmal sieht es nicht so aus, als wenn sich random number damit anders verhalten würde. So ergibt random number from 1 to 6 with seed 1 vielleicht bei der Ausführung eine 3. Egal, wie oft Sie dann das Skript erneut aufrufen, es wird immer diese 3 als Zahl erscheinen. Das dient vor allem Testzwecken, da sich damit Code mit einem zufälligen Wert reproduzierbar testen lässt. Erst wenn Sie den Wert für seed oder die Bereichsgrenze ändern, wird ein neuer Wert ermittelt. Power User Übrigens, auch wenn sich random number with seed in einer Schleife befinden sollte und damit mehrmals aufgerufen wird, erhalten Sie immer nur dieselbe Zahl. Erst wenn Sie auch den Wert für seed in jedem Durchgang ändern, zum Beispiel über eine Integer-Schleifenvariable, erhalten Sie über die Schleife eine jedes Mal reproduzierbare Sequenz derselben »Zufallszahlen«. Eine weitere Möglichkeit, eine zufällige Auswahl zu erhalten, und zwar von Objekten jeder Art, also auch von Text oder Objekten einer Anwendung, gibt es mit der Referenzform some, welche bei den Listen im Detail erklärt wird. Damit lässt sich zum Beispiel auch eine Zufallszahl aus einem nicht zusammenhängenden Bereich ermitteln. some item of {2, 3, 5, 7, 11} ergibt bei jeder Ausführung eine andere Zahl aus der geschweiften Klammer.
107
SmartBooks
AppleScript
Kommentare Kommentare sind in jeder Programmiersprache äußerst wichtig. Kommentare sind kein Code und werden bei der Ausführung daher einfach ignoriert. Ihr Sinn liegt also einzig und alleine darin, Ihnen die Möglichkeit zu geben, Ihr Skript mit Anmerkungen zu versehen. Benutzen Sie Kommentare, um Ihren eigenen Code zu kommentieren. Konzentrieren Sie sich dabei auf das Was und nicht auf das Wie. Beschreiben Sie also, was der Code an dieser Stelle macht. AppleScript ist zwar eine einfach lesbare Sprache, trotzdem ist es auch hier hilfreich, wenn man die Funktion eines Skripts auch nach Jahren noch anhand der Kommentare schnell wieder begreift. Offensichtliches sollten Sie weglassen. An besonders kniffligen, nicht leicht verständlichen Stellen sollten Sie dabei durchaus auch einzelne Zeilen kommentieren. Verwenden Sie Kommentare auch, um Anmerkungen auf noch zu erledigende Arbeiten im Skript zu machen oder für Hinweise auf mögliche Verbesserungen. Daneben werden Kommentare aber auch am Anfang eines Skripts verwendet, um den Skriptnamen, die Versionsnummer, das Datum, den Autor und ein eventuelles Copyright zu benennen. Eine der wichtigsten Funktionen von Kommentaren ist, dass man mit ihnen ganze Skriptzeilen »auskommentieren« kann. Damit ist gemeint, dass man Codezeilen als Kommentar kennzeichnet, anstatt sie zu löschen, wodurch der Code dieser Zeilen nicht mehr ausgeführt wird. Dies wird besonders gerne beim Testen gemacht, wenn man noch nicht sicher ist, ob sich einzelne Zeilen im Skript wie gewünscht verhalten. So können Sie dann schnell verschiedene Varianten an Code ausprobieren, ohne diesen im Skript löschen und jedes Mal neu eingeben zu müssen. Wenn Sie in einem AppleScript einen Kommentar schreiben wollen, verwenden Sie zwei aufeinander folgende Bindestriche. Alles, was nach den beiden Bindestrichen folgt, wird bis zum Ende der Zeile als Kommentar behandelt: -- Dies ist ein Kommentar auf einer Zeile Solch ein Kommentar kann also immer nur auf einer Zeile sitzen. Möchten Sie den Kommentar auf der nächsten Zeile fortführen, so müssen Sie auch diese Zeile wieder mit zwei Bindestichen beginnen: -- Dieses Skript ist noch experimentell -- Benutzung auf eigene Gefahr!
108
Die Sprache
Kapitel 4
Die zwei Bindestriche funktionieren auch am Ende einer Codezeile, jedoch niemals mitten drin: 2 + 3.5 -- Hier wird die Ganzzahl 2 mit der Dezimalzahl 3,5 addiert Der Code vor den beiden Bindestrichen wird noch ausgeführt, der Rest der Zeile wird ignoriert. Seit Leopard können Sie auch das Zeichen # zur Einleitung eines Kommentars verwenden. Auch dieser Kommentar ist nur bis zum Ende der Zeile gültig. #Dies ist ein Kommentar, der erst ab Mac OS X 10.5 gültig ist. Aufgepasst Beachten Sie dabei aber unbedingt, dass diese Kommentare unter Mac OS X 10.4 oder früher nicht angezeigt werden. Wenn Sie ein Skript mit solchen Kommentaren dort öffnen, dann werden Sie diese Kommentare nicht sehen. Wenn Sie dann das Skript sichern und unter Leopard erneut öffnen, dann sind sogar alle Kommentare dieser Art vollständig gelöscht! Vermeiden Sie daher diese Art von Kommentar, wenn diese auch unter früheren Mac OS X-Versionen lesbar bleiben müssen. Dieser Kommentar wurde mit Leopard eingeführt, um ein AppleScript mittels der sogenannten Shebang-Zeile #!/usr/bin/osascript auch als Shellskript starten zu können. Verwenden Sie diesen Kommentar daher nur für diesen Zweck. Die letzte Möglichkeit, einen Kommentar zu schreiben, ist die, ihn mit der Zeichenfolge (* einzuleiten und *) abzuschließen. Dies ist die einzige Möglichkeit, einen Kommentar über beliebig viele Zeilen laufen zu lassen. Haben Sie also sehr viel zu erzählen, verwenden Sie diese Kommentarart. (* Dies ist ein Kommentar über mehrere Zeilen *) Dabei lassen sich auch weitere Kommentare darin schachteln, was vor allem für das Auskommentieren von Code nützlich ist.
109
SmartBooks
AppleScript
Aufgepasst Kommentare liegen seit Leopard nunmehr vollständig in Unicode vor. Einem Kommentar in Japanisch oder anderen Fremdsprachen steht also nichts mehr im Weg. Beachten Sie jedoch, dass die Zeichen außerhalb der üblichen 256 Zeichen der MacRoman-Codierung unter Mac OS X Tiger und früheren Systemen nicht angezeigt werden können. Stattdessen sehen Sie nur Fragezeichen (???) an den Stellen, an denen UnicodeZeichen im Kommentar stehen. Vermeiden Sie daher die Verwendung von solchen Unicode-Zeichen, wenn Ihre Kommentare auch unter älteren Mac OS-Versionen gelesen werden sollen.
Kommentare über das Kontextmenü des Skripteditors Der Skripteditor bringt Ihnen noch eine nützliche Hilfe für die Arbeit mit Kommentaren mit. Wenn Sie in Ihrem AppleScript einmal eine Stelle im Code auskommentieren wollen, so können Sie auch das Kontextmenü dafür verwenden. Schreiben Sie einmal ein paar Codezeilen in den Skripteditor, wie zum Beispiel die folgenden Zeilen: 5 + 30 / 5 * 3 5 div 2 class of 1.25 Nun stellen Sie sich vor, dass Sie die letzten beiden Zeilen vorerst nicht brauchen. Sie wollen den Code in den beiden Zeilen aber nicht löschen, da Sie ihn später vielleicht wieder gebrauchen können. In solch einem Fall ist es hilfreich, solche Zeilen auszukommentieren. Sie könnten nun von Hand auskommentieren, indem Sie Bindestriche am Anfang der beiden Zeilen anfügen oder sie mit (* und *) einklammern. 5 + 30 / 5 * 3 --5 div 2 --class of 1.25 Damit werden nun die beiden letzten Zeilen nicht mehr ausgeführt. Schneller geht es jedoch, wenn Sie beide Zeilen markieren, mit der rechten Maustaste darauf klicken und dann im Kontextmenü Comment Tags auswählen. Der markierte Bereich wird mit (* und *) auskommentiert.
110
Die Sprache
Kapitel 4
5 + 30 / 5 * 3 (* 5 div 2 class of 1.25 *) Mit demselben Comment Tags können Sie die Kommentarzeichen auch wieder entfernen. Wählen Sie dafür den gesamten Kommentartext inkl. Kommentarzeichen aus und wählen Sie erneut Comment Tags. Nun sind die Kommentarzeichen wieder verschwunden und der Code an dieser Stelle kann wieder ausgeführt werden. Wenn Sie eine leere Zeile markieren (Doppelklick auf die Zeile) und Comment Tags ausführen, erhalten Sie die zwei Kommentarzeichen vor und nach der Zeile, und Sie können direkt mit dem Schreiben des Kommentars beginnen.
Das Fortführungszeichen Jede Anweisung muss in einem Appleskript immer auf einer Zeile stehen, darf also nicht von Zeilenumbrüchen unterbrochen werden. Normalerweise ist das kein Problem. Sie können im Skripteditor beliebig lange Zeilen eingeben. Jedoch wird es dann etwas unhandlich, diese Zeile zu lesen, wenn Sie jedes Mal dafür das Fenster nach rechts rollen müssen. Aus diesem Grund gibt es in AppleScript das Fortführungszeichen ¬, von Apple continuation character genannt (Unicode: 00AC, Dezimal: 172, Mathematisches Not Sign). Geben Sie dieses Zeichen am Ende einer Zeile ein, und die Anweisung auf der nächsten Zeile wird als Fortsetzung der vorherigen betrachtet. Jetzt zu Anfang, werden Sie wenige Fälle dieser Art haben, doch es ist nur eine Frage von wenigen Seiten in diesem Buch, bis Sie mit den ersten längeren Codezeilen hantieren. Dieses Fortführungszeichen wird auch in diesem Buch verwendet, um anzuzeigen, dass die nach dem Fortführungszeichen folgende Zeile zur vorherigen Zeile gehört. Sie können dieses Zeichen im Skripteditor eingeben, indem Sie die [Return]-Taste mit gedrückter [Alt]-Taste betätigen. Wenn Sie noch Platz in der Zeile haben, brauchen Sie dieses Zeichen natürlich nicht einzugeben. Wenn der Platz auf der Zeile jedoch bei Ihnen ebenfalls knapp wird, so geben Sie dieses Zeichen mit ein und schreiben Sie dann auf der nächsten Zeile weiter.
111
SmartBooks
AppleScript
Nach dem ¬-Zeichen dürfen Sie auf der gleichen Zeile keinen weiteren Text mehr eingeben – Sie müssen auf der nächsten Zeile weiter schreiben. Hier ein kleines Beispiel: display dialog "Ein schöner Tag heute!" buttons {"Ja", "Wirklich?"} ¬ default button "Wirklich?" giving up after 3 Sie sehen, dass der zweite Teil der Anweisung, nach dem Fortführungszeichen, eingerückt dargestellt wird. Die beiden Zeilen sind eine einzige Anweisung und müssen daher auf einer einzigen Zeile stehen. Damit das Editieren solch langer Codezeilen nicht zum Albtraum wird, gibt es das Fortführungszeichen. Bevor Sie beim Schreiben von Code im Fenster des Skripteditors nach rechts scrollen, drücken Sie also einfach [Alt]+[Return] und schreiben Sie auf der nächsten Zeile weiter. Das Fortsetzungszeichen darf jedoch nicht innerhalb eines in Anführungszeichen gesetzten Textes stehen, es sei denn, dieses Zeichen soll Teil des Textes werden. Fügen Sie eine Trennung am besten immer nach logischen Gesichtspunkten durch, wie oben zum Beispiel vor der Angabe weiterer Parameter nach dem Ende der Klammer. Aufgepasst Wenn Sie eine Zeile mit Fortführungszeichen auskommentieren wollen, so müssen Sie übrigens auch die nachfolgende Zeile auskommentieren.
Variablen Bisher wurden die Zahlen immer direkt als Literal, also »wörtlich«, in den Code geschrieben. Für einen schlicht gehaltenen Einzeiler ist das natürlich ausreichend. Stellen Sie sich jedoch einmal vor, Sie wollen mehrere Berechnungen nacheinander vornehmen, zum Beispiel als ersten Schritt die Mehrwertsteuer berechnen und als zweiten Schritt diese zum Betrag hinzurechnen. Das kann man lösen, indem man die Berechnung auf eine Zeile schreibt. Für einen Betrag von 1500 sieht das zum Beispiel so aus: (1500 * 0,19) + 1500
112
Die Sprache
Kapitel 4
Nun haben Sie aber vielleicht mehrere solcher Berechnungen und wollen am Ende nur die Summe über alles erhalten. Sie müssen das Ergebnis der ersten Berechnung also irgendwo ablegen, um es später zu dem Ergebnis der nächsten Berechnung hinzufügen zu können. Hier kommen die Variablen ins Spiel. Variablen sind so etwas wie Behälter mit einem Etikett. Man steckt etwas hinein, zum Beispiel eine Zahl, und holt sie später bei Bedarf wieder heraus. Stellen Sie sich eine Variable dabei ruhig als einen Schuhkarton mit einem Etikett vor, nur dass in AppleScript natürlich keine Schuhe darin abgelegt werden, sondern Zahlen oder auch jede beliebige andere AppleScript-Klasse, wie Sie später noch sehen werden. Power User Variablen sind in AppleScript schwach typisiert, das heißt, Sie können in einer Codezeile eine Zahl in die Variable hineinstecken, in der nächsten einen Text und danach ein Skriptobjekt oder die Referenz auf eine Datei. Eine Variable ist nicht auf irgendeinen bestimmten Typ beschränkt, kann die Inhaltsart im Laufe ihres Lebens also nach Belieben wechseln. Eine Variable wird in AppleScript erzeugt, indem man sich einen Namen für sie ausdenkt und dann etwas in sie hineinlegt. Um beim Schuhkarton-Gleichnis zu bleiben: Sobald Sie auf einen Schuhkarton ein Namenschildchen kleben und etwas hineinlegen, ist die Variable fertig zum Gebrauch. Damit Sie später noch wissen, was Sie hineingesteckt haben, sollte der Name natürlich möglichst den Inhalt beschreiben. Wollen Sie in einer Variablen den Nachnamen einer Person abspeichern, so nennen Sie die Variable einfach »nachname«, wollen Sie die Mehrwertsteuer darin abspeichern, so nennen Sie sie zum Beispiel »mwst«. Soll die Variable die Summe der Brutto-Beträge enthalten, so nennen Sie sie »brutto_summe«. Grundlagen Es hat sich unter Skriptern dabei eingebürgert, Variablen immer mit einem Kleinbuchstaben zu beginnen. In eine Variable wird etwas mit den Befehlen set oder copy hineingepackt. Zum Beispiel so: set meineVariable to 2.25 copy 2.25 to meineVariable Auf Deutsch liest sich das ungefähr so: »Setze meineVariable auf 2,25.« »Kopiere 2,25 in meineVariable«.
113
SmartBooks
AppleScript
Hier wird also eine Variable mit dem Namen meineVariable angelegt, einfach indem man sie beim Namen nennt. Man nennt das auch »Initialisierung«. Im gleichen Schritt wird dann ein Wert, hier 2.25, mit dem Befehl set oder copy in die Variable hineingelegt. Verwenden Sie zu Anfang bitte immer den Befehl set. Auf den Unterschied zwischen beiden Befehlen werde ich später noch näher eingehen. Fortan können Sie also überall, wo Sie sonst 2.25 schreiben würden, stattdessen auch meineVariable schreiben. Doch zuerst einmal gibt es ein paar Regeln bei der Benennung von Variablen zu beachten.
Bezeichner Folgende Regeln gelten in AppleScript für alle Bezeichner, also nicht nur für die Namen von Variablen, sondern auch für die Namen von Klassen, Eigenschaften (properties) und Handler. Ein Bezeichner darf in AppleScript nur Buchstaben, Zahlen und Unterstriche enthalten. Der Name muss dabei immer mit einem Buchstaben oder einem Unterstrich beginnen und kann beliebige Groß- und Kleinschreibung enthalten. Nicht erlaubt sind sämtliche Sonderzeichen und Interpunktionszeichen bis auf den Unterstrich. Grundlagen Um erst gar keine Zweifel aufkommen zu lassen, hier die Liste der erlaubten Zeichen: a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U VWXYZ_1234567890 Folgende Bezeichner für eine Variable wären also ungültig: 2teZahl anzahl_moleküle zweite.Zahl 2teZahl beginnt mit einer Zahl, was nicht erlaubt ist. anzahl_moleküle enthält das Sonderzeichen ü, ebenfalls nicht erlaubt. zweite.Zahl enthält einen Punkt. Interpunktionszeichen wie Punkt, Komma oder Bindestrich sind nicht erlaubt. AppleScript unterscheidet nicht zwischen Groß- und Kleinschreibung.
114
Die Sprache
Kapitel 4
Die folgenden beiden Namen wären also identisch. PlatzierungDerGewinnner platzierungdergewinnner Trotzdem merkt sich AppleScript bei der ersten Verwendung einer Variablen deren Großund Kleinschreibung und behält diese danach konstant bei. Tipp Diese Eigenart lässt sich prima dafür verwenden, um zu überprüfen, ob man die Variable korrekt geschrieben hat. Schreiben Sie eine Variable bei der ersten Verwendung gemischt groß und klein und übersetzen Sie das Skript. Diese Schreibweise hat sich das Skript nun gemerkt. Danach schreiben Sie dieselbe Variable bei der weiteren Verwendung immer klein. Bei jedem erneuten Übersetzen wird die klein geschriebene Variable wieder gemischt groß und klein geschrieben. Wenn nicht, dann erkennen Sie daran sofort, dass Sie einen Tippfehler gemacht haben und aus Versehen eine neue Variable initialisiert wurde, ein häufig vorkommender Grund für Fehler im Skript. Trotz dieser Regeln gibt es aber auch ein Hintertürchen. Möchten Sie unbedingt einen ungültigen Variablennamen verwenden, dann setzen Sie diesen einfach zwischen zwei senkrechte Striche. Den Strich erreichen Sie mit der Tastenkombination [alt]+[7]. |Ein ungültiger ☺ Variablen-Name| Obiger Name ist eigentlich ungültig. Er enthält Leerzeichen, ein Sonderzeichen (ü), ein Unicode-Zeichen (Smiley) und einen Bindestrich. Indem Sie den Namen aber wie gezeigt zwischen zwei senkrechte Striche setzen, wird er von AppleScript akzeptiert. Ich nenne diese Art, einen ungültigen Namen zu klammern, einfach mal »Bezeichnerklammer«. Trotzdem sollten Sie unbedingt davon Abstand nehmen, diese Art der Namensgebung zu verwenden. Ein Skript wird dadurch nicht gerade leichter lesbar. Allerdings kann es hilfreich sein, diese Klammer zu Testzwecken einzusetzen, nämlich immer dann, wenn man einen Namenskonflikt vermutet, wie im Folgenden beschrieben.
Reservierte Wörter Es gibt einige Wörter, die AppleScript für seine volle Funktionsfähigkeit benötigt und die Sie daher nicht als Bezeichner für Ihre eigenen Variablen verwenden dürfen. Eine vollständige Liste dieser reservierten Wörter finden Sie im Anhang.
115
SmartBooks
AppleScript
Erschwerend kommt hinzu, dass auch jede von Ihrem Skript gesteuerte Anwendung, als auch jede geladene Skripterweiterung, wiederum eigene Schlüsselwörter verwendet, die Sie nicht als Namen verwenden dürfen. Es gibt in AppleScript 2.0 leider keine klar getrennten Namensräume wie in anderen Programmiersprachen. Um Namenskonflikte mit diesen reservierten Wörtern zu vermeiden, empfiehlt es sich, folgende Ratschläge zu beherzigen: << Vermeiden Sie kurze Namen, die auch im Englischen eine Bedeutung haben. So scheint z. B. name als Bezeichner für den Namen eines Objekts eine gute Idee zu sein, und tatsächlich gehört diese Bezeichnung auch nicht zu den Schlüsselwörtern von AppleScript. Aber dieser Begriff ist auch eine häufig verwendete Eigenschaft von vielen Klassen, und das kann schnell zu Missverständnissen führen. << Setzen Sie Ihre Bezeichner immer aus zwei Wörtern zusammen, zum Beispiel hauptKategorie oder maxRadius. Schreiben Sie den Anfangsbuchstaben des zweiten Worts dabei groß, und der Name lässt sich leichter lesen. Oder trennen Sie die einzelnen Wörter mit einem Unterstrich: haupt_kategorie, max_radius. << Beginnen Sie alle Ihre Variablen mit einem Unterstrich. Das sieht zwar nicht so schön aus, hilft aber ebenfalls gegen Namenskonflikte. << Packen Sie eine Variable mit einem Namen, der eventuell Konfliktpotential haben könnte, in eine Bezeichnerklammer (zwei senkrechte Striche), wie auf den vorigen Seiten beschrieben. Tipp Achten Sie auch auf die Syntaxfärbung Ihrer Bezeichner. Standardmäßig werden Variablen im Skripteditor grün geschrieben (solange dies nicht unter Skripteditor | Einstellungen | Formatierung abgeändert wurde). Wird so ein Name nach dem Übersetzen des Skripts aber auf einmal blau geschrieben, dann wurde der Bezeichner als Schlüsselwort von AppleScript, einer Skripterweiterung oder einem der angesprochenen Programme erkannt. Ändern Sie dann den Namen, bevor Sie in Probleme laufen.
Zuweisungsoperationen mit dem Befehl set Eine Variable wird in AppleScript einfach dadurch definiert und gleichzeitig initialisiert, dass man ihr einen Wert zuweist. (Wie später beschrieben, kann man Variablen auch mit den Schlüsselwörtern local oder global initialisieren.)
116
Die Sprache
Kapitel 4
Eine Variable hat in AppleScript keinen festen Typ wie in anderen Programmiersprachen, Sie müssen bei der Deklaration daher nicht angeben, ob in der Variable Texte oder Zahlen gespeichert werden sollen. Nehmen Sie einfach einen gültigen Bezeichner und weisen Sie diesem einen Wert zu. Damit ist die Variable einsatzfertig. set a to 1 Hier wird einer Variablen mit dem Namen a der Wert 1 zugewiesen. Danach enthält der Schuhkarton mit dem Etikett a also eine 1, eine Integerzahl. Grundlagen Wenn Sie von anderen Skriptsprachen kommen, werden Sie sich eventuell über diese Art der Zuweisung mit set a to 1 sehr wundern. In der Tat können Sie in AppleScript nicht a = 1 schreiben, da das Zeichen = in AppleScript nur ein Vergleichsoperator ist. Mit = wird in AppleScript verglichen, ob der Wert links des Gleichheitszeichens gleich dem Wert rechts davon ist, und nichts anderes. Der =-Operator ist in AppleScript also nicht mit anderen Funktionen überladen. Verwenden Sie zu Anfang immer den Befehl set, um einer Variablen einen Wert zuzuweisen. Es gibt auch noch den Befehl copy, der sich dafür verwenden lässt und der bei Zahlen keinen Unterschied macht, wohl aber bei Listen und anderen Objekten. Grundlagen Mit set lernen Sie nach round und random number einen weiteren (und wohl den wichtigsten) AppleScript-Befehl kennen. Dieser Befehl wird ständig benötigt. Mit set variablenName to wert werden in AppleScript Variablenzuweisungen vorgenommen. Statt den Wert direkt der Variablen zuzuweisen, kann die Zuweisung auch wiederum aus Variablen bestehen, die nach Wunsch auch noch berechnet werden können: set a to 3 set b to 5 set c to a + b -- Ergebnis: 8 Hier werden in der dritten Zeile die Werte von a und b addiert. Das Ergebnis wird dann der Variablen mit dem Namen c zugewiesen. Als Ergebnis erhalten Sie schließlich die 8. Wichtig ist hier, dass der Ausdruck nach dem to immer als Erstes berechnet und dann das Ergebnis in der Variable vor dem to abgespeichert wird. Die Berechnungsgeschichte a + b ist danach also nicht mehr in der Variablen c erkennbar.
117
SmartBooks
AppleScript
Das Rechnen mit Variablen funktioniert genauso wie mit Zahlliteralen, nur dass Sie hier natürlich als Vorbereitung erst einmal die benötigten Variablen anlegen müssen. Beachten Sie auch immer die Reihenfolge der Anweisungen. Ein AppleScript wird in der Regel immer von oben nach unten, also Zeile für Zeile, abgearbeitet. Sie können a also erst dann mit b addieren, wenn beide Variablen vorher einen Wert erhalten haben. set a to 3 a+b set b to 5 In diesem Beispiel wurde die Reihenfolge geändert. Als Ergebnis erhalten Sie bei der Ausführung des Codes die Fehlermeldung »Die Variable „b“ ist nicht definiert«. Das ist auch logisch so, denn in der zweiten Zeile existiert die Variable b ja noch nicht, trotzdem wird dort aber versucht, diese zu addieren. Erst in der dritten Zeile wird sie ins Leben gerufen, indem ihr der Wert 5 zugewiesen wird. Ändern Sie die Reihenfolge in solch einem Fall, und das Skript funktioniert. Wenn erst einmal ein Ergebnis in einer Variablen abgespeichert wurde, können Sie damit sofort weiterrechnen: set set set set
a to 3 b to 5 c to a + b d to c * 2
Hier wird c mit 2 malgenommen und das Ergebnis davon wiederum in einer neuen Variable mit dem Namen d abgespeichert. Der Inhalt von d ist dann 16. Sie müssen aber nicht jedes Mal eine neue Variable erzeugen. Sie können bisher verwendete Variablen auch weiter verwenden, abändern und nach Belieben damit umspringen. set set set set set
a to 3 b to 5 c to a + b a to 15.2 b to 8
Hier wird der Variablen a in der ersten Zeile der Wert 3 zugewiesen und nach der Berechnung in der dritten Zeile der Wert 15.2, also eine Dezimalzahl. Ebenso wird der Variablen b zum Schluss eine neue Zahl zugewiesen.
118
Die Sprache
Kapitel 4
Egal, was eine Variable vorher für einen Inhalt hatte, sie nimmt grundsätzlich jeden neuen Inhalt an. Eine feste Typisierung wie in anderen Skriptsprachen gibt es hier nicht. Wenn Sie einer Variablen wie oben einen neuen Inhalt zuweisen, wird der alte Inhalt gelöscht! Alles, was vorher im Schuhkarton war, wird entfernt, um Platz zu schaffen. Der vorige Inhalt landet damit sozusagen im elektronischen Nirwana. Wenn Sie den Wert darin noch brauchen, sollten Sie eine Variable also niemals so überschreiben. Möchten Sie den alten Wert nur verändern, zum Beispiel um etwas hinzuzuaddieren, dann müssen Sie das so schreiben: set a to 3 set b to 5 set a to a + b Hier wird die Variable a dafür verwendet, b hinzuzuaddieren. Nach dem Ausführen des Skripts ist der Wert in der Variablen a dann 8 und nicht mehr 3. Die Variable a erscheint hier also auf beiden Seiten des to. Die Berechnung a + b wird wie bekannt zuerst berechnet. Zu diesem Zeitpunkt hat die Variable a noch den Inhalt 3. 3 plus der 5 aus der Variablen b ergeben also 8. Erst jetzt wird die 8 der Variablen a zugewiesen, womit der alte Wert (die 3) darin überschrieben wird. Diese Selbstzuweisung wird sehr häufig verwendet, immer dann, wenn der Originalwert in der Variablen mit weiteren Werten berechnet werden soll. set set set set set set
a to 3 summe to a a to 5 summe to summe + a a to 6 summe to summe + a --Ergebnis: 14
Hier wird die Variable a stets mit neuen Werten gefüttert, und die Variable summe addiert alle Werte, die a eingenommen hatte. Am Schluss ergibt sich damit die Gesamtsumme über alle Werte, die a jemals besessen hat. Schreiben Sie die obigen Zeilen immer paarweise in den Skripteditor hinein. Führen Sie das Skript nach Eingabe der ersten zwei Zeilen aus. Das Ergebnis ist 3. Schreiben Sie die nächsten zwei Zeilen hinzu und klicken Sie auf Ausführen. Das Ergebnis ist 8.
119
SmartBooks
AppleScript
Schreiben Sie die nächsten zwei Zeilen hinzu. Das Ergebnis ist 14. Sie sehen, wie die Variable summe jedes Mal um den neuen Wert von a wächst. In der Praxis wird so etwas natürlich in einer sogenannten Schleife gemacht, und natürlich werden die Werte der Variablen nicht manuell im Skript eingegeben, sondern die Werte kommen meist aus anderen Anwendungen, werden aus Dokumenten ausgelesen oder per Dialog abgefragt.
Der Befehl get Es gibt ein Verb (und meistens sind Verben in AppleScript Befehle), welches Sie schon die ganze Zeit verwendet haben, ohne es zu bemerken, da es fast immer implizit in Anweisungen vorhanden ist. Es handelt sich um das Verb get. Jede Zeile in AppleScript (und damit jede gültige Anweisung) enthält einen Befehl! Wie kommt es dann, dass eine Variable, die Sie alleine auf eine Zeile schreiben, Ihren Inhalt als Ergebnis zurückliefert, obwohl dazu eindeutig keine Order vorlag? set x to 3 x -- Ergebnis: 3 Obwohl die Zeile mit dem x hier keinen Befehl enthält, wird der Wert von x als Ergebnis zurückgeliefert. Dabei wurde gar nicht danach gefragt. Die Ursache liegt darin, das AppleScript das Verb get annimmt, sollte ein Befehl fehlen. AppleScript versteht also Folgendes: set x to 3 get x -- Ergebnis: 3 Genau dasselbe passiert bei den Rechenoperationen. Sie schreiben: 1 + 1 -- Ergebnis: 2 AppleScript versteht: get 1 + 1 -- Ergebnis: 2 Mit get machen Sie also nichts anderes, als das Ergebnis eines Ausdrucks abzufragen. Das Ergebnis wird dann im Ergebnisbereich des Skripteditors angezeigt. Das, was get abfragen soll, muss dabei direkt hinter dem Schlüsselwort get stehen. Da dieses Verb so häufig gebraucht wird, kann man es meistens auch weglassen. Es gibt jedoch Fälle, wo Sie AppleScript
120
Die Sprache
Kapitel 4
mit einem get auf die Sprünge helfen müssen, vor allem dann, wenn mehrere Ausdrücke ineinander geschachtelt werden. Ein einfaches Beispiel lässt sich mit display dialog im Finder konstruieren. Diesen Befehl haben Sie nun schon mehrfach kennengelernt. Es ist ein Befehl zur Anzeige einfacher Dialoge, welcher im Kapitel zu den Standarderweiterungen erklärt wird. Öffnen Sie vor der Ausführung der folgenden Zeile ein Fenster im Finder. tell application "Finder" to display dialog (name of window 1) Diese Zeile soll einen Dialog mit dem Namen des vordersten Fensters anzeigen. Beim Ausführen erhalten Sie jedoch diese Fehlermeldung: -- Fehlermeldung: name of window 1 kann nicht in Typ string umgewandelt werden Helfen Sie AppleScript in solch einem Fall mit einem get auf die Sprünge. Damit wird sichergestellt, dass der Ausdruck in der Klammer zuerst ermittelt und dann erst als Parameter für den Dialog verwendet wird: tell application "Finder" to display dialog (get name of window 1) Sobald Ausdrücke komplexer werden, wie in diesem Fall, wo zwei Befehle in einer Zeile durchgeführt werden müssen – zuerst im Finder den Namen eines Fensters ermitteln und dann einen Dialog mit diesem Namen anzeigen –, ist die explizite Verwendung von get unverzichtbar.
Die Variable result Wenn Sie das Ergebnis einer Anweisung keiner Variablen zuweisen, wie Sie es zum Beispiel am Anfang mit den Zahlen gemacht haben, wird das Ergebnis einer Operation übrigens trotzdem, ohne dass Sie es merken, immer einer Variablen (genau genommen einer AppleScript-Property) mit dem Namen result zugewiesen. Sie dient dazu, das Ergebnis der letzten Operation festzuhalten. Jede neue Anweisung überschreibt jedoch das vorige Ergebnis darin. Der Inhalt von result ist also sehr flüchtig. Das, was Sie im Skripteditor unten im Ergebnisbereich sehen, ist dann auch nichts anderes als der Inhalt dieser Variablen result – und zwar immer der Inhalt der letzten Anweisung, wenn denn diese Anweisung ein Ergebnis zurücklieferte. Wenn Sie also im Skripteditor 6*5
121
SmartBooks
AppleScript
tippen und dieses Skript dann ausführen, erscheint im Ergebnisbereich eine 30. Die Variable result hat jetzt also den Inhalt 30. Mit result können Sie dabei durchaus auch weiterrechnen und es wie eine normale Variable verwenden und dieser neue Werte zuweisen: 6*5 set result to result + 3 ergibt dann 33. Das Ergebnis von 6 * 5 wird unsichtbar in der Variablen result abgespeichert und in der zweiten Zeile wird 3 zu result addiert. Vermeiden Sie solche Konstruktionen aber unbedingt! Sie haben keine Kontrolle darüber, was in dieser Variablen alles landet. AppleScript wird den Inhalt jederzeit rücksichtslos überschreiben, wenn eine Aktion ein Ergebnis zurückliefert, ob Sie es wollen oder nicht. Also, gehen Sie immer den sicheren Weg und weisen Sie das Ergebnis einer Anweisung immer einer selbst definierten Variablen zu: set a to 6 * 5 set a to a + 3 Auch das Ergebnis einer solchen Zuweisung landet dann übrigens in der Variablen result, wie man im Bereich Ergebnis des Skripteditors sehen kann. Sie können aber jetzt mit der Variablen a weiterarbeiten, welche garantiert nicht von AppleScript ungefragt überschrieben wird.
Der Befehl log Da der Ergebnisbereich im Skripteditor immer nur das letzte Ergebnis von result anzeigt, können Sie dort natürlich nicht die Zwischenschritte bei komplexen Skripts ablesen. Hier empfiehlt es sich, Zwischenergebnisse bewusst zu protokollieren. Dafür können Sie im Skripteditor den Bereich Event-Protokoll in Verbindung mit dem Befehl log verwenden. Hier noch einmal das Beispiel von zuvor, diesmal mit log-Anweisung. Wenn Sie dieses Skript bei geöffnetem Event-Protokoll ausführen, werden dort alle Zwischenergebnisse sauber ausgeführt. set a to 3 set summe to a log summe
122
Die Sprache
Kapitel 4
set a to 5 set summe to summe + a log summe set a to 6 set summe to summe + a log summe Im Event-Protokoll steht danach: (*3*) (*8*) (*14*) Die Ergebnisse der Variable summe werden dabei in Kommentarklammern gepackt. Jetzt können Sie also immer bequem die Ergebnisse der einzelnen Zwischenschritte erkennen. Beachten Sie dabei jedoch, dass alle Werte immer in Text konvertiert werden. Bei einfachen Zahlen wie oben macht das nichts aus, später bei den Listen schon eher. Da das Event-Protokoll durchaus auch sehr geschwätzig sein kann, ist es oft hilfreich, einer log-Anweisung noch einen Hinweis in Form eines Textes in Anführungszeichen hinzuzufügen. Zum Beispiel so: set a to 3 set summe to a log "Der Endbetrag ist " & summe führt zu dem Eintrag (*Der Endbetrag ist 3*)im Event-Protokoll. Bezüglich & und Text geht es gleich noch ins Detail. Merken Sie sich aber schon mal, wie Sie auf diese Weise die Ergebnisse einzelner Schritte in Ihrem Skript beschreibend nachvollziehen können. Später, wenn das Skript dann zur Zufriedenheit läuft, sollten Sie natürlich die log-Anweisungen wieder herausnehmen oder besser noch auskommentieren.
123
SmartBooks
AppleScript
Textgrundlagen Bisher ging es nur um Zahlen, aber natürlich ist die Arbeit mit AppleScript nicht darauf beschränkt. Eine der wichtigsten Klassen neben integer und real ist in AppleScript die Klasse text. Um Text direkt im Code als Literal darzustellen, müssen Sie diesen in Anführungszeichen setzen, und zwar in einfache hochgestellte Anführungszeichen. Verwenden Sie in keinem Fall geschwungene typografische Anführungszeichen. Der Skripteditor mag diese als Abgrenzung für Text gar nicht und würde darüber meckern. "grün" Das ist ein einfacher Text. Da Text aus einer Aneinanderreihung von Zeichen besteht, wird er auch als Zeichenkette oder auf Englisch als »String« (»Faden, Kette«) bezeichnet. String ist dabei unter Programmierern üblicher. In AppleScript ist string nur ein Synonym für die Klasse text. Wann immer Sie in AppleScript etwas in Anführungszeichen begegnen, handelt es sich also um Text.
Der Verknüpfungsoperator & Für Text gibt es einen speziellen Operator, den &-Operator, mit dem sich Texte miteinander verbinden lassen. Sie können dafür nicht den +-Operator verwenden wie in anderen Sprachen, die diesen Operator »überladen«, also für Zahlen und Text verwenden. "hell" & "grün" Wenn Sie diese Zeile in den Skripteditor schreiben und ausführen, erhalten Sie als Ergebnis: "hellgrün" Oder mittels Variablen: set erstesWort to "hell" set zweitesWort to "grün" set drittesWort to erstesWort & zweitesWort Das lässt sich natürlich beliebig erweitern: "hell" & "grün" & "er" & " Frosch" ergibt "hellgrüner Frosch"
124
Die Sprache
Kapitel 4
Beachten Sie dabei die Leerstelle vor Frosch. Ohne diese würden beide Worte zusammen geschrieben.
Steuerzeichenkonstanten Statt einer Leerstelle können Sie in einem Text auch die Konstante space verwenden. Beachten Sie, dass space nicht in Anführungszeichen gesetzt wird. Wenn Sie das tun, wäre der Text "space" gemeint und nicht das Leerzeichen. "rotes" & space & "Leinen" ergibt "rotes Leinen" Weitere Steuerzeichenkonstanten sind tab für einen Tabulator und return für einen Zeilenumbruch. "lila" & tab & "Leinen" ergibt "lila ⇒ Leinen" Je nach Wortlänge ist ein Tabulator dabei nicht immer am Abstand erkennbar. Hilfreich wäre es hier, wenn der Skripteditor Steuerzeichen einblenden könnte, aber das geht leider nur beim Script Debugger. Einen Zeilenumbruch können Sie mit return im Text einfügen: "Rot" & return & "Grün" & return & "Blau" Das Ergebnis: "Rot Grün Blau" Bei return handelt es sich übrigens um das Unicode-Zeichen 13 (Hexadezimal: 0xD), also einen »Carriage Return« wie er im klassischen Mac OS üblich war und teilweise noch heute ist. Statt space, return und tab können Sie aber auch die entsprechenden Tasten auf der Tastatur direkt betätigen, Sie müssen also nicht diese Konstanten verwenden. set meinText to "dies ⇒ ist ⇒ ein text ⇒ mit ⇒ return ⇒ und ⇒ tab"
125
SmartBooks
AppleScript
Obige Zeile ist ein völlig legaler Text in AppleScript, der hier der Variablen meinText zugewiesen wird. Es sieht nur ungewohnt aus, wenn sich der Text im Code über mehrere Zeilen verteilt und durch die Tabulatoren so viel Abstand erhält. Auch ein direkt im Text vorgenommener Zeilenumbruch besteht aus dem Unicode-Zeichen 13. Wenn Sie einen Unix-Zeilenumbruch benötigen, dann verwenden Sie bitte die Konstante linefeed. Da beide, return und linefeed, unter Mac OS als Zeilenumbruch akzeptiert werden, gibt es keinen sichtbaren Unterschied. Es kann jedoch sein, dass Sie später einmal mit Dateien zu tun haben, die unbedingt einen Unix-Zeilenumbruch benötigen. Spätestens dann ist es wichtig, linefeed statt return zu verwenden. "Rot" & linefeed & "Grün" & linefeed & "Blau" ergibt: "Rot Grün Blau" Das Ergebnis ist im Skripteditor also nicht von einem return zu unterscheiden. Wenn Sie einmal ein Anführungszeichen selbst benötigen, welches Sie ja nicht verwenden können, da es als Textbegrenzer fungiert, dann verwenden Sie dafür die Konstante quote: "Man nannte ihn den " & quote & "Terrier" & quote & "." Das Ergebnis ist: "Man nannte ihn den \"Terrier\"." Diese Schrägstriche sind sogenannte »Escape-Zeichen«, die gleich noch erklärt werden. Um zu sehen, ob das mit quote hier wirklich geklappt hat, ist ein display dialog hilfreicher: "Man nannte ihn den " & quote & "Terrier" & quote & "." display dialog result Als Ergebnis erhalten Sie einen Dialog mit dem Text »Man nannte ihn den "Terrier".«
126
Die Sprache
Kapitel 4
Abb. 4-2 Ob Escape-Zeichen funktioniert haben, überprüft man am einfachsten in einem Display-Dialog. Apple bezeichnet all diese Steuerzeichen als Konstanten. Aber eigentlich handelt es sich hierbei, wie bei result, nur um vorgefertigte Eigenschaften (properties) von AppleScript. Die obigen Konstanten sind also nicht unveränderlich, wie man vermuten könnte. Das bedeutet, dass Sie all diesen »Konstanten« – space, return, linefeed, tab und quote – durchaus einen anderen Wert zuweisen können. So wird mit set return to character id 9755 dem Return eine nach rechts weisende Hand untergeschoben. (Zu character id gleich im Kapitel »Unicode« mehr.) "" Aufgepasst Wenn Sie einmal damit anfangen, den Inhalt von space, return, linefeed, tab und quote zu verändern, können Sie sich nicht mehr darauf verlassen, dass diese tatsächlich immer den Inhalt haben, den Sie brauchen. Lassen Sie es daher am besten gleich. Legen Sie sich immer eigene Variablen an, statt die vorgegebenen von AppleScript zu verändern. Falls Sie jedoch einmal damit herumgespielt haben, so können Sie die Konstanten wieder durch Beenden und Neustarten des Skripteditors auf ihren ursprünglichen Wert zurücksetzen.
Escape-Sequenzen Die Verwendung der Konstanten space, return, linefeed, tab und quote ist nicht die einzige Art und Weise, diese speziellen Zeichen in einem Text darzustellen. Sie können auch sogenannte Escape-Sequenzen verwenden. Sobald Sie ein Anführungszeichen in einen Text einbauen, hält AppleScript den Text an dieser Stelle ja bereits für beendet: "Man nannte ihn den "Terrier"" Obige Zeile würde daher zu einer Fehlermeldung beim Übersetzen führen, da AppleScript den Text "Man nannte ihn den " als Textliteral betrachtet. Der darauf folgende
127
SmartBooks
AppleScript
Text besitzt dann am Anfang keine Anführungszeichen mehr und wird folglich von AppleScript nicht verstanden. Ganz zum Schluss stehen dann noch mal zwei Anführungszeichen, die einen leeren Text (also gar nichts) enthalten, da sie direkt aufeinander folgen. Statt der Konstante quote können Sie auch die Escape-Sequenz dafür verwenden. Fügen Sie dafür vor den »inneren« Anführungszeichen im Text einen umgekehrten Schrägstrich mit der Tastenkombination [Alt]-[Shift]-[7] ein. "Man nannte ihn den \"Terrier\"" Obige Zeile wird beim Übersetzen korrekt als Text erkannt. Der rückwärtsgewandte Schrägstrich ist das Escape-Zeichen in AppleScript. Der Ergebnisbereich im Skripteditor wird allerdings weiterhin die Schrägstriche anzeigen. Erst wenn Sie den Text ausgeben, zum Beispiel mit display dialog, wird der Text ohne die Escape-Sequenz angezeigt. Probieren Sie das einfach mal mit der folgenden Zeile aus. set einText to "Man nannte ihn den \"Terrier\"" display dialog einText Doch was ist, wenn man einen solchen Schrägstrich im Text verwenden will? In diesem Fall müssen Sie dem Schrägstrich wiederum einen Schrägstrich voranstellen. set einText to "Das Escape-Zeichen in AppleScript ist \\" display dialog einText Auch die Steuerzeichen für einen Zeilenumbruch und einen Tabulator lassen sich mit Escape-Sequenz schreiben. Für ein Return schreibt man \r und für einen Tabulator \t. Als Zeilenumbruch wird dabei das Unicode-Zeichen 13 (CR, carriage return) verwendet, wie es auf dem Mac üblich war. "Rot \r Blau \r Grün" wird zu: "Rot Blau Grün" Wenn Sie einen Unix-Zeilenumbruch benötigen, verwenden Sie \n, das Zeichen »line feed«, auch »newline«-character genannt (Unicode-Zeichen 10). Benötigen Sie einen Zeilenumbruch für einen Windows-Rechner, so verwenden Sie beide Escape-Sequenzen in der Reihenfolge \r\n.
128
Die Sprache
Kapitel 4
Hier noch ein Beispiel mit Tabulator: "1. Platz \t 2. Platz \t 3. Platz" wird zu: "1. Platz 2. Platz
3. Platz"
Das Besondere bei dieser Art von Tabulatoren und Zeilenumbrüchen ist Folgendes: Im Skript selber ändert sich die Anzeige des Textes ebenfalls. Die Zeilenumbrüche \r werden also nach dem Kompilieren entfernt und gegen echte Zeilenumbrüche ausgetauscht und \t gegen echte Tabulatoren. Das kann dann manchmal etwas verwirren oder merkwürdig aussehen, wenn es sich um recht viel Text handelt. Wenn Ihnen das nicht gefällt, können Sie es in den Einstellungen des Skripteditors auch abschalten, was ich empfehlen würde. Sie finden diesen Schalter in der Tafel Bearbeitung, und er trägt den langen Namen EscapeSequenz für Tabs und Zeilenumbrüche in Strings. Nach dem Einschalten werden die Escape-Zeichen nach dem Kompilieren nicht mehr ausgetauscht, und der Text bleibt schön auf einer Zeile.
Abb. 4.3 Der Schalter zum Umstellen der Darstellung von Escape-Sequenzen im Skripteditor in der Tafel »Bearbeitung« der Skripteditor-Einstellungen; links und rechts die Auswirkung vor und nach dem Einschalten dieser Option Mit diesen Escape-Zeichen kann man also in AppleScript einen Text zusammenbauen, ohne ihn jedes Mal aus einzelnen Textelementen, den Steuerzeichenkonstanten und dem &-Operator, zusammenzupfriemeln.
129
SmartBooks
AppleScript
Listengrundlagen Wenn Sie mehrere Texte oder Zahlen in AppleScript bearbeiten wollen, ist es hilfreich, diese nicht alle einzeln als Text oder Zahl zu schreiben oder einzeln in Variablen zu verpacken, sondern in eine Liste. Eine Liste ist eine Klasse mit der angenehmen Eigenschaft, wiederum andere Klassen als Elemente enthalten zu können, und zwar unbegrenzt viele. Grundlagen In einer Liste lassen sich auch Zahlen, Texte und jede andere Klasse beliebig miteinander mischen. Eine Liste hat damit in AppleScript keinen fest definierten Typ. Eine Liste wird in AppleScript als Literal in geschweifte Klammern geschrieben, die Sie mit der Tastenkombination [alt]+[8] und [alt]+[9] erreichen: {3, 1.25, "Grün"} Innerhalb dieser geschweiften Klammer werden die einzelnen Werte mit einem Komma voneinander getrennt. Texte werden natürlich wieder von Anführungszeichen eingeschlossen und Zahlen werden ohne diese geschrieben. Obige Liste enthält zum Beispiel drei Elemente, die Zahl 3, die Zahl 1,25 (mit einem Punkt als Dezimalzeichen) und den Text »Grün« in Anführungszeichen. Mit Listen als Ganzes kann man nicht rechnen, sondern nur mit den einzelnen Elementen darin. Wie man auf einzelne Elemente einer Liste zugreift, wird gleich erklärt. Listen lassen sich wie Texte mit dem &-Operator verbinden. Aus {"Rot", "Blau"} & {"Grün"} wird dann {"Rot", "Blau", "Grün"} An diesem Beispiel sehen Sie auch, dass eine Liste trotz ihres Namens nicht unbedingt immer mehrere Elemente enthalten muss. Hier enthält die zweite Liste tatsächlich nur einen einzigen Wert.
130
Die Sprache
Kapitel 4
Eine Liste kann auch leer sein. Eine leere Liste wird so geschrieben: {} Eine Liste kann mit dem &-Operator auch mit Text oder Zahlliteralen erweitert werden. {"Rot", "Blau", "Grün"} & 1 & "Zwei" & 3 führt zu folgender Liste: {"Rot", "Blau", "Grün", 1, "Zwei", 3} Auch tab, return und space sowie Unicode-Zeichen können in einem Listenliteral verwendet werden: {"Rot", tab, return, space, "Grün", "♔"} wird im Ergebnisbereich zu {"Rot", " ", " ", " ", "Grün", "♔"} Listen können auch wiederum Listen als Element enthalten. Die folgende Liste enthält zum Beispiel vier Elemente. Das letzte Element ist dabei wiederum eine Liste mit den Zahlen 1 bis 3. {"A", "B", "C", {1, 2, 3}}
Eine Liste aus Variablen zusammenbauen Wirklich genial ist jedoch, dass eine Liste auch aus bereits bestehenden Variablen zusammengebaut werden kann: set set set set
eineZahl to 3.5 einText to "Hallo" eineListe to {"A", "B", "C"} neueListe to {eineZahl, einText, eineListe}
Die Variable neueListe enthält danach die Liste {3.5, "Hallo", {"A", "B", "C"}}. Die Variablen in der Liste rechts werden also aufgelöst und erst dann der Variablen links zugewiesen. Wenn Sie einen Variablennamen in eine Liste setzen, müssen Sie nur darauf achten, diesen nicht in Anführungszeichen zu setzen, sonst wird er als Text interpretiert. set neueListe to {"eineZahl", "einText", "eineListe"}
131
SmartBooks
AppleScript
würde die Liste {"eineZahl", "einText", "eineListe"} ergeben und nicht eine Liste mit dem Inhalt der Variablen dieses Namens. Sie dürfen rechts der Variablen, also nach dem to, ruhig auch noch rechnen: set eineZahl to 3 set zweiteZahl to 5 set eineListe to {eineZahl, zweiteZahl, eineZahl * zweiteZahl} -- Ergebnis: {3, 5, 15} Die Berechnung wird immer zuerst ausgeführt und erst dann das Ergebnis der Liste hinzugefügt.
Referenzformen am Beispiel von Listen Eine alltägliche Aufgabe in einer Programmiersprache ist die, aus einer Liste ein bestimmtes Element herauszuangeln. Dafür gibt es in AppleScript die sogenannten Referenzformen, die Ihnen später auch bei Text, Records und Programmobjekten begegnen werden. Hier werden alle diese Formen am Beispiel von Listen behandelt.
Auswahl eines einzelnen Elements Nehmen wir an, Sie haben eine Liste mit fünf Elementen, die aus drei Zahlen, einem Text und einer weiteren Liste besteht: {2, "Oben", 5, {11, 12}, 4}
first, second, third item… Um daraus das erste Element herauszubekommen, schreiben Sie in den Skripteditor folgende Zeile: first item of {2, "Oben", 5, {11, 12}, 4} Das Ergebnis ist 2. Probieren Sie auch folgende Befehle aus: second item of {2, "Oben", 5, {11, 12}, 4} third item of {2, "Oben", 5, {11, 12}, 4}
132
Die Sprache
Kapitel 4
das können Sie bis zu tenth item, also dem zehnten Element, fortführen. Danach müssen Sie eine der folgenden Schreibweisen bemühen. 1st item of {2, "Oben", 5, {11, 12}, 4} -- Resultat: 2 2nd item of {2, "Oben", 5, {11, 12}, 4} -- Resultat: "Oben" 3rd item of {2, "Oben", 5, {11, 12}, 4} -- Resultat: 5 4th item of {2, "Oben", 5, {11, 12}, 4} -- Resultat: {11, 12} Bei dieser Schreibweise können Sie auch über das zehnte Element hinausgehen: 21st item of {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,"A"} --Ergebnis: "A" Tipp Übrigens ist es nicht so schlimm, wenn Sie die Endungen st, nt, rd und th durcheinanderbringen, AppleScript ist so nett, eine Verwechslung der Endungen nach dem Kompilieren automatisch zu korrigieren. Mit anderen Worten: Es ist egal, welche dieser Endungen Sie schreiben, Hauptsache, es ist eine vorhanden. Sie können dabei auch von hinten zählen: -1st item of {2, "Oben", 5, {11, 12}, 4} -- Resultat: 4 -2nd item of {2, "Oben", 5, {11, 12}, 4} -- Resultat: {11, 12} Mit einem einfachen Minuszeichen vor der Indexzahl kehren Sie also den Anfang um und rollen die Liste von hinten auf. Für das erste und letzte Element einer Liste gehen auch folgende Schreibweisen mit beginning und end: beginning of {2, "Oben", 5, {11, 12}, 4} end of {2, "Oben", 5, {11, 12}, 4} In Kombination mit item geht auch: front item of {2, "Oben", 5, {11, 12}, 4} -- Ergebnis: 2 last item of {2, "Oben", 5, {11, 12}, 4} -- Ergebnis: 4 oder back item of {2, "Oben", 5, {11, 12}, 4} -- Ergebnis: 4
item n Die gebräuchlichste Schreibweise, um auf ein Element in einer Liste zuzugreifen, ist die folgende:
133
SmartBooks
AppleScript
item 1 of {2, "Oben", 5, {11, 12}, 4} item 2 of {2, "Oben", 5, {11, 12}, 4} item 3 of {2, "Oben", 5, {11, 12}, 4} usw. Grundlagen Wenn Sie bereits andere Sprachen kennen, wird Ihnen hier vielleicht auffallen, dass ein Listenindex in AppleScript nicht null-basiert ist, sondern immer mit 1 beginnt. Das erste Element einer Liste ist also immer das Element Nummer 1 und nicht Nummer 0. Da dies auch unserem natürlichen Sprachgebrauch entspricht, braucht man sich in AppleScript nicht umzugewöhnen. Sie können aber auch rückwärts vorgehen und von hinten zählen: item -1 of {2, "Oben", 5, {11, 12}, 4} liefert das letzte Element der Liste, also von hinten gezählt das erste Element, hier die Zahl 4. Alles, was Sie hier tun müssen, ist, nur ein Minuszeichen vor der Indexzahl nach item zu setzen. item -2 of {2, "Oben", 5, {11, 12}, 4} gibt dann die Liste {11, 12} als Ergebnis zurück, das von hinten gezählt das zweite Element ist. Das lässt sich natürlich beliebig bis zur Anzahl der Elemente in der Liste fortführen. Aufgepasst Achten Sie bei Listenzugriffen immer darauf, dass Sie nicht auf Elemente zugreifen, die nicht vorhanden sind. Wenn Sie auf das achte Element zugreifen wollen, die Liste aber nur fünf Elemente enthält, erhalten Sie eine Fehlermeldung, wenn Sie das Skript ausführen. Da dieser Fehler erst beim Ausführen und nicht schon beim Übersetzen auftritt, ist er besonders störend.
item n of item n Wie greife ich eigentlich auf ein Element in einer Liste zu, welches sich wiederum in einer Liste befindet? Wenn ich auf das vierte Element der Beispielliste zugreife erhalte ich ja als Ergebnis {11, 12}, also die ganze Liste und nicht einen einzelnen Wert daraus. Glücklicherweise lässt sich item auch beliebig tief schachteln, und zwar mit Hilfe von of: item 1 of item 4 of {2, "Oben", 5, {11, 12}, 4}
134
Die Sprache
Kapitel 4
Hier wird also das erste Element des vierten Elements (item 1 of item 4) geholt. Als Ergebnis wird die 11 zurückgeliefert, das erste Element der Liste {11, 12}, welche das vierte Element der Liste {2, "Oben", 5, {11, 12}, 4} ist. Haben Sie sich vergriffen, und das Element ist keine Liste, sondern eine Zahl, zum Beispiel bei item 1 of item 3, erhalten Sie eine Fehlermeldung. Diese Schachtelung kann theoretisch beliebig tief gehen. Es sind also durchaus Konstruktionen wie item 1 of item 3 of item 5 of item 7 möglich, wenn die Liste derart tief verschachtelt ist. Für einen übersichtlichen Code sorgen solche Schachtelungen natürlich nicht, und man sollte sie daher besser vermeiden.
Auswahl eines Bereiches Die obigen Operatoren holen immer nur ein einzelnes Element aus der Liste heraus. Sie können aber auch ganze Bereiche aus der Liste holen.
through Eine Möglichkeit, einen Bereich abzufragen, ist mit through oder in abgekürzter Schreibweise thru gegeben. Der Begriff item wird dann in der Mehrzahl items geschrieben. Wenn Sie das vergessen, macht es aber auch nichts, AppleScript ergänzt das Plural-s automatisch. items 1 through 4 of {2, "Oben", 5, {11, 12}, 4} Als Ergebnis erhalten Sie die Liste {2, "Oben", 5, {11, 12}} mit den Elementen 1 bis 4 der Liste. Auch hier ist die Angabe eines negativen Index möglich. items -2 thru -4 of {2, "Oben", 5, {11, 12}, 4} liefert {"Oben", 5, {11, 12}} zurück. Also die Elemente 2 bis 4 von hinten gezählt. Sie können auch von vorne und hinten gezählten Index mischen: items 1 thru -1 of {2, "Oben", 5, {11, 12}, 4} liefert die gesamte Liste zurück, vom ersten bis zum letzten Element. Oder items 1 thru -2 of {2, "Oben", 5, {11, 12}, 4} liefert alle Elemente bis auf das letzte zurück. Es spielt übrigens keine Rolle, wenn sich die Indexzahlen überlappen und der zweite Index weiter vorn ist als der erste. Der Index, der weiter vorne ist, bildet immer den Anfang:
135
SmartBooks
AppleScript
items 3 thru -4 of {2, "Oben", 5, {11, 12}, 4} ergibt {"Oben", 5}. Da item -4 von vorne gezählt item 2 ist, wird hier also item 2 to 3 zurückgeliefert. Wenn es sich um das erste oder letzte Element einer Liste handelt, sind statt einer Indexzahl auch die Wörter beginning oder end erlaubt. items beginning thru 3 of {2, "Oben", 5, {11, 12}, 4} oder items 3 thru end of {2, "Oben", 5, {11, 12}, 4}
from … to Statt mit thru können Sie einen Bereich aber auch mit from … to spezifizieren: items from 2 to 3 of {2, "Oben", 5, {11, 12}, 4} -- Resultat: {"Oben", 5} AppleScript wandelt diese Form nach dem Kompilieren automatisch in die through-Form ab: items 2 thru 3 of {2, "Oben", 5, {11, 12}, 4}
some, middle und every Neben den oben beschriebenen Zugriffsmöglichkeiten gibt es noch folgende besondere Referenzformen. Mit some können Sie aus einer Liste ein zufälliges Element auswählen: some item of {"Rechts", "Links", "Geradeaus", "Zurück"} Geben Sie obige Zeile in den Skripteditor ein und klicken Sie dann mehrmals auf Ausführen, und Sie werden sehen, dass im Bereich Ergebnis jedes Mal ein anderer Wert steht. Mit middle item holen Sie das mittlere Element aus einer Liste. Bei einer geraden Anzahl von Elementen wird das Element vor der Mitte zurückgeliefert. Beispiel: middle item of {1, 2, 3, 4} liefert 2 zurück. middle item of {1, 2, 3, 4, 5} liefert 3.
136
Die Sprache
Kapitel 4
Mit every holen Sie alle Elemente einer Liste ab: every item of {1, 2, 3, 4, 5} liefert {1, 2, 3, 4, 5} als Ergebnis. Alternativ können Sie auch das every weglassen und die Mehrzahl von item benutzen: items of {1, 2, 3, 4, 5} every spielt in AppleScript noch an vielen anderen Stellen eine große Rolle, zum Beispiel bei der Umwandlung von Text in eine Liste.
Zuweisungsoperationen mit Referenzformen Das Ergebnis einer Referenzform lässt sich natürlich auf die rechte Seite einer Variablenzuweisung packen. Damit ist das referenzierte Objekt gleich fest in einer Variablen gespeichert und geht nicht mit dem nächsten Schritt verloren. Setzen Sie dafür einfach ein set … to vor die Anweisung, zum Beispiel: set meineVariable to items -2 thru -4 of {2, "Oben", 5, {11, 12}, 4} Das wird in der Regel sogar immer so gemacht. Denn ohne Variable sind Ergebnisse ja bekanntlich flüchtig und werden nur in der eingebauten AppleScript-Variablen result abgespeichert und damit von jedem neuen Ergebnis überschrieben.
Referenzformen mit Angabe der Klasse Da eine Liste unterschiedliche Klassen enthalten kann, also zum Beispiel Zahlen (integer oder real) und Text (text), aber auch weitere Listen, können Sie auch über die Klassenbezeichnung auf ein spezifisches Element dieser Art zugreifen. set myList to {2, "Oben", 5, {11.5, 12.3}, 4} integer 2 of myList -- Ergebnis: 5 Hier wird die zweite Integerzahl aus der Liste zurückgeliefert, also die 5. Mit anderen Worten: Das bisher verwendete item nimmt keine Rücksicht auf die Klasse der Elemente. Mit item sind immer alle Elemente einer Klasse gemeint. set myList to {2, "Oben", 5, {11.5, 12.3}, 4} list 1 of myList -- Ergebnis: {11.5, 12.3} liefert die erste Liste in der Liste.
137
SmartBooks
AppleScript
set myList to {2, "Oben", 5, {11.5, 12.3}, 4} text 1 of myList -- Ergebnis: "Oben" holt den ersten Text in der Liste. Schachteln geht auch: set myList to {2, "Oben", 5, {11.5, 12.3}, 4} real 2 of list 1 of myList -- Ergebnis: 12.3 Als Ergebnis erhalten Sie hier die zweite Dezimalzahl aus der ersten Liste in der Liste myList. Das funktioniert später übrigens auch mit anderen Klassen als den bisher bekannten list, text, real und integer. Auch mit ganzen Bereichen funktioniert diese Form der Auswahl: set myList to {2, "Oben", 5, {11.5, 12.3}, 4} integers 1 thru 2 of myList -- Ergebnis: {2, 5} Sie können es auch ohne thru mit from … to schreiben: integers from integer 1 to integer 3 of mylist Beim Kompilieren wird diese Form dann aber durch die entsprechende Form mit thru ersetzt: integers 1 thru 3 of myList Wenn es um die Auswahl einer Zahl geht und es dabei egal ist, ob es sich um Integer oder Real handelt, dann sollten Sie number verwenden. number ist ein Synonym für Integer und Real. set mylist to {2, "O", 5, 3.7, 4} numbers 2 thru 3 of mylist -- Ergebnis: {5, 3.7}
Referenzformen mit Klasse und every, some und middle Wenn Sie schlichtweg alle Elemente einer bestimmten Klasse aus einer Liste herausziehen wollen, benutzen Sie every mit entsprechendem Klassenamen: set myList to {2, "Oben", 5, {11.5, 12.3}, 4} every integer of myList -- Ergebnis: {2, 5, 4} oder set myList to {2, "Oben", "Unten", {11.5, 12.3}, 4} every text of myList -- Ergebnis: {"Oben", "Unten"} 138
Die Sprache
Kapitel 4
Mit some können Sie auch einen beliebigen zufälligen Wert einer bestimmten Klasse aus der Liste herausangeln: set myList to {2, "Oben", "Unten", {11.5, 12.3}, {5, 6}, 4} some list of myList oder set myList to {2, "Oben", "Unten", {11.5, 12.3}, {5, 6}, 4} some integer of myList Nur mit text als Klasse funktioniert das nicht. Das ist ein bekannter Bug. Verwenden Sie stattdessen das Synonym string, um einen zufällig ausgewählten Text aus der Liste zu holen: set myList to {2, "Oben", "Unten", {11.5, 12.3}, {5, 6}, 4} some string of myList Und zu guter Letzt funktioniert das auch mit middle: set myList to {1, 2, "Links", 3, "Mitte", 4, "Rechts"} middle text of myList -- Ergebnis: "Mitte" oder set myList to {1, 2, "Links", 3, "Mitte", 4, "Rechts"} middle integer of myList -- Ergebnis: 2 Bei einer ungeraden Anzahl an Elementen wird das Element links der Mitte zurückgeliefert, genauer: die Anzahl der Elemente geteilt durch 2, aufgerundet auf die nächste Ganzzahl.
Relative Referenzformen mit before und after Es gibt noch eine Referenzform, welche die Schlüsselwörter before (oder in front of) und after (oder in back of oder behind) verwendet. Damit lassen sich Elemente anhand ihrer relativen Position zu einem anderen Element ermitteln. Das geht zum Beispiel so: set myList to {1, 2, "Links", 3, "Mitte", 4, "Rechts"} item before integer 2 of myList Wenn Sie das übersetzen, erhalten Sie jedoch eine Fehlermeldung!
139
SmartBooks
AppleScript
Diese Form der Referenz funktioniert leider nicht mit den Standard-Werteklassen von AppleScript, sondern nur mit Programmobjekten, die sich über einen Index ansprechen lassen. Beispiele zu dieser Art der Referenzierung finden Sie daher erst später im Buch (siehe Kapitel zur tell-Kontrollstruktur).
Arbeiten in der Liste Sie können aus einer Liste natürlich nicht nur Werte auslesen, Sie können auch Werte darin verändern, und zwar mit set, also demselben Befehl, mit dem Sie auch Werte in eine Variable stecken. Mit demselben Befehl weisen Sie auch einem Listenelement einen Wert zu.
Ändern von Werten Folgende Anweisung ersetzt zum Beispiel das erste Element in einer Liste: set myList to {1, 2, 3} set item 1 of myList to "x" myList -- Ergebnis: {"x", 2, 3} Zum Schluss wird der Inhalt von myList einfach durch Aufruf des Variablennamens ermittelt. Der Inhalt von myList landet dadurch in der Variablen result und kann dann von Ihnen im Ergebnisbereich des Skripteditors abgelesen werden. Aufgepasst Alternativ könnten Sie natürlich auch log myList schreiben und das Ergebnis im EventProtokoll nachsehen. Zu beachten ist dabei jedoch, dass die Listenelemente durch log immer in Text konvertiert werden. Die einzelnen Elemente der Liste werden dabei mit Komma voneinander getrennt. Unterlisten werden dabei ebenfalls in deren Elemente aufgelöst. Unterscheidungen zwischen Texten, Zahlen und Unterlisten sind dadurch also nicht mehr möglich. Im Zweifelsfall sollten Sie daher durchaus auch einzelne Elemente der Liste mit log verfolgen: set myList to {3.5, "Hallo", {"A", "B", "C"}} set item 2 of item 3 of myList to "D" log item 3 of myList -- Event-Protokoll: (*A, D, C*)
140
Die Sprache
Kapitel 4
Die Auswahl des zu ersetzenden Listenelements geschieht also auf dieselbe Art, in der Sie auch bisher den Wert eines Listenelements abgefragt haben. Dementsprechend lassen sich einzelne Elemente über alle bisher bekannten Referenzformen ersetzen. Gegebene Liste: set myList to {1, 2, 3} Beispiele darauf angewandter Zuweisungen: set set set set set set set
first item of myList to "x" -- Ergebnis {"x", 2, 3} last item of myList to "x" -- Ergebnis {1, 2, "x"} second item of myList to "x" -- Ergebnis {1, "x", 3} 3rd item of myList to "x" -- Ergebnis {1, 2, "x"} -1st item of myList to "x" -- Ergebnis {1, 2, "x"} item -2 of myList to "x" -- Ergebnis {1, "x", 3} front item of myList to "x" -- Ergebnis {"x", 2, 3}
Schreiben Sie für jede der obigen Zeilen myList auf die letzte Zeile, um die ganze Liste als Ergebnis zurückgeliefert zu bekommen: set myList to {1, 2, 3} set first item of myList to "x" -- Ergebnis {"x", 2, 3} myList Auch hier können Sie natürlich beliebig tief schachteln: set myList to {2, "Oben", 5, {11, 12}, 4} set item 1 of item 4 of myList to "x" mylist -- Ergebnis: {2, "Oben", 5, {"x", 12}, 4} Ganze Bereiche lassen sich übrigens nicht ersetzen. Müssen mehrere Elemente in der Liste ersetzt werden, so macht man das üblicherweise in einer Schleife.
Hinzufügen von Werten Sie können einer Liste auch am Anfang oder Ende Werte hinzufügen und die Liste damit verlängern. Dafür müssen Sie wieder beginning und end und den Befehl copy oder set verwenden: set myList to {2, 5, {11.5, 12.3}} copy {8, 3} to the end of myList myList -- Ergebnis: {2, 5, {11.5, 12.3}, {8, 3}}
141
SmartBooks
AppleScript
Alternativ mit set: set mylist to {2, 5, {11.5, 12.3}} set end of mylist to {8, 3} myList -- Ergebnis: {2, 5, {11.5, 12.3}, {8, 3}} Das Hinzufügen eines Wertes am Anfang der Liste geht so: set myList to {2, 5, {11.5, 12.3}} copy {8, 3} to the beginning of myList myList -- Ergebnis: {{8, 3}, 2, 5, {11.5, 12.3}} oder mit set: set mylist to {2, 5, {11.5, 12.3}} set beginning of mylist to {8, 3} mylist -- Ergebnis: {{8, 3}, 2, 5, {11.5, 12.3}} Das Hinzufügen von Werten zwischen bereits vorhandene Listenelemente (mit before und after) geht nicht! Sie müssen beim Aufbau einer Liste also immer auf die richtige Reihenfolge achten. Auch das beliebige Sortieren innerhalb einer Liste ist nicht direkt möglich. (Sie müssen sich die gewünschte Sortierung in einer neuen Liste anhand der alten zusammenbauen.) Alternativ zu beginning und end funktioniert auch das Verknüpfen von Listen mit dem &-Operator, was allerdings nicht zu empfehlen ist: set myList to {0, 1, 1, 2, 3} set myList to myList & 5 myList -- Ergebnis: {0, 1, 1, 2, 3, 5} oder wenn Sie eine Zahl am Anfang der Liste einfügen wollen: set myList to {1, 1, 2, 3, 5} set myList to 0 & myList myList -- Ergebnis: {0, 1, 1, 2, 3, 5} Aber Vorsicht, wenn Sie Text oder andere Klassen am Anfang der Liste einfügen wollen: set myList to {1, 1, 2, 3, 5} set myList to "0" & myList myList -- Ergebnis: "011235" Die Liste wird dann ebenfalls in Text konvertiert! Verwenden Sie daher besser die Form mit beginning, wenn Sie etwas am Anfang der Liste einfügen wollen, und Sie vermeiden dadurch diese impliziten Umwandlungen bei unterschiedlichen Klassen.
142
Die Sprache
Kapitel 4
Aufgepasst Verwenden Sie diese Methoden nach Möglichkeit nicht in einer Schleife! Sie sind sehr langsam und eignen sich daher nur für gelegentlich hinzuzufügende Werte! In einer Schleife empfiehlt es sich, nur mit einer Referenz auf der Liste zu arbeiten. Details dazu im Kapitel Schleifen.
Entfernen von Werten Um ein Element aus einer Liste zu entfernen, verwenden Sie am besten rest. Mit rest entfernen Sie dabei immer das erste Element der Liste. Bauen Sie die Liste daher so zusammen, dass die Elemente, die zuerst entfernt werden sollen, auch am Anfang stehen. rest of {1, 2, 3} -- Ergebnis {2, 3} Möchten Sie der Liste Elemente von hinten wegnehmen, so müssen Sie die Liste vorher mit reverse umdrehen. set mylist to reverse of {1, 2, 3} -- Ergebnis {3, 2, 1} rest of myList -- Ergebnis {2, 1} rest und reverse sind Eigenschaften (Propertys) einer Liste und keine Befehle. Jede Liste besitzt also eine Eigenschaft »umgekehrt sortiert« und eine Eigenschaft »alle, außer dem ersten Wert«. Mit of fragen Sie diese Eigenschaft einer Liste ab.
Eigenschaften einer Liste Eine Liste ist, wie eine Zahl oder Text, eine AppleScript-Klasse. Das heißt, wie fast jede Klasse hat auch eine Liste damit besondere Eigenschaften. Die grundlegendste Eigenschaft einer jeden Klasse ist ihre Klassenart. Wenn Sie eine Liste nach ihrer Klasse fragen, erhalten Sie list als Antwort. class of {1, 2, "B", 3.5} -- Ergebnis: list Verwenden Sie diese Abfrage, wenn Sie vor einer Operation sichergehen wollen, dass sich in der Variablen wirklich eine Liste befindet. Ebenfalls hilfreich ist es zu erfahren, wie viele Elemente eine Liste enthält. Aus diesem Grund gibt es die Eigenschaft length, die Sie abfragen können.
143
SmartBooks
AppleScript
Wenden Sie den Befehl auf folgende Art an: length of {1.53, 2.0, 3.14, 4.5} Als Ergebnis erhalten Sie 4, da die Liste vier Elemente enthält. Fragen Sie die Länge einer Liste immer ab, bevor Sie auf Elemente in der Liste zugreifen. So können Sie sicher gehen, dass Sie nicht auf Elemente zugreifen, die nicht existieren. In obigem Beispiel wüssten Sie nach der Abfrage der length-Property also Bescheid, dass Sie nur bis item 4 fragen können. Manchmal ist es auch hilfreich, eine Liste umzudrehen, zum Beispiel, um nicht immer von hinten zählen zu müssen. Wenn man die Reihenfolge in einer Liste umdrehen will, hilft folgender Befehl: reverse of {1, 2, 3, 4, 5} ergibt {5, 4, 3, 2, 1} als Ergebnis. Dieselbe Liste, aber alle Elemente wurden in umgekehrter Reihenfolge sortiert. Die Eigenschaft rest einer Liste kann hilfreich sein, wenn man eine Liste nach und nach verkleinern will, nachdem einzelne Elemente darin abgearbeitet wurden. rest of {1, 2, 3, 4, 5} liefert {2, 3, 4, 5} zurück. Mit anderen Worten: Das erste Element der Liste wird verworfen. Das Resultat lässt sich natürlich auch gleich mit set in eine Variable packen: set restListe to rest of {1, 2, 3, 4, 5} restListe enthält dann also die Liste {2, 3, 4, 5} Mit einem darauf folgenden set restListe to rest of restliste wird in der Liste wieder das erste Element entfernt, und restListe enthält dann {3, 4, 5}. Immer wieder erneut angewendet, erhalten Sie zum Schluss eine leere Liste. Fragen Sie dann die leere Liste nach ihrem rest, erhalten Sie eine Fehlermeldung, und die Ausführung Ihres Skripts wird unterbrochen. Fragen Sie also nur nach rest, wenn die Liste mindestens noch eine length von 1 hat.
144
Die Sprache
Kapitel 4
Massenzuweisungen über Listen Listen eignen sich auch hervorragend dazu, mehrere Variablen in einem Rutsch mit Werten zu füllen: set {a, b, summe} to {1, 2, 3} Dabei erhält die Variable a den Wert 1, die Variable b den Wert 2 und die Variable summe den Wert 3. Wichtig sind hier die geschweiften Klammern! Es handelt sich also um zwei Listen. In die erste Liste gehören die Namen der Variablen, in die zweite die dazugehörigen Werte. Beide Listen müssen die gleiche Anzahl von Elementen enthalten. Diese Art der Zuweisung eignet sich auch gut, um Werte zu tauschen: set {a, b} to {1, 2} -- a enthält nun 1 und b 2 set {a, b} to {b, a} -- a enthält nun 2 und b 1 Die Aufspaltung geht auch indirekt, indem man zuerst eine Liste mit den Werten erstellt: set a to {3, 8} und diese dann einer Liste mit Variablen als »Futter« vorwirft: set {b, c} to a Die Variable b erhält dann die 3, und in c landet die 8, wie man mit log im Event-Protokoll leicht überprüfen kann: set a to {3, 8} set {b, c} to a log "Variable b enthält " & b log "Variable c enthält " & c Im Event-Protokoll steht danach: (*Variable b enthält 3*) (*Variable c enthält 8*) Wichtig ist hierbei, dass auf beiden Seiten Listen mit der gleichen Anzahl an Elementen stehen. Sind auf der linken Seite weniger Elemente vorhanden als rechts, werden die übrigen Elemente der rechten Seite bei der Zuweisung ignoriert. Sind auf der rechten Seite weniger Elemente als links, erhalten Sie eine Fehlermeldung, und die Ausführung des Skripts wird gestoppt.
145
SmartBooks
AppleScript
Der Befehl count in Listen Einige Befehle haben Sie bereits kennengelernt. Der wichtigste Befehl set, mit dem Sie dem Element einer Liste einen neuen Wert zuweisen können, oder copy. Ein Befehl für Listen, der noch fehlt, ist der Befehl count. Alles, was irgendwie Listenstruktur hat, also aus geordneten Einzelelementen besteht, lässt sich mit diesem Befehl »zählen«. count {1, 2, 3, "A", {1, 2, 3}} -- Ergebnis: 5 count macht also im Prinzip dasselbe, was Sie auch mit der Eigenschaft length erreichen: length of {1, 2, 3, "A", {1, 2, 3}} -- Ergebnis: 5 Eine leere Liste ergibt null: count {} -- Ergebnis: 0 Statt count können Sie auch die form number of verwenden. number of {1, 2, 3, "A", {1, 2, 3}} -- Ergebnis: 5 number of ist dabei nur ein Pseudonym für count. Obwohl es so aussieht, handelt es sich hier also nicht um eine Eigenschaft namens number. Diese Eigenschaft existiert nicht. Es ist nur eine verkleidete Form des Befehls count. Sie können mit count auch spezifisch nur ganz bestimmte Klassen in der Liste zählen, was Sie mit der Eigenschaft length nicht können. Dabei müssen Sie den Klassennamen und every verwenden, wenn Sie alle Elemente dieser Klasse zählen wollen, beziehungsweise einen Bereich, wenn nur die Elemente der Klasse in diesem Bereich gezählt werden sollen. set myList to {1, 2, 3.5, "A", "B"} count every integer of myList -- Ergebnis: 2 set myList to {1, 2, 3.5, "A", "B"} count every real of myList -- Ergebnis: 1 Verwenden Sie number, wenn Sie alle Zahlen, egal ob Integer oder Real, zählen wollen: set myList to {1, 2, 3.5, "A", "B"} count every number of myList -- Ergebnis: 3 Auch Text und Listen können als Elemente einer Liste gezählt werden: set myList to {1, 2, 3.5, "A", "B"} count every text of myList -- Ergebnis: 2
146
Die Sprache
Kapitel 4
set myList to {1, 2, 3.5, {3, 4}, {1, 2}} count every list of myList -- Ergebnis: 2 Wenn nur ein bestimmter Bereich abgefragt werden soll, gehen Sie mit den bekannten Bereichsreferenzen an die Liste heran: set myList to {1, 2, 3.5, "A", "B"} count integers 1 thru 2 of myList -- Ergebnis: 2 Bei Angabe eines Bereiches ist es meist jedoch sinnvoller, item zu verwenden, da durch die Angabe eines Index für integer ja sowieso schon bekannt ist, wie viele Integer gezählt werden. Mit item kommt jedoch jedes Listenelement in Frage: set myList to {1, 2, 3.5, "A", {1, 2, 3}} count integers from item 1 to item 4 of myList -- Ergebnis: 2
Der Unterschied zwischen set und copy Bei Listen unterscheidet sich die Auswirkung von set und copy. Hier ist daher nun auch der Zeitpunkt gekommen, den feinen Unterschied zu erklären. Zuerst einmal scheinen sich set und copy bei Listen genauso zu verhalten wie bei den Zahlen. Ob ich eine Liste mit set zuweise set a to {1, 2, 3} oder mit copy copy {1, 2, 3} to a macht erst mal keinen Unterschied. In beiden Fällen enthält a nun eine Liste {1, 2, 3}. Betrachten Sie jedoch folgenden Fall: set a to {1, 2, 3} set b to a set item 1 of b to "A" get a -- Ergebnis: ? Preisfrage: Welchen Wert hat nun die Variable a? Obwohl a überhaupt nicht angerührt wurde, die Zuweisung also nur an b erfolgte, sieht a nun so aus: {"A", 2, 3}.
147
SmartBooks
AppleScript
Was ist da geschehen? In der ersten Zeile wird eine Liste in die Variable a gesteckt: set a to {1, 2, 3} In der nächsten Zeile wird eine zweite Variable mit dem Namen b angelegt, und dieser wird der Wert der Variablen a zugewiesen: set b to a b enthält nun ebenfalls die Liste {1, 2, 3}. Und das ist nun das Besondere: Es enthält dieselbe Liste wie a! Es liegen hier also gar keine zwei Listen vor. a und b weisen auf dasselbe Objekt, dieselbe Liste hin, so wie zwei Türen, die in dasselbe Zimmer führen. Ob nun a oder b verändert wird, es handelt sich hier nur um zwei Namen für ein und dasselbe Objekt. Dieses Verhalten betrifft alle AppleScript-Werteklassen, die veränderbar (mutable) sind, dazu gehören Listen, aber auch die Klassen record, date und script. Mit anderen Worten: Bei Zahlen und Text tritt dieses Verhalten nicht auf. Was passiert nun, wenn man der Variablen a zwischenzeitlich einen völlig neuen Wert zuweist? Probieren Sie es aus: set a to {1, 2, 3} set b to a set a to {"Hello"} get b -- Ergebnis: ? Welchen Wert hat nun b? Lösung: In der ersten Zeile wird wieder der Variablen a die Liste {1, 2, 3} zugewiesen, und darauf wird b wieder auf dieselbe Liste gesetzt, b ist also wieder genau dasselbe Objekt wie a – soweit also alles wie vorhin. Nun wird in der dritten Zeile nicht nur einem einzelnen Element von a ein anderer Wert zugewiesen, sondern a bekommt einen gänzlich neuen Wert, nämlich die Liste {"Hello"}. Ist der Wert von b nun ebenfalls {"Hello"}?
148
Die Sprache
Kapitel 4
Nein! b enthält weiterhin {1, 2, 3}. b bezieht sich also auf den Wert selber und nicht auf den Namen der Variablen a. Es ist wichtig, das gut zu verstehen. Aufgepasst Ein Objekt kann verschiedene Namen haben, und einer dieser Namen kann jederzeit einem anderen Objekt zugewiesen werden. Vorher wurden beide Namen noch für ein und dasselbe Objekt verwendet. Danach wird der zweite Name für ein anderes Objekt verwendet! Aus dem Gesagten ergibt sich auch der Sinn des Befehls copy. Verwenden Sei copy immer dann, wenn Sie wirklich eine Kopie eines Objekts benötigen. (Wenn in der Variablen aber eine Objektreferenz steckt, erzeugt copy natürlich eine zweite Objektreferenz auf dasselbe Objekt, siehe auch a reference to.) Hier das erste Beispiel mit copy anstatt mit set: set a to {1, 2, 3} copy a to b set item 1 of b to "A" get a -- Ergebnis: {1, 2, 3} Als Ergebnis bleibt die Liste in a nun unberührt von der Veränderung in der dritten Zeile, da vorher eine Kopie der Liste in a hergestellt und dann in b abgespeichert wurde. Und nur in dieser Kopie wird jetzt das erste Element auf "A" gesetzt. copy erzeugt immer eine »deep copy«. Das heißt, dass auch in der Liste enthaltene Unterlisten vollständig bis in die tiefste Verschachtelung kopiert werden: set a to {1, 2, 3} set b to {"a", "b", "c"} set c to {a, b} copy c to d set first item of a to "A" log a log c log d -- Event-Protokoll: (*A, 2, 3*) (*A, 2, 3, a, b, c*) (*1, 2, 3, a, b, c*)
149
SmartBooks
AppleScript
Auch wenn eine Liste aus mehreren Unterlisten besteht, werden durch copy also immer alle Teile kopiert. Die Kopie ist danach vollständig unabhängig von den Originalen. Sie können also nach dem copy die Werte in a, b oder c verändern, ohne dass d davon beeinflusst wird. Die Liste c wird durch die Veränderung in a in Zeile 5 aber weiterhin beeinflusst, da diese mit dem Befehl set auf die Listenobjekte a und b gesetzt wurde. Die Variable c enthält also dieselben Variablen a und b. Jede Änderung in a und b macht sich daher auch in c bemerkbar. Die Variable d bleibt jedoch, dank des copy, völlig unbeeinflusst davon.
Umwandlung von Listen Listen lassen sich natürlich auch in Zahlen umwandeln und umgekehrt. Die Umwandlungsmöglichkeiten von Listen und Text wird im Kapitel Arbeiten im Text behandelt. Wenn Sie eine oder mehrere Zahlen in eine Liste umwandeln wollen, so geschieht das bei einer einzelnen Zahl mit dem as-Operator. set x to 3.15 set x to x as list -- Ergebnis {3.15} Liegt bereits eine Liste vor, die Sie mit einer Zahl erweitern möchten, verwenden Sie die zuvor im Abschnitt Hinzufügen von Werten beschriebenen Techniken. Soll umgekehrt eine Liste mit einer einzelnen Zahl in die Werteklasse real oder integer umgewandelt werden, so gehen Sie umgekehrt vor: set x to {3.15} set x to x as real -- Ergebnis: 3.15 oder set x to {3.15} set x to x as integer -- Ergebnis: 3 Enthält die Liste mehrere Zahlen, brauchen Sie nur nach dem entsprechenden Element zu fragen. Eine Umwandlung ist dabei nicht notwendig, wenn der Wert in der Liste schon in der richtigen Werteklasse vorliegt. Wenn nicht, kann die Umwandlung ebenfalls mit as bereits bei der Abfrage des Wertes erfolgen: set x to {3.15, 7} item 1 of x as integer -- Ergebnis: 3
150
Die Sprache
Kapitel 4
Arbeiten mit Text Zur Arbeit mit Text gibt es in AppleScript eine ganze Reihe an Möglichkeiten, und um die dreht sich alles in diesem Kapitel. Noch mal zur Erinnerung: Text liegt in AppleScript 2.0, also seit Mac OS X 10.5 Leopard, komplett in Unicode-Codierung vor. Damit fällt die frühere Unterscheidung zwischen den Textklassen text (MacRoman-Encoding) und unicode text (Unicode-Encoding) weg, was die Arbeit wesentlich vereinfacht. Ebenfalls überflüssig wird damit die Klasse international text, die für die diversen fremdsprachlichen Mac-Encodings gebraucht wurde. Es steht Ihnen also frei, auch Text in Chinesisch oder jeder anderen Sprache im Skripteditor einzugeben, vorausgesetzt, dieser Text befindet sich inAnführungszeichen, in einer Variablen oder in einem Kommentar. Text kann nicht an Ort und Stelle verändert werden. Sie können also nicht einzelne Elemente im Text ersetzen oder löschen. Text ist im Gegensatz zu Listen »immutable«, also unveränderlich. Sie können jedoch alles, was Sie brauchen, aus dem Text herausziehen und daraus einen neuen Text zusammenbauen.
Unicode Innerhalb von Anführungszeichen und in Kommentaren können Sie in einem Appleskript auch andere Zeichen als die bei Programmierern üblichen ASCII-Zeichen verwenden. Zum Einfügen in den Skripteditor leistet einem die Zeichenpalette aus dem Tastaturmenü dabei hilfreiche Dienste. Hilfe Falls Sie die Zeichenpalette noch nicht kennen: Sie wird in den Landeseinstellungen der Systemeinstellungen aktiviert. Gehen Sie dort in den Reiter Tastaturmenü und setzen Sie einen Haken bei Tastaturmenü in der Menüleiste zeigen. Sie erhalten dann rechts oben neben der Uhrzeit eine Landesflagge als Symbol. Kreuzen Sie dann noch Tastaturübersicht und Zeichenpalette an. Danach können Sie die Zeichenpalette über die Landesflagge aufrufen und von dort die gewünschten Zeichen in den Skripteditor ziehen. In folgendem Beispiel wurden die zwei Hexagramme des I-Ging für Himmel und Erde im Skripteditor miteinander vermählt: "䷀" & "䷁" ergibt im Skripteditor dann "䷀䷁""
151
SmartBooks
AppleScript
id und character id Statt die Unicode-Zeichen in den Skripteditor zu kopieren, können Sie die Unicode-Zeichen auch über Ihren Dezimalwert einfügen. Jeder Text hat in AppleScript 2.0 dafür die Eigenschaft id spendiert bekommen. Das funktioniert so: set mytext to character id 9445 Als Ergebnis erhalten Sie das Unicode-Zeichen Ⓥ, ein v in einem Kreis. Alles, was Sie dafür kennen müssen, ist den Dezimalwert des Unicode-Zeichens, und den erfahren Sie … leider nicht in der Zeichenpalette. Dort erfahren Sie den Hexadezimalwert, welchen Sie dann noch umrechnen müssen. Wählen Sie sich in der Zeichenpalette einfach ein Zeichen aus. Klicken Sie es an und halten Sie die Maus ruhig darüber. Ein gelber Hinweiszettel erscheint, auf dem der Hexadezimalwert steht, zum Beispiel »Unicode: 24E5«. Jetzt brauchen Sie noch den Taschenrechner von Apple. Das Programm Rechner finden Sie im Programmordner. Wenn der Rechner gestartet ist, schalten Sie ihn über das Darstellungs-Menü oder mit dem Tastaturkürzel [Befehl]+[3] auf Programmierer um. Wählen Sie dann rechts oben Hex als Eingabemodus aus und tippen Sie den Hexadezimalwert ein. Buchstaben dabei bitte klein schreiben. Nun schalten Sie den Eingabemodus einfach auf Dec um und Sie können den Dezimalwert ablesen, den Sie für character id brauchen.
Abb. 4-4 Der Hexadezimalwert eines Unicode-Zeichens wird in der Zeichenpalette am Mauszeiger eingeblendet.
152
Die Sprache
Kapitel 4
Abb. 4-5 Der Hexadezimalwert wird mit dem Rechner in einen Dezimalwert umgewandelt. Das dem Wert entsprechende Unicode-Zeichen wird links unten in der Ecke des Displays auch gleich angezeigt, wenn der Knopf »Unicode« eingedrückt ist. Die führenden Zeichen 0x werden nicht mit eingegeben. Wenn Sie mehrere Werte in einem Schwung in einen Text einfügen wollen, benutzen Sie eine Liste für character id: set mytext to character id {9404, 9438, 9438, 9427} Das Ergebnis ist ein Text mit vier Zeichen: "Ⓖⓞⓞⓓ" (Statt character id können Sie auch string id, unicode text id oder text id schreiben, wobei text id aufgrund eines bekannten Bugs bisher jedoch nicht funktioniert.) Statt den Weg über den Taschenrechner zur Ermittlung des Dezimalwertes zu gehen, können Sie den Wert aber auch in AppleScript selbst ermitteln, wenn Sie das Zeichen schon gefunden haben. Fügen Sie das Zeichen aus der Zeichenpalette in den Skripteditor ein und fragen Sie nach dessen id: set mytext to id of "Ⓖ" liefert Ihnen den Dezimalwert 9404 zurück. Wenn Sie eine ganze Kette von Zeichen angeben, erhalten Sie eine Liste mit allen Dezimalwerten der Zeichen. set mytext to id of "Ⓖⓞⓞⓓ" liefert {9404, 9438, 9438, 9427}
153
SmartBooks
AppleScript
Grundlagen Die Eigenschaft id für Text ist neu in Leopard. In Tiger müssen Sie die Befehle ASCII character und ASCII number verwenden. Beide sind nunmehr »deprecated«, also veraltet, und sollten unter Leopard nicht mehr verwendet werden. Beide funktionieren auch nur mit den 256 Zeichen des MacRoman Encodings. Damit können Sie jetzt übrigens auch herausfinden, welches Zeichen sich hinter der Konstanten return verbirgt. Wenn Sie id of return im Skripteditor eingeben, erhalten Sie 13 als Ergebnis. Es handelt sich also um einen »alten« Mac-Zeilenumbruch und keinesfalls um einen Unix-Linefeed, welcher das Zeichen 10 wäre. id of linefeed ergibt dann natürlich 10.
Kombinierte Unicode-Zeichen Für viele Unicode-Zeichen gibt es mehrere Varianten. Manche Zeichen werden so zum Beispiel aus einem Grundbuchstaben und einem Akzent zusammengesetzt, daneben gibt es das Zeichen dann aber auch noch einmal als eigenständiges Zeichen, wie zum Beispiel das é mit dem accent aigu. Wenn Sie nach einem character in einem Text fragen, wird bei solchen Zeichen immer das ganze zusammengesetzte Unicode-Zeichen zurückgeliefert und nicht das erste Zeichen daraus. set eAkut to character id {101, 769} -- Ergebnis: "é" setzt die Variable eAkut auf die Zeichen e und ´ die zusammen é ergeben. Dafür gibt es in Unicode aber auch ein eigenes Zeichen, welches den Akzent bereits enthält. Obige Zeile ist daher identisch mit set eAkut to character id 233 -- Ergebnis: "é" Oben wird das Zeichen é aus zwei Zeichen zusammengesetzt, unten ist es nur ein Zeichen. Wenn Sie nach dem ersten Zeichen eines zusammengesetzten Zeichens fragen set eAkut to character id {101, 769} first character of eAkut -- Ergebnis: "é" 154
Die Sprache
Kapitel 4
erhalten Sie das ganze Zeichen é als Antwort und nicht etwa nur das e. Und wenn Sie die Anzahl der Zeichen zählen set eAkut to character id {101, 769} count eAkut -- Ergebnis: 1 erhalten Sie 1 als Antwort, obwohl das Zeichen zuvor aus zwei Zeichen zusammengesetzt wurde! Wenn Sie danach wieder nach der id fragen set eAkut to character id {101, 769} count eAkut -- Ergebnis: 1 id of eAkut -- Ergebnis: {101, 769} sehen Sie, dass sich der Inhalt der Variablen nicht klammheimlich nach der Zuweisung geändert hat! Aufgepasst Zusammengesetzte Unicode-Zeichen werden also immer nur als ein einzelnes Zeichen gezählt. Dieses Verhalten ist neu in AppleScript 2.0.
Eigenschaften eines Textes Jede Klasse hat auch Eigenschaften (auf Englisch properties). Bei einer Liste sind das class, length, rest und reverse. Bei der Klasse text sind es die Eigenschaften class, id, length und quoted form. Wenn man einen beliebigen Text nach seiner Klasse fragt, so erhält man die Antwort text. set meineVariable to "Hiho" class of meineVariable -- Ergebnis: text Nützlich ist diese Eigenschaft vor allem, wenn man, bevor man eine Anweisung eingibt, sicher gehen will, ob sich in der Variablen wirklich Text befindet. Vor Leopard gab es noch die Unterscheidung zwischen normalem text, der in MacRomanCodierung vorlag, und unicode text. Diese Unterscheidung fällt nunmehr weg. Es gibt nur noch eine Klasse text und die ist durchgehend Unicode. Trotzdem existiert die Klasse unicode text aus Kompatibilitätsgründen auch weiterhin in AppleScript, sollte aber nach Möglichkeit nicht mehr verwendet werden.
155
SmartBooks
AppleScript
Die Eigenschaft id ist neu in AppleScript 2.0 und wurde eben im Kapitel Unicode im Detail behandelt. id liefert Ihnen die Nummer eines oder mehrerer Unicode-Zeichen im Text zurück, und zwar als Integer, nicht in hexadezimaler Schreibweise. set meinText to "ABC" id of meinText -- Ergebnis: {65, 66, 67} id wird mit of abgefragt! Um umgekehrt das zu einer id gehörige Zeichen zu erfahren, fragen Sie nach der id des characters: set meineID to {65, 66, 67} character id meineID -- Ergebnis: "ABC" character id wird nicht mit of abgefragt! Wie eine Liste, so hat auch ein Text die Eigenschaft Länge. Die Länge ist dabei durch die Anzahl an Zeichen (characters) bestimmt. Falls ein character aus mehreren Zeichen (mit Akzenten) zusammengesetzt ist, so zählen diese Akzente nicht mit. set meinText to "Liberté" length of meinText -- Ergebnis: 7 Die Eigenschaft quoted form dient dazu, einen Text so einzupacken, dass er bei einer Übergabe an die Unix-Shell nicht von dieser weiter interpretiert werden kann. Alles, was diese Eigenschaft macht, ist, den Text in einfache Anführungszeichen zu packen: set meinPfad to quoted form of "/Users/Hans/Documents/Eigene Webseiten" -- Ergebnis: "'/Users/Hans/Documents/Eigene Webseiten'" Damit ist in obigem Beispiel der Pfad sicher eingepackt und wird von der Unix-Shell nicht weiter interpretiert. Diese Form ist nötig, weil der obige Pfad eine Leerstelle enthält. Jetzt können Sie den Text in meinPfad mit dem Befehl do shell script als Argument an die Shell übergeben. Hier als Argument eines einfachen ls-Befehls: set meinPfad to quoted form of "/Users/Hans/Documents/Eigene Webseiten" set x to do shell script "ls -l " & meinPfad Zum Ausprobieren bitte den Benutzernamen im Pfad an Ihren anpassen und auf die Leerstellen zwischen den Anführungszeichen im Text der zweiten Zeile achten! Der Inhalt des Verzeichnisses wird dann in die Variable x zurückgeliefert und im Ergebnisbereich des Skripteditors angezeigt.
156
Die Sprache
Kapitel 4
Ohne quoted form würde do shell script wegen der Leerstelle bei Eigene Webseiten fehlschlagen.
Elemente eines Textes Text kann in Zeichen, Wörter und Absätze oder nach eigenen, freien Kriterien unterteilt werden. AppleScript kennt dafür die Begriffe character, word, paragraph, text item und text, auf die im Folgenden näher eingegangen wird.
character Als character wird ein einzelnes Zeichen in einem Text bezeichnet. So ist zum Beispiel der erste Buchstabe in "Brimborium" das "B". Wie vorhin bereits erwähnt, ist ein character dabei immer das ganze Zeichen, falls es aus mehreren Bestandteilen zusammengesetzt wurde.
word Als word wird ein Wort in einem Text bezeichnet. Wie zum Beispiel das Wort "Himmel" in "Der Himmel ist blau". Ein Wort endet dabei meist mit einem Leerzeichen, aber auch andere Zeichen werden als Worttrenner angesehen, wie zum Beispiel Komma, Punkt und andere Satzzeichen. Welche das genau sind, hängt von den Spracheinstellungen in den Landeseinstellungen der Systemeinstellungen ab. Dort gibt es die Option Wortgrenze. Diese steht normalerweise auf Standard, lässt sich hier aber auch auf Englisch (Vereinigte Staaten, Posix) und Japanisch umstellen. Eine genaue Dokumentation hierzu habe ich bisher nicht gefunden. Daher sollte man sich besser nicht darauf verlassen, dass ein word in AppleScript wirklich immer ein Wort in unserem Wortsinn ist. Folgendes konnte ich soweit jedoch feststellen: << Sind zwei Zeichen von einem Leerzeichen, einem Tabulator oder einem anderen Steuerzeichen (white space) getrennt, so gelten diese als getrennte Wörter. Die Steuerzeichen gelten als zu keinem Wort gehörig und werden ignoriert. << Sind zwei Zeichen durch ein Satzzeichen wie Punkt, Komma, Semikolon, Doppelpunkt, Bindestrich oder andere nicht alphabetische Satzzeichen getrennt, auch ohne Leerzeichen, so gelten beide Zeichen als zu verschiedenen Wörtern gehörend. Die Satzzeichen werden ignoriert und gehören zu keinem Wort. 157
SmartBooks
AppleScript
<< Aber: Steht ein Komma oder Punkt zwischen zwei Zahlen, so gehört der Punkt oder das Komma zu der Zahl dazu, und an dieser Stelle wird keine Worttrennung vorgenommen. Eine Zahl gilt also solange als Wort, wie sie von keinem anderen Zeichen außer einem Komma oder Punkt getrennt wird. << Auf diese Weise bleiben der Tausendertrenner und das Dezimalkomma in einer Zahl erhalten, und die Zahl wird als Ganzes als Wort betrachtet. Befindet sich jedoch eine Leerstelle in der Zahl als Tausendertrenner, so wird die Zahl an dieser Stelle in zwei Wörter aufgeteilt. << Bei Schweizern ist zu beachten, dass das Hochkomma nicht als Tausendertrenner erkannt wird und Zahlen an dieser Stelle getrennt werden! Diese Einstellung ist leider nicht von den Formaten in den Landeseinstellungen des Betriebssystems abhängig, warum auch immer. << Währungssymbole vor oder hinter der Zahl werden als eigenes Wort betrachtet, auch wenn das Symbol keinen Abstand zu den Zahlen hat. << Sind in einem Wort Zahlen und Buchstaben vermischt, so gelten die Zahlen aber als zu dem Wort gehörig. << Buchstaben, die mit einem Apostroph vom Hauptwort abgetrennt sind, werden als zum Wort gehörig betrachtet. Insgesamt sollten Sie sich nicht auf die Zuverlässigkeit dieser Regeln verlassen. Erstens besteht die Möglichkeit, dass Apple hier etwas ändert, zweitens ist jeder Text anders und benötigt eventuell sowieso eigene Regeln. Verlassen Sie sich dann besser auf selbstdefinierte text items.
paragraph Als paragraph wird ein einzelner Absatz bezeichnet. Ein Absatz ist dabei der Text von einem Absatzendezeichen (Konstanten return oder linefeed bzw. character id 13 und 10) bis zum nächsten. Auch ein Windows-Zeilenumbruch, der ja aus beiden Zeichen besteht, wird als Absatzende erkannt. Das Zeichen für den Zeilenumbruch gehört nicht zum Absatz dazu.
text Als text bezeichnet man alles, was Text ist, also auch character, word und paragraph sind text. text ist also der Oberbegriff und ist auch als Klasse implementiert. Dementsprechend werden Sie, wenn Sie eine Variable mit Text nach ihrer Klasse fragen, text als Antwort erhalten: set x to "abc" class of x -- Ergebnis: text
158
Die Sprache
Kapitel 4
text kann aus Zeichen aus dem gesamten Unicode-Bereich bestehen. Wenn Sie einen Text nach seinem text fragen, erhalten Sie seinen gesamten Inhalt als Antwort: set x to "abc" text of x -- Ergebnis: "abc"
text item Ein text item ist ein frei definierbarer Teil eines Textes. Wo ein text item anfängt und wo es aufhört, wird dabei durch sein Trennzeichen definiert, welches durch text item delimiter definiert ist. So wie ein Wort meist durch ein Leerzeichen vom nächsten Wort getrennt ist, so können Sie mit einem beliebigen text item delimiter eine andere Unterteilung des Textes vornehmen und auf die einzelnen Teile dann mit text item zugreifen.
Referenzformen auf Textelemente Wie funktioniert das nun genau, der Zugriff auf einzelne Elemente in einem Text? Prinzipiell genauso wie bei den Listen. Alle Techniken, die dort vorgestellt wurden, gelten auch für Text, nur dass Sie statt item ein Textelement, nämlich character, word, paragraph oder text item, verwenden sollten. (Item geht zwar auch, verhält sich aber identisch zu character. Benutzen Sie item nur für Listen, bei Text ist dessen Verwendung eher ungewöhnlich.) Hier ein paar Beispiele: first character of "Brimborium" -- Ergebnis: "B" third character of "Brimborium" -- Ergebnis: "i" last word of "Dies ist das Ende" -- Ergebnis: "Ende" 2nd paragraph of "Rot\rGrün\rBlau" -- Ergebnis: "Grün" word 2 of "Dies ist das Ende" -- Ergebnis: "ist" Rückwärts, also von hinten gezählt, geht es auch: character -2 of "Brimborium" -- Ergebnis: "u" word -4 of "Dies ist das Ende" -- Ergebnis: "Dies"
159
SmartBooks
AppleScript
Eine Schachtelung ist nur dort möglich, wo ein Element Teil eines anderen ist, so können Sie zum Beispiel auf ein Zeichen in einem Wort oder auf ein Wort in einem Absatz zugreifen, aber nicht umgekehrt. set meinText to "Der Anfang\rDas Ende" character 3 of word 2 of paragraph 1 of meinText -- Ergebnis: Das "f" von "Anfang"
Auswahl eines Textbereichs Auch die Abfrage eines Bereiches im Text lässt sich wie bei den Listen mit through oder seiner Kurzform thru erreichen. Dabei wird ein Plural-s an das auszuwählende Textelement angehängt. characters 2 through 4 of "Brimborium" ergibt "rim"? Nein! Tatsächlich erhalten Sie eine Liste mit den einzelnen Buchstaben, nämlich {"r", "i", "m"}! Dies ist ein häufiger Fehler am Anfang. Wenn Sie nach characters fragen, bekommen Sie characters, also eine Liste, wenn es mehrere sind, und nicht einen zusammenhängenden Text. Dementsprechend gilt auch: Wenn Sie nach Wörtern fragen, erhalten Sie eine Liste von Wörtern. Fragen Sie nach Absätzen, erhalten Sie eine Liste mit Absätzen. words 1 through 3 of "Berlin, Hamburg, München, Dresden, Stuttgart" ergibt eine Liste mit den ersten drei Städtenamen: {"Berlin", "Hamburg", "München"} Beachten Sie hier, dass die Kommas wegfallen. Sie gelten, zusammen mit dem Leerzeichen, als Worttrenner. Das würde auch Punkte und andere Satzzeichen betreffen. words 1 thru -1 of "13:45 Uhr, Montag, den 16.4.2008, 13.245,08 €" ergibt: {"13", "45", "Uhr", "Montag", "den", "16.4.2008", "13.245,08", "€"}
160
Die Sprache
Kapitel 4
Sie sehen hier, dass Punkt und Komma innerhalb von Zahlen (auch in Form eines Datums) nicht als Worttrenner gelten. Aufgepasst Achtung! Dies ist nicht von Ihren Landeseinstellungen abhängig. Bei Schweizer Landeseinstellung wird ein Hochkomma durchaus als Wortende interpretiert, eine Zahl mit einem Hochkomma wird also auseinandergerissen. Das ist etwas seltsam, weil man vermuten könnte, dass die implizite Erkennung von Text als Zahl auch eine Rolle bei Wörtern spielt. Bei der Auftrennung eines Textes mit Zahlen auf einzelne Wörter ist das Ergebnis daher unbedingt vorher zu prüfen. Manchmal ist es besser, mit text items zu arbeiten. Auch Bereiche funktionieren natürlich wieder mit negativem Index: words -1 through -3 of "Berlin, Hamburg, München, Dresden, Stuttgart" ergibt {"München", "Dresden", "Stuttgart"}. Auch ein gemischter Index ist möglich, wobei es egal ist, wenn sich beide Elemente überlappen. Der Index, der weiter vorne ist, bildet immer den Anfang. So ergibt paragraphs -4 thru 3 of "Berlin\rHamburg\rMünchen\rDresden\rStuttgart" {"Hamburg", "München"} als Ergebnis. Für das erste und letzte Element eines Textes können Sie statt der Indexzahl 1 oder -1 auch die Wörter beginning und end verwenden: word beginning through end of "Berlin, Hamburg, München" ergibt {"Berlin", "Hamburg", "München"} Wenn Sie nach dem text eines Textes fragen erhalten Sie übrigens den gesamten Text als Antwort, und diesmal wirklich als Text, nicht als Liste: set meinWort to "Hallo" text of meinWort Das Ergebnis ist "Hallo". Beachten Sie auch die detaillierte Beschreibung der Referenzen im Kapitel Listen, die Sie auch auf Text anwenden können. Ersetzen Sie dort nur den Begriff item gegen character, word, paragraph, text item oder text.
161
SmartBooks
AppleScript
some, middle und every im Text Wie bei den Listen können Sie auch auf Text mit some, middle und every zugreifen. Das funktioniert natürlich mit allen Textelementen. Ein paar Beispiele: some paragraph of "Würfeln\rAusetzen\rIns Gefängnis\rÜber Los" liefert hier bei jeder Ausführung einen zufälligen Absatz aus dem Text zurück. Das Ergebnis ist ein Text und keine Liste: middle word of "Links Rechts Mitte Oben Unten" -- Ergebnis: "Mitte" Hier ist zu beachten, dass bei einer geraden Anzahl von Elementen das Element links der Mitte ausgewählt wird. every character of "Holla" ergibt als Ergebnis {"H", "o", "l", "l", "a"}, also eine Liste. every wird daher gerne dafür verwendet, um einen Text in einzelne Elemente aufzuspalten, die dann als Liste bearbeitet werden.
text items und text item delimiters Ein Textelement wurde bisher ausgespart, und zwar die text items. Mit text items haben Sie die volle Kontrolle über den Text und können ganz nach eigenen Gesichtspunkten Teile darin auswählen. Was ist zum Beispiel, wenn Sie eine Tabelle mit kommagetrennten Werten in eine Variable eingelesen haben und diese nun in eine Liste aufspalten möchten, um die einzelnen Werte zu bearbeiten? Für solche Fälle sind die text items da. Wo ein text item anfängt und wo es aufhört, wird dabei durch die text item delimiters definiert, eine globale Eigenschaft von AppleScript. Grundlagen Apple bezeichnet viele der mitgelieferten Eigenschaften (properties) von AppleScript als »Constant«, obwohl sich deren Wert ändern lässt. Mit »konstant« ist in AppleScript eher die Tatsache gemeint, dass diese Eigenschaften »stets« in jedem Skript vorhanden sind. Die meisten sind keine unveränderlichen Konstanten, wie man sie aus anderen Skriptsprachen kennt.
162
Die Sprache
Kapitel 4
Wenn Sie einmal text item delimiters in den Skripteditor eingeben und ausführen, erhalten Sie als Ergebnis {""}. Dies ist der Standardwert der text item delimiters. Also ein leerer Text in einer Liste. Ein text item delimiter, der leer ist, teilt den Text immer in seine kleinste Einheit auf, also in einzelne Zeichen. every text item of "Meier, Hans" ergibt {"M", "e", "i", "e", "r", ",", " ", "H", "a", "n", "s"} Wenn Sie den Text an den Kommastellen aufschneiden wollen, müssen Sie daher den text item delimiters ein Komma zuweisen. set text item delimiters to "," text items of "Meier, Hans, Am Schlierweg 7, 80808, München" Nun erhalten Sie {"Meier", " Hans", " Am Schlierweg 7", " 80808", " München"} Das sieht schon ganz gut aus, aber vielleicht fällt Ihnen auf, dass das Leerzeichen nach dem Komma leider nicht berücksichtigt wird. Glücklicherweise kann text item delimiters auch aus mehreren Zeichen bestehen. Setzen Sie daher in diesem Beispiel die text item delimiters auf ", " (also mit einer Leerstelle nach dem Komma) und schauen Sie dann mal, wie das Ergebnis aussieht. set text item delimiters to ", " text items of "Meier, Hans, Am Schlierweg 7, 80808, München" ergibt: {"Meier", "Hans", "Am Schlierweg 7", "80808", "München"} Wunderbar! Nachname, Vorname und Adressbestandteile sind nun sauber getrennt und lassen sich damit perfekt weiterverarbeiten. Diese Auftrennung von Text ist zum Beispiel sehr hilfreich, wenn man Dateien im CSV-Format (comma separated value) verarbeiten will.
163
SmartBooks
AppleScript
Aufgepasst Veränderungen an den text item delimiters gelten übrigens so lange, wie der Skripteditor (oder das Skriptprogramm) läuft. Nach dem Beenden des Skripteditors werden sie wieder auf den Standardwert "" zurückgesetzt. Falls Sie mehrere Skripts geöffnet haben, gelten die eingestellten text item delimiters für alle geöffneten Skripts. Hier ist also Vorsicht geboten. Gehen Sie niemals davon aus, dass die text item delimiters wirklich den angenommenen Wert besitzen. Setzen Sie diese immer explizit vor Anwendung auf den gewünschten Wert und ersparen Sie sich damit unangenehme Überraschungen. Auch das Zurücksetzen der text item delimiters auf ihren Ursprungswert nach Verwendung ist zu empfehlen. Nun wird in der angenommenen Tabelle sicher nicht nur eine einzelne Adresse stehen, sondern mehrere, auf jeder Zeile eine. In folgendem Beispiel habe ich nach einem eingefügten Return (\r) noch einen zweiten Datensatz angehängt. set text item delimiters to ", " text items of "Meier, Hans, Am Schlierweg 7, 80808, München\rSchulz, Gertrud, Hofgarten 1, 20000, Hamburg" Das Ergebnis sieht so aus: {"Meier", "Hans", "Am Schlierweg 7", "80808", "München Schulz", "Gertrud", "Hofgarten 1", "20000", "Hamburg"} Das heißt, München und Schulz sind zu einem einzigen Text (mit Zeilenumbruch) zusammengewachsen. Beide sollen aber durch ein Komma getrennt werden. Mit anderen Worten: Ein Zeilenumbruch muss hier ebenfalls als text item delimiter gelten. Schön wäre es nun, wenn text item delimiters mehrere Werte in Form einer Liste aufnehmen könnten in der Form: set text item delimiters to {", ", return} Da text item delimiters ja eine Liste ist, sollte das auch funktionieren, und diese Zuweisung wird auch tatsächlich akzeptiert, doch leider wird nur der erste Wert der Liste verwendet! Die Verwendung mehrerer Werte ist zwar von Apple schon seit langem vorgesehen, aber leider immer noch nicht umgesetzt worden. Mit anderen Worten, Sie müssen hier in mehreren Schritten vorgehen. Zuerst muss das Return gegen ein Komma ersetzt werden:
164
Die Sprache
Kapitel 4
set text item delimiters to return set x to text items of "Meier, Hans, Am Schlierweg 7, 80808, München\rSchulz, Gertrud, Hofgarten 1, 20000, Hamburg" Ergebnis: {"Meier, Hans, Am Schlierweg 7, 80808, München", "Schulz, Gertrud, Hofgarten 1, 20000, Hamburg"} In der Variablen x steckt nun eine Liste mit zwei Datensätzen, die nun wieder in Text umgewandelt werden muss. Jetzt kommt das Interessante: Die text item delimiters bestimmen auch beim Zusammenbau von Text aus einer Liste, welche Trennzeichen im Text eingefügt werden! Man muss jetzt also nur die Delimiter auf ", " setzten und dann die Liste mit den zwei Datensätzen als Text zusammenbauen – und schon sind alle Werte auf die gleiche Art getrennt. Der Code als Ganzes sieht nun so aus: set text item delimiters to return set x to text items of "Meier, Hans, Am Schlierweg 7, 80808, München\rSchulz, Gertrud, Hofgarten 1, 20000, Hamburg" set text item delimiters to ", " set x to x as text -- Ergebnis: "Meier, Hans, Am Schlierweg 7, 80808, München, Schulz, Gertrud, Hofgarten 1, 20000, Hamburg" Ein durchgehender Text ohne Zeilenumbrüche, und alle Werte sind durch Komma und Leerstelle voneinander getrennt. Nun kann dieser Text sauber mit den text item delimiters wieder als Liste aufgespalten werden. Als text item delimiters muss vorher ", " angegeben werden, da dies nun das einheitliche Trennzeichen zwischen allen Wörtern darstellt. Alles in allem sieht der Code nun so aus: set text item delimiters to return set x to text items of "Meier, Hans, Am Schlierweg 7, 80808, München\rSchulz, Gertrud, Hofgarten 1, 20000, Hamburg" set text item delimiters to ", " set x to x as text 165
SmartBooks
AppleScript
set x to text items of x - - Ergebnis: {"Meier", "Hans", "Am Schlierweg 7", "80808", "München", "Schulz", "Gertrud", "Hofgarten 1", "20000", "Hamburg"} Endlich eine saubere Liste mit allen Werten. In einer Schleife kann diese Liste nun bequem abgearbeitet werden. Das mag sich zu Anfang etwas kompliziert anfühlen, ist in AppleScript aber der bequemste und vor allem schnellste Weg, Text an beliebigen Stellen aufzuspalten oder auch darin zu suchen und zu ersetzen. Wie Sie gesehen haben, bestimmen die text item delimiters nicht nur, an welchen Stellen der Text in eine Liste zerlegt wird, sondern auch, welches Zeichen zwischen zwei Textelementen eingefügt wird, wenn eine Liste in Text umgeformt wird.
Schnelles Suchen und Ersetzen mit text item delimiters Wie Sie im vorigen Kapitel gesehen haben, eigenen sich die text item delimiters hervorragend dazu, Texte in kleine Happen zu schneiden und auch wieder zusammenzufügen, auf Wunsch auch mit Trennzeichen. Es handelt sich dabei also auch um ein Suchen und Ersetzen, und tatsächlich sind die text item delimiters auch die schnellste Methode, in AppleScript ein Suchen und Ersetzen vorzunehmen. Hier derselbe Code noch einmal aus dem Gesichtspunkt des Suchens und Ersetzens und mit der Maßgabe, dass am Ende wieder ein Text und nicht eine Liste herauskommen soll: set suchText to "Hans" set ersetzText to "Konrad" set meinText to "Ja, das war der Hans, ganz sicher!" set text item delimiters to suchText set meinText to text items of meinText -- Ergebnis: {"Ja, das war der ", ", ganz sicher!"} set text item delimiters to ersetzText set meinText to meinText as text -- Ergebnis: "Ja, das war der Konrad, ganz sicher!" In den ersten drei Zeilen wird zuerst einmal der Suchtext, der Text, der diesen ersetzen soll, und der zu durchsuchende Text in eine Variable gepackt. Damit sehen die nachfolgenden vier Zeilen gleich übersichtlicher aus.
166
Die Sprache
Kapitel 4
Danach werden die text item delimiters auf den Suchtext gesetzt, und meinText wird in eine Liste umgewandelt. Als Resultat fehlt dort dann der Suchtext, da dieser ja als Texttrennzeichen gilt. meinText sieht damit an dieser Stelle so aus: {"Ja, das war der ", ", ganz sicher!"} Eine Liste mit zwei Elementen, genau am Wort »Hans« getrennt. Das Suchwort »Hans« selbst fehlt. Danach werden die text item delimiters auf ersetzText gesetzt und meinText, welches ja jetzt als Liste vorliegt, wieder in einen Text umgewandelt (set meinText to meinText as text). Bei der Umwandlung in Text wird zwischen den Listenelementen dabei der Text aus ersetzText eingefügt. Damit ist das Suchen und Ersetzen beendet, und der Text sieht nun so aus: "Ja, das war der Konrad, ganz sicher!" Verwenden Sie obige Routine für jegliches Suchen und Ersetzen im Text. Power User Wenn Sie in AppleScript nach Möglichkeiten suchen, Platzhalter (Wildcards wie ? oder *) oder sogar Reguläre Ausdrücke (Regular Expressions) zu verwenden, dann suchen Sie vergebens. AppleScript ist bewusst einfach gehalten. Aber natürlich gibt es für alles Erweiterungen. Der Befehl find text in der Scripting-Addition Satimage (wird bei der Installation von Smile mit installiert) beherrscht auch ausgeklügelte Reguläre Ausdrücke. Alternativ empfiehlt sich aber auch die Steuerung einer darauf spezialisierten Textverarbeitung wie zum Beispiel BBEdit oder sogar die Auslagerung dieses Codes in ein Perl-Skript, das vom Appleskript aufgerufen wird.
AppleScript's text item delimiters
Manchmal kann es in einem Skript erforderlich sein, anzugeben, um welche text item delimiters es sich handelt. Das kann zum Beispiel vorkommen, wenn Sie in Ihrem Skript gerade mit einem Programm reden. Das Programm, welches Sie gerade steuern, kennt vielleicht keine text item delimiters oder hat diese ebenfalls implementiert, aber in einer ganz anderen Weise. In beiden Fällen ist es nötig, im Skript anzugeben, wer sich um die text item delimiters kümmern soll. Falls Sie also eine Fehlermeldung oder falsche Ergebnisse erhalten, fügen Sie einfach AppleScript's oder my vor text item delimiters ein, und die Anweisung geht direkt an die laufende AppleScript-Instanz oder das Skript als Objekt. set AppleScript's text item delimiters to "," oder set my text item delimiters to "," 167
SmartBooks
AppleScript
Der Befehl count im Text Mit dem Befehl count lassen sich nicht nur Listenelemente, sondern auch Elemente in einem Text zählen. Ohne Angabe eines bestimmten Textelements wird die Anzahl der Zeichen (characters) im Text gezählt: count "Ich bin ein Berliner" -- Ergebnis: 20 count macht hier also dasselbe, was Sie auch mit der Eigenschaft length erreichen können: length of "Ich bin ein Berliner" -- Ergebnis: 20 Ein leerer Text ergibt eine 0: count "" -- Ergebnis: 0 Statt count können Sie auch das Pseudonym number of verwenden: number of "Ich bin ein Berliner" -- Ergebnis: 20 Die Besonderheit von count liegt jedoch darin, dass Sie damit auch gezielt bestimmte Elemente in einem Text zählen können: set mytext to "Ich bin ein Berliner" count every word of mytext -- Ergebnis: 4 Sie können every auch weglassen und stattdessen die Mehrzahl des Elementnamens nehmen: set mytext to "Ich bin ein Berliner" count words of mytext -- Ergebnis: 4 set mytext to "Ich bin ein Berliner" count paragraphs of mytext -- Ergebnis: 1 Sie können auch mit thru einen Bereich angeben: set mytext to "Ich bin ein Berliner" count characters 1 thru 5 of mytext -- Ergebnis: 5 Bei Angabe eines Bereiches lassen sich die Klassen mit from … to auch mischen, was auch sinnvoll ist, da durch die Angabe des Indexes wie im vorigen Beispiel ja sowieso schon bekannt ist, wie viele Zeichen gezählt werden: set mytext to "Ich bin ein Berliner" count characters from word 1 to word 2 of mytext -- Ergebnis: 7
168
Die Sprache
Kapitel 4
Umwandlung einer Liste in Text Wie Sie gesehen haben, wird bei der Abfrage von Textelementen über einen Bereich immer eine Liste zurückgeliefert. Wenn Sie aber Text als Ergebnis benötigen und keine Liste, dann fragen Sie explizit nach text: text from character 1 to 4 of "Brimborium" -- Ergebnis: "Brim" Beachten Sie, dass hier kein thru verwendet wird, sondern from … to. Sie können auch verschiedene Textklassen mischen. text from character 3 to word 2 of "Eins Zwei Drei" -- Ergebnis: "ns Zwei" Wenn es um die Rückgabe einzelner Zeichen (characters) geht, können Sie auch wie gewohnt thru schreiben und character weglassen. text 1 thru 4 of "EinsZweiDrei" -- Ergebnis "Eins" Alternativ können Sie auch eine Liste mit Textelementen mit dem as-Operator in Text verwandeln. characters 2 through 4 of "Brimborium" as text -- Ergebnis: "rim" Oder nachträglich nach Speicherung in einer Variablen: set x to characters 2 through 4 of "Brimborium" -- Ergebnis: {"r", "i", "m"} set x to x as text -- Ergebnis: "rim"
Umwandlung von Text in eine Liste Es gibt zwei Möglichkeiten, einen Text in eine Liste umzuwandeln. Erstens: Man verwendet eine Bereichsabfrage mit thru, und zwar vom ersten bis zum letzten Element, wenn der gesamte Text in eine Liste umgewandelt werden soll. Wichtig dabei ist die richtige Auswahl des Textelements, aus dem die Liste bestehen soll, also characters, words, paragraphs oder text items. words 1 through -1 of "Berlin, Hamburg, München" ergibt die Liste {"Berlin", "Hamburg", "München"}mit allen Wörtern von Anfang (1) bis Ende (-1) des Textes. Zweitens: Man verwendet, wie bereits beschrieben, every mit dem gleichen Ergebnis: every word of "Berlin, Hamburg, München" 169
SmartBooks
AppleScript
Beides führt zu demselben Ergebnis, wobei every meist dann verwendet wird, wenn alle entsprechenden Elemente des Textes in eine Liste umgewandelt werden müssen. Verwenden Sie thru, wenn Sie nur einen Teilbereich des Textes als Liste brauchen. Der Operator as funktioniert hier übrigens anders als erwartet! "Holla" as list ergibt {"Holla"}. Das ist zwar eine Liste, aber sie besteht nur aus einem Element. Text wird also mit as list nicht in kleinere Elemente aufgespalten.
Implizite Umwandlung von Text in Zahlen Wenn Sie in einem Text eine Zahl haben und damit einfach rechnen, ohne den Text vorher explizit umgewandelt zu haben – was Sie normalerweise unbedingt tun sollten –, so versucht AppleScript, den Text bei einer Rechenanweisung automatisch als Zahl zu interpretieren. Für diese Interpretation werden dabei die Formateinstellungen in den Systemeinstellungen berücksichtigt. Das heißt, die Zahl im Text muss bei einer deutschen Formateinstellung ein Komma als Dezimaltrenner verwenden und den Punkt als Tausendertrenner, entsprechend in der Schweiz den Punkt als Dezimalzeichen und das Hochkomma als Tausendertrenner. "3,0" * 2.1 ergibt auf einem bundesdeutschen Betriebssystem 6.3. Die "3,0" wird korrekt als Dezimalzahl erkannt. Haben Sie jedoch einen Punkt als Dezimaltrenner im Text stehen, wird dieser auf einem bundesdeutschen System als Tausendertrenner interpretiert, und Sie erhalten zu große Werte: "3.0" * 2.1 Das Ergebnis ist dann 63, da die "3.0" als 30 gelesen wird. Der Punkt wird als Taussendertrenner erkannt. Wenn Sie mit dieser impliziten Umwandlung arbeiten, sollten Sie auf jeden Fall sicherstellen, dass falsche Dezimalzeichen früh genug erkannt werden. Aufgepasst Wenn Sie sich auf diese Umwandlung verlassen, binden Sie Ihr Skript vollständig an eine bestimmte Sprache im Betriebssystem, und es wird zum Beispiel auf einem englischen System mit dort als Text eingelesenen Zahlen nicht funktionieren!
170
Die Sprache
Kapitel 4
Power User Lösungen: Am einfachsten ist es, vom Benutzer Dezimal- und Tausendertrenner abzufragen, da die Landeseinstellungen bisher nur über GUI-Scripting zugänglich sind. Alternativ können Sie aber auch die Landeseinstellung des Betriebssystems als Ganzes mit der folgenden Zeile abfragen (aus den Standard-Erweiterungen): user locale of (get system info) Sie erhalten dann zum Beispiel bei einem bundesdeutschen System "de_DE" als Antwort, bei einem Schweizer System aber "de_CH". Darauf basierend können Sie dann im Skript entsprechend unterschiedliche Routinen starten.
Explizite Umwandlung von Text in Zahlen Sie können auch mit dem as-Operator aus einem Text eine Zahl machen, wenn denn der Text eine Zahl enthält. Sie haben dabei die Möglichkeiten as real, as integer und as number. as real verwandelt den Text in eine Dezimalzahl. set einText to "3" set meineZahl to einText as real -- Ergebnis: 3.0 as integer verwandelt den Text in eine Ganzzahl. set einText to "3,0" set meineZahl to einText as integer -- Ergebnis: 3 Auch hier ist zu beachten, dass der im Betriebsystem eingestellte Dezimaltrenner zur Erkennung des Kommas herangezogen wird (Systemeinstellungen | Landeseinstellungen | Formate)! Würden Sie für einText "3.0" einsetzen, so würde der Punkt nicht als Dezimalzeichen erkannt, sondern bei bundesdeutscher Einstellung als Tausendertrenner, und 30 wäre das Ergebnis! Aufgepasst Bei der Umwandlung von einer Dezimalzahl in eine Ganzzahl wird auf- oder abgerundet, und zwar nach der Methode round to nearest. Damit verhält sich die Rundung anders, als wir es im alltäglichen Gebrauch gewohnt sind! (Siehe hierzu das Kapitel Der Befehl round.) Hier kann es daher unter Umständen empfehlenswert sein, den Text zuerst mit as real oder as number in eine Zahl umzuwandeln und dann die Rundung manuell mit einem anderen round-Befehl vorzunehmen.
171
SmartBooks
AppleScript
Verwenden Sie as number, wenn der Wert so übernommen werden soll, wie er im Text steht, also mit Dezimalkomma, wenn eines vorhanden ist, ansonsten ohne. Die Klasse number ist ein Synonym für integer und real, kann also verwendet werden, wenn die Unterscheidung zwischen beiden keine Rolle spielt und es nur darum geht, dass der Inhalt eine Zahl ist. set set set set
einText to "3" meineZahl to einText as number -- Ergebnis: 3 einText to "3,2" meineZahl to einText as number -- Ergebnis: 3.2
Die Umwandlung von Text in eine Zahl mit as funktioniert natürlich nur, wenn wirklich nur Zahlen und die im Betriebssystem eingestellten Tausendertrenner oder Dezimaltrennzeichen vorkommen. Bei allen anderen Zeichen wird es eine Fehlermeldung geben, aber erst bei Ausführung des Skripts. Achten Sie daher darauf, dass wirklich nur erwünschte Zeichen im Text vorhanden sind.
Records Mit den Records komme ich zur letzten der drei großen grundlegenden Klassen in AppleScript (list, text und record), welche die Fähigkeit haben, mehrere Elemente zu enthalten. »Record« kann man mit »Datensatz« übersetzen. Da der größte Teil der Literatur über AppleScript jedoch in Englisch vorliegt, bleibt dieser Begriff meist auch in deutschen Texten unübersetzt, so auch in diesem Buch. Der Unterschied von einem Record zu einer Liste liegt darin, dass in einem Record jedes Element einen Namen trägt. Des Weiteren sind Records ungeordnet. Das heißt, die Anordnung der Elemente spielt bei einem Record also keinerlei Rolle. Sie sind daher auch nicht über einen Index ansprechbar.
Record-Literale Ein Record wird als Literal wie eine Liste in geschweifte Klammern geschrieben. Jedes Element ist darin aber in zwei Hälften aufgeteilt, den Namen des Elements und dessen Inhalt. Beide Teile werden mit einem Doppelpunkt voneinander getrennt. Mehrere Elemente werden mit einem Komma voneinander getrennt. Konkret sieht das so aus: {vorname: "Gustav", nachname: "Müller"}
172
Die Sprache
Kapitel 4
Der obige Record enthält zwei Elemente mit den Namen »vorname« und »nachname« und den Werten "Gustav" und "Müller". Ein Element eines Records bezeichnet man dabei als »Property«, also als »Eigenschaft des Records«. Ich verwende in diesem Buch mal das deutsche Wort »Eigenschaft«, mal den englischen Begriff property, nicht um Sie zu verwirren, sondern damit Ihnen beide Begriffe vertraut werden. Es ist wichtig, dass Sie sich immer im Klaren darüber sind, dass Propertys nichts anderes sind als die Eigenschaften eines Objekts (einer Klasse). Hier sind es die Eigenschaften eines Record-Objekts, aber auch andere Objekte haben Eigenschaften, wie die zuvor beschriebenen Eigenschaften der Klassen list und text. Records sind jedoch zusammen mit script-Objekten die einzigen Objekte, bei denen Sie Eigenschaften selbst definieren können! Man könnte also auch sagen: Der obige Record hat zwei Eigenschaften, einmal die Eigenschaft Vornamen und einmal die Eigenschaft Nachnamen, womit noch nichts darüber gesagt ist, welcher Vor- und welcher Nachname es denn nun ist. Der eigentliche Vorname und Nachname steht hinter dem Doppelpunkt, natürlich in Anführungszeichen, wenn es sich um Text handelt. Was hinter dem Doppelpunkt steht, ist der Inhalt oder Wert der Property. Die Namen selbst, also »vorname« und »nachname«, werden ohne Anführungszeichen geschrieben! Der Name muss dabei immer mit einem Buchstaben oder Unterstrich beginnen und darf danach nur Buchstaben, Zahlen und den Unterstrich enthalten. Sonderzeichen wie unsere Umlaute ä, ö, ü oder das ß sind verboten. Es gelten hier dieselben Bestimmungen wie beim Benennen von Variablen! Außerdem dürfen Namen innerhalb eines Records nicht doppelt vorkommen. Der Skripteditor wehrt sich aber ohnehin erfolgreich gegen die doppelte Eingabe eines Namens in einem Record, indem er den doppelten Eintrag nach dem Kompilieren einfach wieder löscht. Während der Name eines Elements in einem Record also strengen Regeln unterliegt, gilt diese Regel nicht für deren Wert. Was nach dem Doppelpunkt folgt, kann alles Mögliche sein, Zahlen, Text, Listen, weitere Records oder auch alle möglichen anderen Objekte, denen Sie im Laufe des Buches noch begegnen werden. In folgendem Beispiel enthält der Record zum Beispiel zwei Propertys mit jeweils einer Liste als Wert: {yKoordinate: {1, 2, 3, 4}, xKoordinate: {"A", "B", "C", "D"}} Auch die Schachtelung eines Records in einem anderen ist möglich: {band1:{titel:"ABC", isbn:123}, band2:{titel:"XYZ", isbn:124}} 173
SmartBooks
AppleScript
Einen Record zusammenbauen Normalerweise werden Sie einen Record über eine Zuweisungsoperation mit set mit Variablen füllen: Hier wird zum Beispiel ein Record aus zwei Listen erzeugt: set yKoord to {1, 2, 3, 4} set xKoord to {"A", "B", "C", "D"} set koordRecord to {yKoordinaten:yKoord, xKoordinaten:xKoord} -- Ergebnis: {yKoordinate:{1, 2, 3, 4}, xKoordinate:{"A", "B", "C", "D"}} Nur der Name der einzelnen Eigenschaften im Record kann nicht aus Variablen bestehen und muss von Ihnen vorgegeben werden! Sie können als Wert für eine Property auch einen Ausdruck verwenden: set mwst to 0.19 set betrag to 1500 set myRecord to {ust:mwst, netto:betrag, brutto:betrag + (betrag * mwst)} -- Ergebnis: {ust:0.19, netto:1500, brutto:1785.0} Hier wird also die Property brutto aus betrag + (betrag * mwst) errechnet. Sie können auch einen Record mit Records füllen: set a to {vorname:"Gustav", nachname:"Müller"} set b to {vorname:"Hans", nachname:"Schulz"} set d to {rec1:a, rec2:b} -- Ergebnis: {rec1:{vorname:"Gustav", nachname:"Müller"}, rec2:{vorname:"Hans", nachname:"Schulz"}}
Hinzufügen und Entfernen von Werten In Records können nachträglich keine Eigenschaften hinzugefügt werden! Verschiedene Records lassen sich jedoch mit dem &-Operator verbinden. set nameRecord to {vorname:"Gustav", nachname:"Müller"} set ortRecord to {plz:"50333", ort:"Bonn"} set newRecord to nameRecord & ortRecord -- Ergebnis: {vorname:"Gustav", nachname:"Müller", plz:"50333", ort:"Bonn"} Aus den zwei Records wurde hier ein neuer dritter Record zusammengesetzt.
174
Die Sprache
Kapitel 4
Ansonsten ist die Liste von Eigenschaften in einem Record nachträglich nicht veränderbar. Dies sollte daher schon bei der Anlage eines Records bedacht werden. Sind Bezeichner in den zu verbindenden Records identisch, so wird der Wert der ersten Property dieses Namens verwendet: set meinRecord to {vorname:"Gustav", nachname:"Müller"} set nochnRecord to {ort:"Bonn", nachname:"Schmitz"} set newRecord to meinRecord & nochnRecord -- Ergebnis: {vorname:"Gustav", nachname:"Müller", ort:"Bonn"} Der Wert "Schmitz" wird hier also ignoriert. Propertys aus einem Record wieder zu entfernen, ist nicht möglich. Wie auch bei Listen und Text, so können Sie nur einen neuen Record mit dem Inhalt des alten zusammenbauen, jedoch ohne die unerwünschten Propertys. Hier ein Beispiel: set alterRecord to {vorname:"Gustav", nachname:"Müller", plz:"50333"} set neuerRecord to {vorname:"", nachname:""} set vorname of neuerRecord to vorname of alterRecord set nachname of neuerRecord to nachname of alterRecord neuerRecord -- Ergebnis: {vorname:"Gustav", nachname:"Müller"}
Zusammenbau über Massenzuweisung Records lassen sich auch über eine Massenzuweisung mit Listen auf beiden Seiten füllen, wobei die Liste auch Variablen enthalten kann, wie in folgendem Beispiel: set {a, b, c} to {"Grün", "Rot", "Gelb"} set myRecord to {links:"", rechts:"", oben:""} set {links of myRecord, rechts of myRecord, oben of myRecord} to {a, b, c} myRecord -- Ergebnis: {links:"Grün", rechts:"Rot", oben:"Gelb"} Die Werte aus der Liste der Variablen rechts werden entsprechend ihrer Reihenfolge den Propertys in der Liste links zugewiesen. Die Liste mit den zuzuweisenden Werten darf dabei nicht kürzer sein als die Anzahl der Propertys in der Liste links, ansonsten erhalten Sie eine Fehlermeldung. Umgekehrt gibt es keine Fehlermeldung. Die überschüssigen Werte werden einfach ignoriert. Die hier verwendete Referenzform links of myRecord wird im Folgenden erklärt.
175
SmartBooks
AppleScript
Referenzformen in einem Record Einen Wert aus einem Record abzufragen, ist denkbar einfach. Es gibt hier nicht die Möglichkeit, wie bei den Listen mit einem Index zu arbeiten. Records sind ungeordnet. Die Position eines Elements im Record ist also nicht garantiert. Daraus ergibt sich auch, dass es nicht möglich ist, einen Bereich abzufragen. Die einzige Möglichkeit, einen Wert aus einem Record abzufragen, ist daher über seinen Namen gegeben: vorname of {vorname: "Gustav", nachname: "Müller"} -- Ergebnis: "Gustav" Haben Sie die Propertys geschachtelt, wie hier in einer Liste, müssen Sie die Hierarchie mit mehreren of widerspiegeln: set a to {vorname:"Gustav", nachname:"Müller"} set b to {vorname:"Hans", nachname:"Schulz"} set c to {rec1:a, rec2:b} -- Ergebnis: {rec1:{vorname:"Gustav", nachname:"Müller"}, rec2:{vorname:"Hans", nachname:"Schulz"}} nachname of rec2 of c -- Ergebnis "Schulz" Enthält die Property eine Liste als Wert, so müssen Sie die Abfrage ebenfalls mit mehreren of schachteln. Auf die Liste müssen Sie dabei mit den Referenzformen der Liste, also zum Beispiel mit Index, zugreifen, auf die Property über deren Namen: set yK to {1, 2, 3, 4} set xK to {"A", "B", "C", "D"} set koordRecord to {yKoordinate:yK, xKoordinate:xK} --Ergebnis: {yKoordinate:{1, 2, 3, 4}, xKoordinate:{"A", "B", "C", "D"}} item 2 of xKoordinate of koordRecord -- Ergebnis: "B"
Auswahl mit some und every Die Abfrage über einen Index ist bei einem Record zwar nicht möglich, andere Referenzformen funktionieren aber durchaus. Wenn Sie eine beliebige Eigenschaft aus dem Record abfragen möchten, so verwenden Sie some in Verbindung mit item: some item of {links: "Grün", rechts: "Rot", oben: "Gelb", unten: "Blau"} Diese Zeile liefert bei jeder Ausführung einen anderen Wert aus dem Record zurück, zum Beispiel "Gelb". Eine Abfrage mit der Referenzform middle ist bei Records übrigens nicht möglich, da middle einen Index und damit eine geordnete Struktur voraussetzt.
176
Die Sprache
Kapitel 4
Eine Abfrage mit every ist allerdings möglich: every item of {links: "Grün", rechts: "Rot", oben: "Gelb", unten: "Blau"} -- Ergebnis: {"Grün", "Rot", "Gelb", "Blau"} Sie erhalten dabei eine Liste mit allen Werten des Records. Dies ist dann auch eine der Möglichkeiten, einen Record in eine Liste umzuwandeln.
Auswahl über die Klasse Auch bei Records können Sie einen Klassennamen angeben, um Werte einer Klasse abzufragen. Da es in einem Record keinen Index gibt, geht das natürlich nur mit den Referenzformen some oder every: some integer of {a:3.124, b:1, c:3, d:5.4} liefert entweder die 1 oder die 3 zurück. Statt der Klasse text müssen Sie jedoch wieder das Synonym string verwenden: some string of {a:3.124, b:{"OK"}, c:"Vorwärts", d:"Pause"} Hier wird entweder "Vorwärts" oder "Pause" als Ergebnis zurückgeliefert. Wenn Sie alle Wert einer bestimmten Klasse aus einem Record herausholen wollen, so verwenden Sie every. Als Ergebnis erhalten Sie dabei immer eine Liste, auch wenn es sich nur um einen Wert handelt. every integer of {a:3.124, b:1.5, c:3, d:5.4} -- Ergebnis: {3} oder every real of {a:3.124, b:1.5, c:3, d:5.4} -- Ergebnis: {3.124, 1.5, 5.4}
Umwandlung eines Records Wie eben beschrieben, führt die Referenz mit every auf alle Elemente eines Records zur Umwandlung in eine Liste. Alternativ können Sie einen Record auch explizit mit dem as-Operator in eine Liste umwandeln: {links:"Grün", rechts:"Rot", oben:"Gelb", unten:"Blau"} as list -- Ergebnis: {"Grün", "Rot", "Gelb", "Blau"}
177
SmartBooks
AppleScript
Dies ist auch die einzige Umwandlungsform, die Records als Ganzes durchmachen können. Ein Record kann also nicht als Ganzes in Text oder in irgendeine andere Klasse umgewandelt werden. Zur Umwandlung in Text müssen Sie daher den Umweg über eine Liste gehen: {links:"Grün", rechts:"Rot", oben:"Gelb", unten:"Blau"} as list as text -- Ergebnis: {"GrünRotGelbBlau"} Einzelne Werte eines Records behalten bei der Abfrage über deren Namen natürlich ihre Originalklasse bei, können aber schon bei der Abfrage in einen anderen Typ umgewandelt werden: links of {links:3.6, rechts:2.1, oben:4, unten:3.7} as integer -- Ergebnis 4 Ansonsten können Sie noch wie vorhin beschrieben mit every alle Werte einer bestimmten Klasse als Liste extrahieren.
Eigenschaften eines Records Records besitzen nur zwei Klasseneigenschaften, nämlich class und length. Beide verhalten sich genauso wie auch die Propertys gleichen Namens bei den Klassen text und list. Verwechseln Sie dabei nicht die Propertys der Klasse record an sich mit den Propertys, die Sie in Ihrem Record selbst angelegten haben. Wenn Sie einen Record nach seiner Klasse fragen, erhalten Sie zur Antwort record: class of {Vorname: "Gustav", Nachname: "Müller"} -- Ergebnis: record Beachten Sie dabei, dass Sie das Wort class nicht als Bezeichner einer Property in einem Record verwenden sollten, denn dann würde die class-Property eines Records überschrieben. Sie würden dann also den Wert von class aus dem Record erhalten und nicht von der Klasse: set meinRecord to {class: "1a", produkt: "Kühlschrank"} class of meinRecord -- Ergebnis: 1a Mit anderen Worten, Sie können dann nicht mehr ermitteln, von welcher Klasse die Variable ist. Tipp Dass Sie eine bereits bestehende Eigenschaft einer Klasse überschreiben, können Sie übrigens auch sofort an der Syntaxfärbung im Skripteditor erkennen. Variablen und Bezeichner von Propertys werden normalerweise grün geschrieben, aber class wird im obigen Beispiel blau dargestellt, weil es ein Schlüsselwort der Sprache ist.
178
Die Sprache
Kapitel 4
Wenn Sie ermitteln wollen, wie viele Elemente ein Record enthält, sollten Sie, wie auch bei Listen und Text, die Eigenschaft Länge verwenden. Jeder Record besitzt sie, und sie kann mit length of abgefragt werden: length of {Vorname: "Gustav", Nachname: "Müller"} -- Ergebnis: 2 Gezählt wird also die Anzahl an Name/Inhalt-Paaren, den Elementen eines Records. Auch hier müssen Sie wieder darauf achten, in einem Record nicht length als Bezeichner einer Property zu verwenden, da Sie sonst die Eigenschaft length der record-Klasse an sich überschreiben und die Länge des Records nicht mehr ermitteln können: set meinRecord to {length:29.7, DinFormat:"A4"} length of meinRecord -- Ergebnis: 29.7 Für meinRecord ist es nun nicht mehr möglich, die Anzahl der Elemente mit length zu ermitteln (wohl aber noch mit dem Befehl count). Auch hier gibt Ihnen die Färbung von length den entscheidenden Hinweis. Eine blaue Färbung weist bei unveränderten Standardeinstellungen der Syntaxfärbung im Skripteditor auf Schlüsselwörter der Sprache hin. Ändern Sie dann den Namen, bis er nach dem Übersetzen grün dargestellt wird. set meinRecord to {paperLength:29.7, DinFormat:"A4"} length of meinRecord -- Ergebnis: 2
Missing value Wenn Sie gleich die Propertys eines Objekts abfragen, wird Ihnen vielleicht bei manchen Propertys der Wert missing value auffallen. Missing value ist eine unveränderbare (diesmal wirklich!) Konstante von AppleScript. Sie dient als Platzhalter für fehlende Werte und kann auch von Ihnen bewusst eingesetzt werden. Wenn Sie zum Beispiel eine Variable brauchen, deren Wert aber zum jetzigen Zeitpunkt noch nicht bestimmen können, so könnten Sie der Variablen auf der einen Seite zum Beispiel den Wert "" für einen leeren Text oder 0 (null) zuweisen. set x to "" set y to 0 Damit wäre die Variable aber nicht wirklich leer, da sie im ersten Fall Text enthält (wenn auch einen leeren Text) und im zweiten eine Zahl (auch wenn es eine Null ist).
179
SmartBooks
AppleScript
Wenn Sie mit class of die Klasse dieser beiden Variablen abfragen, erhalten Sie aber text und integer als Antwort. Das kann in dem einen oder anderen Fall stören. Stattdessen können Sie auch einfach missing value verwenden. set x to missing value -- Ergebnis: missing value Damit ist die Variable fertig deklariert, ohne bereits eine der Werteklassen als Klasse zu haben. Wenn Sie jetzt nach class of x fragen, erhalten Sie als Antwort class. Variablen mit dieser Klasse haben noch keinen Wert zugewiesen bekommen. Wenn Sie im Ergebnisbereich des Skripteditors nachsehen, werden Sie dort auch missing value als Ergebnis der Variablen sehen. Sie können also vor einer Operation an einer Variablen deren Klasse oder Inhalt abfragen und so sichergehen, dass diese nicht leer ist.
Der Befehl count in Records Wenn Sie den Befehl count auf einen Record anwenden, um die Anzahl seiner Propertys zu ermitteln, erhalten Sie als Antwort die Anzahl der Namen/Inhalt-Paare. count {vorname:"Gustav", nachname:"Müller", plz:"50333"} -- Ergebnis: 3 count verhält sich damit exakt genauso wie die Eigenschaft length eines Records: length of {vorname:"Gustav", nachname:"Müller", plz:"50333"} -- Ergebnis: 3 Beides kann verwendet werden.
Eigenschaften von Objekten Die Abfrage von Propertys spielt in AppleScript bei der Steuerung von anderen Anwendungen eine sehr wichtige Rolle. Ein Grossteil der Steuerung von Programmen besteht nämlich darin, Eigenschaften von Objekten dieses Programms zu ändern. Jedes Objekt besitzt in AppleScript Eigenschaften. Ein Objekt einer Anwendung, (ein Dokument, ein Zeichnungsobjekt, eine E-Mail, ein Rechenblatt, ein Absatz …) besitzt normalerweise (also nicht immer!) auch eine Eigenschaft namens properties, mit der sich alle Eigenschaften dieses Objekts ermitteln lassen. Diese Eigenschaften werden dann in Form eines Records zurückgeliefert, welcher sich hervorragend dazu eignet, mehr über das
180
Die Sprache
Kapitel 4
Objekt herauszufinden. Eigenschaften dieses Objekts können dann, wie bei einem Record, einfach durch Zuweisung eines anderen Wertes geändert werden. Dazu gleich mehr. Hier ein Beispiel aus dem Finder: Legen Sie sich vorher bitte einen neuen Ordner mit dem Namen »Neuer Ordner« auf dem Schreibtisch an. (Tastenkombination [Befehl]+[Umschalt]+[N]) tell application "Finder" set x to folder "Neuer Ordner" of desktop properties of x end tell Hier wird mit properties of die Eigenschaft mit dem Namen properties des Ordners "Neuer Ordner" auf dem Schreibtisch abgefragt. (Der Bedeutung von tell wird später noch im Detail nachgegangen.) Falls ein Objekt die Eigenschaft properties nicht besitzt, heißt das nicht unbedingt, dass dieses Objekt keine Eigenschaften hat. Sie müssen diese dann nur extra im Funktionsverzeichnis der Anwendung nachsehen. In der ersten Zeile wird hier erst einmal angegeben, welches Programm den folgenden Befehl empfangen soll. Hier ist es der Finder. In der nächsten Zeile wird der Variablen x ein Objekt zugeordnet. In diesem Fall ein Ordner (folder). Sie sehen hier zum ersten Mal, dass eine Variable nicht nur Zahlen und Text enthalten kann, sondern auch Objekte eines Programms. Wenn Sie die Zeile properties of x einmal auskommentieren und das Skript erneut ausführen, können Sie den Wert von x im Ergebnisbereich des Skripteditors nachsehen: --Ergebnis: folder "Neuer Ordner" of folder "Desktop" of folder "Detlef" of folder "Users" of startup disk of application "Finder" In der Variablen x ist hier also genau angegeben, welches Objekt gemeint ist. Sie können daran auch die sogenannte Objekthierarchie dieses Ordners erkennen. Ganz zuletzt steht die Angabe, welches Programm für den Ordner zuständig ist, der Finder. Wenn Sie den Kommentar wieder wegnehmen und das Skript ausführen, zeigt Ihnen der Skripteditor im Ergebnisbereich die Eigenschaften des Ordners Neuer Ordner auf dem Schreibtisch an. Da es sich um einen ganz normalen Ordner handelt, können Sie davon ausgehen, dass jeder Ordner diese Eigenschaften besitzen wird.
181
SmartBooks
AppleScript
Dass das Ergebnis ein Record ist, erkennen Sie sofort an den geschweiften Klammern und den Doppelpunkten, mit denen Bezeichner und Inhalt voneinander getrennt sind. Power User Merken Sie sich diese Abfrage der Eigenschaft eines Objekts sehr gut! Sie kann Ihnen dort weiterhelfen, wo sich das Funktionsverzeichnis ausschweigt. Packen Sie das Objekt in eine Variable (set x to object) und fragen Sie dann nach dessen Eigenschaften (properties of x). Ich habe das Ergebnis der obigen Abfrage auf meinem Rechner hier zur Ansicht eingefügt und dabei auf eine Eigenschaft pro Zeile aufgeteilt. Damit können Sie, auch wenn Sie gerade nicht vor Ihrem Rechner sitzen, dem restlichen Verlauf in diesem Kapitel leichter folgen. {class:folder, name:"Neuer Ordner", index:31, displayed name:"Neuer Ordner", name extension:"", extension hidden:false, container:folder "Desktop" of folder "Detlef" of folder "Users" of startup disk of application "Finder", disk:startup disk of application "Finder", position:{-1, -1}, desktop position:{1012, 216}, bounds:{-33, -33, 31, 31}, kind:"Ordner", label index:0, locked:false, description:missing value, comment:"", size:0, physical size:147456, creation date:date "Donnerstag, 24. April 2008 12:28:07 Uhr", modification date:date "Donnerstag, 24. April 2008 12:30:48 Uhr", icon:missing value, URL:"file://localhost/Users/Detlef/Desktop/Neuer%20Ordner/", owner:"Detlef", group:"staff", owner privileges:read write, group privileges:read only, everyones privileges:read only, container window:container window of folder "Neuer Ordner" of folder "Desktop" of folder "Detlef" of folder "Users" of startup disk of application "Finder"} 182
Die Sprache
Kapitel 4
So ein Ordner hat offensichtlich eine ganze Menge Eigenschaften. Das Besondere daran ist jetzt, dass sich viele dieser Eigenschaften auch ändern lassen. Wenn Sie genau wissen wollen, welche Propertys sich ändern lassen, schauen Sie bitte in das Funktionsverzeichnis des Finders. Im Bibliotheksfenster unter Fenster | Bibliothek den Finder doppelklicken (oder Ablage | Funktionsverzeichnis öffnen wählen und dann in der Liste der Programme den Finder doppelklicken). Wählen Sie dann in der Übersicht Containers and folders | folder aus. Unter Properties inherited from container und Properties inherited from item sehen Sie alle Eigenschaften aufgelistet, die ein Ordner haben kann.
Abb. 4-6 Das Funktionsverzeichnis des Finders mit den Eigenschaften eines Ordners Hinter dem fett geschriebenen Namen der Property finden Sie in Klammern noch den Hinweis, welchen Typ (Klasse) diese Property hat und ob sie eventuell nur read-only ist (r/o, also schreibgeschützt). Befindet sich solch ein r/o in der Klammer, kann diese Eigenschaft zwar gelesen, aber nicht verändert werden.
183
SmartBooks
AppleScript
Tipp Trotzdem kann es sich manchmal lohnen, zu versuchen, ob sich eine r/o-Property nicht doch verändern lässt. Man muss den Angaben in einem Funktionsverzeichnis nicht immer blind vertrauen. Aber Vorsicht, das sollten Sie natürlich nur mit Eigenschaften machen, die keinen potentiellen Schaden anrichten können. Viele Propertys sind natürlich aus gutem Grund schreibgeschützt!
Ändern einer Eigenschaft eines Objekts Da ein Objekt bei der Abfrage seiner Propertys einen Record zurückliefert, ist es naheliegend, zu vermuten, dass sich diese Eigenschaften wie bei einem Record ändern lassen. Und damit liegen Sie genau richtig. Wenn Sie die Propertys eines Ordners abfragen, dann werden Sie in dem zurückgelieferten Record schon meist am Namen der Eigenschaften erkennen, wofür diese wahrscheinlich gedacht sind. Trotzdem sollten Sie natürlich besser auf Nummer Sicher gehen und vorher noch im Funktionsverzeichnis die Beschreibung zu diesen Eigenschaften nachlesen. Dort steht dann auch, welche Werte diese Eigenschaft erwartet (integer, text ...). Ein bisschen Englischkenntnisse vorausgesetzt, ist man damit dann schnell in der Lage, die Eigenschaften des Objekts zu verändern und damit erste sichtbare Auswirkungen und Erfolgserlebnisse zu haben. Hier ein paar Beispiele: tell application "Finder" set x to folder "Neuer Ordner" of desktop set label index of x to 2 end tell Hier bekommt der Ordner ein Etikett (label index). Das Etikett wird dabei durch eine Integer-Zahl bestimmt. Die Werte reichen von 0 bis 7, wobei die 0 das Etikett Kein Etikett darstellt. Geben Sie eine größere oder kleinere Zahl ein, so erhalten Sie eine Fehlermeldung. Im Funktionsverzeichnis steht folgende kurze Beschreibung zu label index: »label index (integer) : the label of the item« Besonders ausführlich ist das nicht, aber wenigsten steht in der Klammer, welche Werte erwartet werden, nämlich Ganzzahlen (integer), und da hier von Index die Rede ist, sind die Etiketten im Finder wahrscheinlich einfach nur von links nach rechts durchgezählt wor-
184
Die Sprache
Kapitel 4
den, wenn man sich die Etiketten im Kontextmenü des Ordners einmal ansieht. Probieren Sie es aus, und Sie werden sehen, dass diese Vermutung zutrifft. Sie sehen, die Beschreibung im Funktionsverzeichnis lässt noch genug Spielraum für Fragen. Aus diesem Grund ist es so wichtig, dass Sie bei Zweifeln zur Selbsthilfe greifen können und einfach die Eigenschaften eines Ordners mit einem bestimmten Etikett abfragen, und schon können Sie sehen welcher Wert dieser Ordner bei label index hat. Ein Teil der Arbeit mit AppleScript besteht also auch immer wieder darin sich offene Fragen durch kurze Tests selber beantworten zu können! tell application "Finder" set x to folder "Neuer Ordner" of desktop set comment of x to "Dies ist ein Testordner" end tell Nach Ausführung dieses Skripts erhält der Ordner den Spotlight-Kommentar »Dies ist ein Testordner«, also einen Text. Um ihn zu sehen, müssen Sie den Ordner einmal anklicken und dann mit [Befehl]+[I] die Information aufrufen. Im Bereich Spotlight-Kommentar steht nun der Text, der, wie der Name auch schon andeutet, auch bei der Suche mit Spotlight berücksichtigt wird. Wenn Sie jetzt mit Spotlight nach »Testordner« suchen, wird dieser Ordner auch gleich gefunden. Zu comment steht im Funktionsverzeichnis: »comment (text): the comment of the item, displayed in the “Get Info” window« Das ist ziemlich klar beschrieben, und es wird text als Wert erwartet. tell application "Finder" set x to folder "Neuer Ordner" of desktop set desktop position of x to {50, 50} end tell Hier wird die Property desktop position verändert, und zwar durch die Angabe einer Liste. Die Liste muss zwei Zahlen enthalten. Die erste Zahl stellt die Position der x-Achse (horizontal) dar, die zweite die Position auf der y-Achse (vertikal). Der Nullpunkt des Bildschirms befindet sich dabei links oben in der Ecke des Bildschirms. Verändern Sie ruhig einmal die Werte in der Liste, um zu sehen, wie Sie damit den Ordner auf dem Schreibtisch wandern lassen können. Zu desktop position steht im Funktionsverzeichnis: »desktop position (point): the position of the item on the desktop«
185
SmartBooks
AppleScript
Die Beschreibung ist klar. Nur eine Klasse point werden Sie wahrscheinlich vergeblich suchen. Es scheint sich um eine undokumentierte Klasse zu handeln. (Ein weiteres Beispiel dafür, dass Funktionsverzeichnisse oft einiges zu wünschen übrig lassen.) Wenn Sie die Propertys eines Ordners abfragen oder wenn Sie in den abgedruckten Propertys auf den vorigen Seiten nachsehen, steht dort bei desktop position eine Liste mit zwei Ganzzahlen. Das scheint also die Art von Wert zu sein, die diese Property erwartet. Wenn Sie ein wenig mit verschiedenen Werten herumspielen, werden Sie schnell feststellen, dass die beiden Werte die Position auf der x- und y-Achse bestimmen und dass der Nullpunkt links oben sein muss. Tipp Das Funktionsverzeichnis wirft in vielen Fällen also weitere Fragen auf. In diesen Fällen ist es für Sie als Skripter ungemein wichtig, die Eigenschaften des Objektes abzufragen und dort selber in den Werten nachzuschauen. Das Herumspielen mit diesen Beispieldaten hilft Ihnen dann, zu verstehen, wie es funktioniert. Manche Propertys eines Objekts erwarten feste Werte in Form von Schlüsselwörtern: tell application "Finder" set x to folder "Neuer Ordner" of desktop set everyones privileges of x to none end tell Hier wird allen Anwendern außer dem Eigentümer und dessen Gruppe jegliches Recht, auf diesen Ordner zuzugreifen, entzogen. Sie können das überprüfen, wenn Sie die Information des Ordners öffnen und dort unter Sharing & Zugriffsrechte nachsehen. Bei everyone wird dort dann Keine Rechte stehen. Im Funktionsverzeichnis werden die Schlüsselwörter, die Sie hier verwenden können, mit einem Schrägstrich voneinander getrennt. Das bedeutet, dass nur jeweils einer dieser Werte verwendet werden kann: »everyones privileges (read only/read write/write only/none)« Diese Begriffe gelten als Schlüsselworte der entsprechenden Anwendung, hier dem Finder, und werden daher nicht in Anführungszeichen gesetzt. Die Beschreibung zu everyones privileges glänzt durch Abwesenheit, hier wird einfach davon ausgegangen, dass die grundlegenden Kenntnisse des Betriebssystems vorhanden sind, wenn man damit herumspielt – und das sollten sie spätestens hier auch sein, wenn man die Rechte an einem Ordner verändert.
186
Die Sprache
Kapitel 4
Abb. 4-7 Der Spotlight-Kommentar, das Etikett und die Rechte für everyone wurden per Skript geändert. Aus Sicht von AppleScript ist das Setzen von Eigenschaften eines Objekts identisch mit dem Verändern von Werten in einem Record. Letztlich ist alles nur ein Objekt mit Eigenschaften. Neben diesen von Ihnen direkt veränderbaren Propertys gibt es natürlich noch eine Reihe weiterer, die sich nicht direkt von Ihnen ändern lassen – wenn man es könnte, würde das auch schnell zu Schäden im Betriebssystem führen. So können Sie zum Beispiel nicht die Propertys size oder physical size verändern. Diese Größen werden durch die Größe des Ordners an sich und die Größe des Ordners mit allen darin enthaltenen Dateien bestimmt. Dieser Wert kann daher nur für Informationszwecke ausgelesen werden.
187
SmartBooks
AppleScript
Die Datumsklasse Nachdem nun genügend Kenntnisse in AppleScript vorhanden sind, wird es Zeit sich einmal mit einer komplexeren Werteklasse von AppleScript zu beschäftigen, nämlich dem Datum. Die Klasse date wird in AppleScript dafür verwendet um mit Datum und Uhrzeit zu rechnen. Die Klasse date enthält immer einen Zeitpunkt, also nicht etwa eine Zeitspanne. Die Genauigkeit liegt bei einer Sekunde. Für feinere Zeitabstufungen oder Messungen eignet sich diese Klasse daher nicht. Tipp Falls Sie kleinere Zeitspannen benötigen, empfiehlt sich der Aufruf einer entsprechenden Methode in Perl oder Python aus AppleScript heraus über do shell script. Ein Beispiel finden Sie im Kapitel Unix. Lassen Sie sich nicht von dem Klassennamen date verwirren. Ein Objekt dieser Klasse enthält auch immer eine Uhrzeit. Ein Datum ist wie eine Liste oder ein Record ein veränderbares (mutable) Objekt. Das heißt Teile daraus können an Ort und Stelle verändert werden ohne deswegen ein neues Objekt erzeugen zu müssen wie beim Text. Die Datumsklasse in AppleScript kennt nur den gregorianischen Kalender. Andere Kalender wie der julianische oder der islamische Kalender sind nicht implementiert.
Der Befehl current date Um sich diese Klasse genauer anzuschauen, verwenden Sie am Besten einfach mal den AppleScript-Befehl current date aus den Standard Additions von AppleScript und schauen Sie sich das Ergebnis im Ergebnisbereich des Skripteditors an. Mit diesem Befehl können Sie an jeder beliebigen Stelle im Skript die aktuelle Zeit abfragen. current date -- Ergebnis: date "Montag, 16. Juni 2008 11:36:26 Uhr" Wie Sie sehen können, wird der Zeitpunkt an sich als ein Textliteral in Anführungszeichen dargestellt. Der Text wird tatsächlich nur durch das vorangestellte date als Datum ausgewiesen.
188
Die Sprache
Kapitel 4
Wie das Datum formatiert ist, hängt einzig und allein von den Landeseinstellungen der Systemeinstellungen ab. Derselbe Befehl wird also zum Beispiel auf einem US-amerikanischen System folgendes Datumsformat anzeigen: date "Monday, June 16, 2008 11:36:26 AM"
Datumsliterale Um ein Objekt der Klasse date selbst zu erzeugen brauchen Sie nur ein Textliteral zu schreiben welches sich als Datum interpretieren lässt und ein date davor schreiben. date "16.06.2008" Nach dem Übersetzen steht in dieser Zeile dann: date "Montag, 16. Juni 2008 0:00:00 Uhr" Da Sie keine Uhrzeit angegeben haben, wird diese auf 0 Uhr, Mitternacht gestellt. Sie können sogar die Jahreszahl weglassen womit einfach das aktuelle Jahr angenommen wird. Das funktioniert auch mit einer Uhrzeit, wobei die Sekunden weggelassen werden können: date "3:00" Nach dem Kompilieren, also dem Klick auf den Knopf Übersetzen, wird dann die Uhrzeit mit dem Datum von Heute ergänzt: date "Montag, 16. Juni 2008 3:00:00 Uhr" Ob der in Anführungszeichen vorliegende Text als Datum erkannt werden kann, hängt wieder von den Landeseinstellungen des Betriebssystems ab. date "6/15/2008" ergibt auf einem deutschen Betriebssystem daher einen Fehler beim Kompilieren, und zwar weil der Tag nach dem Monatsname erscheint, nicht aber wegen den Schrägstrichen! Nach amerikanischer Lesart handelt es sich hierbei um den 15. Juni, nach deutscher jedoch um den 6 Tag des 15. Monats. Da wir aber nur 12 Monate im Jahr zählen, ergibt das natürlich einen Fehler. date "6/12/2008" wäre dann nach amerikanischer Lesart der 12. Juni. Auf einem deutschen Betriebssystem wird diese Zeile jedoch zum 6. Dezember: date "Samstag, 6. Dezember 2008 0:00:00 Uhr" 189
SmartBooks
AppleScript
Aufgepasst Vorsicht daher, wenn Sie Text als Datum einlesen. Überprüfen Sie, dass das Format stimmt. Bei Benutzereingaben ist auf das nötige Format hinzuweisen. Soll Ihr Skript unter unterschiedlichen Betriebssystemsprachen funktionieren, ist es angeraten die Landeseinstellungen des Systems mit user locale of (get system info) abzufragen. Beim Einlesen von Datum oder Uhrzeit verhält sich AppleScript ziemlich liberal, was das Trennzeichen betrifft. So können Sie neben Punkt und Doppelpunkt auch den Schrägstrich oder den Bindestrich verwenden. Im Zweifelsfall sollten Sie aber immer ausprobieren, welche Zeichen mit welchen Landeseinstellungen funktionieren und welche eventuell zu einer falschen Interpretation führen oder gar nicht gehen. Statt Text können Sie natürlich auch eine Variable oder einen Ausdruck schreiben, der sich als Datum interpretieren lässt, was in den meisten Fällen sicher der normale Weg ist, denn nur so können Sie ein Datumsliteral davor bewahren beim Kompilieren in das landestypische Format umgewandelt zu werden: set x to "13:15" set y to date x -- Ergebnis: date "Montag, 16. Juni 2008 13:15:00 Uhr"
Rechnen mit date Mit date können Sie nur genau zwei Rechenoperationen durchführen: Addieren und Subtrahieren. Wenn Sie ein späteres Datum von einem früheren abziehen, erhalten Sie die Anzahl der Sekunden zwischen diesen beiden Zeitpunkten: date "13:15" - date "13:00" wird nach dem Kompilieren aber erstmal als vollständiges Datum ergänzt: (date "Montag, 16. Juni 2008 13:15:00 Uhr") - ¬ (date "Montag, 16. Juni 2008 13:00:00 Uhr") Das Ergebnis ist dann 900. Das ist die Anzahl Sekunden von 15 Minuten Zeitunterschied. Ansonsten können Sie nur eine Zeitspanne zu einem Datum hinzufügen oder abziehen. Diese Zeitspanne muss als Integer immer in Sekunden vorliegen: date "13:15" - 900
190
Die Sprache
Kapitel 4
wird zu: date "Montag, 16. Juni 2008 13:00:00 Uhr" date "23:45" + 1800 wird zu: date "Dienstag, 17. Juni 2008 0:15:00 Uhr" Beim Abziehen oder Hinzufügen von Sekunden zu einem Datum wird, falls nötig, also automatisch zum nächsten/vorigen Tag gesprungen. Da das Rechnen mit Zeitspannen immer in Sekunden erfolgen muss kann es natürlich zu sehr großen Zahlen kommen. Deswegen gibt es in AppleScript die Konstanten minutes, hours, days und weeks. << weeks steht für die Zahl 604800, die Anzahl der Sekunden einer Woche. << days steht für 86400, die Anzahl der Sekunden eines Tages. << hours steht für 3600, die Anzahl der Sekunden in einer Stunde. << minutes steht für die Zahl 60, die Anzahl der Sekunden in einer Minute. Sie können diese Konstanten überall dort verwenden wo eine Integerzahl erwartet wird und damit rechnen. Brauchen Sie ein Mehrfaches, so multiplizieren Sie die Konstante einfach entsprechend: 3 * minutes -- Ergebnis: 180 Möchten Sie eine bestimmte Anzahl Wochen, Tage, Stunden oder Minuten zu einem Datum hinzuaddieren oder abziehen, so verwenden Sie einfach diese Konstanten beim Rechnen und Sie müssen nicht alles in Sekunden umrechnen: set x to "12.06.2008 13:15:10" set y to date x set y to y + 2 * weeks -- Ergebnis: date "Donnerstag, 26. Juni 2008 13:15:10 Uhr" Damit ist das Datum zwei Wochen weiter gesprungen. Sie können natürlich auch mehrere dieser Zeitkonstanten hinzuaddieren (oder subtrahieren):
191
SmartBooks
AppleScript
set x to "12.06.2008 13:15:10" set y to date x set y to y + 2 * weeks + 3 * days + 5 * hours - 5 * minutes - 10 -- Ergebnis: date "Sonntag, 29. Juni 2008 18:10:00 Uhr" Ohne Angabe irgendeiner Konstante stellt eine Ganzzahl selbst immer Sekunden dar. Am Schluss der Zeile werden also auch noch 5 Minuten und 10 Sekunden abgezogen. Zur einfacheren Handhabung, besitzt die Datumsklasse auch einige Eigenschaften und weitere Konstanten, welche die Arbeit mit der Zeit erheblich erleichtern.
Eigenschaften von date Die Klasse date besitzt eine ganze Menge an Eigenschaften die im Folgenden erklärt werden.
class Wenn Sie ein Datum nach seiner Klasse fragen erhalten Sie date als Antwort: set x to date "12.06.2008 13:15:10" class of x -- Ergebnis: date Diese Abfrage bietet sich als Prüfung an, wenn man nicht sicher ist, ob in einer Variablen wirklich ein Datum steckt.
day Wenn Sie ein date mit day nach seinem Tag fragen, erhalten Sie den Monatstag als Zahl, also die Anzahl der Tage die seit Monatsanfang vergangen sind: Das Ergebnis ist immer eine Ganzzahl, also vom Typ Integer. Diese Eigenschaft kann aber nicht nur gelesen, sondern auch verändert werden: set x to "12.06.2008 13:15:10" set y to date x set day of y to 31 get y -- Ergebnis: date "Dienstag, 1. Juli 2008 13:15:10 Uhr" Wenn wie hier eine Tageszahl genannt wird, die über der Anzahl der Tage liegt, die in diesem Monat enthalten sein kann – der Juni hat nur 30 Tage nicht 31 – werden die überzähligen Tage automatisch auf den nächsten Monat addiert und das Datum springt automatisch um. So erhalten Sie hier den 1. Juli als Ergebnis.
192
Die Sprache
Kapitel 4
Wenn Sie Tage zu einem Datum hinzuzählen oder abziehen wollen, so sollten Sie aber besser die unter Rechnen mit date behandelten Methoden verwenden und nicht die Eigenschaft day auch wenn Sie hier Werte über 31 vergeben können, so ist das doch nicht dokumentiert, so dass von einer Verlässlichkeit hier nicht ausgegangen werden kann. Verwenden Sie also besser keine Werte außerhalb des Bereichs von 1 bis 31. Verwechseln Sie die Eigenschaft day nicht mit der Konstante days die für die Anzahl der Sekunden eines Tages steht und die Sie verwenden können um ganze Tage von einem Datum abzuziehen oder hinzuzufügen.
weekday Diese Eigenschaft liefert den Wochentag eines Datums zurück und ist »read only«. Diese Eigenschaft kann also nur ausgelesen, aber nicht verändert werden. Bei der Abfrage erhalten Sie jedoch nicht, wie man erwarten könnte, eine Zahl von 1 bis 7 oder den Namen des Wochentags, nein, date liefert eine Konstante für diesen Wochentag die den Namen des Wochentags trägt. Dieser Unterschied ist bedeutsam! set x to "12.06.2008 13:15:10" set y to weekday of date x -- Ergebnis: Thursday Das Ergebnis Thursday steht nicht in Anführungszeichen! Es handelt sich hier also um keinen Text sondern um eine der Konstanten über die AppleScript verfügt. Jeder Wochentag ist in AppleScript als eine Konstante angelegt die den englischen Namen des Wochentags trägt: Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday Um daraus die Wochentagszahl zu erhalten oder den Tagesnamen müssen Sie diese Konstante nur in eine Ganzzahl oder einen Text umwandeln: set x to "12.06.2008 13:15:10" set y to weekday of date x -- Ergebnis: Thursday y as text -- Ergebnis "Thursday" y as integer -- Ergebnis: 5 Worüber man sich als deutscher Skripter aber schon seit Bestehen von AppleScript ärgert, ist die Tatsache, dass der Wochentag bei dieser Umwandlung nicht anhand der Landeseinstellungen in seine deutsche Bezeichnung "Donnerstag" umgewandelt wird. Des Weiteren fällt Ihnen vielleicht auf, dass bei der Umwandlung des Wochentags in eine Ganzzahl, der Donnerstag der fünfte Tag der Woche ist. Das heißt der Sonntag ist in AppleScript immer der erste Tag der Woche. Auch hier findet keine Anpassung an die Landeseinstellungen statt!
193
SmartBooks
AppleScript
Da die Eigenschaft weekday nur gelesen werden kann, können Sie den Wochentag nicht direkt verändern, was ja auch Sinn macht, da dieser ganz vom Datum abhängig ist. Möchten Sie den Wochentag ändern, so müssen Sie eine entsprechende Anzahl an Tagen zum Datum hinzufügen oder abziehen: set x to "12.06.2008 13:15:10" set y to date x set y to y + 1 * days weekday of y -- Ergebnis: Friday Oder, solange Sie im Bereich 1 bis 31 bleiben, können Sie auch die Eigenschaft day setzen: set x to "12.06.2008 13:15:10" set y to date x set day of y to (day of y) + 1 weekday of y -- Friday Tipp Was macht man nun aber um den deutschen Wochentagsnamen aus einem Datum zu extrahieren? Eine Möglichkeit besteht darin, den Namen mit den text item delimiters herauszuholen: set x to "12.06.2008 13:15:10" set y to date x -- Ergebnis: date "Donnerstag, 12. Juni 2008 13:15:10 Uhr" set text item delimiters to "," set wochenTag to first text item of (y as text) --Ergebnis: "Donnerstag" Die andere Möglichkeit besteht darin eine Liste mit den Wochentagsnamen anzulegen (Mit "Sonntag" als erstem Tag!) aus denen man dann durch Angabe der Wochentagszahl den entsprechenden deutschen Namen herausholt: set tagesListe to {"Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"} set x to "12.06.2008 13:15:10" set y to date x -- Ergebnis: date "Donnerstag, 12. Juni 2008 13:15:10 Uhr" set y to weekday of date x as integer -- Ergebnis: 5 set wochenTag to item y of tagesListe --Ergebnis: "Donnerstag"
194
Die Sprache
Kapitel 4
Da beim Zugriff über item die Konstante implizit in eine Zahl konvertiert wird, lässt sich das noch folgendermaßen abkürzen: set tagesListe to {"Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"} set x to "12.06.2008 13:15:10" -- Ergebnis: date "Donnerstag, 12. Juni 2008 13:15:10 Uhr" set wochenTag to item (weekday of date x) of tagesListe --Ergebnis: "Donnerstag" Die Wochentagskonstanten können also auch wie eine Zahl verwendet werden, da Sie, wenn eine Zahl in der Operation erwartet wird, automatisch darin umgewandelt werden, was deren Handhabung doch erleichtert. Das sich weekdays auch als integer interpretieren lassen, ist neu seit Mac OS X 10.4, funktioniert daher nicht unter älteren Betriebssystemen.
month Diese Klasse verhält sich identisch zur Property weekday mit der Ausnahme, dass diese Eigenschaft auch gesetzt werden kann. Von month wird immer der Monatsname eines Datums zurückgeliefert, welcher, wie bei den Wochentagen, als Konstante verwirklicht ist. Sie erhalten also keine Zahl von 1 bis 12 zurück und auch keinen Monatsnamen als Text: set x to "12.06.2008 13:15:10" set y to month of date x -- Ergebnis: June Wie Sie an diesem Beispiel sehen, tragen die Konstanten wieder die englische Bezeichnung der Monatsnamen. Die zwölf Konstanten für die Monate des Jahres lauten dementsprechend: January, February, March, April, May, June, July, August, September, October, November, December Um daraus die Monatszahl zu erhalten oder den Monatsnamen als Text, müssen Sie diese Konstante noch in eine Ganzzahl oder einen Text umwandeln: set x to "12.06.2008 13:15:10" set y to month of date x -- Ergebnis: June y as text -- Ergebnis "June" y as integer -- Ergebnis: 6
195
SmartBooks
AppleScript
Tipp Wie bei den Wochentagen werden die Monatsnamen nicht an Hand der Landeseinstellungen lokalisiert. Sie müssen sich also wieder selbst darum kümmern, zum Beispiel über text item delimiters oder eine Liste mit den Monatsnamen: set x to "12.06.2008 13:15:10" set y to date x -- Ergebnis: date "Donnerstag, 12. Juni 2008 13:15:10 Uhr" set text item delimiters to " " -- Leerstelle set monatsName to text item 3 of (y as text) --Ergebnis: "Juni" oder: set monatsListe to {"Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"} set x to "12.06.2008 13:15:10" -- Ergebnis: date "Donnerstag, 12. Juni 2008 13:15:10 Uhr" set monatsName to item (month of date x) of monatsListe --Ergebnis: "Juni" Die Monatskonstanten können also auch wie oben (month of date x) als Zahl verwendet werden, da sie, wenn eine Zahl in der Operation erwartet wird wie weekdays automatisch in eine Zahl umgewandelt werden. Da die Eigenschaft month auch gesetzt werden kann, können Sie mit einem set den Monat verändern: set x to "12.06.2008 13:15:10" set y to date x -- Ergebnis: date "Donnerstag, 12. Juni 2008 13:15:10 Uhr" set month of y to July get y -- Ergebnis: date "Samstag, 12. Juli 2008 13:15:10 Uhr" Statt die Monatskonstante mit set month of y to July anzugeben, können Sie aber auch eine Zahl von 1 bis 12 verwenden um die Monate an Hand Ihres Index zu setzen: set month of y to 8 Damit wird der Monat in dem Datum auf den August gesetzt. Diese Fähigkeit von month wurde mit Tiger eingeführt. Wenn die Zahl größer ist als 12 gibt es zwar keine
196
Die Sprache
Kapitel 4
Fehlermeldung, Sie haben dann aber auch keine Gewissheit mehr über das Ergebnis, da diese Fähigkeit nicht dokumentiert ist. Zurzeit ist diese undokumentierte Eigenschaft aber die einzige Möglichkeit wirklich ganze Monate zu einem Datum zu addieren, da die Konstanten zum Rechnen mit Sekunden logischerweise bei weeks aufhören. Ein Monat hat ja schließlich keine fest definierte Anzahl an Sekunden. Wenn Sie also mit der Eigenschaft month rechnen und einem Datum Monate hinzufügen, dann überprüfen Sie auf jeden Fall das Ergebnis und verlassen Sie sich nicht blind darauf. Sie können den Monatsnamen zwar mit einer Zahl setzen, aber nicht mit einem Text: set month of y to "July" Eine Fehlermeldung ist das Resultat. Ein Text wird also nicht implizit in eine Monatskonstante umgewandelt. Wenn beim Setzen eines Monats ein Überlauf passiert, weil zum Beispiel die Tageszahl über der Anzahl Tage liegt die der Monat haben kann, werden die überschüssigen Tage auf den nächsten Monat addiert. Wenn Sie also den Monat auf den Februar setzen, die Tagesanzahl aber auf 31 steht, dann werden die im Februar nicht möglichen Tage 29 bis 31 (bei einem Schaltjahr 30 bis 31) zum Datum hinzugezählt wodurch Sie dann mit dem Datum in den März hineinspringen: set x to "31.07.2008 13:15:10" set y to date x -- Ergebnis: date "Donnerstag, 31. Juli 2008 13:15:10 Uhr" set month of y to 2 get y -- Ergebnis: date "Sonntag, 2. März 2008 13:15:10 Uhr"
year Mit year können Sie das Jahr in einem Datum abfragen und auch verändern. Wenn Sie ein Datum nach seiner Eigenschaft year fragen, erhalten Sie das Jahr als vierstellige Ganzzahl: set x to "12.06.2008 13:15:10" set y to year of date x -- Ergebnis: 2008 Das Ergebnis ist immer vom Typ Integer, mit dem Sie dann ganz nach Belieben rechnen können.
197
SmartBooks
AppleScript
Diese Eigenschaft kann auch verändert werden: set x to "12.06.2008 13:15:10" set y to date x set year of y to 2012 get y -- Ergebnis: date "Dienstag, 12. Juni 2012 13:15:10 Uhr" Steht das Datum auf dem 29. Februar und ist das Jahr kein Schaltjahr, so wird das Datum entsprechend auf den 1. März gesetzt: set x to "29.02.2008 13:15:10" set y to date x set year of y to 2011 get y -- Ergebnis: date "Dienstag, 1. März 2011 13:15:10 Uhr"
date string und short date string Diese Eigenschaft eines Datums ist dafür gedacht den Datumsteil als Text zu extrahieren: set x to "12.06.2008 13:15:10" set y to date string of date x -- Ergebnis: "Donnerstag, 12. Juni 2008" Wenn Sie also einen Text benötigen, der das Datum ohne Uhrzeit enthält, ist diese Eigenschaft die richtige Wahl. Die Formatierung des Datums hängt von den Landeseinstellungen im Betriebssystem ab. Wenn Sie das Datum in einem Kurzformat benötigen, verwenden Sie die Variante short date string: set x to "12.06.2008 13:15:10" set y to short date string of date x -- Ergebnis: "12.06.08" Auch diese Formatierung hängt ganz von den Landeseinstellungen des Betriebssystems ab. Wenn Sie dort auf den Knopf Anpassen klicken und für das kurze Datumsformat eine vierstellige Jahreszahl wählen, erhalten Sie auch mit short date string ein vierstelliges Jahr. Wenn Sie ein anderes, eigenes Format benötigen und dafür nicht jedes Mal die Einstellungen im Betriebessystem ändern wollen, so bauen Sie das Datum mit year, month und day auseinander und bauen Sie die Bestandteile dann wieder mit beliebigen Trennzeichen als Text zusammen.
198
Die Sprache
Kapitel 4
time Mit time fragen Sie die Anzahl der Sekunden ab, die seit Mitternacht des angegebenen Tages vergangen sind: set x to "12.06.2008 13:15:10" set y to time of date x -- Ergebnis: 47710 Mit dieser Eigenschaft der Klasse date ersparen Sie sich die lästige Umrechnung von Stunden und Minuten in Sekunden. Umgekehrt, können Sie die Eigenschaft time auch setzen, zum Beispiel so: set x to "12.06.2008 13:15:10" set y to date x -- date "Donnerstag, 12. Juni 2008 13:15:10 Uhr" set time of y to 3690 get y -- Ergebnis: date "Donnerstag, 12. Juni 2008 1:01:30 Uhr" Hier wird die Uhrzeit im Datum auf 3690 Sekunden (1 Stunde, 1 Minute und 30 Sekunden) gesetzt. Ein Wechsel des Datums findet automatisch statt, wenn der Wert größer ist als ein Tag Sekunden hat: set x to "12.06.2008 13:15:10" set y to date x -- date "Donnerstag, 12. Juni 2008 13:15:10 Uhr" set time of y to 86430 get y -- Ergebnis: date "Freitag, 13. Juni 2008 0:00:30 Uhr" Sie können auch Sekunden auf die Zeit hinzuaddieren: set x to "12.06.2008 13:15:10" set y to date x -- date "Donnerstag, 12. Juni 2008 13:15:10 Uhr" set time of y to (time of y) + 86400 get y -- Ergebnis: date "Freitag, 13. Juni 2008 13:15:10 Uhr" Das Datum schlägt dann gegebenenfalls automatisch auf den nächsten Tag um. Umgekehrt geht es jedoch nicht, wenn Sie nämlich Sekunden von der Zeit abziehen und auf den Vortag landen. Folgendes Skript schlägt daher fehl:
199
SmartBooks
AppleScript
set x to "12.06.2008 13:15:10" set y to date x -- date "Donnerstag, 12. Juni 2008 13:15:10 Uhr" set time of y to (time of y) - 86400 -- Fehler: »Einige Daten können nicht in den erwarteten Typ umgewandelt werden.« Die Eigenschaft time ist definiert als die Anzahl der Sekunden ab Mitternacht und kann daher nicht negativ werden. Für die Addition oder Subtraktion von Zeitspannen auf ein Datum würde ich Ihnen daher immer empfehlen nicht die Eigenschaft time zu verwenden, sondern wie unter Rechnen mit date beschrieben, direkt Sekunden auf das Datum zu addieren oder zu subtrahieren.
hours Diese Eigenschaft ist zusammen mit minutes und seconds neu in Tiger. Verwechseln Sie diese Eigenschaft nicht mit der Konstante gleichen Namens, die für die Angabe der Sekunden in einer Stunde steht. Mit hours können Sie die Anzahl der vollen Stunden die seit Mitternacht verstrichen sind aus dem Datum herausholen: set x to "12.06.2008 13:15:10" set y to hours of date x -- Ergebnis: 13 Diese Eigenschaft kann aber nur abgefragt und nicht gesetzt werden und liegt immer im 24-Stunden-Format vor, kann damit also maximal 23 Stunden groß sein, da 24 Stunden schon den Beginn des nächsten Tages darstellen. Es handelt sich immer um eine Ganzzahl.
minutes Minutes verhält sich wie hours. Sie können damit den Minutenanteil der Uhrzeit abfragen: set x to "12.06.2008 13:15:10" set y to minutes of date x -- Ergebnis: 15 Auch minutes kann nicht gesetzt werden, ist also read only und maximal 59 Minuten groß, da 60 Minuten schon die nächste Stunde darstellen. Es handelt sich immer um eine Ganzzahl. Verwechseln Sie diese Eigenschaft nicht mit der Konstante gleichen Namens, die für die Angabe der Sekunden in einer Minute steht.
200
Die Sprache
Kapitel 4
seconds Mit seconds können Sie den Sekundenanteil eines Datums abfragen: set x to "12.06.2008 13:15:10" set y to seconds of date x -- Ergebnis: 10 Auch seconds ist schreibgeschützt, hat eine maximale Größe von 59 und ist immer eine Ganzzahl.
time string Mit time string extrahieren Sie die Zeitangabe in einem Datum als Text: set x to "12.06.2008 13:15:10" set y to date x -- Ergebnis: date "Donnerstag, 12. Juni 2008 13:15:10 Uhr" set z to time string of y -- Ergebnis: "13:15:10" Beachten Sie, dass das Wort Uhr wegfällt und nicht mit übernommen wird. Verwenden Sie diese Eigenschaft, wenn Sie nur die Uhrzeit benötigen. Das Format der Uhrzeit ist abhängig von den gewählten Landeseinstellungen des Betriebssystems und zwar von dem Uhrzeitformat mittlerer Länge. Sie können aber auch durch Abfrage mit hours, minutes und seconds die Zeit auseinander nehmen und dann nach Belieben mit eigener Formatierung als Text wieder zusammenbauen ohne die Landeseinstellungen dafür zu ändern.
Datum oder Zeit in vorhandenes Datum einsetzen Zeit- oder Datumsteil in einem date lassen sich auch getrennt vom anderen Teil austauschen indem ein Datums- oder Zeitstring als Eigenschaft eines anderen Datums angegeben wird: Hier bekommt das Datum 12.06.2008 eine Uhrzeit eingesetzt: set myDate to "12.06.2008" set myDate to date myDate -- Ergebnis: date "Donnerstag, 12. Juni 2008 0:00:00 Uhr" set myDate to date "8:15" of myDate -- Ergebnis: date "Donnerstag, 12. Juni 2008 8:15:00 Uhr" Hier wird der Uhrzeit 8:15 ein Datum verliehen: set myTime to "8:15" set myTime to date myTime -- Ergebnis: date "Montag, 12. Juni 2008 8:15:00 Uhr" set myTime to date "23.09.2008" of myTime -- Ergebnis: date "Dienstag, 23. September 2008 8:15:00 Uhr" 201
SmartBooks
AppleScript
Der Befehl time to GMT Mit diesem Befehl ermitteln Sie die Differenz zwischen der lokalen Zeit zur Greenwich Mean Time (GMT), beziehungsweise Universal Time (UT). Dieser Befehl hat keine Parameter und liefert einen Integer-Wert zurück welcher den Abstand in Sekunden ausdrückt. Grundlage ist die in den Systemeinstellungen unter Datum & Uhrzeit eingestellte Zeitzone. Der Wert kann entsprechend der Zeitzonen positiv (nach Osten hin) oder negativ (nach Westen hin) sein. Der Befehl time to GMT stammt aus den Standard Additions von AppleScript. So ergibt time to GMT während der Sommerzeit in Deutschland einen Wert von 7200 Sekunden, sonst 3600. Das entspricht zwei oder einer Stunde. set timeDif to time to GMT -- Ergebnis: 7200 Wenn Sie die Zeitzone einer anderen Stadt oder Region in der Welt kennen, können Sie damit leicht errechnen wie viel Uhr es dort gerade ist. Besteht an dem Zielort allerdings eine Sommerzeit wird diese nicht berücksichtigt, es sei denn Sie haben die Zeitzone damit schon korrigiert. So liegt Hawaii zum Beispiel in der Zeitzone UTC-10h, während der Sommerzeit allerdings UTC-9h. Wenn Sie nun wissen wollen, wie viel Uhr es im Sommer auf Hawaii ist, wenn es bei uns 8 Uhr morgens ist, dann können Sie das über time to GMT berechnen. Hier ein Beispiel, welches Sie in einem Dialog nach einer Uhrzeit fragt und Ihnen dann in einem weiteren Dialog anzeigt, wie viel Uhr (und welcher Tag!) es gerade in Hawaii ist: -- Uhrzeitabfrage: set timeHere to text returned of ¬ (display dialog "Bitte eine Uhrzeit im 24h-Format hh:mm eingeben:" ¬ default answer "08:00") -- Lokale Zeitzone set localTimeDif to time to GMT -- Zeitzone des Ziels set targetTimeDif to -9 * hours -- Zielzeitermittlung set targetTime to date timeHere 202
Die Sprache
Kapitel 4
-- Ergebnis: date "Dienstag, 17. Juni 2008 8:00:00 Uhr" set targetTime to targetTime - (localTimeDif - targetTimeDif) -- Differenz in Sekunden abziehen display dialog "Zeit in Hawaii: " & targetTime as text ¬ buttons "OK" default button "OK" -- Ergebnis: date "Montag, 16. Juni 2008 21:00:00 Uhr" Sie werden sehen, dass es in Hawaii 21:00 Uhr ist, wenn es bei uns 8 Uhr morgens schlägt, und zwar der Abend des bei uns bereits verstrichenen gestrigen Tages. Wenn Sie Sekunden von einem date abziehen oder hinzufügen, springt das Datum immer korrekt um. Ziehen Sie dafür keinesfalls Sekunden von der Eigenschaft time ab, da eine negative Zahl zu keiner Änderung des Datums führt, sondern zu einer Fehlermeldung. Sie können Sekunden immer direkt einem Datumsobjekt hinzufügen oder abziehen.
Der Befehl delay Dieser Befehl hat eigentlich nichts mit einem date zu tun, sonder eher damit AppleScript eine bestimmte Zeit lang warten zu lassen. Er stammt aus den Standard Additions von AppleScript. Da Warten mit Zeit zu tun hat, erkläre ich ihn hier. Während der Arbeit mit einem Programm kann es manchmal vorkommen, dass das Skript zu schnell für ein Programm ist. Eigentlich sollte das durch Abwarten auf die Antwort des Programms durch die standardmäßig in AppleScript aktive Anweisung considering application responses nicht vorkommen. Trotzdem kann es sein, das ein Programm nach seiner Antwort noch eine Gedenksekunde benötigt, bis es sich wirklich gesammelt hat und für den nächsten AppleEvent bereit ist. In solchen Fällen hilft ein delay. Der Befehl delay kennt nur einen einzigen Parameter, welcher als Zahl vorliegen muss. Diese Zahl kann eine Ganzzahl oder eine Kommazahl sein. Bei einer Kommazahl wird der Wert hinter dem Komma entsprechend als Teil einer Sekunde gewertet. Der Parameter ist optional, kann also auch weggelassen werden, womit dann ein delay von Null vorliegt. delay 2.5 beep lässt Ihr Skript genau zweieinhalb Sekunden warten bevor es mit dem nächsten Befehl fortfährt – hier nur ein kurzes beep.
203
SmartBooks
AppleScript
Die maximale Genauigkeit von delay liegt bei 1/60 Sekunde. Apple weist in seiner Dokumentation explizit darauf hin, dass sich delay nicht für Arbeiten eignet, bei denen es auf zeitliche Genauigkeit oder die Synchronisation von Ereignissen ankommt.
Umwandlungen von date Ein Wert der Klasse date kann, als Ganzes, nur in zwei andere Werteklassen umgewandelt werden: In einen Text oder in eine Liste. Die Umwandlung in einen Text kann implizit geschehen, wenn der &-Operator beteiligt ist und der Text vor dem Datum steht: set x to date "Freitag, 11. Mai 2007 0:00:00 Uhr" "Das Datum ist: " & x -- Ergebnis: "Das Datum ist: Freitag, 11. Mai 2007 0:00:00 Uhr" Steht das Datum vor dem Text wird jedoch eine Liste erzeugt: set x to date "Freitag, 11. Mai 2007 0:00:00 Uhr" x & ", Mitternacht" -- Ergebnis: {date "Freitag, 11. Mai 2007 0:00:00 Uhr", ", Mitternacht"} Auf diese Weise können Sie also eine Liste mit dem Datum als erstem Element erzeugen. Ansonsten müssen Sie mit as text das Datum explizit in einen Text umwandeln: set x to date "Freitag, 11. Mai 2007 0:00:00 Uhr" (x as text) & ", Mitternacht" -- Ergebnis: "Freitag, 11. Mai 2007 0:00:00 Uhr, Mitternacht" Die zweite Möglichkeit der Umwandlung eines Datums in eine Liste geschieht explizit mit as list. Wenn Sie dann an diese Liste mit dem &-Operator weitere date-Elemente anfügen werden diese der Liste angefügt und Sie erhalten eine Liste mit mehreren dateObjekten: set x to date "Freitag, 11. Mai 2007 0:00:00 Uhr" set y to "15.8.1961" (x as list) & date y -- Ergebnis: {date "Freitag, 11. Mai 2007 0:00:00 Uhr", date "Dienstag, 15. August 1961 0:00:00 Uhr"} Wenn Sie ein Datum in eine Zahl umwandeln wollen, so geht das nur mit einzelnen Elementen des Datums. Fragen Sie dann die benötigte Eigenschaft ab und wandeln Sie diese,
204
Die Sprache
Kapitel 4
wenn nötig, mit as number, as real oder as integer in eine Zahl um. Beachten Sie hierzu die Beschreibung der Eigenschaften des Datums auf den vorigen Seiten. Die Umwandlung einer anderen Klasse in ein Datumsobjekt geschieht, wie zu Anfang des Kapitels bereits beschrieben, ausschließlich über Textstrings. Sie können einen als Zahl vorliegenden Wert also nicht direkt in ein Datum umwandeln, auch wenn sich diese, dank einer Nachkommastelle als Datum interpretieren ließe: set x to 25.5 date x Ob real oder integer, Sie erhalten eine Fehlermeldung. Wandeln Sie daher die Zahl, die als Datum interpretiert werden soll zuerst in einen Text um und die Erkennung als Datum funktioniert, so es denn ein entsprechendes Datum gibt. set x to 25.5 date (x as text) -- Ergebnis: date "Sonntag, 25. Mai 2008 0:00:00 Uhr" Soll eine Zahl als Uhrzeit interpretiert und in ein Datum eingefügt werden, so addieren Sie am Besten diese Zahl als Sekunden zu dem entsprechenden Datum hinzu. Alternativ können Sie auch direkt die Eigenschaft time eines Datums setzen. Ansonsten können Sie auch den Dezimalpunkt oder das Dezimalkomma gegen einen Doppelpunkt austauschen und damit die Zahl als Uhrzeit interpretieren: set x to 18.3 set x to (x as text) & "0" -- "18,30" set text item delimiters to "," set x to every text item of x -- {"18", "30"} set text item delimiters to ":" date (x as text) -- date "Dienstag, 17. Juni 2008 18:30:00 Uhr" Die explizite Umwandlung von Text in ein Datum mit dem Operator as (as date) geht nicht. Sie müssen einen Text also immer mit einem vorangestellten date zu einem Datum machen.
205
SmartBooks
AppleScript
Vergleichsoperatoren Natürlich besteht die Haupttätigkeit in einer Programmiersprache nicht nur darin mit Zahlen, Text, Listen, Records und Zeit zu hantieren, es müssen auch Entscheidungen getroffen werden, die dann darüber bestimmen, welcher Weg eingeschlagen wird. Um solche Entscheidungen treffen zu können, brauchen Sie Informationen. Diese Informationen werden in einer Programmiersprache durch boolesche Aussagen ermittelt. Eine boolesche Aussage ist eine Behauptung die wahr oder unwahr sein kann. Sie erfolgt, indem ein oder mehrere Werte miteinander verglichen werden. Der zurück gelieferte Wert eines Vergleichs wird Wahrheitswert oder auch boolescher Wert genannt. Dieser kann immer nur einen von zwei Zuständen einnehmen, entweder wahr oder unwahr. In AppleScript heißen diese zwei Zustände true und false. Da es nur diese zwei Arten von Antworten gibt, hängt also alles davon ab, die richtigen Fragen zu stellen. Wie in einem Fernsehquiz, in welchem Sie nicht direkt nach der Antwort fragen dürfen und der Kandidat nur mit Ja oder Nein antwortet, so können Sie auch in AppleScript nur eine Behauptung aufstellen und AppleScript antwortet Ihnen dann mit true oder false. Wenn Sie im entscheidenden Moment in Ihrem Code nicht die richtige Frage stellen, nützt Ihnen die ansonsten meisterhafte Beherrschung von AppleScript wenig. Eine falsch gestellte Frage führt zu einer Antwort, die an sich zwar richtig ist – der Code lügt niemals –, bei der Sie aber von falschen Annahmen ausgehen und daher falsche Entscheidungen treffen. Als Resultat funktioniert das Skript nicht wie es soll. Die anschließende Fehlersuche können Sie von Anfang an vermeiden, indem Sie sich mit den Vergleichsoperatoren sehr gut vertraut machen. Die Kunst der richtigen Fragestellung ist in jeder Programmiersprache von zentraler Bedeutung. Dieses Kapitel widmet sich den verschiedenen Möglichkeiten eine Behauptung durch einen Vergleich aufzustellen. Das Kapitel ist eher etwas trockener Natur. Sie können es daher auch überfliegen und später zurückkehren. In jedem Fall sollten Sie aber einen Gesamteindruck aller möglichen Vergleichsoperatoren und dessen Möglichkeiten aus diesem Kapitel mitnehmen, bevor Sie fortfahren. Danach besitzen Sie das nötige Grundwerkzeug um an Hand der gewonnenen Antworten, Entscheidungen zu treffen und den Code in Schleifen, Verzweigungen und Handler fließen zu lassen – womit Sie dann die ersten großen Skripts zu Wasser lassen können.
206
Die Sprache
Kapitel 4
Die Klasse boolean Das Ergebnis eines Vergleichs ist von der Klasse boolean, welche, für sich alleine verwendet, sich selbst wiederum als Resultat ergibt. Wenn Sie true in den Skripteditor schreiben und ausführen, so erhalten Sie im Ergebnisbereich auch true als Ergebnis, bei false entsprechend false. Fragen Sie nach der Klasse eines booleschen Wertes class of false erhalten Sie boolean als Ergebnis. Fragen Sie boolean nach seiner Klasse erhalten Sie class als Antwort. class ist die Mutter aller Klassen und letztlich stammt alles davon ab. class of boolean -- Ergebnis: class Hilfe Sie können sich die beiden Werte true and false durchaus wie einen Schalter vorstellen der ein oder ausgeschaltet sein kann. Sie können einen booleschen Wert auch einfach einer Variablen zuweisen: set istAus to true set istLetzteZahl to false Versuchen Sie mit dem Variablennamen schon so etwas wie eine Aussage vorzunehmen, die sich dann mit deren Inhalt beantworten lässt. Das erleichtert später das Lesen von Anweisungen mit dieser Variablen. Die Klasse boolean kann also nur exakt zwei Werte enthalten, nämlich true und false. Ein maybe (vielleicht) gibt es in AppleScript also nicht. Die Welt einer Programmiersprache kann ziemlich schwarz/weiß sein.
is equal to Die einfachste Form einer Aussage ist die, zu behaupten, dass der Inhalt eines Objektes gleich ist mit dem Inhalt eines anderen Objekts.
207
SmartBooks
AppleScript
Mit Gleichheit ist immer derselbe Wert gemeint. Es bedeutet nicht, dass das Objekt an sich identisch ist. Beachten Sie diesen feinen Unterschied zwischen gleich und identisch! Gleich und identisch ist also nicht dasselbe. Wie im Kapitel Der Unterschied zwischen set und copy beschrieben, können zwei Variablen durchaus auf dasselbe Objekt zeigen. Mit is equal to wird jedoch nicht das Objekt an sich, sondern nur sein Wert verglichen. Aber natürlich, wenn zwei Variablen für dasselbe Objekt stehen, dann haben Sie immer denselben Wert. Um auf Gleichheit zu prüfen gibt es mehrere Schreibweisen. Die sprachlich schönste (und längste) Form verwendet is equal to: set {x, y} to {2, 3} x is equal to y -- Ergebnis: false Hier wird also behauptet, dass der Wert in der Variablen x gleich ist mit dem Wert in der Variablen y. Diese Behauptung ist falsch, deshalb erhalten Sie hier false als Ergebnis. Sie können beim Schreiben is und to auch weglassen und nur equal oder equals schreiben. Der Skripteditor vervollständigt den Ausdruck beim Übersetzen dann automatisch. Die kürzeste Form verwendet das Gleichheitszeichen: x=y Grundlagen Wenn Sie bereits andere Programmiersprachen kennen, beachten Sie bitte, dass Sie in AppleScript das Gleichheitszeichen nicht dazu verwenden können, einer Variablen einen Wert zuzuweisen. Das Gleichheitszeichen ist in AppleScript nicht »überladen« und dient damit wirklich nur dem hier behandelten booleschen Vergleich und keinem anderen Zweck. Die zweitkürzeste Form verwendet nur is: x is y Bei allen diesen Schreibweisen handelt es sich immer um den gleichen Operator. Es handelt sich um einen binären Operator, das heißt links und rechts des Operators wird jeweils ein Operand, also eine Aussage erwartet. Die Auswertung geschieht von links nach rechts.
208
Die Sprache
Kapitel 4
Statt nur einer Variablen können auf beiden Seiten auch komplexere Ausdrücke stehen. Beide Seiten werden vor einem Vergleich ausgewertet und erst danach wird der Vergleich vorgenommen: set {x, y} to {2, 3} x + 2 = y + 1 -- Ergebnis: true
Verneinungsformen Möchten Sie die Aussage umkehren, also behaupten, dass die beiden Werte ungleich sind, so verwenden Sie x is not equal to y oder x is not y oder x≠y Das Zeichen ≠ erhalten Sie mit der Tastenkombination [alt]+[0] (Alt-Taste und die Zahl Null) Sie können auch isn't, isn't equal, does not equal oder doesn't equal, schreiben. Alle diese Schreibweisen werden beim Übersetzen jedoch in eine der obigen Formen umgewandelt.
Implizite Typumwandlungen Jede beliebige Klasse lässt sich auf Gleichheit oder Ungleichheit prüfen. Damit zwei Werte gleich sein können, müssen Sie jedoch immer von der gleichen Klasse sein! set {a, b} to {3, "3"} a is equal to b -- Ergebnis: false Obwohl hier beide Seiten die 3 enthalten sind diese nicht gleich, denn: class of a -- Ergebnis: integer class of b -- Ergebnis: text Links ist die 3 von der Klasse integer und rechts von der Klasse text und damit können diese nicht gleich sein! Beide Werte müssen von der gleichen Klasse sein um gleich sein zu können. Zwei gleiche Werte, aber in unterschiedlichen Klassen verpackt, ergeben bei einem Vergleich mit = also immer false.
209
SmartBooks
AppleScript
Beachten Sie dies bei allen Prüfungen auf Gleichheit und Ungleichheit. Überprüfen Sie im Zweifelsfall ob die Variablen oder Ausdrücke den erwarteten Wertetyp besitzen und wandeln Sie diese gegebenenfalls explizit mit as in denselben Wertetyp um: set {a, b} to {3, "3"} a is equal to b as integer -- Ergebnis: true Die einzige Ausnahme von dieser Regel betrifft den Vergleich von Real und Integer: set {a, b} to {3, 3.0} a = b -- Ergebnis: true Wenn man nach der Klasse fragt, sieht man, das a von der Klasse integer und b von der Klasse real ist. class of a -- Ergebnis: integer class of b -- Ergebnis: real
Zahlen Bei Ganzzahlen ist es ziemlich klar, wann beide Zahlen gleich sind. Vorsicht ist jedoch bei Kommazahlen, also real geboten! Prüfen Sie besser vorher mit class of ob die zu vergleichenden Variablen eventuell real enthalten. Wenn ja, empfiehlt es sich diese zu runden oder mit as integer in eine Ganzzahl umzuwandeln. Besser noch, Sie lassen diesen Fall erst gar nicht zu, denn auch durch die Rundung können Probleme entstehen, wenn die Kommazahl genau auf der Kippe zwischen zwei Ganzzahlen steht. In folgendem Beispiel unterscheiden sich die zwei Dezimalzahlen erst an der siebten Stelle: set a to 2.7357134 set b to 2.7357135 a = b -- Ergebnis: false Eine Prüfung auf Gleichheit schlägt fehl, egal wie weit hinter dem Komma die Abweichung liegt. Wenn es Ihnen im Endeffekt nur auf die letzten zwei Stellen ankommt, so könnten Sie die Dezimalzahlen vor dem Vergleich runden: set a to 2.736 set b to 2.737 (round a / 0.01 rounding as taught in school) * 0.01 is equal to ¬ (round b / 0.01 rounding as taught in school) * 0.01 -- Ergebnis: true In Grenzfällen kann das aber natürlich zu Problemen führen.
210
Die Sprache
Kapitel 4
set a to 2.744 set b to 2.745 (round a / 0.01 rounding as taught in school) * 0.01 is equal to ¬ (round b / 0.01 rounding as taught in school) * 0.01 --Ergebnis: false Und genau solche »Grenzfälle« darf es in keinem Programm geben! Besser ist es Dezimalzahlen nur mit den Operatoren greater than und less than zu vergleichen und niemals equals to darauf anzuwenden, auch nicht in gerundetem Zustand.
Listen Zwei Listen sind dann gleich, wenn Sie dieselbe Anzahl Elemente besitzen und alle Elemente denselben Wert haben. Da Listen ein geordneter Wertetyp sind, müssen die Elemente in beiden Listen alle an exakt derselben Stelle stehen. Folgende Listen wären also nicht gleich obwohl Sie dieselben Elemente enthalten. set a to {2.5, 4, "A"} set b to {2.5, "A", 4} a is equal to b -- Ergebnis: false Tipp Es gibt in AppleScript keine eingebaute Funktion zum Sortieren einer Liste. Hier muss man die Sortierung selber skripten oder zum Beispiel den Befehl sortlist aus der Skripterweiterung Satimage verwenden. Diese Erweiterung wird bei der Installation von Smile mit installiert. Siehe Kapitel 3. Sie können auch eine Listenauswahl mit einer Auswahl einer anderen Liste vergleichen: set b to {"a", "b", 1, 2, 3} set a to {1, 2, 3} a is equal to items -1 thru -3 of b -- Ergebnis: true Wichtig ist nur, dass das Ergebnis der Auswahl eine Liste ist: items -1 thru -3 of b ergibt die Liste {1, 2, 3} und {1, 2, 3} is equal to {1, 2, 3} ist natürlich wahr. 211
SmartBooks
AppleScript
Bei verschachtelten Listen ist darauf zu achten, dass die Verschachtelung bei der Auswahl berücksichtigt wird, entweder als Ganzes: set b to {"a", "b", {1, 2, 3}} set a to {1, 2, 3} a is item -1 of b -- Ergebnis: true Oder als Teil, hier sogar auf beiden Seiten des Vergleichs: set b to {"a", "b", {1, 2, 3}} set a to {1, 2, 3} items 1 thru 2 of a = items -2 thru -3 of last item of b -- Ergebnis: true Achten Sie nur darauf, dass der Überblick nicht verloren geht. Aufgelöst sieht das in diesem Beispiel jedenfalls so aus: {1, 2} is equal to {1, 2} -- Ergebnis: true
Records Bei Records verhält es sich wie bei den Listen, nur mit dem Unterschied, das die Reihenfolge der Elemente keine Rolle spielt. Das heißt der Namen der Property und dessen Wert müssen gleich sein, die Position jedoch nicht. Records sind im Gegensatz zu Listen ungeordnet, die Position eines Elementes darin spielt daher niemals eine Rolle. set a to {xWert:2.5, yWert:4, etikett:"A"} set b to {yWert:4, xWert:2.5, etikett:"A"} a is equal to b -- Ergebnis: true Beide Records enthalten hier die gleichen Eigenschaften und Werte, allerdings in unterschiedlicher Reihenfolge, trotzdem ergibt ein Vergleich der beiden true. Beide Records sind also gleich. Möchten Sie nur eine einzelne Eigenschaft eines Records mit der eines anderen Records vergleichen, verwenden Sie die übliche Form der Auswahl an Hand ihres Namens. set a to {xWert:2.5, yWert:4, etikett:"A"} set b to {yWert:4, xWert:2.5, etikett:"A"} xWert of a = xWert of b -- Ergebnis: true Da die Propertys in einem Record nicht geordnet sind, gibt es im Gegensatz zu Listen keine Möglichkeit einen ganzen Bereich an Hand eines Indexes abzufragen. Wenn Sie mehrere Werte eines Records mit einem anderen vergleichen möchten, so müssen Sie die Werte also immer einzeln, einen nach dem anderen vergleichen (oder den Operator contains verwenden).
212
Die Sprache
Kapitel 4
set a to {xWert:2.5, yWert:4, etikett:"A"} set b to {yWert:4, xWert:2.5, etikett:"A"} xWert of a = xWert of b yWert of a = yWert of b etikett of a = etikett of b -- Ergebnis: true Sie können die einzelnen Eigenschaften auch in eine Liste packen und dann auf einer einzigen Zeile eine Liste mit der anderen vergleichen: set a to {xWert:2.5, yWert:4, etikett:"A"} set b to {yWert:4, xWert:2.5, etikett:"A"} {xWert of a, yWert of a, etikett of a} = ¬ {xWert of b, yWert of b, etikett of b} -- Ergebnis: true Letztlich werden zwei Listen miteinander verglichen die aus Werten des Records bestehen. Wenn es nur auf das Gesamtergebnis ankommt, können die einzelnen Vergleiche auch, wie später beschrieben, mit and oder or verknüpft werden. Wenn Sie zum Beispiel wissen wollen ob alle drei Propertys zu allen drei Propertys des andere Records gleich sind: set a to {xWert:2.5, yWert:4, etikett:"A"} set b to {yWert:4, xWert:2.5, etikett:"A"} xWert of a = xWert of b and yWert of a = ¬ yWert of b and etikett of a = etikett of b -- Ergebnis true Diese Abfrage ergibt nur true wenn wirklich alle drei Propertys gleich sind.
Text Zwei Texte sind dann gleich wenn sie aus exakt denselben Zeichen in exakt derselben Reihenfolge bestehen. Die Groß- und Kleinschreibung wird standardmäßig nicht berücksichtigt. Das heißt: "abc" is equal to "ABC" -- Ergebnis: true Beide Zeichenketten werden also als gleich betrachtet. Textvergleiche lassen sich mit considering und ignoring, wie im Kapitel Kontrollstrukturen beschrieben, weitgehend beeinflussen. Falls die Groß- und Kleinschreibung zum Beispiel für den Vergleich wichtig ist, sieht das mit considering so aus:
213
SmartBooks
AppleScript
considering case "abc" is equal to "ABC" -- Ergebnis: false end considering Text besteht wie Listen aus einer geordneten Sequenz von Einzelelementen. Daher kann ein Vergleich sich auch auf einzelne Teilelemente oder Bereiche eines Textes beziehen. Verwenden Sie dafür die üblichen Formen der Textauswahl. Zum Beispiel: set meinText to "Die Schwerkraft habe ich nie vermisst." second word of meinText is equal to "Schwerkraft" -- Ergebnis: true oder set meinText to "Die Schwerkraft habe ich nie vermisst." characters 1 thru 3 of meinText is equal to ¬ characters 5 thru 7 of "Ah, die" -- Ergebnis: true Hier gibt es einen wichtigen Fallstrick zu beachten! Wie Sie ja bereits wissen ergibt die Abfrage eines Textbereiches eine Liste: set meinText to "Die Schwerkraft" characters 1 thru 3 of meinText -- Ergebnis: {"D", "i", "e"} Die Abfrage eines einzelnen Textelements ergibt aber einen Text: set meinText to "Die Schwerkraft" first word of meinText -- Ergebnis: "Die" Folgendes Ergebnis einer Abfrage könnte daher für Verwirrung sorgen: set meinText to "Die Schwerkraft" characters 1 thru 3 of meinText is equal to first word of "Die Sonne" -- Ergebnis: false Das Ergebnis dieses Vergleiches ist unwahr! Warum? Weil die Abfrage mit thru eine Liste mit den Zeichen 1 bis 3 zurückliefert {"D", "i", "e"} und first word den Text "Die". Das ergibt folgenden aufgelösten Vergleich: {"D", "i", "e"} is equal to "Die" -- Ergebnis: false Da zwei unterschiedliche Klassen niemals gleich sein können ergibt die Abfrage natürlich false.
214
Die Sprache
Kapitel 4
Hier müssen Sie also dafür sorgen, dass der Typ auf beiden Seiten gleich ist: set meinText to "Die Schwerkraft" characters 1 thru 3 of meinText as text is equal to ¬ first word of "Die Sonne" -- Ergebnis: true
Datum Bei einer Prüfung auf Gleichheit oder Ungleichheit ist ein Datum nur dann mit einem anderen Datum gleich, wenn es bis auf die letzte Sekunde identisch ist. set x to date "Freitag, 11. Mai 2007 0:00:00 Uhr" set y to date "Freitag, 11. Mai 2007 0:00:00 Uhr" x = y -- Ergebnis: true Wenn Ihnen das zu genau ist und Sie nur wissen wollen, ob der Datumsteil gleich ist, dann vergleichen Sie nur den Datumsteil: set x to date "Freitag, 11. Mai 2007 12:00:07 Uhr" set y to date "Freitag, 11. Mai 2007 3:30:15 Uhr" date string of x = date string of y -- Ergebnis: true Letztlich werden dadurch also nur zwei Texte mit dem Datumsteil verglichen. Genau so können Sie, durch die Abfrage anderer Bestandteile des Datums, auch diese auf Gleichheit prüfen.
greater than, less than Mit den hier behandelten Operatoren können Sie feststellen, ob ein Wert größer oder kleiner ist als ein anderer. Um das behaupten zu können, muss es sich natürlich um eine Klasse handeln, die sich auf irgendeine Weise messen lässt. Diese Art von Vergleich kann daher nicht auf alle Objekte angewendet werden und funktioniert daher nur bei den Klassen real, integer, text und date. Alle diese Operatoren sind binär, das heißt, dass links und rechts des Operators jeweils ein Operand erwartet wird. Die Auswertung geschieht von links nach rechts. Verwenden Sie folgende Schreibweisen um zu prüfen, ob der Wert vor dem Operator größer ist als der Wert danach:
215
SmartBooks
AppleScript
set {x, y} to {2, 3} x is greater than y -- Ergebnis: false oder x comes after y oder x>y Das is in is greater than können Sie beim Schreiben auch weglassen, es wird beim Kompilieren automatisch hinzugefügt. Verwenden Sie folgende Schreibweisen um zu prüfen, ob der Wert vor dem Operator kleiner ist als der Wert danach: set {x, y} to {2, 3} x is less than y -- Ergebnis: true oder x comes before y oder x
= y oder x≥y
216
Die Sprache
Kapitel 4
Das is und das to in is greater than or equal to können Sie beim Schreiben auch weglassen, es wird beim Kompilieren automatisch hinzugefügt. Das Zeichen ≥ erhalten Sie mit der Tastenkombination [alt]+[shift]+[<]. Die Schreibweisen für kleiner als oder gleich sehen so aus: set {x, y} to {2, 3} x is less than or equal to y -- Ergebnis: false oder x <= y oder x≤y Das is und das to in is less than or equal to können Sie beim Schreiben auch weglassen, es wird beim Kompilieren automatisch hinzugefügt. Das Zeichen ≤ erhalten Sie mit der Tastenkombination [alt]+[<].
Verneinungsformen Die obigen Aussagen können natürlich auch verneint werden. Für nicht größer als gibt es folgende Möglichkeiten: set {x, y} to {2, 3} x is not greater than y -- Ergebnis: true oder x does not come after y Sie können auch isn't greater than oder doesn't come after schreiben. Diese Form wird dann beim Kompilieren automatisch in eine der obigen Formen umgewandelt. Für nicht kleiner als gibt es folgende Möglichkeiten: set {x, y} to {2, 3} x is not less than y -- Ergebnis: false oder x does not come before y Sie können auch isn't less than oder doesn't come before schreiben. Diese Form wird dann beim Kompilieren automatisch in eine der obigen Formen umgewandelt. Für nicht größer als oder gleich gibt es folgende Schreibweise:
217
SmartBooks
AppleScript
set {x, y} to {3, 3} x is not greater than or equal to y -- Ergebnis: true Sie können auch das to in is not greater than or equal to weglassen oder isn't greater than or equal to schreiben. Beim Kompilieren wird dann automatisch in die obige Schreibweise umgewandelt. Für nicht kleiner als oder gleich gibt es folgende Schreibweise: set {x, y} to {3, 3} x is not less than or equal to y -- Ergebnis: true Sie können auch das to in is not less than or equal to weglassen oder isn't less than or equal to schreiben. Beim Kompilieren wird dann automatisch in die obige Schreibweise umgewandelt.
Implizite Typumwandlungen Wie beim equal-Operator müssen hier bei einem Vergleich beide Operanden von der gleichen Klasse sein. Im Gegensatz zu equal findet hier jedoch eine implizite Typumwandlung statt, falls die Klassen beider Operanden nicht gleich sein sollten. Sie können also durchaus Werte aus unterschiedlichen Klassen miteinander vergleichen. Dabei gilt es aber folgende Grundregel im Auge zu behalten: Der Wert rechts des Operators wird in den Wertetyp links des Operators umgewandelt. Ist das nicht möglich, gibt es eine Fehlermeldung zur Laufzeit, also erst wenn das Skript bereits läuft und nicht schon beim Übersetzen. 2 is greater than "1" -- Ergebnis: true Hier wird verglichen ob die Zahl 2 größer ist als der Text "1". Die Antwort ist erstaunlicherweise true, weil der Text "1" vor dem Vergleich in die Zahl 1 umgewandelt wird. Das bedeutet dann aber auch: Obwohl die »größer als«- und »kleiner als«-Operatoren nur für die Wertetypen Real, Integer, Text und Date verwendet werden können, dürfen auf der rechten Seite des Operators durchaus Listen erscheinen, wenn sich diese problemlos in den Typ links des Operators umwandeln lassen. So sind folgende Vergleichsmöglichkeiten durchaus möglich: "Anton" comes before {"B", "e", "r", "t", "a"} -- Ergebnis: true oder 3 is less than {4} -- Ergebnis: true
218
Die Sprache
Kapitel 4
Im ersten Fall wird die rechte Liste vor dem Vergleich in den Text "Berta" umgewandelt und im zweiten Fall wird die Liste {4} in die Integerzahl 4 umgewandelt. Befinden sich rechts aber mehrere Zahlen in der Liste schlägt der Vergleich fehl, allerdings erst zur Laufzeit: 3 is less than {4, 5} -- Fehler: {4, 5} kann nicht in Typ number umgewandelt werden. Doch was passiert nun, wenn auf der linken Seite und nicht auf der rechten Seite ein nicht erlaubter Wertetyp erscheint? Erst einmal meckert AppleScript beim Kompilieren nicht darüber, und nicht nur das, es versucht sogar den Wertetyp links vor dem Vergleich ebenfalls in eine Zahl, einen Text oder ein Datum umzuwandeln. So schlägt folgender Vergleich nicht fehl: {3} is less than 4 -- Ergebnis: true Sobald links jedoch mehrere Zahlen in der Liste stehen, gibt es wieder eine Fehlermeldung. Wenn links eine Liste mit Textelementen steht, schlägt die Konvertierung aber fehl: {"B", "e", "r", "t", "a"} comes after "Anton" Tatsächlich funktionieren auf der linken Seite wirklich nur einzelne Zahlen als einziges Element einer Liste. Hüten Sie sich aber davor diese Eigenart zu nutzen. Merken Sie sich, dass grundsätzlich versucht wird den Typ rechts des Operators in den Typ links des Operators umzuwandeln. Für alles andere sollten Sie immer explizite Typumwandlungen mit as anwenden. Sie ersparen sich damit unangenehme Überraschungen und schwer ermittelbare Fehler. Records funktionieren auf Grund ihrer »Ungeordnetheit« bei diesen Operatoren auf keiner Seite der Gleichung eine Rolle. Jeder Versuch diese Operatoren auf Records anzuwenden schlägt fehl, aber erst zur Laufzeit!
Zahlen Für Zahlen aller Art sind diese Operatoren ideal geeignet. Welche Zahl größer oder kleiner ist als eine andere ist immer zweifelsfrei ermittelbar und bei den kombinierten Operatoren ≤ und ≥ ist auch der seltene Fall einer Gleichheit mit berücksichtigt. set a to 2.736 set b to 2.735 a ≥ b --Ergebnis: true 219
SmartBooks
AppleScript
oder b ≤ a -- Ergebnis: true Wie bei allen Vergleichsoperatoren können auf beiden Seiten durchaus noch Berechnungen vorgenommen werden: set a to 2.736 set b to 2.735 a + 1 ≥ b - 1 --Ergebnis: true Beide Seiten werden vor dem Vergleich aufgelöst.
Listen Wie oben bereits erwähnt, sind diese Operatoren nicht für Listen gedacht. Listen können jedoch auf der rechten Seite eines Operators stehen und werden dort dann vor dem Vergleich in die Klasse des linken Operanden umgewandelt, soweit möglich. Da Listen viele unterschiedliche Elemente enthalten können, ist es immer besser explizit einzelne Elemente aus der Liste zu vergleichen. Verwenden Sie dafür die üblichen Listenreferenzen wie zum Beispiel. set a to {"Anton", "Berta"} item 1 of a comes before item 2 of a -- Ergebnis: true Wichtig ist auch hier, das auf beiden Seiten der selbe Wertetyp steht, ansonsten wird der rechte Operand in den Wertetyp des linken umgewandelt wie in folgendem Fall, wo der Text "5" für den Vergleich in die Zahl 5 umgewandelt wird. set a to {3, "5"} item 1 of a is less than item 2 of a -- Ergebnis: true
Records Records als Ganzes können Sie nicht mit diesen Operatoren vergleichen, jedoch durchaus einzelne Propertys, wenn diese eine Zahl, einen Text oder ein Datum darstellen: set a to {xWert:2.5, yWert:4, etikett:"A"} set b to {xWert:2.8, yWert:5, etikett:"B"} xWert of b is greater than xWert of a -- Ergebnis: true oder etikett of a comes before etikett of b
220
Die Sprache
Kapitel 4
Text Es mag verwundern, aber Text kann größer oder kleiner sein. Entscheidend dafür ist die Sortierreihenfolge der entsprechenden Sprache im Betriebssystem. Die Einstellung dafür verbirgt sich in den Landeseinstellungen in den Systemeinstellungen. Dort gibt es ein Einblendmenü namens Reihenfolge für sortierte Listen. Standardmäßig steht dieses auf Deutsch. Wenn Sie also einmal nach den Regeln einer anderen Sprache vergleichen wollen, müssen Sie dort vorher die Sprache umstellen. "Berta" is greater than "Anton" -- Ergebnis: true Das B kommt in unserem Alphabet nach dem A, deswegen ist Berta größer als Anton und die Aussage ist wahr. Da die Denkweise mit größer oder kleiner für das Alphabet sehr ungewöhnlich ist, hat Apple auch noch das Synonym comes after geschaffen, welches in Verbindung mit Text natürlicher klingt. "Berta" comes after "Anton" -- Ergebnis: true Berta kommt im Alphabet also nach Anton. Dieser Vergleich bezieht sich nicht nur auf den Anfangsbuchstaben eines Textes, sondern geht beliebig in die Tiefe: "Bilderbuch" comes before "Bilderrahmen" -- Ergebnis: true und auch über Wortgrenzen oder sogar Absätze hinweg: "Die Aussage ist unwahr" comes before "Die Aussage ist wahr" -- Ergebnis: true "Absatz A\rAbsatz B" comes before "Absatz A\rAbsatz C" -- Ergebnis: true Der Vergleich eignet sich jedoch nicht für Zahlengruppen wie zum Beispiel Versionsnummern oder IP-Adressen, wo jeder Bereich aus einer oder mehreren Zahlen bestehen kann! "192.168.1.7" comes before "192.168.1.22" -- Ergebnis: false Die 7 kommt nach der 2 und nicht davor (oben fett dargestellt). Daher ist diese Aussage falsch. Textvergleiche finden immer nur Zeichen für Zeichen statt. Für diesen Zweck ist es besser die text item delimiters auf den Punkt zu setzen und die vier Bereiche dann einzeln als text items zu extrahieren und dann als Integer zu vergleichen
221
SmartBooks
AppleScript
oder, noch einfacher, man verwendet die mit Tiger neu eingeführte Anweisung considering numeric strings: considering numeric strings "192.168.1.6" comes before "192.168.1.22" -- Ergebnis: true end considering Alle Textvergleiche lassen sich mit solchen considering oder ignoring Anweisungen beeinflussen. Beachten Sie hierzu den entsprechenden Abschnitt im Kapitel Kontrollstrukturen. Für Zahlen, die immer dieselbe Anzahl an Stellen haben, wie zum Beispiel Postleitzahlen, ist ein Vergleich in Textform aber durchaus direkt möglich und manchmal sogar sinnvoll, da man bei einer Umwandlung in eine Zahl führende Nullen verlieren würde.: "50000" comes after "09000" -- Ergebnis: true Ohne die führende Null bei "09000", wäre der Vergleich falsch, da die 5 im Alphabet vor der 9 kommt und nicht danach. Auch bei Vergleichen auf größer und kleiner können Sie natürlich wieder mit character, word, paragraph und text item Einzelelemente aus dem Text herauspicken und vergleichen: word 1 of "Anton und Berta" comes before word 3 of "Anton und Berta" -- Ergebnis: true Hier ein Beispiel, bei dem der Text in text items aufgespalten wird (am Doppelpunkt) und dann die Zahl im zweiten text item (dem Text hinter dem Doppelpunkt) als numeric string verglichen wird. set a to "FC Dussel: 16 Punkte" set b to "SV-Kickers: 9 Punkte" set text item delimiters to ":" considering numeric strings text item 2 of a comes after text item 2 of b -- Ergebnis: true end considering Aufgelöst sieht dieser Vergleich dann so aus: considering numeric strings " 16 Punkte" comes after " 9 Punkte" end considering Wegen der considering numeric strings-Anweisung wird der Vergleich der darin vorkommenden Zahlen, trotz vorangehender Leerstelle und nachfolgendem Text korrekt abgeschlossen.
222
Die Sprache
Kapitel 4
Auch das Zusammensetzen von Text mit dem &-Operator ist natürlich auf beiden Seiten der Aussage möglich. Der Text wird zusammengesetzt und erst dann verglichen. "abc" & "e" comes after "abc" & "d" -- Ergebnis: true
Datum Bei einer Prüfung auf größer oder kleiner gilt ein Datum als größer, wenn es zeitlich dem anderen folgt. Ein Datum in der Zukunft ist also immer größer als eines in der Vergangenheit. Auf Grund der zeitlichen Abfolge empfiehlt sich die Verwendung von comes after oder comes before, da wir im Zusammenhang mit Zeit ja nicht von größerer oder kleiner sprechen sonder von früher oder später: set x to date "Freitag, 11. Mai 2007 0:00:00 Uhr" set y to date "Sonntag, 13. August 1995 0:00:00 Uhr" x comes after y -- Ergebnis: true Die Genauigkeit liegt wieder bei einer Sekunde. Wenn ein Datum nur eine Sekunde später liegt, als ein anderes, ist es größer. Wenn diese Genauigkeit stört, extrahieren Sie mit date string den Datumsteil und wandeln Sie diesen mit date wieder zurück in ein Datum wodurch die Uhrzeit bei beiden auf 0 Uhr gestellt wird. set x to date "Sonntag, 13. August 1995 3:15:00 Uhr" set y to date "Sonntag, 13. August 1995 3:15:01 Uhr" x comes before y -- Ergebnis: true date (date string of x) comes after date (date string of y) -- Ergebnis: false
contains Der Operator contains prüft, ob in dem Wert links des Operators der Wert rechts des Operators enthalten ist. Mit anderen Worten, dieser Operator lässt sich nur mit Listen, Records und Text verwenden, denn nur diese können mehrere Elemente enthalten. Es handelt sich hier wieder um einen binären Operator der links und rechts von sich einen Operanden erwartet und der von links nach rechts ausgewertet wird. Verwenden Sie das Wort contains um zu ermitteln, ob ein Wert in einem anderen enthalten ist: set y to {1, 2, 3} y contains 3 -- Ergebnis: true Die Variable y enthält die Zahl 3.
223
SmartBooks
AppleScript
Sie können die Behauptung auch passiv darstellen: 3 is in {1, 2, 3} Die 3 ist enthalten in der Liste {1, 2, 3}. Bei dieser Schreibweise sind die Operanden umgekehrt angeordnet. Das heißt hier wird geprüft ob der Wert links des Operators in dem Wert rechts des Operators enthalten ist. Alternativ können Sie auch is contained by schreiben, welches dann beim Kompilieren in die obige Form umgewandelt wird.
Verneinungsformen Möchten Sie feststellen, ob ein Wert nicht enthalten ist, verwenden Sie die Form mit not: set y to {1, 2, 3} y does not contain 3 -- Ergebnis: false Sie können auch doesn't contain schreiben. Diese Form wird dann beim Kompilieren automatisch in obige Form umgewandelt. Für die passive Form: 3 is not in {1, 2, 3} -- Ergebnis: false Die Zahl 3 ist nicht enthalten in {1, 2, 3}. Alternativ können Sie auch isn't in, isn't contained by oder is not contained by schreiben. Diese Schreibweisen werden beim Kompilieren aber in die obige Form umgewandelt.
Implizite Typumwandlungen Die Operanden auf beiden Seiten müssen von derselben Klasse sein. Wenn das nicht der Fall ist wird bei contains versucht den Operanden rechts in den Wertetyp des linken Operanden zu konvertieren. Bei dem Operator is in umgekehrt, dort wird der linke Operand in den Typ des rechten umgewandelt. Bei dem Beispiel {1, 2, 3} contains 3 -- Ergebnis: true wird daher tatsächlich die 3 vorher in eine Liste konvertiert und dann verglichen: {1, 2, 3} contains {3} Das betrifft dann auch Text: {"a", "b", "c"} contains "b" -- Ergebnis: true 224
Die Sprache
Kapitel 4
wird tatsächlich so verglichen: {"a", "b", "c"} contains {"b"} Steht bei contains auf der linken Seite (bei is in auf der rechten) eine Zahl, so wird versucht diese vor dem Vergleich in eine Liste umzuwandeln. So ergibt folgender Vergleich daher true: 3 contains 3 -- Ergebnis: true Tatsächlich wird hier {3} contains {3} geprüft. Steht links jedoch Text, so wird dieser niemals in eine Liste umgewandelt, schließlich kann Text, anders als Zahlen, Einzelelemente enthalten und ist daher durchaus berechtigt links zu stehen. Steht auf der linken Seite daher Text, so wird auf der rechten Seite versucht den Wert ebenfalls in einen Text zu konvertieren: "a1bc" contains 1 -- Ergebnis: true Tatsächlich wird hier also folgendes verglichen: "a1bc" contains "1" -- Ergebnis: true
Zahlen Für Zahlen ist dieser Operator absolut nicht geeignet, auch wenn sich eine einzelne Zahl wie eben beschrieben mit einer einzelnen anderen Zahl auf diese Weise vergleichen lässt, so ist dafür doch eher der Gleichheitsoperator equal gedacht.
Listen Wie verhält es sich, wenn man danach fragt ob mehrere Listenelemente in einer anderen Liste enthalten sind? Die Grundregel lautet: Eine Liste von Elementen muss in der anderen Liste in derselben Reihenfolge, ohne Unterbrechungen vorkommen um als darin enthalten zu gelten. Listen sind geordnet, die Reihenfolge spielt daher immer eine Rolle: set y to {1, 2, 3, 4} y contains {1, 2} -- Ergebnis: true y contains {2, 1} -- Ergebnis: false
225
SmartBooks
AppleScript
Die Liste {2, 1} ist also nicht in y enthalten, obwohl jedes Element für sich (die 1 und die 2) durchaus in y vorkommen, aber halt nicht in dieser Reihenfolge. Wenn die abgefragte Liste jedoch in der Originalliste verschachtelt ist, erhalten Sie immer false: set y to {1, 2, {"a", "b"}} y contains {"a", "b"} -- Ergebnis: false Hier müssen Sie explizit mit dem entsprechenden Element in der Liste vergleichen: set y to {1, 2, {"a", "b"}} item 3 of y contains {"a", "b"} -- Ergebnis: true Oder Sie fragen explizit nach der vollständigen verschachtelten Liste: set y to {1, 2, {"a", "b"}} y contains {{"a", "b"}} -- Ergebnis: true Diese Art der Abfrage funktioniert nur mit einer ganzen Liste, also nicht mit einem einzelnen Element daraus! set y to {1, 2, {"a", "b"}} y contains {{"a"}} -- Ergebnis: false Hier müssen Sie daher wieder explizit nach dem Inhalt des entsprechenden Elements fragen: set y to {1, 2, {"a", "b"}} item 3 of y contains "a" -- Ergebnis: true Links und rechts des Operators können natürlich auch wieder Berechnungen stattfinden, die vor dem Vergleich zuerst ausgeführt werden: {1, 2 + 3, 3} contains {4 + 1} -- Ergebnis: true Aufgelöst sieht der Vergleich dann so aus: {1, 5, 3} contains {5} -- Ergebnis: true
Records Damit eine Property in einem Record als enthalten gilt, muss diese Property erstens vorhanden sein und zweitens auch denselben Wert enthalten. Ihre Position im Record spielt keine Rolle. {xRes:1024, yRes:768} contains {yRes:768} -- Ergebnis: true Ist die Property zwar vorhanden, besitzt aber einen anderen Wert, erhalten Sie false: {xRes:1024, yRes:768} contains {yRes:480} -- Ergebnis: false 226
Die Sprache
Kapitel 4
Vergleichen Sie mehrere Propertys spielt deren Reihenfolge im Gegensatz zu den Listen keine Rolle; Records sind ungeordnet. {xRes:1024, yRes:768, ratio:1.33} contains {yRes:768, xRes:1024} -- Ergebnis: true Da es keinen Wertetyp gibt, der sich in einen Record umwandeln lässt, bleiben Records unter sich. Es findet also keine implizite Konvertierung von Werten auf der rechten oder sogar linken Seite statt. Auf beiden Seiten muss immer ein Record stehen oder Sie erhalten eine Fehlermeldung. Folgender Ausdruck ergibt daher bei der Ausführung eine Fehlermeldung, {xRes:1024, yRes:768, ratio:1.33} contains 1024 -- Fehler: 1024 kann nicht in Typ record umgewandelt werden. Wenn Sie unbedingt prüfen müssen, ob ein einzelner Wert irgendwo in einem Record enthalten ist, wandeln Sie den Record vor der Prüfung in eine Liste um: ({xRes:1024, yRes:768, ratio:1.33} as list) contains 1.33 -- Ergebnis: true Aufgelöst ergibt das folgenden Vergleich: {1024, 768, 1.33} contains 1.33 Wenn es darum geht den Wert einer Eigenschaft in einem Record zu vergleichen, ist contains für Zahlen der falsche Operator. Verwenden Sie dann equals oder greater than/ less than. set a to {xRes:1024, yRes:768, ratio:1.33} xRes of a is equal to 1024 -- Ergebnis true Enthält die Property jedoch einen Text oder eine Liste, können Sie contains verwenden um zu ermitteln, ob darin ein bestimmtes Unterelement enthalten ist: set a to {titel:"Neuigkeiten", schlagwoerter:{"Unix", "Unicode"}} schlagwoerter of a contains "Unicode" -- Ergebnis true oder titel of a contains "Neu" -- Ergebnis true
Text Text verhält sich als geordneter Wertetyp beim Vergleich mit contains wie eine Liste. Das heißt, alle Werte rechts des Operators müssen in derselben Reihenfolge im Wert
227
SmartBooks
AppleScript
links des Operators vorkommen um das Ergebnis true zu erhalten. Bei is in natürlich umgekehrt. "Der Sommer kam." contains "omm" -- Ergebnis: true Auf der rechten Seite wird ebenfalls der Wertetyp Text erwartet, wenn dort kein Text steht, wird versucht in Text umzuwandeln. (Bei is in natürlich wieder der linke Wert) "Spielstand 1:0" contains 1 -- Ergebnis: true Hier wird die 1 vor dem Vergleich in den Text "1" konvertiert. Der tatsächlich stattfindende Vergleich lautet also: "Spielstand 1:0" contains "1" Für Text können Sie natürlich wieder alle bekannten Referenzen für einzelne Zeichen, Wörter, Absätze oder text items verwenden: set x to "Sonne und Mond" word 1 of x contains "n" -- Ergebnis true oder set x to "Sonne und Mond" x contains paragraph 2 of "Mars und Venus\rSonne und Mond" -- Ergebnis true Bei text items ist durch Setzen der text item delimiters wieder jede beliebige Trennung von Text möglich, wie hier an den Kommastellen: set x to "Merkur,Venus,Erde,Mars" set text item delimiters to "," text item 2 of x contains "Ven" -- Ergebnis: true Textvergleiche unterscheiden nicht zwischen Groß- und Kleinschreibung. Falls Sie dieses Verhalten (und andere) ändern möchten, schlagen Sie im Kapitel Kontrollstrukturen bei den considering- und ignoring-Anweisungen nach.
Datum Eine Prüfung auf Inhalt funktioniert bei einem Datum nicht: set x to date "Freitag, 11. Mai 2007 0:00:00 Uhr" x contains "Frei" -- Ergebnis: false Das liegt daran, dass das Datum anders gespeichert, als angezeigt wird. Wenn Sie prüfen wollen ob in einem Datum ein bestimmter Wert als Text enthalten ist, sollten Sie vorher die entsprechende Eigenschaft von date abfragen und diese dann vergleichen. Beachten Sie dann, dass Wochentage und Monatsnamen als Konstanten in
228
Die Sprache
Kapitel 4
englischer Sprache zurückgeliefert werden, also noch in Text oder Zahl umgewandelt werden müssen: set x to date "Freitag, 11. Mai 2007 0:00:00 Uhr" (weekday of x as text) contains "Fri" -- Ergebnis: true (Friday!) Sie können ein Datum nur dann auf Inhalt vergleichen, wenn beide Vergleichspartner vom Typ Datum sind und auch dabei wird immer ein komplettes Datum mit einem anderen verglichen. set x to date "Freitag, 11. Mai 2007 0:00:00 Uhr" set y to "11. Mai 2007" x contains date y -- Ergebnis: true Liegt das Datum auch nur eine Sekunde daneben, »enthält« es nicht mehr das andere. Statt einer Prüfung auf Inhalt sollte also besser gleich eine Prüfung auf Gleichheit stattfinden.
starts with, ends with Diese Operatoren funktionieren nur mit Listen und Text, denn nur diese können Elemente in geordneter Reihenfolge enthalten und damit über einen Anfang und ein Ende verfügen. Beide Operatoren sind binäre Operatoren, erwarten also auf beiden Seiten einen Operanden. Beide Operanden müssen dieselbe Klasse besitzen. Ist das nicht der Fall wird versucht den rechten Operanden in die Werteart des linken umzuwandeln. Die Auswertung erfolgt von links nach rechts. Wenn Sie prüfen möchten, ob eine Liste oder ein Text mit einem bestimmten Wert beginnt, so fragen Sie auf folgende Weise danach: set x to {"Grün", "Rot", "Blau"} x starts with {"Grün"} -- Ergebnis: true Alternativ können Sie auch folgende Form verwenden: set x to {"Grün", "Rot", "Blau"} x begins with {"Grün"} -- Ergebnis: true Um zu prüfen ob eine Liste mit einem bestimmten Wert aufhört: set x to {"Grün", "Rot", "Blau"} x ends with {"Blau"} -- Ergebnis: true
229
SmartBooks
AppleScript
Verneinungsformen Möchten Sie den Ausdruck verneinen, funktioniert das wieder mit does not: {"Grün", "Rot", "Blau"} does not start with {"Rot"} -- Ergebnis: true {"Grün", "Rot", "Blau"} does not end with {"Rot"} -- Ergebnis: true Sie können hier auch wieder doesn't schreiben. Diese Form wird beim Übersetzen dann automatisch in does not übersetzt.
Implizite Typumwandlungen Für diesen Operator ist es wichtig, dass die Operanden auf beiden Seiten von derselben Klasse sind. Wenn das nicht der Fall ist wird versucht den Operanden rechts in den Wertetyp des linken Operanden zu konvertieren. Steht links also zum Beispiel ein Text werden Werte rechts ebenfalls in einen Text umgewandelt. Bei "3 x Grün" starts with 3 -- Ergebnis: true wird also tatsächlich Folgendes verglichen: "3 x Grün" starts with "3" -- Ergebnis: true Steht links ein Text und rechts eine Liste, wird die Liste in Text konvertiert "Hans und Karl" starts with {"Hans", " ", "und"} -- Ergebnis: true Obiger Vergleich ergibt true wenn die text item delimiters auf "" stehen, also einen leeren Text. Verglichen wird dann tatsächlich Folgendes: "Hans und Karl" starts with "Hans und" -- Ergebnis: true Zur Erinnerung: Bei der Umwandlung einer Liste in Text werden die Einzelelemente mit dem aktuellen Wert des text item delimiters zusammengesetzt! Würden die text item delimiters zum Beispiel auf "," stehen würde es "Hans und Karl" starts with "Hans, ,und" heißen und der Vergleich wäre natürlich false. Immer wenn Sie Listen mit Text vergleichen sollten Sie den Wert der text item delimiters vorher explizit setzen! Steht links eine Liste und rechts ein Text wird der Text rechts in eine Liste konvertiert, und zwar in eine Liste mit einem einzigen Element, nämlich dem Text.
230
Die Sprache
Kapitel 4
Bei {"abc", "def"} starts with "abc" -- Ergebnis: true findet tatsächlich folgender Vergleich statt: {"abc", "def"} starts with {"abc"} -- Ergebnis: true Steht links eine Zahl wird diese in eine Liste umgewandelt (nicht in Text!) und der Wert rechts wird dann ebenfalls versucht in eine Liste zu konvertieren. 35 starts with 35 -- Ergebnis: true ergibt daher true da tatsächlich {35} starts with {35} -- Ergebnis: true verglichen wird.
Zahlen Für Zahlen ist dieser Operator nicht geeignet, auch wenn durch die implizite Typumwandlung eine links stehende Zahl vor dem Vergleich in eine Liste mit der Zahl als Element umgewandelt wird, sollten Sie davon nicht Gebrauch machen.
Listen Eine Liste von Elementen muss in der anderen Liste in derselben Reihenfolge, ohne Unterbrechungen am Anfang oder Ende vorkommen um als damit beginnend oder endend zu gelten. set y to {1, 2, 3, 4} y starts with {1, 2} -- Ergebnis: true y starts with {2, 1} -- Ergebnis: false Wenn der Anfang oder das Ende der Liste eine Unterliste ist, erhalten Sie false: set y to {1, 2, {"a", "b"}} y ends with {"a", "b"} -- Ergebnis: false Hier müssen Sie explizit mit dem entsprechenden Element in der Liste vergleichen: set y to {1, 2, {"a", "b"}} item -1 of y ends with {"a", "b"} -- Ergebnis: true Oder Sie fragen explizit nach der vollständigen verschachtelten Liste: set y to {1, 2, {"a", "b"}} y ends with {{"a", "b"}} -- Ergebnis: true Diese Art der Abfrage funktioniert nur mit der ganzen Unterliste, also nicht mit einem einzelnen Element daraus!
231
SmartBooks
AppleScript
set y to {1, 2, {"a", "b"}} y ends with {{"b"}} -- Ergebnis: false Hier müssen Sie daher explizit nach dem Inhalt des entsprechenden items fragen: set y to {1, 2, {"a", "b"}} item 3 of y starts with "a" -- Ergebnis: true Der Ausdruck rechts oder links kann natürlich auch das Element einer Liste sein: set x to {"Grün", "Rot", "Blau", {1, 2, 3}} x starts with item 1 of {"Grün", "Rot", "Blau"} -- Ergebnis: true oder: set x to {"Grün", "Rot", "Blau", {1, 2, 3}} second item of x starts with "R" -- Ergebnis: true Die Ausdrücke können natürlich auch das Ergebnis einer Berechnung und impliziten Konvertierung in eine Liste sein: set x to {"Grün", "Rot", "Blau", {1, 2, 3}} x starts with "G" & "r" & "ü" & "n" -- Ergebnis: true Links und rechts des Operators können natürlich auch hier wieder Berechnungen stattfinden, die vor dem Vergleich zuerst ausgeführt werden: {1, 2, 3 + 2} ends with {4 + 1} -- Ergebnis: true Aufgelöst sieht der Vergleich dann so aus: {1, 2, 5} ends with {5} -- Ergebnis: true
Records Für Records können diese Vergleichsoperatoren nicht verwendet werden, da diese ungeordnet sind.
Text Bei Text verhält es sich wie mit den Listen. Der Text auf der rechten Seite muss komplett am Anfang oder Ende des Textes auf der linken Seite enthalten sein und zwar Zeichen für Zeichen in derselben Reihenfolge. "Die Sonne" starts with "Die" -- Ergebnis true oder "Die Sonne" ends with "onne" -- Ergebnis true 232
Die Sprache
Kapitel 4
Wenn auf der rechten Seite eine Liste steht, wird diese vor dem Vergleich implizit in Text umgewandelt: "Die Sonne" starts with {"D", "i", "e"} -- Ergebnis true was dasselbe ist wie die explizite Umwandlung mit as: "Die Sonne" starts with ({"D", "i", "e"} as text) Der Vergleich kann auch über einzelne Elemente erfolgen: character 3 of "Die Sonne" starts with "e" -- Ergebnis: true 2nd word of "Die Sonne" starts with "So" -- Ergebnis: true first paragraph of "Die Schwerkraft\rDie Schwerelosigkeit" ends with "kraft" -- Ergebnis: true Besonders nützlich ist die Abfrage nach text items, da sich diese über die text item delimiters frei definieren lassen: set text item delimiters to ":" text item 2 of "Frankfurt:München" starts with "Mün" -- Ergebnis: true Auch auf der rechten Seite können natürlich Elemente eines Textes stehen: set text item delimiters to ", " set x to "Meier, Hans, München" text item 3 of x starts with text item 2 of "Ham, Mün, Ber" -- Ergebnis: true Textvergleiche in AppleScript beachten standardmäßig nicht die Groß- und Kleinschreibung. "Die Schwerkraft" starts with "die" -- Ergebnis true Ob bei einem Textvergleich die Groß- und Kleinschreibung sowie andere Kriterien berücksichtigt werden, lässt sich mit den considerung- und ignoring-Anweisungen beeinflussen, die im Kapitel Kontrollstrukturen behandelt werden.
Datum Ein Datum selbst kann nicht mit starts with oder ends with verglichen werden. Auch hier gilt wieder: Erst eine Eigenschaft des Datums abfragen und dann erst auf den so gewonnenen Text diesen Operator anwenden. set x to date "Freitag, 11. Mai 2007 0:00:00 Uhr" date string of x starts with "Frei" -- Ergebnis: true 233
SmartBooks
AppleScript
and, or Jede der bisherigen Aussagen, die ja alle einen Wahrheitswert zurückliefern, also entweder true oder false, lassen sich auch mit einem und oder oder mit weiteren Aussagen verknüpfen. In AppleScript werden diese Operatoren natürlich auf Englisch and und or genannt. Bei beiden handelt es sich um binäre Operatoren, das heißt Sie benötigen zwei Operanden. In diesem Fall zwei Aussagen, eine links und eine rechts des Operators. Beide Aussagen müssen einen booleschen Wert ergeben. Andere Wertetypen sind nicht erlaubt. Ausgewertet wird immer von links nach rechts, es sei denn es wurde mit Klammern eine andere Reihenfolge forciert.
and Mit and können mehrere Vergleiche verbunden werden: set x to {"Grün", "Rot", "Blau"} item 1 of x equals "Grün" and item 2 of x starts with "R" In obigem Fall werden zwei Aussagen mit einander verknüpft, einmal die Aussage item 1 of x equals "Grün" welche hier true als Ergebnis zurückliefert und einmal die Aussage item 2 of x starts with "R" welche ebenfalls zutrifft und damit true ergibt. Nach Auflösung beider Seiten entsteht also Folgendes: true and true Wenn Sie das als Skript schreiben und ausführen lassen, erhalten Sie ebenfalls true als Ergebnis. Und das ist das ganze Geheimnis von mit und verknüpften Aussagen. Alle Einzelaussagen müssen zutreffen, damit die Gesamtaussage wahr ist. Ist auch nur eine der Einzelaussagen falsch, so ist die gesamte Aussage falsch. Verkürzt lässt sich das so auch als Code schreiben und damit im Skripteditor Zeile für Zeile verifizieren: true and true -- Ergebnis: true true and false -- Ergebnis: false false and true -- Ergebnis: false false and false -- Ergebnis: false
234
Die Sprache
Kapitel 4
Genau genommen findet eine so genannte Kurzschlussauswertung (short-circuiting) statt. Da bei dem ersten auftreten eines false das Ergebnis nicht mehr wahr sein kann, wird die Auswertung bereits abgebrochen und die restlichen Aussagen werden nicht mehr überprüft. Nur wenn alle Werte wahr sind, mussten tatsächlich alle Aussagen überprüft werden. Das betrifft auch mehr als zwei verknüpfte Aussagen: set x to {"Grün", "Rot", "Blau"} item 1 of x equals "Grün" and 2nd item of x starts with "R" ¬ and item -1 of x contains "au" Alle drei Aussagen treffen zu und damit ist die gesamte Aussage wahr. Würde auch nur eine einzige der Einzelaussagen false als Ergebnis zurückliefern, wäre auch die gesamte mit und verknüpfte Aussage falsch, wie sich leicht überprüfen lässt: true and true and true -- Ergebnis: true true and false and true -- Ergebnis: false
or Wenn man mehrere Vergleiche mit or verknüpft, so bedeutet das, dass es reicht, wenn eine der Aussagen wahr ist, um die gesamte Aussage wahr werden zu lassen. set x to {"Grün", "Rot", "Blau"} x contains "Grün" or x contains "Gelb" --Ergebnis: true x contains "Grün" ergibt true als Ergebnis. x contains "Gelb" ergibt false als Ergebnis. Zusammengefasst sieht die Aussage also so aus: true or false -- Ergebnis true Nur die erste Aussage ist wahr, trotzdem ergibt die gesamt Aussage wahr als Ergebnis. Mit or verknüpfte Vergleiche funktionieren folgendermaßen: true or true -- Ergebnis: true true or false -- Ergebnis: true false or true -- Ergebnis: true false or false -- Ergebnis: false
235
SmartBooks
AppleScript
Grundlagen Bei and kommt also true heraus wenn alle Teilaussagen wahr sind. Bei or kommt false heraus wenn alle Teilaussagen falsch sind. Das or ist also großzügiger, ihm reicht es wenn eine Aussage dabei ist, die stimmt, um grünes Licht zu geben und true als Ergebnis abzuliefern. Das and besteht immer auf eine lückenlose Wahrheit aller Aussagen. Auch bei or findet eine Kurzschlussauswertung statt. Das heißt die Überprüfung der Aussagen wird abgebrochen sobald die erste Aussage wahr ist. Nur wenn alle Aussagen falsch sind wurden tatsächlich alle Aussagen geprüft.
Klammern Es spielt keine Rolle wie viele Aussagen Sie mit and oder or verknüpfen, die Aussagen werden immer von links nach rechts ausgewertet bis die erste unwahre oder wahre Aussage aufgetreten ist. Bei sehr umfangreichen Verknüpfungen kann es hilfreich und manchmal sogar unumgänglich sein, die einzelnen Aussagen zu klammern um den Bezug der Vergleiche klarzustellen. Im folgenden Beispiel dienen die Klammern nur der klareren Gliederung für den Programmierer, könnten also genauso gut weggelassen werden: (item 1 of x equals "Grün") and (item 2 of x starts with "R") Im nächsten Beispiel sind die Klammern Pflicht, ja, werden hier sogar vom Skripteditor automatisch hinzugefügt. In anderen Fällen meckert der Skripteditor beim Kompilieren über den Ausdruck weil er ihn nicht versteht. Helfen Sie ihm dann mit Klammern auf die Sprünge. set {a, b, c, d} to {false, true, false, false} a is equal to (b is equal to c) and d --Ergebnis: false Der Operator equals hat eine höhere Priorität als der Operator and, wird also vorher aufgelöst. Vielleicht wollten Sie aber zuerst c and d auflösen? Dann müssen Sie auch die Klammern entsprechend setzen: set {a, b, c, d} to {false, true, false, false} a is equal to (b is equal to (c and d)) --Ergebnis: true 236
Die Sprache
Kapitel 4
Tipp Eine genaue Tabelle zur Reihenfolge der Operatoren finden Sie im Anhang. Statt diese Tabelle auswendig zu lernen, würde ich Ihnen jedoch generell raten großzügig mit Klammern umzugehen. Das ist kein Zeichen von Schwäche, sondern erleichtert das Verständnis wesentlich, auch wenn Sie sich den Code später nach längerer Zeit einmal wieder ansehen. Ohne Klammern müssten Sie sich für eine komplizierte Aussage erst einmal wieder die Operator-Reihenfolge verdeutlichen, um dann Stück für Stück die Aussage aufzubröseln, bevor Sie verstehen, was genau eigentlich verglichen wird.
not Jede Aussage lässt sich mit einem vorgeschaltetem not-Operator ins Gegenteil verkehren. Viele der obigen Vergleichsoperatoren besitzen natürlich bereits eine eigene negierte Aussageform wie zum Beispiel does not equal to. Mit not können Sie diese aber noch einmal ins Gegenteil umkehren. Als unärer Operator bezieht sich not immer nur auf eine einzelne Aussage, und zwar auf die ihm unmittelbar folgende. (Im Gegensatz zu den binären Operatoren and und or wo sich rechts und links jeweils eine Aussage befinden muss.) not "Berta" comes before "Anton" -- Ergebnis: true Für comes before und comes after gibt es ja keine eigene Verneinungsform in der Form wie comes not before/after. Hier ist es daher nötig die Aussage mit dem not-Operator am Anfang der Aussage umzukehren. Bei und-/oder-verknüpften Aussagen ist es eventuell schwer erkennbar worauf sich das not eigentlich bezieht: not "Anton" comes after "B" and "Berta" comes before "A" --Ergebnis: false Worauf bezieht sich hier das not am Anfang? Auf die erste Aussage: "Anton" comes after "B" oder auf beide Aussagen? Wenn Sie das so schreiben bezieht sich das not immer nur auf die erste darauf folgende Aussage, also auf "Anton" comes after "B". Wenn beide Aussagen verneint werden sollen, müssen Sie der zweiten Aussage daher ebenfalls noch ein not voranstellen: not "Anton" comes after "B" and not "Berta" comes before "A" -- Ergebnis: true
237
SmartBooks
AppleScript
Das Ergebnis dieser Aussage wird folgendermaßen aufgelöst: not false and not false -- Ergebnis: true Zuerst werden also die Einzelaussagen ausgewertet welche beide false ergeben und dann erst werden diese vom not in das Gegenteil verkehrt: true and true -- Ergebnis: true Wenn Sie jedoch das Gesamtergebnis beider Aussagen negieren wollen, sollten Sie die gesamte Aussage klammern und dann ein not davor einfügen: not ("Anton" comes after "B" and "Berta" comes before "A") -- Ergebnis: true Die beiden Aussagen in der Klammer werden zuerst ausgewertet und ergeben dann: (false and false) -- Ergebnis: false Dieses false wird dann mit not umgekehrt: not (false) -- Ergebnis: true Beachten Sie, das beide Vorgehensweisen, das Verneinen jeder einzelnen Aussage und das Verneinen der Gesamtaussage zwei völlig unterschiedliche Vorgehensweisen sind und daher nicht unbedingt zum selben Ergebnis führen müssen, wie man an dem folgenden Beispiel sieht: not "Anton" comes after "B" and not "Berta" comes before "C" -- Ergebnis: not false and not true -- Ergebnis: true and false -- Ergebnis: false Dagegen führt die Klammerung des gesamten Ausdrucks zu einem wahren Ausdruck: not ("Anton" comes after "B" and "Berta" comes before "C") -- Ergebnis: not (false and true) -- Ergebnis: not (false) -- Ergebnis: true Eine klare Planung, was genau herausgefunden werden soll, ist daher von großer Wichtigkeit.
238
Die Sprache
Kapitel 4
Umwandlung von booleschen Werten Die booleschen Werte true oder false können auch in eine Liste, in Text oder in eine Ganzzahl umgewandelt werden. true as list -- Ergebnis: {true} Bei der Verwendung des &-Operators entsteht ebenfalls eine Liste: true & false -- Ergebnis: {true, false} solange man diese nicht explizit in Text umwandelt: true & false as text -- Ergebnis: "truefalse" So können Sie dann auch einen booleschen Wert in einen Text umwandeln: true as text -- Ergebnis: "true" Interessant wird es wenn man true oder false in eine Ganzzahl konvertiert: true as integer -- Ergebnis: 1 false as integer -- Ergebnis: 0 Wahr entspricht also in Zahlen ausgedrückt einer Eins und falsch einer Null.
Umwandlung in boolesche Werte Wie eben gesehen, wird ein boolescher Wert, der in eine Ganzzahl konvertiert wird, in eine 1 oder 0 umgewandelt. Was passiert nun, wenn ich eine Zahl in einen booleschen Wert umwandle? 1 as boolean -- Ergebnis: true 0 as boolean -- Ergebnis: false Soweit verhält es sich wie erwartet. 3 as boolean ergibt jedoch einen Fehler, ebenso jede andere Zahl. Es kann also nicht jede beliebige Zahl als boolescher Wert interpretiert werden, wie das in anderen Programmiersprachen oft der Fall ist, wo die Null false ergibt und alle anderen Zahlen immer true sind. Bei Text verhält es sich anders. Egal welchen Text Sie nehmen, Sie erhalten immer den booleschen Wert false, außer Sie verwenden wirklich "true" als Text.
239
SmartBooks
AppleScript
"0" as boolean -- Ergebnis: false "1" as boolean -- Ergebnis: false "" as boolean -- Ergebnis: false "true" as boolean -- Ergebnis: true !!! "false" as boolean -- Ergebnis: false Die Groß- Kleinschreibung spielt übrigens keine Rolle. Der Text kann also auch "TRUE" geschrieben werden. Auch considering case hat darauf übrigens keinen Einfluss! Wenn Sie eine Liste in einen booleschen Wert umwandeln möchten, so darf diese Liste nur einen Wert enthalten und dieser muss ein boolescher Wert sein oder den Text "true" oder "false" enthalten: {true} as boolean -- Ergebnis: true {"true"} as boolean -- Ergebnis: true Enthält die Liste mehrere Elemente, gibt es eine Fehlermeldung, dass die Liste nicht in den Typ boolean umgewandelt werden kann.
240
Die Sprache
Kapitel 4
Kontrollstrukturen Wie Sie bereits wissen, werden Appleskripts in der Regel von oben nach unten, Zeile für Zeile, ausgeführt. Für einfache Rezepte wie bei einem Kochrezept, wo Schritt für Schritt vorgegangen wird, ist das auch durchaus ausreichend. Doch was ist, wenn in dem Rezept steht: »Falls Sie keine Butter haben, nehmen Sie Margarine«? An diesem Punkt tritt eine Verzweigung im Programm auf. Entweder, Sie fahren mit Butter oder mit Margarine fort, beides geht nicht. Auf den Finder angewendet, könnte es zum Beispiel heißen: »Wenn der Ordner "Briefe 2008" existiert, öffne ihn, ansonsten lege diesen Ordner an und öffne ihn.« Mit solchen Verzweigungen sind Sie wesentlich flexibler und können Ihr Skript auch für die widrigsten Tücken des Computeralltags fit machen. Des Weiteren kann es bei Anweisungen in einem Kochrezept auch heißen: »Rühren Sie, bis die Sahne steif wird.« Das heißt, Sie müssen mit einer Aktion solange fortfahren, bis ein bestimmtes Ereigniss eingetreten ist, hier, bis die Sahne steif wird. Auf ein Programm angewendet, könnte es zum Beispiel heißen: »Öffne nacheinander die Dateien im Ordner "Briefe 2008", bearbeite sie und speichere sie unter anderem Namen im Ordner "Archiv" ab, bis alle Dateien im Ordner "Briefe 2008" bearbeitet wurden.« Hier wird die Anweisung in einer Schleife so lange fortgesetzt, bis die Endbedingung eingetreten ist, nämlich die Bearbeitung aller Dateien im Ordner "Briefe 2008". Verzweigungen und Schleifen sind die grundlegendsten Kontrollstrukturen in jeder Programmiersprache. Im Folgenden werden diese an praktischen Beispielen direkt ausprobiert. Jetzt geht es also in die Praxis der Steuerung, wobei ich hauptsächlich den Finder als Übungsprogramm verwende. Auf diese Weise lernen Sie nebenbei auch gleich, wie man diesen steuert.
Anreden mit tell Wenn Sie in AppleScript einem bestimmten Objekt einen Befehl geben wollen, dann müssen Sie den Befehl natürlich auch an dieses Objekt richten, es also als Ziel bestimmen. Das wird mit dem Schlüsselwort tell gemacht. Da AppleScript dazu dient, andere Programme zu steuern, brauchen Sie diese Möglichkeit, um zu bestimmen, welche Anwendung oder welches Objekt nun gesteuert werden soll.
241
SmartBooks
AppleScript
tell auf einer einzelnen Zeile Wenn es sich um einen einzelnen Befehl handelt, geht das auf einer einzigen Zeile: tell application "Finder" to make new Finder window Da sich dieser Befehl an ein Programm richtet, muss dies explizit mit application gesagt werden. Sie können sich Schreibarbeit sparen und application auch mit app abkürzen. Der Programmname muss darauf in Anführungszeichen folgen. Dieser Befehl weist das Programm mit dem Namen Finder an, ein neues Fenster zu öffnen. Make ist ein Befehl, mit dem neue Objekte erzeugt werden (jedoch keine elementaren AppleScript-Objekte wie die Werteklassen integer, list usw.), und welcher von jedem Programm meist auf eigene Art und Weise implementiert wird. Das new kann hier übrigens auch weggelassen werden, in anderen Fällen kann es jedoch erforderlich sein.
tell als Blockanweisung Haben Sie mehr als nur einen einzelnen Befehl an das Programm zu richten, wäre es mühsam, auf jeder Zeile immer tell application "Programmname" to Befehlsanweisung zu schreiben. Verwenden Sie dann besser die Blockform von tell: tell application "Finder" activate make new Finder window end tell Alles, was sich hier zwischen tell und end tell befindet, richtet sich an den Finder als Ziel. Mit dem Befehl activate wird dafür gesorgt, dass der Finder »aktiviert« wird. Er tritt damit als aktives Programm in den Vordergrund. Falls Ihr Bildschirm mit anderen Fenstern zugepflastert ist, würden Sie sonst das neu erzeugte Fenster nicht sofort sehen.
Das implizite tell und die Schlüsselwörter AppleScript, me und my Konsequenterweise lässt sich ein tell auch an AppleScript selbst richten, das Ziel ist dann das Skript als oberstes Objekt: set x to {1, 2, 3} tell AppleScript to get length of x Hier wird die property length, welche ja jede Liste besitzt, abgefragt. Da eine Liste ein Objekt von AppleScript ist, ist die Adressierung also durchaus richtig.
242
Die Sprache
Kapitel 4
Normalerweise macht man das natürlich auf die einfache Art: length of x Genau genommen handelt es sich aber wirklich um eine abgekürzte Form. Wenn Sie kein bestimmtes Ziel mit einem tell angeben, ist immer das Skript selber das Ziel. Sie können ein tell sogar an eine Variable wie x selbst richten, da auch die grundlegenden Wertetypen in AppleScript Objekte sind: set x to {1, 2, 3} tell me to tell x to get length Solchen Konstruktionen werden Sie aber normalerweise nie begegnen, da, wie gesagt, beim Fehlen eines Ziels, automatisch das Skript das Ziel ist und damit auch die darin enthaltenen Variablen. Wenn Sie aber eine Eigenschaft von AppleScript wie zum Beispiel die text item delimiters verändern wollen, so ist es, wenn diese innerhalb des tell-Blocks an eine andere Anwendung stehen, nötig, explizit drauf hinzuweisen, dass es sich um die text item delimiters von AppleScript handelt und nicht um eine Eigenschaft der Anwendung. So liefert folgende Verwendung der text item delimiters einen Fehler: tell application "Finder" --Anweisungen an den Finder set text item delimiters to "," --Anweisungen an den Finder end tell Der Finder kennt keine text item delimiters, und deswegen schlägt die Ausführung des Skripts fehl. Wenn Sie jedoch einfach ein my oder AppleScript's davor setzen, funktioniert es sofort: tell application "Finder" --Anweisungen an den Finder set my text item delimiters to "," --Anweisungen an den Finder end tell Statt AppleScript können Sie auch das Wort my oder me verwenden. Me wird in der Form mit einem besitzanzeigenden führendem of verwendet (of me). set text item delimiters of me to ","
243
SmartBooks
AppleScript
Wenn Sie also einmal Probleme haben sollten, dass ein Begriff nicht erkannt wird, überlegen Sie zuerst, zu welchem Programm dieser Begriff gehört. Wenn es sich bei der vom Skripteditor angemahnten Stelle um grundlegende AppleScript-Terminologie handelt, die sich in einem tell-Block an eine Anwendung befindet, dann kann es manchmal erforderlich sein, darauf explizit hinzuweisen. Das betrifft insbesondere die text item delimiters, unter Umständen aber auch andere Objekte von AppleScript, nämlich dann, wenn die Anwendung ebenfalls eine solche Eigenschaft implementiert hat. So ist zum Beispiel version eine Eigenschaft in AppleScript, welche die Versionsnummer von AppleScript zurückliefert. Der Finder und alle Programme kennen aber ebenfalls eine Eigenschaft namens version. Eine Abfrage danach in einem tell-Block an den Finder führt daher zur Ermittlung der Version des Finders und nicht von AppleScript: tell application "Finder" to get version -- Ergebnis: "10.5.6" Fragen Sie jedoch nach my version oder version of me, erhalten Sie die Versionsnummer von AppleScript selber, obwohl Sie die Anfrage an den Finder richten: tell application "Finder" to get version of me -- Ergebnis: "2.0.1" Dasselbe ist beim Aufruf eines Handlers nötig, wenn dieser innerhalb eines tell-Blocks an eine Anwendung steht, wie im Kapitel Handler beschrieben. Tipp Normalerweise werden Sie die Schlüsselwörter AppleScript, me oder my außer beim Aufruf von Handlern und bei text item delimiters eher selten benötigen, da fast alle Objekte von AppleScript von einer Anwendung in Ruhe gelassen, also nicht überschrieben werden. Denken Sie jedoch daran, wenn Sie einmal ein ungewöhnliches Ergebnis erhalten sollten. Die Ursache kann dann darin liegen, dass das Programm einen Begriff aus AppleScript wieder verwendet hat. Ein my hilft dann weiter. Zusammengefasst läst sich also sagen: Wenn Codezeilen sich in keinem tell-Block befinden, so bedeutet das nicht, dass die Anweisungen in diesen Zeilen kein Ziel hätten, sondern das sich diese immer an das Skript als Ziel richten (zu Skripts als Objekten siehe Kapitel Skriptobjekte). Um innerhalb des tell an eine Anwendung auf ein Objekt von AppleScript zuzugreifen, kann es erforderlich werden, dies explizit mit den Schlüsselwörtern AppleScript, me oder my anzuzeigen.
Explizite Zielbestimmung mit dem Schlüsselwort it So wie man mit my oder me explizit auf das Skript als oberstes Objekt Bezug nehmen kann, so kann man mit dem Schlüsselwort it oder its explizit noch einmal auf das Ziel des tell-Blocks Bezug nehmen.
244
Die Sprache
Kapitel 4
Befindet sich it in keinem tell-Block, so ist damit das Skript als Ziel gemeint. In diesem Fall unterscheidet sich it also nicht von me oder my. it -- Ergebnis: «script» me -- Ergebnis: «script» Wenn sich it jedoch in einem tell-Block befindet, so bezieht sich it immer auf das mit tell referierte Ziel, me bleibt jedoch immer auf das Skript gerichtet: tell application "Finder" me -- Ergebnis: «script» it -- Ergebnis: application "Finder" end tell Merken Sie sich diesen Unterschied zwischen it und me/my sehr gut. Das me bezieht sich immer auf das Skript, it jedoch immer auf das Ziel des tell. Nur wenn ein tell nicht vorhanden ist, bezieht sich it ebenfalls auf das Skript. Meistens ist die Verwendung von it nicht notwendig, es kann jedoch manchmal unverzichtbar werden, zum Beispiel dann, wenn eine Anwendung denselben Namen für eine Klasse und eine Eigenschaft verwendet. Hier ist es dann nötig, mit it darauf hinzuweisen, dass die Eigenschaft des Ziels gemeint ist, wie bei der Property container der Klasse desktop-object. Der Begriff container ist gleichzeitig aber auch eine Klasse des Finders: tell application "Finder" tell desktop container end tell end tell -- Ergebnis: container tell application "Finder" tell desktop its container end tell end tell -- Ergebnis: folder "Detlef" of folder "Users" of startup disk of application "Finder" Mit its wird hier also klargestellt, dass die Eigenschaft container des Ziels desktop gemeint ist. Sie erhalten dann den Ordner, in welchem der Ordner Schreibtisch liegt, also Ihren Heimordner.
245
SmartBooks
AppleScript
Objekthierarchien Wie mit tell desktop gezeigt, können Sie ein tell auch an ein Objekt eines Programms richten, Sie müssen dafür nur deutlich machen, zu welchem Programm dieses Objekt gehört. Für einen einzelnen Befehl kann man dafür mehrere tell auf einer Zeile mit to verbinden. Die Zeile kann dann allerdings sehr lang werden: tell application "Finder" to tell Finder window 1 to set collapsed to true Diese Zeile bedeutet übersetzt: »Sage der Anwendung "Finder", sie soll dem Fenster 1 sagen, es soll sich ins Dock minimieren (seine Eigenschaft collapsed auf true setzen).« Die Hierarchie wird hier von oben nach unten, also von der »großen« Anwendung bis zum »kleinsten« Anwendungsobjekt vorgenommen. Durch Schachtelung mit of kann man auch vom kleinsten Objekt nach oben klassifizieren. Nur das »Mutter«-Objekt, also die Anwendung, muss immer in einem eigenen tell stehen bleiben. Folgende Klassifizierung schlägt daher fehl: set collapsed of Finder window 1 of app "Finder" to true Wenn Sie jedoch dem Finder ein eigenes tell gönnen, funktioniert es: tell application "Finder" set collapsed of Finder window 1 to true end tell Alternativ können Sie das Programm auch an den Anfang der Zeile stellen und dahinter mit of weiter klassifizieren: tell application "Finder" to set collapsed of Finder window 1 to true Haben Sie mehrere Befehle für ein Objekt, so verwenden Sie dafür am besten die geschachtelte Blockform: tell application "Finder" tell Finder window 1 activate properties -- weitere Befehle end tell end tell
246
Die Sprache
Kapitel 4
Hier wird also innerhalb des tell-Blocks an den Finder ein weiterer tell-Block eingefügt, der sich an das Fenster Nummer 1 richtet. Das Fenster mit der Indexnummer 1 ist das zuletzt im Vordergrund befindliche. Mit activate wird es nach vorne geholt, also zum aktiven Fenster gemacht. Ist kein Finderfenster geöffnet, erhalten Sie eine Fehlermeldung. Hilfe Mit properties können Sie sich alle Eigenschaften eines Objekts, wie oben die eines Finderfensters, auch gleich im Ergebnisbereich des Skripteditors anzeigen lassen, ohne extra das Funktionsverzeichnis des Finders öffnen zu müssen. Das funktioniert auch mit anderen Objekten und in vielen anderen Programmen – aber leider nicht in allen! Die Eigenschaften eines Finderfensters (nach Ausführung des vorigen Codes) sehen zum Beispiel so aus: (Greifen Sie auf diese Liste zurück, wenn auf den folgenden Seiten mit Fenstern herumgespielt wird und Sie nicht gerade am Rechner sitzen.) {class:Finder window, id:1536, name:"Detlef", position:{350, 108}, bounds:{350, 108, 1177, 852}, index:1, zoomed:false, closeable:true, titled:true, floating:false, modal:false, resizable:true, zoomable:true, visible:true, collapsed:false, target:folder "Detlef" of folder "Users" of startup disk of application "Finder", current view:list view, icon view options:icon view options of Finder window id 1536 of application "Finder", list view options:list view options of Finder window id 1536 of application "Finder", column view options:column view options of Finder window id 1536 of application "Finder", toolbar visible:true, statusbar visible:true, sidebar width:0}
247
SmartBooks
AppleScript
Diese Eigenschaften eines Fensters können Sie mit einem einfachen set propertyname to wert ändern. Weitere Details zu den Eigenschaften eines Fensters finden Sie im Funktionsverzeichnis des Finders unter der Rubrik Window classes. Dort können Sie auch sehen, dass sich manche der Eigenschaften nicht von Ihnen verändern lassen. Diese sind im Funktionsverzeichnis mit dem Kürzel r/o, also read only, gekennzeichnet. Diese Informationen können Sie zwar zu Informationszwecken auslesen, aber nicht verändern. Im Funktionsverzeichnis können Sie auch sehen, dass Finder window von der Klasse windows abstammt. Das heißt, Sie können auch tell window 1 schreiben, statt tell Finder window 1, würden dann aber auch andere Fenstertypen wie zum Beispiel Informationsfenster erwischen, welche nicht alle Eigenschaften mit einem Finder window teilen. Bei einem einzigen Befehl an ein Objekt verwendet man meist eine kombinierte Form der Ansprache. Das Programm wird im tell-Block angesprochen, das Objekt wird mit of spezifiziert, das vermeidet unnötige viele Einrückungsebenen: tell application "Finder" activate properties of Finder window 1 end tell Das Skript wird dadurch viel leichter lesbar. Aufgepasst Die komplette Abstammung eines Objektes muss immer klar ersichtlich sein, ansonsten gibt es eine Fehlermeldung, im günstigsten Fall schon beim Kompilieren, im ungünstigsten Fall erst zur Laufzeit. Diese Notwendigkeit einer vollständigen Objektzugehörigkeit kann dann durchaus schon mal zu extrem vielen of … of … of Staffelungen führen oder zu sehr tief verschachtelten tell-Blöcken, je nachdem, wie viele Unterobjekte ein Objekt enthalten kann. Tabellenkalkulationen sind hier ein schönes Beispiel, hier der Zugriff auf eine Zelle in einem Rechenblatt von Excel mit tell-Schachtelungen:
248
Die Sprache
Kapitel 4
tell application "Microsoft Excel" tell document 1 tell sheet 1 tell row 1 tell cell 1 set column width to 10 end tell end tell end tell end tell end tell Hier mit of: tell application "Microsoft Excel" tell cell 1 of row 1 of sheet 1 of document 1 to set column width to 10 end tell Dabei sollten Sie darauf achten, dass in den Programmen oft Abkürzungen definiert sind! So ist die Angabe von document, sheet und row in Excel zum Beispiel nicht unbedingt notwendig. Diese Objekte können komplett weggelassen werden, da eine Zelle im Funktionsverzeichnis zusätzlich auch als Objekt der Anwendung selbst definiert ist. Das erspart einige eventuell unnötige Schachtelungen. Bei der letzten Ebene in einer größeren tellHierarchie wird zudem oft die Form mit of beibehalten, wenn nicht zu viele Befehle an das gleiche Objekt vorliegen. Verschiedene tell, wie zum Beispiel an das Rechenblatt und das Dokument, können auch mit of zusammengefasst werden, wenn es keine extra Befehle nur für eines dieser Objekte gibt. Solchermaßen abgekürzt sieht obige Staffelung dann schon wesentlich handlicher aus: tell application "Microsoft Excel" tell sheet 1 of document 1 set column width of cell 1 to 10 end tell end tell Oder, wenn Sie die Tatsache ausnutzen, dass eine Zelle auch ein direktes Objekt der Anwendung ist: tell application "Microsoft Excel" set column width of cell 1 to 20 end tell
249
SmartBooks
AppleScript
Wobei hier natürlich davon ausgegangen wird, dass in Excel bereits eine Arbeitsmappe geöffnet ist. Trotzdem kann die Angabe von document, sheet und row (oder auch column statt row) natürlich notwendig werden, wenn Sie mit mehreren Dokumenten oder Arbeitsmappen hantieren und diese nicht über Index ansprechen wollen oder können. Wie die Objekthierarchie in einer Anwendung tatsächlich aussieht, lässt sich am schönsten über die Diagramm-Funktion des Script Debuggers von Late Night Software erkennen. Dort werden die Klassen des Funktionsverzeichnisses einer Anwendung grafisch dargestellt und lassen sich auf- und zuklappen.
Abb. 4-8 Das Diagramm im Funktionsverzeichnis des Script Debuggers und seine Darstellung der Objekthierarchie einer Anwendung – hier von Excel Im Skripteditor können Sie die Objekthierarchie ermitteln, indem Sie die mittlere Darstellungsschaltfläche in der Symbolleiste des Funktionsverzeichnisses (Ablage | Funktionsverzeichnis öffnen) eindrücken und sich dann durch die Klassen bis zum entsprechenden Objekt durchhangeln. Auch hier ist sofort erkennbar, dass die Klasse cell direkt von application abstammt. Sie ist aber ebenso unter sheet, range und an anderen Stellen zu finden.
250
Die Sprache
Kapitel 4
Abb. 4-9 Bei Auswahl der mittleren Darstellungsschaltfläche wird auch im Skripteditor die Objekthierarchie deutlich. Ziehen Sie daher immer das Funktionsverzeichnis einer Anwendung zu Rate, wenn Sie nicht wissen, wie die tell-Hierarchie in einem Skript für ein bestimmtes Objekt aussehen muss.
Lesen eines Funktionsverzeichnisses Damit wird es nun Zeit, so ein Funktionsverzeichnis näher zu erklären.
Symbolik der Übersicht In der Übersicht des Funktionsverzeichnisses helfen Ihnen kleine Symbole vor einem Begriff, diesen einzuordnen: Klassen (Objekte) haben ein kleines quadratisches Symbol in lila Farbe mit einem C. Das C steht für das c in class. Damit sind alle Begriffe gekennzeichnet, bei denen es sich um Klassen handelt. Handelt es sich bei einem Begriff um einen Befehl, dann trägt dieser einen blauen Kreis mit einem C (c wie in command). Ein lila Quadrat mit einem P kennzeichnet properties, also Eigenschaften einer Klasse. Ein quadratisches, braunes Symbol mit einem E kennzeichnet Elemente einer Klasse, die üblicherweise wiederum Klassen sind. Ein S in einem quadratischen, braunen Symbol kennzeichnet sogenannte Suites. Das ist eine thematische Zusammenstellung von Befehlen und Klassen. Wenn Sie nur an Begriffen zu einem bestimmten Thema interessiert sind, so wählen Sie im Funktionsverzeichnis die linke Darstellungsform und suchen Sie sich dann eine der Suites aus.
251
SmartBooks
AppleScript
Darstellungsarten der Übersicht Die Übersicht lässt sich über die Darstellungsknöpfe in der Symbolleiste auf drei verschieden Arten anzeigen, nach Gruppen, Inhalt oder Hierarchie. << Darstellung nach Gruppe: Wenn Sie den linken Knopf wählen und damit die Anzeige der Übersicht auf Gruppen einstellen, werden die Begriffe aus dem Funktionsverzeichnis nach den Suiten angeordnet. Das ist eine mehr oder weniger willkürliche thematische Gruppierung, die sich vor allem dazu eignet, alle Begriffe herauszufinden, die mit einem bestimmten Thema zu tun haben. Wenn Sie zum Beispiel gerade mit Ordnern arbeiten und alles darüber herausfinden möchten, so schauen Sie im Funktionsverzeichnis des Finders am besten in der Suite Containers and folders nach. << Darstellung nach Inhalt: Wenn Sie den mittleren Darstellungsknopf eindrücken, werden die Begriffe entsprechend ihrer Hierarchie im Programm angeordnet. Ganz links steht dann application als oberstes Objekt. Alle anderen Objekte sind Elemente von application, die dann wiederum andere Objekte als Elemente enthalten können. Mit dieser Darstellungsform können Sie die Objekthierarchie am besten beurteilen, also, welches Objekt Element eines anderen ist. Davon ist dann zum Beispiel die Anrede mit tell oder die Besitzanzeige mit of abhängig. << Darstellung nach Hierarchie: Wenn Sie den rechten Darstellungsknopf wählen, werden Ihnen nur die Klassen, die voneinander erben, angezeigt. Sie können damit gut erkennen, welche Klassen Kinder von welcher anderen Klasse sind und damit die Eigenschaften der Eltern geerbt haben. In dieser Ansicht werden Sie daher nicht alle Elemente des Funktionsverzeichnisses wieder finden. Unterscheiden Sie diese Ansicht gut von der mittleren Darstellungsform. Ich bezeichne diese zwar ebenfalls als Hierarchie, dort ist aber die Hierarchie des »Enthaltens« gemeint, hier die Hierarchie der Abstammung. Dass eine Klasse ein Element von einer anderen Klasse sein kann, heißt längst nicht, dass Sie von dieser Klasse auch etwas erbt. So kann eine Zahl ja auch ein Element einer Liste sein, erbt deswegen aber nicht die Eigenschaften length der Liste! (Zur Vererbung siehe das Kapitel Skriptobjekte.) Alternativ zur Übersicht am oberen Rand, können Sie auch am linken Rand eine Übersicht einblenden, indem Sie den Griff dort nach rechts ziehen. Diese Übersicht ist jedoch immer fest nach Gruppe eingestellt und lässt sich nicht auf eine andere Darstellungsform ändern (siehe die Abbildung zu den list view options auf einer der folgenden Seiten).
Die Beschreibung Im unteren Teil des Funktionsverzeichnisses finden Sie die genaue Beschreibung zu dem oben in der Übersicht ausgewählten Begriff. Die Titelzeile darin sieht zum Beispiel so aus: folder n [inh. container > item] : every folder 252
Die Sprache
Kapitel 4
Hinter dem Namen des Begriffs steht immer ein einzelner Buchstabe, und zwar entweder ein n oder ein v. Das n steht für noun und kennzeichnet ein Substantiv. Das v steht für verb, kennzeichnet also ein Verb. Befehle (commands) aller Art sind üblicherweise Verben. Alle anderen Begriffe wie Klassennamen und Eigenschaften sind Substantive. Wenn eine Klasse von einer anderen Klasse abstammt, wird das hinter dem n oder v in eckigen Klammern angezeigt, zum Beispiel [inh. container > item]. Das inh. steht für inherits from. Die Klasse folder stammt in diesem Beispiel also von container ab und erbt damit alle Eigenschaften und Elemente dieser Klasse. Die Klasse container wiederum stammt von item ab und erbt alles von dieser Klasse, was mit dem >-Zeichen angezeigt wird. Wenn Sie im Skripteditor im Menü Skripteditor | Einstellungen in der Tafel Allgemein die Option Vererbte Objekte im Funktionsverzeichnis anzeigen einschalten, werden diese Eigenschaften in der Beschreibung der Klasse mit aufgelistet, und zwar unter der Überschrift Properties inherited from klassenName beziehungsweise Elements inherited from klassenName. Schalten Sie diese Option daher unbedingt ein und öffnen Sie das Funktionsverzeichnis dann erneut, damit die Änderung wirksam wird. Wenn diese Option nicht eingeschaltet ist, müssen Sie auf den als Hyperlink angelegten Klassennamen in der eckigen Klammer klicken und dann in der Elternklasse nach deren Eigenschaften und Elementen nachsehen, was etwas umständlich ist. Am Ende einer Überschrift zu einer Klasse steht hinter dem Doppelpunkt noch eine kurze Beschreibung zu dem Begriff, mehr oder weniger – meist weniger – selbsterklärend. Unterhalb der Titelzeile steht meist Elements oder Elements inherited from klassenName und danach eine Liste mit Elementen, die diese Klasse enthalten kann. Bei der Klasse folder sieht das zum Beispiel so aus: ELEMENTS INHERITED FROM CONTAINER contains items, containers, folders, files, alias files, application files, document files, internet location files, clippings, packages. ELEMENTS INHERITED FROM ITEM contained by application, containers, disks, folders, desktop-objects, trash-objects. Hier sieht man also, dass ein folder von container und item erbt, selbst aber keine zusätzlichen Elemente hinzufügt, sonst gäbe es nämlich noch eine Überschrift »ELEMENTS« ohne ein »inherited« dahinter.
253
SmartBooks
AppleScript
Nach der Überschrift steht ein contains und dahinter eine Liste aller Elemente, die ein container (und nun auch folder) enthalten kann. Jedes dieser Elemente ist als Hyperlink angelegt. Wenn Sie darauf klicken, gelangen Sie zur Beschreibung dieser entsprechenden Klasse. Bei ELEMENTS INHERITED FROM ITEM steht statt contains ein contained by. Items ist eine abstrakte Klasse und kann selbst keine Elemente mehr enthalten, es ist bereits das kleinste Element. Deswegen wird hier umgekehrt angegeben, in welchen anderen Klassen item als Element enthalten ist. Nach der Auflistung der Elemente folgt dann die Auflistung der Propertys unter den Überschriften PROPERTIES und PROPERTIES INHERITED FROM klassenName. Hinter dem Namen einer Property steht immer eine Klammer mit der Angabe der Klasse, in welcher diese Eigenschaft vorliegt. Wenn diese Klasse nur read only ist, also nur mit get geholt, aber nicht mit set gesetzt werden kann, steht in der Klammer zusätzlich noch ein r/o.
Hierarchische tell-Beispiele Ziehen Sie für die folgenden Beispiele auch den Abdruck der Eigenschaften eines Finderfensters einige Seiten zuvor zu Hilfe. In folgendem Beispiel wird den list view options des ersten Fensters gesagt, es solle die Berechnung der Ordnergröße einschalten. Um das Objekt korrekt anzusprechen, muss dessen Objekthierarchie auch mit mehreren of (oder mehreren tell) klargestellt werden: tell application "Finder" tell list view options of Finder window 1 ¬ to set calculates folder sizes to true end tell Wichtig ist hier, dass die Mutter der Objekte, also der Finder, weiterhin in einem extra tell-Block stehen muss, denn er ist die Instanz, die beurteilen kann, ob der folgende Ausdruck sinnvoll ist. Das Mutterobjekt darf also nicht selbst im Ausdruck enthalten sein, es sei denn, es steht direkt am Anfang der Zeile. Diese Form gerät jedoch meist zu lang und unübersichtlich und wird daher kaum verwendet: tell application "Finder" to tell list view options of Finder window 1 to ¬ set calculates folder sizes to false Bei folgendem tell erhalten Sie einen Fehler, da während des Übersetzens nicht klar ist, mit welchem Anwendungsvokabular die Zeile zu interpretieren ist, und AppleScript selbst
254
Die Sprache
Kapitel 4
keine Objekte wie Finder window kennt. Das Programm ist hier das letzte Objekt in der Hierarchie, es muss jedoch immer das erste sein oder auf einer eigenen tell-Zeile stehen: tell list view options of Finder window 1 of application "Finder" to ¬ set calculates folder sizes to true Diese Zeile ergibt daher einen Fehler beim Kompilieren, auch wenn die Abstammung der einzelnen Objekte durchaus richtig wiedergegeben wurde.
Abb. 4-10 Die »list view options« eines Finderfensters sind eine Eigenschaft des Fensters, welche wiederum Propertys besitzt. Sie liefern einen eigenen Record als Ergebnis zurück und ist als eigene Klasse unter Type Definitions implementiert. List view options ist eine Eigenschaft eines Objekts vom Typ Finder window, welches wiederum ein Objekt des Finders ist. List view options liefert als Typ ebenfalls list view options zurück (und nicht eine der eingebauten AppleScript-Klassen wie boolean, integer etc.), ist also als Klasse implementiert, die wiederum eigene Eigenschaften besitzt, wovon hier die Eigenschaft calculates folder sizes auf wahr gesetzt wird. Da die Eigenschaft list view options wiederum eigene Eigenschaften hat, müssen Sie diese gesondert abfragen: tell application "Finder" properties of list view options of Finder window 1 end tell
255
SmartBooks
AppleScript
Achten Sie daher im Funktionsverzeichnis immer darauf, welcher Wert in Klammern hinter dem Namen steht. Ist es eine eigene, vom Programm definierte Klasse, können Sie auf den Namen klicken, um sich die Eigenschaften dieser Klasse genauer anzusehen. Haben Sie einem Finderfenster gleich mehrere Befehle zu geben, sollten Sie tell-Blöcke verwenden: tell application "Finder" activate tell Finder window 1 set toolbar visible to true set collapsed to true end tell end tell Damit haben Sie in einem Rutsch gleich mehrere Eigenschaften des Fensters verändert. In obigem Beispiel verschwindet das Fenster übrigens gleich in das Dock, da dessen Eigenschaft collapsed auf true gesetzt wird. Verschachtelungen sind auch ein übliches Merkmal von Ordnern. Ein Objekt (ein Ordner) kann also ein Element eines anderen Objekts (eines anderen Ordners) sein. Diese Verschachtelung muss in einem tell immer exakt angegeben werden, entweder mit einem langen Einzeiler wie hier vom untersten Objekt nach oben: tell application "Finder" tell folder "Briefe" of folder "Dokumente" of home to set label index to 2 end tell oder verschachtelt wie hier vom obersten Objekt nach unten: tell application "Finder" tell home tell folder "Dokumente" tell folder "Briefe" set label index to 2 end tell end tell end tell end tell Legen Sie sich zum Testen einen Ordner Briefe im Ordner Dokumente in Ihrem Heimatordner an. Sie erhalten sonst eine Fehlermeldung, wenn Sie das Beispiel ausführen und der Ordner nicht existiert.
256
Die Sprache
Kapitel 4
Glücklicherweise kennt der Finder den Begriff home, der immer auf den eigenen Heimatordner zeigt, ansonsten muss man hier noch weiter über das Verzeichnis Benutzer bis auf den Namen der Festplatte hinauf gehen. Dieses Skript setzt übrigens das Etikett des Ordners auf das Etikett mit dem Index Nummer 2. Bei mir wird der Ordner dann in Rot angezeigt.
tell auf Objekte In den bisherigen Beispielen haben Sie nebenbei bereits zwei Möglichkeiten der Ansprache an ein Programm oder ein Objekt kennengelernt. Erstens über die Angabe des Namens des Objekts (application "Finder") und zweitens über dessen Indexnummer (Finder window 1).
tell auf den index Die Indexnummer unterliegt ständigen Änderungen. Wenn Sie ein anderes Fenster nach vorne holen, wird dieses zur Nummer 1 und die anderen Fenster rutschen entsprechend ihrer letzten Verwendung eine Indexnummer nach hinten. Sie haben keine Kontrolle darüber, was der Anwender macht. Das vorherige Fenster Nummer 1 wird also unter Umständen zur Nummer 2 oder 3. Bei dieser Ansprache eines Objekts ist es daher schwer für Sie als Programmierer nachzuvollziehen, welche Nummer das gewünschte Fenster gerade hat. Die Programmierung kann dann schnell zu einer Art Hütchenspiel werden (wo ist die 2, wo ist die 2, hier ist die 2). Verwenden Sie den Index daher am besten nur dort, wo der Anwender nicht direkt auf die Objekte zugreifen kann und Sie damit die volle Kontrolle über den Index haben. Mit einer Minuszahl arbeiten Sie sich, wie bei einem Index in einer Liste, von hinten gezählt an die Fenster heran, so wird mit einer -1 das hinterste Fenster angesprochen und mit einer -2 das vorletzte und so weiter. Nicht jedes Objekt einer skriptfähigen Anwendung verfügt über eine Eigenschaft index. Falls ein Index also nicht vorhanden ist, müssen Sie das Objekt auf eine der folgenden Arten ansprechen.
tell auf den Namen Statt eines Indexes kann es eventuell besser sein, das Fenster oder ein anderes Objekt über seinen Namen anzusprechen, wobei darauf hingewiesen werden muss, dass auch hier nicht jede Objektart unbedingt über eine Property name, also einen Namen, verfügen muss. Ob diese Eigenschaft vorliegt, hängt unter anderem auch von der Mühe ab, die sich die Programmierer bei der Erstellung der Skriptfähigkeit des Programms gemacht haben.
257
SmartBooks
AppleScript
tell application "Finder" activate tell Finder window "Detlef" set toolbar visible to true -- Weitere Befehle hier end tell end tell Hier wird das Fenster über seinen Namen angesprochen. Wichtig ist, dass vor dem Namen auch immer die Klasse steht, um die es geht (hier also Finder window) oder in der ersten Zeile application. Der Name eines Fensters kann in dessen Titelzeile abgelesen werden. Alternativ können Sie auch schreiben: tell application "Finder" tell Finder window named "Detlef" to set collapsed to false end tell
tell auf eine id Da der Name eines Fensters üblicherweise der Name des darin geöffneten Ordners ist, kann es durchaus dazu kommen, dass es zwei oder mehr Fenster mit demselben Namen gibt. Die Ansprache eines Objekts über den Namen ist daher nicht eindeutig. Wenn Sie die eben abgerufenen Eigenschaften eines Fensters im Skripteditor betrachten, wird Ihnen vielleicht aber auch noch eine Eigenschaft namens id auffallen. Diese Eigenschaft ist üblicherweise eindeutig und unverwechselbar. Jedes Fenster, welches Sie öffnen, erhält seine eigene id und diese wird sich während ihres Lebens nicht ändern und auch an kein anderes Fenster vergeben. Die Ansprache über die id funktioniert dann auf die folgende Weise: tell application "Finder" activate tell Finder window id 1536 set toolbar visible to false -- Weitere Befehle hier end tell end tell Hier stellt die id also eine Zahl dar.
258
Die Sprache
Kapitel 4
Das Problem ist nur, dass Sie diese natürlich erst einmal herausbekommen müssen, und auch dafür müssen Sie das Fenster natürlich irgendwie ansprechen, zum Beispiel über Index: tell application "Finder" activate id of Finder window 1 -- Ergebnis z. B.: 1699 end tell Auch hier: Die Ansprache über id funktioniert natürlich nur bei Programmobjekten, die auch über eine solche Eigenschaft verfügen.
tell auf eine Objektreferenz Kommen wir zur Lösung, die normalerweise immer angewendet wird, und zwar nach Möglichkeit direkt schon bei der Erzeugung des Objekts, hier also bei der Erzeugung eines Fensters. Wenn Sie ein Fenster erstellen, packen Sie das Ergebnis des Befehls make new Finder window gleich in eine Variable, wie in folgender Anweisung: tell application "Finder" activate set myWindow to make new Finder window end tell -- Ergebnis: Finder window id 1690 of application "Finder" Als Ergebnis erhalten Sie in der Variablen myWindow eine Referenz auf das Finderfenster »Finder window id 1690 of application "Finder"«. Die id-Nummer weicht natürlich bei Ihnen von der hier gezeigten ab. Handelt es sich wirklich um eine Referenz auf das Objekt? Oder wird hier nicht einfach nur die id in der Variablen gespeichert? Das können Sie leicht selbst beantworten, indem Sie nach der Klasse der Variablen myWindow fragen. Enthält diese eine id, so würde man die Klasse integer oder zumindest text erwarten. tell application "Finder" activate set myWindow to make new Finder window class of myWindow end tell -- Ergebnis: Finder window
259
SmartBooks
AppleScript
Wie Sie sehen, steckt in der Variablen tatsächlich ein Objekt der Klasse Finder window. Natürlich steckt nicht wirklich das Fenster in der Variablen, sondern nur die Art und Weise, wie das Objekt in der Sprache des entsprechenden Programms erreicht werden kann. Eine solche Objektreferenz unterscheidet sich damit vom Konzept der Pointer in anderen Programmiersprachen. In AppleScript wird bei einer Referenz nicht die Adresse des Objekts gespeichert, sondern tatsächlich die Art und Weise, wie das Programmobjekt in der Sprache AppleScript erreicht wird. Es handelt sich quasi um eine eingefrorene AppleScript-Anweisung. So können Sie dann durchaus das Ergebnis einer Objektzuweisung auch als Beispiel dafür heranziehen, wie das Programm auf seine eigenen Objekte Bezug nimmt, und diese Syntax »abgucken« und für eigene Skripts verwenden. tell application "Finder" set myWindow to make new Finder window end tell -- Ergebnis: Finder window id 1690 of application "Finder" So ist das Ergebnis der obigen Variable myWindow auch ein Beispiel für eine gültige Ansprache des Objekts, nur dass Sie den Programmnamen als oberste Instanz natürlich nach vorne holen müssen, da vor dem Kompilieren der Zeile bekannt sein muss, mit welchem Funktionsverzeichnis man die Begriffe darin (Finder window id) übersetzen muss: tell application "Finder" tell Finder window id 1690 -- Code end tell end tell Wenn Sie ein Objekt einer Variablen zugewiesen haben, können Sie ab sofort diese Variable anstelle des Objekts verwenden, also zum Beispiel ein tell an die Variable richten: tell application "Finder" activate set myWindow to make new Finder window tell myWindow set toolbar visible to false set current view to icon view end tell end tell Da in myWindow die Referenz Finder window id 1690 of application "Finder" steckt, erreichen die folgenden Zeilen, welche die Werkzeugleiste und die Ansicht einstellen, das korrekte Ziel, nämlich das gewünschte Fenster.
260
Die Sprache
Kapitel 4
Dies ist die Form, in der üblicherweise Objekte angesprochen werden, die natürlich auch funktioniert, wenn die Objekte bereits existieren. tell application "Finder" activate set myWindow to Finder window 1 tell myWindow set toolbar visible to true set current view to column view end tell end tell Hier wird also einfach das Objekt Finder window 1 in die Variable myWindow gesteckt. Power User Wann immer Sie ein Objekt erzeugen oder ein bestehendes ausfindig gemacht haben, packen Sie es bei dieser Gelegenheit gleich in eine Variable, und Sie können auf dieses Objekt jederzeit und überall ohne erneute Sucherei wieder zugreifen. Da die Referenz auf das Objekt in myWindow (Finder window id 1690 of application "Finder") eine vollständige Adresse ist, also auch die Angabe enthält, zu welchem Programm das Objekt gehört, könnte man denken, dass das tell an das Objekt auch ohne ein zusätzliches tell an den Finder verwendet werden kann: tell application "Finder" activate set myWindow to make new Finder window end tell tell myWindow set statusbar visible to true end tell Hier wird zuerst der Finder angewiesen, ein Fenster zu erzeugen. Die Adresse des Fensters wird in der Variablen myWindow abgelegt. Danach wird der tell-Block an den Finder beendet und ein tell direkt an myWindow gerichtet. Es funktioniert aber nicht. Der Grund ist einfach: Beim Kompilieren des Skripts wird die Variable myWindow nicht ausgewertet! Mit anderen Worten: Der Skripteditor meckert über die Zeile mit dem statusbar visible. Diese Eigenschaft kennt AppleScript nicht, sondern nur der Finder, und das AppleScript hier den Finder fragen muss, was dieser Begriff bedeutet, ist nicht erkennbar, da beim Kompilieren die Variable myWindow ja nicht ausgewertet wird.
261
SmartBooks
AppleScript
Ein tell an ein Objekt in einer Variablen muss sich also weiterhin im Kontext eines tellBlocks der zu ihm gehörenden Anwendung befinden, um kompiliert werden zu können. Aber nur, wenn Sie darin Begriffe aus dem Kontext der Anwendung verwenden. Im folgenden Beispiel gibt es keinen Fehler, weil der Begriff name auch AppleScript selbst bekannt ist und es dafür nicht den Finder fragen muss. Daher klappt das Kompilieren, und Sie erhalten den Namen des neuen Fensters. tell application "Finder" activate set myWindow to make new Finder window end tell tell myWindow get name end tell Diese Beschränkung lässt sich nur mit einem weiteren tell oder mit using terms from umgehen (siehe Kapitel using terms from). Grundlagen Nicht alle Objekte müssen über Eigenschaften wie id, index und name verfügen. Wenn diese vorhanden sind, schön, damit haben Sie mehr Möglichkeiten, sich darin einzuhaken. Wenn diese Eigenschaften jedoch fehlen, schauen Sie einmal in dessen Propertys nach, ob es eine ähnliche Eigenschaft gibt, über die sich das Objekt eventuell ansprechen lässt. Falls auch das nicht geht, bleibt Ihnen nur die direkte Referenz auf das Objekt bei dessen Erstellung. Die Art, wie Sie das Objekt ansprechen, und die Art und Weise, wie AppleScript auf das Objekt zugreift, können sich durchaus voneinander unterscheiden. Hier ist das Event-Log von sehr großer Bedeutung. Dort können Sie nämlich genau verfolgen, wie AppleScript Ihre Anweisungen tatsächlich interpretiert und ausführt. Im folgenden Beispiel wird ein Fenster anhand seines Namens im Titel adressiert: tell application "Finder" set myWindow to window "Dokumente" tell myWindow activate end tell end tell Wenn Sie auf das Event-Log umschalten und dann das Skript ausführen, wird dort Folgendes stehen:
262
Die Sprache
Kapitel 4
tell application "Finder" get window "Dokumente" Finder window id 33 activate Finder window id 33 Finder window id 33 end tell Diesen Text aus dem Event-Log können Sie übrigens herauskopieren und als Skript verwenden. Er funktioniert! Sie sehen hier aber auch, dass Sie das Fenster zwar anhand seines Namens identifiziert haben, trotzdem wird das Fenster dann aber vom Finder über seine id angesprochen und aktiviert. Wenn Sie ein Objekt in eine Variable stecken, so erzeugen Sie damit immer eine Referenz, und die Art und Weise dieser Referenz liegt ganz in der Hand des Programms. Wenn Sie das Skript mit geöffnetem Ergebnisbereich im Skripteditor ausführen, sehen Sie auch, dass trotz Ihrer Referenz über den Namen in myWindow eine window id steckt: --Ergebnis: Finder window id 33 of application "Finder" Diesbezüglich ist dann auch manchmal Vorsicht angeraten. Die window id kann zum Glück nicht verändert werden, wenn aber eine andere veränderbare Referenzform gespeichert wird, wie zum Beispiel bei einer Referenz auf einen Ordner, dann lässt sich die Referenz leicht durcheinanderbringen. Im folgenden Beispiel wird ein Ordner in eine Variable gepackt: tell application "Finder" set myFolder to folder "Testordner" of desktop end tell In myFolder steht daraufhin: -- Ergebnis: folder "Testordner" of folder "Desktop" of folder "Detlef" of folder "Users" of startup disk of application "Finder" Sie sehen, die Ordner werden anhand ihres Namens identifiziert und nicht anhand einer id. Der Namen eines Ordners kann aber im Gegensatz zu der window id eines Fensters geändert werden. Wenn Sie daher den Namen des Ordners ändern, um danach erneut über die Variable myFolder auf den Ordner zuzugreifen, erhalten Sie eine Fehlermeldung, weil die Referenz in der Variablen myFolder nicht mehr funktioniert. Sie weist ins Leere, weil sich der Name geändert hat, welcher in der Referenz verwendet wird:
263
SmartBooks
AppleScript
tell application "Finder" set myFolder to folder "Testordner" of desktop set name of myFolder to "Test" get properties of myFolder -- Fehler!!! end tell Wenn Sie also eine Eigenschaft eines Objekts ändern, welche von dem Programm als Bezug verwendet wird, müssen Sie darauf achten, das Objekt danach erneut der Variablen zuzuweisen: tell application "Finder" set myFolder to folder "Testordner" of desktop set name of myFolder to "Test" set myFolder to folder "Test" of desktop get properties of myFolder -- Jetzt klappt's! end tell
tell every Wenn Sie allen Objekten eines Programms etwas zu sagen haben, können Sie diese auch mit every ansprechen: tell application "Finder" activate tell every Finder window set collapsed to true end tell end tell Schon werden alle Fenster des Typs Finder window schön nacheinander in das Dock geschickt. Tatsächlich wird hier ein Objekt nach dem anderen ausgewählt und die Befehle im tell-Block werden darauf angewendet.
tell some, tell middle Diese Formen, auf ein Objekt zuzugreifen, finden eher selten Anwendung. Sie haben diese Auswahlformen auch schon bei den Listen kennengelernt. Auch bei einem tell auf ein Programmobjekt können Sie diese anwenden. tell application "Finder" activate tell some Finder window to set collapsed to true end tell
264
Die Sprache
Kapitel 4
Hier wird einem zufällig ausgewählten Finderfenster befohlen, ins Dock zu verschwinden. tell application "Finder" activate tell middle Finder window to set collapsed to true end tell Hier wird dem mittleren Finderfenster gesagt, ins Dock zu verschwinden. Die Mitte richtet sich nach dem Index der Fenster. Bei einer geraden Anzahl von Fenstern ist das Fenster links der Mitte betroffen. Bei vier Fenstern wäre das also das Fenster mit dem Index 2.
tell mit relativem Bezug Sie können in einem tell auch auf ein Objekt Bezug nehmen, indem Sie dessen Position relativ zu einem anderen Objekt beschreiben. Verwenden Sie before oder in front of, um ein Objekt auszuwählen, welches vor einem anderen liegt, oder after, in back of oder behind, um ein Objekt hinter einem anderen auszuwählen. Ob ein Objekt vor oder hinter einem anderen liegt, ist am Index erkennbar. Folgendes Beispiel schickt das Fenster vor Finder window 2, also das vorderste Fenster, ins Dock: tell application "Finder" activate tell Finder window before Finder window 2 to set collapsed to true end tell Verwenden Sie die Wörter beginning oder front für das erste Objekt und end oder back für das letzte Objekt. Folgendes Beispiel schickt das hinterste Finderfenster ins Dock. Achten Sie darauf, dass sich noch kein Fenster im Dock befindet. Wenn das hinterste Fenster schon im Dock ist, passiert natürlich nichts mehr: tell application "Finder" activate tell back Finder window to set collapsed to true end tell
tell auf einen Bereich Eine Bereichsreferenz auf den Index lässt sich nicht direkt mit tell verwenden. tell application "Finder" tell Finder windows 1 thru 2 to set collapsed to true end tell Dieses Beispiel kompiliert zwar, ergibt aber eine Fehlermeldung bei der Ausführung. Wenn Sie einem Bereich von Objekten etwas zu sagen haben, sollten Sie den Filter whose verwenden.
265
SmartBooks
AppleScript
Der Filter whose Diese Möglichkeit, gleich an mehrere Objekte Anweisungen zu schicken, wird oft übersehen. Manche Anwendungen, unter anderem auch der Finder, unterstützen bei vielen ihrer Klassen, unter anderem auch bei Fenstern, Ordnern und Dateien, die Möglichkeit, gleich mehrere davon anhand eines Filterkriteriums auszuwählen. Diese Filterung geschieht mit einer sogenannten »whose-clause«. Alles, was Sie brauchen, ist eine Eigenschaft, die alle Objekte gemeinsam haben. Bei einem Fenster kann das zum Beispiel der Name sein. Öffnen Sie einmal mehrere Fenster im Finder, so dass alle denselben Ordner anzeigen (zum Beispiel den Heimatordner) und rufen Sie dann folgendes Skript auf: tell application "Finder" activate tell (Finder windows whose name is "Detlef") set current view to icon view set toolbar visible to false set collapsed to true end tell end tell Alternativ können Sie statt whose auch where oder that schreiben, die Bedeutung ist die gleiche. Hier werden alle Finderfenster ausgewählt, die den Namen Detlef tragen. Ändern Sie in obigem Skript den Namen daher auf den Namen Ihrer Fenster, damit das Skript funktioniert. Alle Fenster dieses Namens werden auf die Icon-Ansicht umgeschaltet, die Statusleiste unter der Titelleiste wird eingeschaltet und die Fenster werden schön der Reihe nach ins Dock geschickt. Wichtig ist hierbei die Verwendung der Mehrzahl von window, also windows. Wenn Sie nur einen einzigen Befehl haben, können Sie Befehl und whose-Filter auch auf einer Zeile unterbringen: tell application "Finder" activate set collapsed of (Finder windows whose name is "Detlef") to true end tell 266
Die Sprache
Kapitel 4
Das Filterkriterium befindet sich immer direkt nach dem Objektnamen (Finder windows) und wird mit whose (oder where/that) eingeleitet. Die Auswahlbedingung lautet in obigem Beispiel also name is "Detlef". Hier sehen Sie auch den ersten Vergleichsoperator (is) in Aktion und können vielleicht schon erahnen, warum das Kapitel über die Vergleichsoperatoren so detailliert ausgefallen ist. Wenn Sie hier eine falsche Bedingung angeben, erhalten Sie die falschen Fenster zur Auswahl und stellen unter Umständen großen Schaden an. Nun – bei Fenstern wohl eher weniger. Aber stellen Sie sich vor, es handelt sich um Dateien, die dann bearbeitet werden! Da Sie ja über die Vergleichsoperatoren und deren alternative Schreibweisen Bescheid wissen, werden Sie sicher sofort erkennen, dass Sie statt name is "Detlef" auch name is equal to "Detlef" oder name = "Detlef" schreiben können. Ergibt die Aussage true, wird das solchermaßen geprüfte Fenster für die folgenden Befehle als Ziel herangezogen. Alles, was Sie im Kapitel über Vergleichsoperatoren gelernt haben, können Sie hier zum ersten Mal praktisch ausprobieren. Wie wäre es zum Beispiel mit einem Vergleich mit contains, also name contains "Det"? Sie werden sehen, das funktioniert ebenfalls. Der Ausdruck Finder windows whose name is "Detlef" liefert ein Element nach dem anderen an den tell-Block, und alle Anweisungen im tell-Block werden dann darauf angewendet. Dem tell wird also jedes Mal nur ein einzelnes Objekt geliefert. Für jedes Fensterobjekt wird geprüft, ob name is "Detlef" true ergibt, wenn ja (und nur dann) werden die Anweisungen darauf angewendet, und zwar schön der Reihe nach: erst die erste Anweisung auf alle Objekte, dann die zweite und so weiter. Grundlagen Die Auswahl mit whose ist hervorragend geeignet, um sich so manche Schleife zu ersparen, und ist in der Regel auch viel schneller als eine Schleife. Allerdings unterstützen nicht alle Programme solche Filterungen, und wenn, dann sind sie auch selten dokumentiert. Und wenn ein Objekt sich mit whose auswählen lässt, heißt das nicht unbedingt, dass andere Objekte dieser Anwendung sich ebenfalls mit whose auswählen lassen. Trotzdem, bevor Sie eine Schleife programmieren, machen Sie es sich zur Gewohnheit, erst einmal zu überprüfen, ob nicht auch whose akzeptiert wird.
267
SmartBooks
AppleScript
Sie können solch einen Filter auch einer Variablen zuweisen und gleich überprüfen, ob auch wirklich mehrere Objekte ausgewählt wurden und ob es die richtigen sind: tell application "Finder" activate set myWindows to (Finder windows whose name is "Detlef") end tell -- Ergebnis: {Finder window id 2160 of application "Finder", Finder window id 2140 of application "Finder", Finder window id 2058 of application "Finder"} Sie erhalten dann in der Variablen eine Liste mit den Adressen aller gefundenen Fensterobjekte. Alternativ können Sie das auch mit every schreiben: set myWindows to (every Finder window whose name is "Detlef") Diese Variable können Sie nicht mehr für einen tell-Block verwenden. Der tell-Block erwartet ein Objekt nach dem anderen und keine Liste von Objekten. Nutzlos ist solch eine Filterung in eine Variable deswegen aber keineswegs. Wenn Sie zum Beispiel unbedingt eine Liste von Objekten mit bestimmten Eigenschaften brauchen, um diese manuell einzeln durchzuarbeiten, wenn Sie also mehr wollen, als nur deren Eigenschaften zu verändern, so ist dies immer noch die schnellste Art, Objekte gleicher Art zu ermitteln. In einer Schleife müssten Sie jedes Objekt einzeln aufrufen und nach seiner Eigenschaft fragen, was einiges an zusätzlicher Zeit kostet. Aufgepasst Vielleicht fragen Sie sich jetzt, ob man diesen whose-Filter nicht auch auf Listen in AppleScript anwenden kann? Nein, leider nicht. Die Referenz mit whose funktioniert nur mit Objekten von Programmen und auch dass nur, wenn das Programm dies unterstützt, wenn also beim Programmieren der Anwendung bewusst darauf geachtet wurde. Die Filterung mit whose funktioniert nicht nur mit Namen, Index und id, sondern auch mit jeder beliebigen anderen Eigenschaft eines Objekts. Und das macht sie so einzigartig. Ein tell ohne whose können Sie nur auf Namen, Index, ID oder Referenz anwenden. Mit einem whose können Sie jedoch auch all die anderen Eigenschaften eines Objekts als Auswahlkriterium verwenden. So können Sie zum Beispiel alle Fenster mit der Eigenschaft collapsed is true ansprechen, sie auf icon view umschalten und dann wieder aus dem Dock holen.
268
Die Sprache
Kapitel 4
tell application "Finder" activate tell (Finder windows whose collapsed is true) set current view to icon view set collapsed to false end tell end tell Beachten Sie hier nur die Reihenfolge der Befehle. Wenn Sie nämlich genau die Eigenschaft abfragen, die Sie dann verändern wollen, kann es zu Konflikten führen wie in folgendem Fall: tell application "Finder" activate tell (Finder windows whose collapsed is true) set collapsed to false set current view to icon view end tell end tell Hier werden alle Fenster, die im Dock sind, aus dem Dock herausgeholt, um sie dann auf icon view umzuschalten. Das schlägt aber fehl, da für diese Fenster nun die Auswahlbedingung collapsed is true nicht mehr zutrifft. Die Fenster wurden ja gerade aus dem Dock geholt, collapsed ist zu diesem Zeitpunkt also false, die Auswahlbedingung greift also nicht mehr. Seien Sie daher vorsichtig, wenn Sie die Eigenschaft verändern, welche Sie als Filter für das tell verwenden. Beachten Sie die richtige Reihenfolge oder vermeiden Sie solche Fälle nach Möglichkeit. Die Auswahlbedingung muss für jede Zeile im tell-Block weiterhin Gültigkeit haben. Statt is (Synonym für is equal to oder =) können Sie natürlich auch beliebige andere Vergleichsoperatoren verwenden. tell application "Finder" activate tell (Finder windows whose index is greater than 1) set toolbar visible to false set collapsed to true end tell end tell Allen Fenstern außer dem vordersten (welches den Index 1 hat) wird die Werkzeugleiste ausgeblendet. Danach werden sie ins Dock geschickt.
269
SmartBooks
AppleScript
Die Filterbedingung funktioniert natürlich nicht nur mit Text, Zahlen und booleschen Werten, sondern auch mit Schlüsselwörtern einer Property wie zum Beispiel der current view, welche die Eigenschaften icon view, list view, column view, group view und flow view kennt. tell application "Finder" activate tell (Finder windows whose current view is list view) set collapsed to true end tell end tell Alle Fenster mit Listenansicht werden hier in das Dock geschickt. Die anderen dürfen draußen bleiben. Im Finder funktioniert whose nicht nur mit Fenstern, sondern auch mit Ordnern und Dateien wie in folgendem Beispiel, wo allen Dateien mit der Dateiendung tiff im Ordner Testordner auf dem Schreibtisch ein Spotlight-Kommentar verliehen wird. tell application "Finder" set myFolder to folder "Testordner" of desktop tell myFolder to tell (files whose name extension is "tiff") set comment to "Weihnachten 2008" end tell end tell
Eigenschaften, mit denen whose nicht funktioniert Die Eigenschaft position eines Finder windows besteht aus einer Liste mit zwei Zahlen, also zum Beispiel {50, 44}. Die beiden Werte definieren die linke obere Ecke eines Fensters. Der linke Wert ist der Abstand des Fensters vom linken Rand des Bildschirms, der rechte Wert ist der Abstand zum oberen Rand des Bildschirms, und zwar gemessen in Pixel. Wenn Sie hier alle Fenster erreichen wollen, die zum Beispiel einen Abstand von mehr als 100 Pixeln zum oberen Rand des Bildschirms haben, so sollte man meinen, dass Sie diese eventuell mit folgender Zeile abfragen können: tell (Finder windows whose first item of position is greater than 100)… Das ist jedoch leider nicht möglich. Diese Zeile wird zwar übersetzt, bei der Ausführung gibt es allerdings den Fehler: »Item 1 of position kann nicht auf true gesetzt werden!«. Der Filter whose kann nur auf den ganzen Wert einer Property zugreifen, nicht jedoch auf einzelne Elemente daraus.
270
Die Sprache
Kapitel 4
So erhalten Sie dieselbe Fehlermeldung auch dann, wenn Sie zum Beispiel nach dem Element eines Textes fragen: tell application "Finder" tell (Finder windows whose second character of name is "e") set collapsed to true end tell end tell -- Fehler: character 2 of name of Finder window id 2366“ kann nicht als „true“ gesetzt werden. Spätestens wenn Sie also auf einzelne Elemente einer Eigenschaft, die als Liste oder Text vorliegt, filtern wollen, müssen Sie doch eine Schleife programmieren – wie Sie gleich lernen werden.
Besonderheiten bei einem tell auf ein Programm Wie bereits erklärt wurde, gibt es für Objekte schon direkt im tell einige Möglichkeiten der Auswahl. Welche Auswahl ist nun eigentlich möglich für das oberste Objekt, die application? In den bisherigen Beispielen wurde das Programm immer mit seinem Namen angeredet. tell application "Finder" Die Eigenschaft Name existiert bei einer Anwendung also schon mal, sonst hätte diese Zeile bisher nie funktioniert. Auch hier empfiehlt es sich, doch einmal anzuschauen, was der Skripteditor Ihnen zu den Eigenschaften des Programms "Finder" so sagen kann: properties of application "Finder" Wenn Sie diese Zeile ausführen, erhalten Sie im Ergebnisbereich folgende Auflistung (aus Gründen der besseren Lesbarkeit wieder auf mehrere Zeilen verteilt): {class:null, name:"Finder", clipboard:missing value, visible:true, frontmost:false, selection:{}, insertion location:folder "Detlef" of folder "Users" of startup disk of application "Finder", product version:"", version:"10.5.3", desktop:desktop of application "Finder", desktop picture:document file "Wallpaper.tif" of folder "Pictures" of folder "Detlef" of folder "Users" of startup disk of application "Finder", 271
SmartBooks
AppleScript
Finder preferences:Finder preferences of application "Finder", startup disk:startup disk of application "Finder", trash:trash of application "Finder", home directory:folder "Detlef" of folder "Users" of startup disk of application "Finder"} Außer einem Namen finden Sie darin weder eine id, noch einen Index. Die einzige andere Form der Referenz, die daher bleibt, ist die, das Programm als Referenz in eine Variable zu packen: set myFinder to application "Finder" tell myFinder to make new Finder window Das gibt dann aber beim Kompilieren wieder ein Problem! Wie ja bereits bekannt, werden Variablen nicht beim Übersetzen evaluiert, sondern erst zur Laufzeit. Das heißt, es gibt eine Fehlermeldung, weil AppleScript zu diesem Zeitpunkt noch nicht weiß, was ein Finder window ist, das weiß nur der Finder, und dass der Finder gefragt werden muss, steht in der Variable, an die AppleScript erst zur Laufzeit herankommt. (Umgehen lässt sich das nur mit einem using terms-Block, wie später beschrieben wird.) Kann man ein Programm also wirklich nur über seinen Namen ansprechen? Kurz gesagt: Die obige Auflistung der Eigenschaften des Finders ist nicht vollständig. Seit AppleScript 2.0 haben Anwendungen nämlich auch eine Eigenschaft id. Darauf wird bisher allerdings nur in der englischen Originaldokumentation hingewiesen. Es ist zu erwarten, dass auch die Abfrage der Propertys und die Funktionsverzeichnisse irgendwann daran angepasst werden. Fragen Sie doch einfach mal nach der id eines Programms: id of application "Finder" -- Ergebnis: "com.apple.finder" Die id eines Programms ist der sogenannte Bundle-Identifier, der in der Datei info.plist im Bundle des Programms steht. Falls kein Bundle-Identifier existiert, wird die Bundlesignatur zurückgeliefert, ein Code aus vier Buchstaben. Beim Finder ist das zum Beispiel »MACS«. Die id eines Programms besteht also in der Regel aus der umgedrehten Internetadresse des Herstellers ohne www und mit angehängtem Programmnamen! Hier wird also keine Zahl verwendet wie bei der id eines Fensters.
272
Die Sprache
Kapitel 4
Wenn Sie nach der id eines Programms fragen, welches nicht von Apple stammt, zum Beispiel nach der id des Programms »TextWrangler«, dann erhalten Sie entsprechend folgende id: id of application "TextWrangler" -- Ergebnis: "com.barebones.textwrangler" Auch hier also wieder die umgedrehte Internetadresse des Anbieters mit angehängtem Programmnamen. Mit diesem Bundle-Identifier (oder der Bundlesignatur) können Sie dann auch ein tell verwenden: tell application id "com.apple.finder" -- oder: tell app id "MACS" activate tell Finder window 1 to set collapsed to true end tell Eine weitere Möglichkeit ist die Auswahl eines Programms anhand seines Pfades, und zwar bevorzugt in POSIX-Schreibweise mit Schrägstrichen: tell application "/System/Library/CoreServices/Finder.app" activate tell window 1 to set collapsed to true end tell Hier ist unbedingt darauf zu achten, dass auch die Endung des Programmnamens, hier app, mit angegeben wird. Bei der Referenz über den Namen ist diese nicht nötig. Und damit die Behandlung der Eigenschaften eines Programms auch gleich vollständig ist, hier noch eine weitere neue Eigenschaft, die in den Propertys eines Programms bisher nicht aufgelistet ist: running of application "Finder" -- Ergebnis: true Wenn Sie nach der Eigenschaft running bei einer Anwendung fragen, erhalten Sie entweder true oder false als Antwort, je nachdem, ob die Anwendung läuft oder nicht. Diese Eigenschaft eignet sich daher gut, um vor Beginn einer Aktion zu prüfen, ob das Programm überhaupt läuft. Die Eigenschaft running ist neu in AppleScript 2.0, wird also nicht unter früheren Versionen funktionieren.
273
SmartBooks
AppleScript
Vor- und Nachteile bei Verwendung der application id Viele Programme heißen auf einem deutschen Mac OS anders als auf einem englischen. Ein englisch geschriebener Programmname wird beim Kompilieren automatisch in den deutschen Programmnamen übersetzt. So wird aus tell app "Script Editor" to make new document ein tell application "Skripteditor" to make new document Des Weiteren können Programmnamen von jedem Anwender im Finder geändert werden. Ein Programm über seinen Namen zu identifizieren, ist also nicht wirklich eindeutig. Über die id ist eine Identifikation wesentlich klarer, auch wenn theoretisch immer noch mehrere Versionen oder Kopien ein und derselben Anwendung installiert sein können. Aufgepasst Normalerweise erledigt AppleScript einen sehr guten Job beim Herausfinden, welches Programm mit einem bestimmten Programmnamen im Skript gemeint ist. Doch wenn Sie Ihr Skript weitergeben, sollten Sie ein tell unbedingt an den Bundle-Identifier richten und nicht direkt an den Programmnamen, es sei denn, Ihr Skript soll auch auf Systemen vor Mac OS X 10.5 laufen. Ein weiterer Vorteil des Bundle-Identifiers ist, dass beim Fehlen des angesprochenen Programms nicht wie bisher nach dem Ablageort dieser Anwendung gefragt wird, sondern stattdessen ein Fehler erzeugt wird, der dann leicht mit einem try-Block abgefangen werden kann. Damit lassen sich leichter Alternativen für den Fall des Fehlens eines Programms programmieren. Vorraussetzung ist, dass das Skript auch als Programm oder Programm-Bundle gespeichert wurde. Für die Bearbeitung als Skript oder Skript-Bundle ist das Vorhandensein des Programms weiterhin erforderlich, um dessen Terminologie in seinem Funktionsverzeichnis nachsehen zu können.
Verzweigungen mit if In einem Skript müssen auch immer wieder Entscheidungen getroffen werden, was in einem bestimmten Fall zu tun ist. Solche Entscheidungen werden in einem sogenannten if-Block anhand eines Vergleichs getroffen.
if auf einer Zeile Die einfachste Form eines if steht auf einer einzelnen Zeile und kann infolgedessen nur eine einzelne Anweisung ausführen:
274
Die Sprache
Kapitel 4
if 2 > 1 then say "The comparison is true" Die grundlegende Struktur lautet also: if Test then Handlung Oder auf Deutsch Wenn Test dann Handlung Die Handlung nach dem then wird nur ausgeführt, wenn der Test wahr ergibt. Mit »Test« ist eine einfache Aussage gemeint, die einen booleschen Wert ergibt, also true oder false. Andere Rückgabewerte sind nicht erlaubt. Ergibt die Aussage false, passiert bei diesem einfachen if gar nichts. Hier ist also wieder die Kunst der richtigen Fragestellung – eigentlich Aufstellung von Behauptungen – gefragt. Was auch immer Sie hier schreiben, es muss einen Wahrheitswert ergeben, sich also mit wahr oder falsch beantworten lassen. Dabei können Sie auf alle Vergleichsoperatoren zurückgreifen, komplexe Aussagen mit und und oder verknüpfen oder auch Aussagen mit not umkehren. Sie können also das ganze Repertoire aus dem Kapitel Vergleichsoperatoren hier anwenden. Der Test in einem if kann dadurch schon mal ziemlich lang werden. Hier ein konstruiertes Beispiel: if ((2 > 1) and (not 1 = 0)) or ({3,5,7} contains 7) then say "Thats true" Der Test zwischen dem if und dem then wurde hier zusätzlich noch manuell mit Klammern versehen, um auf den ersten Blick erkennen zu können, wie dieser Test aufgelöst wird. Nach dem Auflösen der innersten Klammer sieht das if so aus: if (true and true) or (true) then say "Thats true" Das true and true ergibt wieder true, wonach das if nun so aussieht: if true or true then say "Thats true" Die Aussage true or true ergibt wiederum true, was dann folgendes Endergebnis bringt: if true then say "Thats true" Mit anderen Worte die Aussage ist wahr und deswegen wird der Befehl say "Thats true" ausgeführt.
275
SmartBooks
AppleScript
if als Blockanweisung Wenn Sie mehr als nur eine Handlungsanweisung haben, empfiehlt es sich, die BlockSchreibweise zu verwenden. if "ABC" starts with "A" then beep say "The comparison is true" end if Die Befehle nach dem then und vor dem end if werden nur ausgeführt, wenn das Ergebnis der Aussage nach dem if ein true ergibt, ansonsten passiert gar nichts. Beim Schreiben des if-Blocks können Sie das if in end if auch weglassen. Beim Kompilieren wird es dann automatisch ergänzt. Diese Form des if trifft also, wie auch das if auf einer Zeile, eine Entscheidung zwischen dem Ausführen der Befehle und dem faulen Nichtstun.
if mit else Doch was ist, wenn Sie bei einer falschen Aussage nicht nichts tun wollen, sondern eine andere Handlungsalternative einschlagen wollen? Dafür gibt es den if-Block mit else: if item 3 of {1.5, "s", 3} is equal to 4 then say "The comparison is true" else beep 2 say "The comparison is false" end if Alles nach dem then und vor dem else wird ausgeführt, wenn die Aussage wahr ist. Alles nach dem else und vor dem end if wird ausgeführt, wenn die Aussage falsch ist. Wenn es AppleScript in Deutsch gäbe, sähe das wahrscheinlich so aus: wenn Test dann --Befehle wenn Aussage wahr ist ansonsten --Befehle wenn Aussage falsch ist ende wenn Bei dieser Form des if wird also für einen ganz bestimmten Fall die Handlung vor dem else ausgeführt und für alle restlichen Fälle, egal welche, die Anweisungen nach dem else.
276
Die Sprache
Kapitel 4
Hier wird also zwischen eins und dem ganzen Rest unterschieden, die alle rücksichtslos auf die gleiche Art behandelt werden.
if mit else if Wenn Sie auf mehr als einen Zustand testen müssen und mehr als zwei Handlungsvarianten benötigen, können Sie die Form mit else if verwenden: set x to 3 if x = 1 then say "x is 1" else if x = 2 then say "x is 2" else if x = 3 then say "x is 3" end if Jede Zeile mit else if stellt wiederum eine weitere Prüfung dar, enthält also eine erneute Aussage. Die erste Aussage, die wahr ist, wird ausgeführt. Die danach folgenden else if werden dann nicht mehr berücksichtigt. Ergibt keine der obigen 3 Aussagen true, passiert in diesem if gar nichts. Sie können beliebig viele else if verwenden.
if mit else if und else Auch die Form mit else if kann einen else-Teil besitzen. Dieser wird wiederum ausgeführt, wenn keine der vorigen Aussagen zutrifft. set x to 4 if x = 1 then say "x is 1" else if x = 2 then say "x is 2" else if x = 3 then say "x is 3" else say "x is not 1, 2, or 3" end if Die Anordnungen nach dem else werden hier nur ausgeführt, wenn x weder 1 noch 2 noch 3 ist.
277
SmartBooks
AppleScript
Hilfe Sie müssen nicht jedes Mal, wenn Sie einen if-Block brauchen, diesen von Hand schreiben. Sie können dafür auch auf vorgefertigte Blöcke des Skripteditors zurückgreifen, zu finden im Kontextmenü unter dem Eintrag Conditionals. Wenn Sie vor dem Einfügen ein Stück Code im Skripteditor markieren, so wird dieser Code an der Stelle des ifBlocks eingefügt, wo im Kontextmenüeintrag <selection> steht.
exists Die grundlegendste Prüfung, die Sie mit if überhaupt machen können, ist die, ob ein bestimmtes Objekt überhaupt existiert. Denn nur wenn es existiert, kann man dem Objekt auch einen Befehl geben. Wenn Sie einen Befehl geben und das Objekt existiert nicht, erhalten Sie sonst nur eine Fehlermeldung, und das Skript bricht seine Ausführung ab, was man natürlich vermeiden sollte. tell application "Finder" if exists Finder window 1 then set collapsed of window 1 to true else set x to make Finder window set current view of x to list view set collapsed of x to true end if end tell Hier wird geprüft, ob es ein Finderfenster mit dem Index 1 gibt. Wenn ja, wird es ins Dock geschickt, ansonsten wird ein neues Fenster erzeugt, dieses auf die Listenansicht eingestellt und dann ins Dock geschickt. Damit ist also sichergestellt, dass das Skript in jedem Fall funktioniert, unabhängig davon, ob bereits ein Fenster geöffnet ist oder nicht. Der Befehl exists lässt sich nur auf Programmobjekte anwenden, nicht auf die grundlegenden Objekttypen in AppleScript selber. Exists liefert einen Wahrheitswert zurück. Wenn also ein Finder window 1 existiert, wird true zurückgeliefert, wenn nicht, erhält man die Aussage false. Exists muss dem zu prüfendem Objekt vorausgehen. Die Syntax lautet also: exists Objektreferenz
278
Die Sprache
Kapitel 4
running Hier noch ein Beispiel zur bereits erwähnten Programmeigenschaft running in AppleScript 2.0. Folgendes Skript prüft, welcher Internetbrowser gerade läuft, und verwendet dann diesen für die Anzeige der Webseite zu diesem Buch. Die Prüfungen auf running wurden fett hervorgehoben. if running of application "Safari" then tell application "Safari" activate make new document with properties {URL:"http://www.skripteditor.de"} end tell else if running of application "Firefox" then tell application "Firefox" activate OpenURL "http://www.skripteditor.de" end tell else tell application "Firefox" activate OpenURL "http://www.skripteditor.de" end tell end if Durch die Prüfung auf running ist das Skript in der Lage, den Browser zu verwenden, der gerade läuft, unabhängig davon, ob es Safari oder Firefox ist. Läuft gerade keines der beiden Programme, wird Firefox im else-Teil verwendet. Laufen beide Programme, wird die erste Prüfung, nämlich die auf Safari, gewinnen und die Webseite in Safari angezeigt. Mit weiteren else if können noch weitere skriptfähige Browser berücksichtigt werden. Für jedes Programm wird ein eigenes tell verwendet und darin die für dieses Programm nötige Syntax zum Anzeigen einer Webseite.
279
SmartBooks
AppleScript
Schachtelung von if Ein if lässt sich nach Bedarf verschachteln. Übertreiben Sie es aber nicht. Mit zunehmender Verschachtelungstiefe wird es immer schwieriger, den Durchblick zu bewahren, und irgendwo gibt es auch eine Grenze, bei deren Überschreitung es zu einer Fehlermeldung kommt. Hier ein durchaus normales Beispiel. Die Prüfungen sind fett hervorgehoben: tell application "Finder" if exists Finder window 1 then tell Finder window 1 if current view is not icon view then set current view to icon view end if end tell else activate set myWindow to make new Finder window set current View of myWindow to icon view end if end tell Hier sind zwei if-Blöcke und zwei tell-Blöcke ineinander geschachtelt worden. Achten Sie penibel darauf, dass jeder tell-Block und jeder if-Block sein korrespondierendes end am richtigen Platz hat. Die Tiefe der Einrückung verrät Ihnen, welches end zu welchem tell oder if gehört. Anfang und Ende eines Blocks sind nämlich immer genau gleich tief eingerückt. Bei einem if-Block mit else steht auch else auf derselben Einrückungsstufe wie Anfang und Ende des if. Im zweiten if sehen Sie, dass Sie als Test auch eine Eigenschaft eines Objekts prüfen können. Hier wird geprüft, ob die current view des Fensters nicht (not) auf icon view steht, wenn ja, wird das Fenster auf die Iconansicht umgestellt. Falls kein Fenster geöffnet ist, also kein Fenster 1 existiert, wird ein Fenster erzeugt und dieses auf Iconansicht eingestellt. Sie sehen, bei verschachtelten if-Strukturen – und dann auch noch in Verbindung mit verschachtelten tell-Blöcken – kann es sehr schnell unübersichtlich werden. Bewahren Sie sich den Überblick, indem Sie immer nur ein if oder tell nach dem anderen aufbauen und niemals alle gleichzeitig.
280
Die Sprache
Kapitel 4
Schleifen mit repeat Schleifen dienen dazu, Anweisungen beliebig oft zu wiederholen. Um zum Beispiel eine Liste mit hundert Zahlen von 1 bis 100 zu erzeugen, könnte man schreiben: set x to {1} copy 2 to end of x copy 3 to end of x … und so weiter, bis zur Zahl 100. Da das viel zu aufwendig und unflexibel wäre, wurden Schleifen in den Programmiersprachen erschaffen. In einer Schleife wird eine Anweisung wie copy y to end of x nach Wunsch beliebig oft ausgeführt. Der Befehl steht in der Schleife also nur ein einziges Mal und wird trotzdem beliebig oft ausgeführt! Es gibt verschiedene Arten von Schleifen, die in AppleScript alle mit dem Schlüsselwort repeat beginnen und mit end repeat enden.
repeat (endlos) Aufgepasst Diese Schleifenart bitte nicht im Skripteditor ausprobieren. Wenn Sie es doch tun, dann brechen Sie das Skript mit [Befehl]+[.] ab, falls der Knopf Stopp nicht mehr reagiert. Falls auch das nicht mehr hilft, mit [Befehl]+[Alt]+[Esc] den Skripteditor gewaltsam beenden. Nicht gesicherte Änderungen an dem Skript gehen dann natürlich verloren. Die einfachste Form einer Schleife ist eine Endlosschleife. Wie der Namen schon sagt, läuft diese für immer oder zumindest so lange, wie der Rechner Strom führt oder das Skript nicht gewaltsam beendet wird. Der Skripteditor wird daher nicht mehr unbedingt reagieren. repeat --Anweisungen --Noch mehr Anweisungen end repeat 281
SmartBooks
AppleScript
Diese Schleife beginnt mit dem Wort repeat und endet mit end repeat. Alle Anweisungen dazwischen werden der Reihe nach endlos ausgeführt. Das heißt, wenn das Ende der Schleife bei end repeat erreicht wurde, beginnt die Ausführung erneut bei der ersten Zeile im repeat-Block. Verwenden Sie diese Schleife niemals ohne eine sogenannte Abbruchbedingung wie die im Folgenden beschriebene exit-Anweisung, welche einen Weg aus der Schleife weist.
exit repeat Das Allerwichtigste an einer Schleife ist ihre Abbruchbedingung. Bis auf die Endlosschleife haben alle anderen Schleifenarten in AppleScript eine implizite Abbruchbedingung. Eine Endlosschleife muss jedoch explizit beendet werden, und zwar mit dem Schlüsselwort exit repeat. Falls eine Schleife keine Abbruchbedingung hat, läuft sie bis in alle Ewigkeit oder zumindest so lange, wie der Strom im Rechner fließt. Das repeat in exit repeat kann beim Schreiben in der Schleife weggelassen werden, es wird beim Übersetzen automatisch hinzugefügt. repeat beep say "Hello" exit repeat end repeat Wenn Sie die Schleife so schreiben, werden die Anweisungen vor dem exit nur genau ein Mal ausgeführt. Da eine einmalige Ausführung nicht der Sinn einer Schleife ist, wird das exit normalerweise an eine if-Bedingung gekoppelt. Hier ein Beispiel, in welchem eine Liste mit einhundert Zahlen erzeugt wird: set myList to {} set zaehler to 1 repeat set end of myList to zaehler if zaehler = 100 then exit repeat set zaehler to zaehler + 1 end repeat get myList Zuerst wird hier eine leere Liste myList erzeugt und dann die Variable zaehler auf 1 gesetzt.
282
Die Sprache
Kapitel 4
Dies sind die Variablen, die gleich innerhalb des repeat verändert werden. Im repeat wird nun der Inhalt von zaehler, also die Nummer 1, an das Ende der Liste myList angehängt. Die Liste ist dann also nicht mehr leer, sondern sieht so aus: {1}. Danach wird geprüft, ob zaehler gleich 100 ist, wenn ja, erfolgt die Anweisung exit repeat. Diese Schleife wird also erst verlassen, wenn der Zähler in der Variable zaehler den Wert 100 erreicht hat. Damit das auch irgendwann der Fall sein wird, muss die Variable zaehler in der letzten Zeile natürlich noch um eins erhöht werden. Damit ist der erste Durchlauf im repeat fertig, und der zweite Durchlauf beginnt. Im zweiten Durchlauf wird nun wieder der Inhalt von zaehler an das Ende der Liste myList angehängt. Da zaehler nun die 2 enthält, sieht die Liste jetzt so aus {1, 2}. Und so geht es weiter, bis die Zahl einhundert erreicht ist und die if-Bedingung wahr wird. Die Liste myList enthält dann die Zahlen von eins bis hundert. Wenn die Schleife fertig ist, wird mit dem Code nach dem end repeat fortgefahren. Dort steht die Anweisung get myList. Das heißt, der Inhalt von myList wird daraufhin im Ergebnisbereich des Skripteditors angezeigt, und Sie können überprüfen, ob die Liste auch wirklich alle hundert Zahlen enthält. Aufgepasst Achten Sie darauf, dass in der Schleife auch immer etwas passiert, was schlussendlich zum Beenden der Schleife führen kann! In obigem Fall ist es die Variable zaehler, die in jedem Durchlauf um eins erhöht wird. Würden Sie das vergessen, hätten Sie eine Endlosschleife erzeugt, da zaehler dann immer auf 1 stehen bleibt. Sie erhalten eine endlose Liste mit lauter Einsen, und der Skripteditor hängt sich auf und muss gewaltsam beendet werden.
Optimierung durch Referenzen Wenn Sie das vorige Beispiel einmal mit einer höheren Zahl als 100 ausprobieren, zum Beispiel mit zehntausend, dann werden Sie Folgendes feststellen: Das Skript braucht lange. Für eine Liste mit zehntausend Werten dauert es beispielsweise bei mir 26 Sekunden, bis das Skript fertig ist und alle Werte in der Liste stehen und angezeigt werden. 3 Sekunden muss man davon abziehen, so lange dauert nämlich das get myList zur Anzeige der zehntausend Werte im Ergebnisbereich. 23 Sekunden dauert es also, die Anweisungen in der Schleife zehntausend Mal durchzuführen.
283
SmartBooks
AppleScript
Die Arbeit mit Listen in einer Schleife lässt sich aber optimieren, und zwar indem man auf die Liste über eine Referenz zugreift, und, oh Wunder, schon ist die Schleife in einer Sekunde fertig. Eine Referenz auf die Liste erzeugen Sie mit dem a reference to-Operator. set myList to {} set zaehler to 1 set myListRef to a reference to myList repeat set end of myListRef to zaehler if zaehler = 10000 then exit repeat set zaehler to zaehler + 1 end repeat --get myList Diese Version der Schleife verwendet innerhalb des repeat nicht direkt die Liste myList, sondern nur deren Adresse, die in der Variable myListRef gespeichert ist. Dass in der Variable wirklich eine Referenz auf die Variable myList steckt, können Sie durch Abfrage überprüfen: set myList to {} set myListRef to a reference to myList get myListRef -- Ergebnis: myList of «script» Als Ergebnis erhalten Sie myList of «script». Die Referenz bezieht sich also auf die Variable myList des aktuellen Skripts. In der Schleife wird damit sozusagen nur noch die Adresse verwendet, an welcher sich diese Schleife befindet.
Referenzen und der Operator »a reference to« An dieser Stelle ist es Zeit, näher auf Referenzen einzugehen, die mit a reference to erzeugt werden. Wenn Sie in einem Skript eine Liste erzeugen und diese abfragen, erhalten Sie deren Inhalt als Ergebnis: set myList to {1, 2, 3} get myList -- Ergebnis: {1, 2, 3} Wenn Sie eine Referenz, die mit a reference to erzeugt wurde, nach ihrem Inhalt fragen, erhalten Sie jedoch: set myList to {1, 2, 3} set myListRef to a reference to myList get myListRef -- Ergebnis: myList of «script» 284
Die Sprache
Kapitel 4
Hier wurde also eine Referenz auf die Variable myList erzeugt und diese Referenz wird in der Variablen mylistRef abgespeichert. So wie Sie bei Programmobjekten, die Sie einer Variablen zuweisen, generell eine Referenz auf das Objekt erhalten, zum Beispiel Finder window id 33 of application "Finder", so erhalten Sie bei den Wertetypen von AppleScript eine solche Referenz nur auf ausdrückliche Anweisung mit a reference to. Die Referenz zeigt an, dass myList ein Element von «script» ist. Das Skript selbst ist also ebenfalls ein Objekt und besitzt mehrere Elemente, darunter zum Beispiel die Variablen (zum Skript als Objekt siehe auch das Kapitel Skriptobjekte). Da bei den eingebauten Werteklassen von AppleScript zwischen den Typen mutable und immutable unterschieden wird (siehe auch Der Unterschied zwischen set und copy), also zwischen veränderlichen und unveränderlichen Wertetypen, hat a reference to aber nur auf die veränderbaren Wertetypen eine Wirkung – und zwar auf die Klassen list, record, date und script. Auf integer, real und text hat der Operator keine Wirkung, da bei jeder Operation ein neues Objekt dieser Art angelegt werden muss und damit die Referenz auf das Objekt sofort wieder dahin ist. Um sich Schreibarbeit zu ersparen, empfiehlt es sich, einfach nur a ref oder ref to zu schreiben. Beim Kompilieren wird der Rest dann ergänzt. Sie können den Operator a reference to aber auch auf andere Objekte wie zum Beispiel Programmobjekte anwenden: Zur Erinnerung: Wenn Sie wie bisher ein Programmobjekt direkt in eine Variable packen, wird die Referenz vom Programm zurückgeliefert und in der Variablen abgespeichert: tell application "Finder" set myWin to window "Dokumente" get myWin end tell -- Ergebnis: Finder window id 295 of application "Finder" Oder Sie packen das Objekt mit a reference to in eine Variable: tell application "Finder" set myWinRef to a reference to window "Dokumente" get myWinRef end tell -- Ergebnis: window "Dokumente" of application "Finder" 285
SmartBooks
AppleScript
Sie sehen den Unterschied? Im zweiten Fall wird in der Variablen eine Referenz über den Namen des Objekts gespeichert, vorher war es eine id. Mit a reference to bekommen Sie also genau das, was Sie gesagt haben, Ihre Anweisungen werden wörtlich genommen. Wenn Sie es also ernst meinen mit Ihrer Wortwahl und keine andere Interpretation dulden, dann verwenden Sie a reference to. Solche Unterschiede können dann manchmal ein Problem und gleichzeitig auch dessen Lösung darstellen. Nämlich immer dann, wenn eine Eigenschaft verändert werden soll, über die man auch den Bezug auf das Objekt hergestellt hat, wie hier den Namen. Verändern Sie den Namen des Objekts, weist die Referenz danach nicht mehr auf das Originalobjekt. Aus diesem Grund gibt es im folgenden Skript auch einen Fehler, weil die Referenz auf das Fenster mit dem Namen "Testordner" weist. Der Ordner dieses Fensters wurde aber in der vorletzten Zeile umbenannt, wodurch in der letzte Zeile dann nicht mehr darauf zugegriffen werden kann, weil ein Fenster mit diesem Namen nicht mehr existiert. Das Fenster ist zwar noch da, es hat aber seinen Namen geändert. tell application "Finder" set myWinRef to a reference to window "Testordner" set name of target of myWinRef to "Test" -- Ordner umbenennen get properties of myWinRef -- Fehler!!! end tell Ohne Referenz klappt es in diesem Fall, manchmal muss man auch den umgekehrten Weg gehen. tell application "Finder" set myWin to window "Testordner" set name of target of myWin to "Test" get properties of myWin -- Jetzt klappt's! end tell Dieser Unterschied zwischen von der Anwendung erzeugter Objektreferenz und selbst erzeugter Objektreferenz hat also überall dort Sinn, wo es darum geht, Eigenschaften zu ändern, über die man auch Bezug auf das Objekt nimmt. Mal muss man vielleicht die normale Objektreferenz verwenden, manchmal muss es explizit a reference to sein.
Rückverweis einer Referenz mit »contents of« Oft ist es notwendig, in AppleScript eine Referenz wieder aufzulösen, also einen Rückverweis auf das Objekt selber vorzunehmen. Eine Auflösung einer Referenz bedeutet nichts anderes, als dass in der Variablen statt einer Referenz auf das Objekt wieder das Objekt selbst gespeichert wird.
286
Die Sprache
Kapitel 4
set myList to {1, 2, 3} set myListRef to a reference to myList -- Ergebnis: myList of «script» set mylist2 to contents of myListRef -- Ergebnis {1, 2, 3} In obigem Codebeispiel wird in der letzten Zeile auf den eigentlichen Inhalt von myListRef zugegriffen, und zwar mit contents of. Der Begriff contents ist eine Eigenschaft von Referenzen. Sie zeigt immer auf den Inhalt des Ziels der Referenz. Das geht natürlich auch mit Programmobjekten, wodurch der Bezug auf das Programmobjekt wieder dem Programm selbst überlassen wird. tell application "Finder" set myWin to a reference to window 1 -- Ergebnis: window 1 of application "Finder" set myWin to contents of myWin -- Ergebnis: Finder window id 327 of application "Finder" end tell Grundlagen Beachten Sie, dass eine Objektreferenz in AppleScript »eingefrorenen« Code darstellt, über den auf das Objekt zugegriffen wird. Es handelt sich hier nicht, wie in anderen Programmiersprachen, um einen Zeiger auf eine Speicheradresse. Nun findet dieser Rückverweis bei vielen Operationen mit einer Referenz automatisch statt, ohne dass Sie es merken, nämlich immer dann, wenn Sie mit dem Objekt rechnen, dessen Eigenschaften abfragen oder ändern. Meistens können Sie eine Referenz also genauso verwenden wie das Originalobjekt. Bei Vergleichen funktioniert das aber nicht. Folgender Vergleich ergibt unverständlicherweise false, obwohl beide Listen eindeutig gleich sind: set a to {1, 2, 3} set b to {1, 2, 3} set aRef to a reference to a -- Ergebnis: a of «script» set bRef to a reference to b -- Ergebnis: b of «script» aRef is equal to bRef -- Ergebnis: false Der Grund liegt darin, dass hier eine Referenz mit einer anderen verglichen wird, und da beide auf unterschiedliche Variablen hinweisen, ergibt der Vergleich falsch. Und das ist ja auch korrekt so. a of «script» kann nicht gleich sein mit b of «script».
287
SmartBooks
AppleScript
Wenn Sie jedoch einzelne Elemente in der Liste vergleichen, klappt es überraschenderweise: set a to {1, 2, 3} set b to {1, 2, 3} set aRef to a reference to a -- Ergebnis: a of «script» set bRef to a reference to b -- Ergebnis: b of «script» item 1 of aRef = item 1 of bRef -- Ergebnis: true Hier wird mit items auf Elemente der Liste zugegriffen. Um auf den Inhalt zugreifen zu können, muss aber ein Rückverweis stattfinden. Wenn ein Rückverweis stattfindet, werden tatsächlich die Werte verglichen und nicht die Referenzen. Aus diesem Grund ergibt sich hier true. Bei allen Vergleichsoperatoren, in denen Referenzen beteiligt sind, sollten Sie die Auflösung einer Referenz daher am besten immer selbst vornehmen. Verlassen Sie sich nicht auf die automatische Rückverweisung einer Referenz. Verwenden Sie contents of, wann immer Sie das Ziel der Referenzen vergleichen wollen und nicht die Referenz selber: set a to {1, 2, 3} set b to {1, 2, 3} set aRef to a reference to a -- Ergebnis: a of «script» set bRef to a reference to b -- Ergebnis: b of «script» contents of aRef is equal to contents of bRef -- Ergebnis: true Aber natürlich kann es manchmal sinnvoll sein, keine Auflösung vorzunehmen, nämlich dann, wenn Sie herausfinden wollen, ob zwei Referenzen auf das gleiche Objekt zeigen. set a to {1, 2, 3} set aRef to a reference to a set bRef to a reference to a aRef = bRef -- Ergebnis: true Damit ist klar, dass beide Variablen eine Referenz auf dasselbe Objekt enthalten, und man kann geeignet darauf reagieren.
Optimierung durch Reduzierung gesendeter Apple-Events Nach diesem Ausflug in die Welt der Referenzen zurück zur Optimierung von Schleifen. Eine weitere Eigenart von AppleScript, die viel Zeit in einer Schleife kosten kann, ist das Senden von Apple-Events an eine Anwendung. Wenn in einer Schleife in jedem Durchgang einer Anwendung ein Befehl erteilt wird, so kann das einige Zeit dauern. Sobald der Befehl an die Anwendung abgesendet ist, kann Ihr Skript nämlich gar nichts mehr tun und wartet erstmal auf die Antwort der Anwendung. Kommt die Antwort, wird der nächste Befehl gesendet und so weiter. Folgendes Beispiel verdeutlicht das. In diesem Beispiel
288
Die Sprache
Kapitel 4
werden die Absätze in einem TextEdit-Dokument durchnummeriert, erhalten also eine Absatznummer am Anfang. Das Skript hat diesmal auch eine einfache Zeitmessung in Sekunden erhalten. -- Start der Zeitmessung set x to current date set i to 1 tell application "TextEdit" to tell document 1 -- Vor Beginn der Schleife ermitteln, wie viele Absätze es gibt: set anzahlAbsaetze to count paragraphs repeat -- Vor dem Absatz "1. " einfügen: set paragraph i to (i as text) & ". " & paragraph i -- Schleife verlassen, wenn alle Absätze durch sind: if i ≥ anzahlAbsaetze then exit repeat -- Schleifenzähler hochsetzen: set i to i + 1 end repeat end tell -- Ende der Zeitmessung display dialog (((current date) - x) as text) & " Sekunden" Wenn Sie das Skript ausprobieren wollen, so öffnen Sie ein Dokument in TextEdit und kopieren Sie ein paar Absätze Text hinein, bevor Sie es ausführen. Die ganze Schleife ist hier in einem tell an das erste Dokument von TextEdit gerichtet. Das heißt, dass in jeder Schleife für jeden Absatz ein Befehl an TextEdit gesendet wird, nämlich den entsprechenden Absatz auszutauschen gegen denselben Absatz mit einer Nummerierung davor. Bei solch einer Schleife kann man bequem zuschauen, wie Absatz für Absatz eine fortlaufende Zahl am Anfang erhält. Wenn Sie einen dickeren Wälzer in solch einer Schleife durcharbeiten wollen, können Sie erstmal Kaffee kochen gehen. Für 1000 Absätze mit jeweils nur einem Wort benötigt das Skript bei mir 529 Sekunden, also knapp 9 Minuten! Der Zeitbedarf für 1000 Befehle an eine Anwendung macht sich also erheblich bemerkbar, und dabei ist das Skript hauptsächlich mit Warten beschäftigt, dem Warten auf TextEdit, wann es bereit ist für den nächsten Befehl.
289
SmartBooks
AppleScript
Von daher ist es zu empfehlen, wo immer möglich, alle benötigten Daten in einem Rutsch aus der Anwendung abzuholen, dann in AppleScript ohne weiteres tell an die Anwendung zu bearbeiten und am Ende außerhalb der Schleife wieder in einem Rutsch in die Anwendung zurückzuschreiben. Folgender abgeänderter Code verdeutlicht das. set x to current date --Text komplett in einem Rutsch in die Variable oldTxt einlesen tell application "TextEdit" to set oldTxt to text of document 1 set anzahlAbsaetze to count paragraphs of oldTxt set newTxt to "" set i to 1 repeat set newTxt to newTxt & (i as text) & ". " & paragraph i of oldTxt & return if i = anzahlAbsaetze then exit repeat set i to i + 1 end repeat -- Text in TextEdit mit newTxt ersetzen tell application "TextEdit" to set text of document 1 to newTxt display dialog (((current date) - x) as text) & " Sekunden" In diesem Skript wird TextEdit nur noch zweimal angesprochen, statt über eintausend Mal, wie im vorigen Skript. Der Geschwindigkeitsgewinn ist enorm. Für 1000 Ein-Wort-Absätze werden bei mir nur noch 13 Sekunden benötigt, 13 Sekunden statt 529! Skriptprofis, die Perl oder Python verwenden, werden natürlich selbst darüber die Nase rümpfen, Dafür ist es aber auch in keiner anderen Sprache so leicht, Informationen aus einer laufenden Anwendung abzufragen, wie in AppleScript. Selbst Perl und Python sind von sich aus nicht dazu in der Lage und müssen mit Hilfe einer Zusatzbibliothek ebenfalls Apple-Events senden – und sind damit dann natürlich auch nicht schneller. Außer Textverarbeitungen sind auch Tabellenkalkulationen gute Kandidaten für diese Art der Optimierung. Lesen Sie zuerst die ganze Tabelle oder Teile als Bereich (range) ein, verarbeiten Sie dann die Zahlen in AppleScript ohne weiteres tell an die Anwendung. Wenn Sie fertig sind, schreiben Sie das Ergebnis ins Rechenblatt zurück. Diese Vorgehensweise ist wesentlich schneller, als für jede einzelne Zelle einen Befehl an die Anwendung zu richten.
290
Die Sprache
Kapitel 4
Natürlich ist diese Optimierung nicht in allen Fällen möglich. Wenn es sich um Text handelt, wie in diesem Beispiel, ist es oft (aber nicht immer) kein Problem, da AppleScript direkt mit Text umgehen kann. Wenn Sie jedoch mit Musik oder Bildern zu tun haben, müssen Sie meist direkt im Programm Schleifen drehen, da AppleScript nur über sehr rudimentäre Möglichkeiten verfügt, mit diesen Datentypen direkt zu arbeiten.
return oder try als Abbruchbedingung Statt mit exit repeat lässt sich eine Schleife auch mit einem return beenden. Damit ist nicht der Zeilenumbruch return gemeint, sondern die Anweisung gleichen Namens. Damit wird normalerweise ein Handler beendet. Wenn Sie es im Hauptskript selber oder in einer Schleife verwenden, wird das Skript an dieser Stelle sofort beendet. Eventuell nachfolgende Befehle werden also nicht mehr ausgeführt. Return kann auch einen optionalen Ausdruck zurückliefern, der dem Schlüsselwort unmittelbar folgen muss. Details finden Sie im Kapitel Handler. In folgendem Beispiel wird das Skript beendet, wenn in der Schleife die Variable zaehler den Wert 1000 erreicht. In dem Augenblick wird das Skript beendet und mit return noch der Wert von zaehler zurückgeliefert. Der Befehl beep am Ende des Skripts kann also nicht mehr ausgeführt werden! set myList to {} set zaehler to 1 set myListRef to a reference to myList repeat copy zaehler to end of myListRef if zaehler = 1000 then return zaehler set zaehler to zaehler + 1 end repeat beep Auch mit einem try kann eine Schleife beendet werden. Beachten Sie hierzu das Kapitel try.
repeat n times Diese Form der Schleife besitzt im Gegensatz zur bisher behandelten Endlosschleife eine implizite Abbruchbedingung, die direkt nach dem repeat folgt. Und zwar muss dem repeat ein Ausdruck folgen, welcher sich als Integer werten lässt, gefolgt von dem Schlüsselwort times: set x to 2 repeat 7 times set x to x * 2 end repeat display dialog x -- Ergebnis: 256 291
SmartBooks
AppleScript
Alles innerhalb des repeat wird so oft wiederholt, wie es durch die Integerzahl nach dem repeat angegeben ist. Wenn diese Anzahl an Schleifen durchgelaufen ist, wird mit dem Code nach dem end repeat fortgefahren. Wenn der Wert der Integerzahl null ist oder ein Minuswert, wird die Schleife überhaupt nicht durchlaufen. Statt die Zahl als Integer direkt anzugeben, kann dort natürlich auch eine Variable oder ein Ausdruck stehen, welcher eine Integerzahl ergibt oder welcher sich in eine Integerzahl konvertieren lässt: repeat x + 5 times funktioniert daher genauso wie repeat "1" & "2" times wobei der Text "12" zur Integerzahl 12 konvertiert wird. Bei dieser Schleifenform brauchen Sie kein exit repeat, da die Schleife nach der vorgegebenen Anzahl an Durchläufen ja automatisch anhält. Ein exit repeat kann aber zusätzlich verwendet werden, zum Beispiel, um in einem if auf andere Bedingungen zu prüfen, die ebenfalls einen Abbruch der Schleife erforderlich machen.
repeat until In dieser Form der Schleife muss dem repeat until ein Ausdruck folgen, welcher einen booleschen Wert ergibt. Nur solange der Wert nicht wahr ist, wird die Schleife durchlaufen. repeat until bedeutet: Wiederhole so lange, bis die folgende Bedingung wahr wird. Achten Sie wieder darauf, dass in der Schleife auch eine Aktion stattfindet, die irgendwann dazu führt, dass der Ausdruck am Anfang des repeat wahr werden kann. set myList to {} set myListRef to a reference to myList set x to 1 repeat until length of myListRef > 99 copy x to end of myListRef set x to x + 1 end repeat get myList Diese Form der Schleife wird also eventuell überhaupt nicht durchlaufen, nämlich dann, wenn der Ausdruck schon bei der ersten Prüfung true ergibt. Das wäre in obigem Beispiel der Fall, wenn myList bereits eine Länge über 99 hätte. Da diese aber gerade frisch als leere Liste definiert wurde, kann der Fall natürlich nicht eintreten.
292
Die Sprache
Kapitel 4
An obigem Beispiel ist auch zu sehen, dass natürlich auch Eigenschaften von Objekten im Ausdruck abgefragt werden können. Hier wird die Eigenschaft length der Liste abgefragt. Am Anfang ist diese 0 und da 0 nicht größer ist als 99, wird die Schleife gestartet und läuft dann weiter bis der Ausdruck wahr ergibt – bis die Liste also 100 Elemente enthält. Eines ist hier unbedingt zu beachten: Der Test nach dem repeat until findet in jeder einzelnen Runde der Schleife statt! Vermeiden Sie es daher, in diese Bedingung Aufrufe an Objekte oder Handler zu packen, da diese Prüfung jedes Mal viel Zeit kostet. Wenn Sie in diesem Test auf eine Liste zugreifen, dann verwenden Sie unbedingt eine Referenz auf die Liste. Wenn Sie obiges Skript nur in einem Punkt abändern, nämlich die Länge der Liste direkt abfragen, dann dauert die Ausführung gleich erheblich länger. Am besten ist das zu messen, wenn man die Liste auch gleich länger macht, wie zum Beispiel 10000 Elemente: set startZeit to current date set myList to {} set myListRef to a reference to myList set x to 1 repeat until length of myList > 9999 -- Das sollte man nicht machen! copy x to end of myListRef set x to x + 1 end repeat --get myList display dialog (((current date) - startZeit) as text) & " Sekunden" Obiges Skript dauert bei mir 18 Sekunden! Verwenden Sie jedoch in der repeat-Bedingung length of myListRef, also eine Referenz auf die Liste, ist es in 1 Sekunde fertig. Die Referenz auf myListRef innerhalb des repeat beim copy spart natürlich auch noch mal erheblich Zeit. Entfernt man auch diese Referenz, wären es sogar 34 Sekunden Laufzeit. Sie sehen: Nicht nur die Anweisungen in der Schleife, auch die Prüfbedingung im repeatKopf kann erheblich Zeit kosten! Wenn immer möglich, verwenden Sie eine einfache Variable mit einer Zahl oder eine Referenz auf eine Liste im repeat-Kopf, aber greifen Sie dort nicht direkt auf Listen, Programmobjekte oder Handler zu. Grundlagen Natürlich werden die Computer immer schneller und die Messergebnisse hier sind nur untereinander vergleichbar. Auf den neuesten Rechnern werden Sie die Schleifen vielleicht noch weiter vergrößern müssen, bevor ein signifikanter Unterschied zutage tritt.
293
SmartBooks
AppleScript
Eine repeat until Schleife lässt sich mit einem exit repeat natürlich auch vor dem natürlichen Schleifenende beenden.
repeat while Die Schleifenform repeat while stellt das Gegenstück zu repeat until dar. Bei repeat until läuft die Schleife, solange die angegebene Bedingung nicht wahr ist. Bei repeat while läuft die Schleife, solange die Bedingung wahr ist. Die Schleife wird also verlassen, sobald der Ausdruck nicht mehr wahr ist. Ist schon beim ersten Test die Bedingung falsch, wird die Schleife überhaupt nicht ausgeführt und sofort mit dem Code nach der Schleife fortgefahren. repeat while bedeutet: Wiederhole, solange die folgende Bedingung wahr ist. Für das Erstellen einer Liste sähe eine Schleife mit while zum Beispiel so aus: set myList to {} set myListRef to a reference to myList set x to 1 repeat while length of myListRef < 100 copy x to end of myListRef set x to x + 1 end repeat get myList Das Einzige, was sich hier im Vergleich zur Schleifenform von repeat until ändert, ist der Test nach dem repeat. Hier muss nun umgekehrt getestet werden, also mit einem Kleiner-Zeichen, damit die Bedingung von Anfang an wahr ist, weil sonst die Schleife gar nicht durchlaufen würde. Auch für die repeat while Schleife gilt: Vermeiden Sie Prüfbedingungen, die AppleEvents an das Programm senden, Handler aufrufen oder direkt auf Listen zugreifen. Eine repeat while-Schleife lässt sich ebenfalls mit einem exit repeat vor ihrem natürlichen Schleifenende beenden.
repeat with Diese Schleifenform hat einige Vorteile gegenüber den bisherigen Schleifen. Wenn Sie die Formen von repeat, repeat until und repeat while vergleichen, fällt Ihnen sicher auf, dass in all diesen Fällen immer eine Variable definiert wurde, die nur dazu diente, die Anzahl der Schleifendurchläufe zu zählen.
294
Die Sprache
Kapitel 4
Wenn Sie darauf angewiesen sind, die Anzahl der Schleifendurchläufe zu kennen, sollten Sie sich die Definition des Schleifenzählers besser sparen, indem Sie die folgende Form des repeat verwenden: set myList to {} set myListRef to a reference to myList repeat with i from 1 to 100 copy i to end of myListRef end repeat get myList Diese Form ist also gleich zwei Zeilen kürzer. Der Schleifenzähler wird nun gleich im repeat-Kopf definiert: repeat with i from 1 to 100 Die Syntax lautet: repeat with schleifenVariable from startWert to stoppWert Die kursiv dargestellten Elemente müssen eine Ganzzahl ergeben oder sich als solche interpretieren lassen. Sie können also auch hier wieder komplexere Ausdrücke verwenden, nur dass diese keinen Wahrheitswert ergeben dürfen, sondern eine Integerzahl. Für schleifenVariable können Sie einen beliebigen Variablennamen einsetzen, oben habe ich es mir einfach gemacht und nur den Buchstaben i verwendet. Dies ist die Schleifenvariable, die in den anderen repeat bisher immer extra definiert werden musste. Hier wird die Schleifenvariable genau an dieser Stelle im Kopf des repeat einfach durch Angabe des Namens definiert und sie erhält als ersten Wert den Wert, der in startWert steht. Wenn dort also eine 1 steht, beginnt die Schleife mit dem Wert eins. Standardmäßig wird dann in den folgenden Runden der Wert der Schleifenvariable jeweils um eins erhöht. Die Schleife endet, wenn der Wert von stoppWert erreicht oder überschritten wurde. Ist stoppWert kleiner als startWert, wird die Schleife erst gar nicht begonnen. Statt Zahlliteralen können Sie für startWert und stopWert natürlich auch Variablen verwenden oder Ausdrücke wie in folgendem Beispiel: set myList to {} set myListRef to a reference to myList set startWert to 50 set stopWert to 150 repeat with i from startWert - 39 to stopWert - 40 copy i to end of myListRef end repeat get myList 295
SmartBooks
AppleScript
Wie Sie hier sehen, muss startWert nicht unbedingt 1 sein! Hier wird von 50 minus 39, also von 11 an, hochgezählt, bis die Schleifenvariable i den Stoppwert von 150 minus 40, also 110, erreicht. Als Ergebnis erhalten Sie hier eine Liste mit den Zahlen von 11 bis 110. Wenn Sie die Schleifenvariable in der Schleife selbst noch einmal verändern, so hat das auf die nächste Schleife keinen Einfluss, diese fährt einfach mit dem nächsten um eins erhöhten Wert fort, wird spätestens dort also wieder zurückgesetzt. Diese Schleife eignet sich daher weniger für die Fälle, bei denen die Schleifenvariable selbst Gegenstand von Änderungen in der Schleife sein muss, damit die Schleife früher oder später als ursprünglich vorgesehen endet. Falls Sie für die Schleifenvariable eine bereits existierende Variable verwenden, wird diese für die Verwendung in der Schleife überschrieben. Der ursprüngliche Wert geht also verloren. Für den Stoppwert lässt sich auch wieder gut die Länge einer Liste verwenden: set myList to {"a", "b", "c", "d", "e"} set myListRef to a reference to myList repeat with i from 1 to length of myListRef set item i of myListRef to item i of myListRef & i end repeat get myList -- Ergebnis: {"a1", "b2", "c3", "d4", "e5"} Bei dieser Schleifenart ist es wichtig zu wissen, dass der Start- und Stoppwert nur ein Mal beim ersten Start der Schleife ermittelt wird. Sie sollten daher keine Ausdrücke darin verwenden, die sich während der Laufzeit der Schleife verändern. Diese Änderung hätte dann keinen Einfluss mehr auf den Start- oder Stoppwert. Das bedeutet dann aber auch: repeat with ist äußerst effektiv. Wenn der Start- und/oder Stoppwert über einen Befehl an eine Anwendung ermittelt wird oder über den Aufruf eines Handlers, dann findet diese Abfrage nur ein einziges Mal beim Start der Schleife statt. Diese Form der Schleife ist also effektiver als repeat until oder repeat while, wo die Bedingung in jeder Schleife jedes Mal neu geprüft werden muss. Hier wird die Schleifenvariable immer um eins hochgezählt. Alternativ können Sie aber auch mit dem zusätzlichen Argument by angeben, wie viel Schritte weit gezählt werden soll. In folgendem Beispiel wird die Schleifenvariable immer um zwei erhöht statt um eins, mit dem Ergebnis, dass nur jede ungerade Zahl in der Liste landet:
296
Die Sprache
Kapitel 4
set myList to {} set myListRef to a reference to myList repeat with i from 1 to 100 by 2 copy i to end of myListRef end repeat get myList Wenn Sie als Schrittweite eine Minuszahl eingeben, wird rückwärts gezählt, was dann aber auch bedeutet, dass der Startwert höher liegen muss als der Stoppwert. In folgendem Beispiel wird von i nach jedem Schleifendurchlauf 5 abgezogen: set myList to {} set myListRef to a reference to myList repeat with i from 100 to 1 by -5 copy i to end of myListRef end repeat get myList -- Ergebnis: {100, 95, 90, 85, 80, 75, 70, 65, 60, 55, 50, 45, 40, 35, 30, 25, 20, 15, 10, 5} Als Ergebnis landen alle durch fünf teilbaren Zahlen zwischen 100 und 1 in der Liste, also von den großen Zahlen herunter zu den kleinen.
repeat with (in Liste) Für den Fall, dass Sie in einer Schleife direkt über die Elemente einer Liste kreisen wollen, gibt es noch eine weitere Version von repeat with, speziell für die Iteration über Listen. In dieser Form erübrigt sich das Ermitteln der Länge einer Liste. Die Form dieser Schleife lautet: repeat with schleifenvariable in listenName Hier ein Beispiel: set oldList to {"a", "b", "c", "d", "e"} set oldListRef to a reference to oldList set newList to {} set newListRef to a reference to newList repeat with i in oldListRef set end of newListRef to i & i end repeat get newList -- Ergebnis: {"aa", "bb", "cc", "dd", "ee"}
297
SmartBooks
AppleScript
Auch hier wird die Schleifenvariable wieder nach dem repeat with definiert. Das Besondere hier ist, dass danach das Schlüsselwort in mit einer Liste folgt. Über diese Liste werden Schleifen gedreht. Eine weitere Besonderheit liegt darin, dass die Schleifenvariable kein Zähler ist! Sie speichert nicht die Anzahl der Schleifendurchgänge, nein, sie nimmt in jedem Schleifendurchlauf den nächsten Wert aus der Liste auf (als Referenz!), so lange, bis das letzte Element der Liste erreicht und abgearbeitet ist. Die Anzahl der Schleifendurchläufe entspricht also immer genau der Anzahl der Elemente in der Liste. Um das zu beweisen, setzen Sie in die obige Schleife einmal als zusätzliche Anweisung ein log i und schauen Sie dann ins Eventprotokoll des Skripteditors. Sie erhalten dort folgende Inhalte von i:
(*a*) (*b*) (*c*) (*d*) (*e*)
Jede Zeile stellt einen Schleifendurchgang dar. Die Schleifenvariable nimmt also einen Wert nach dem anderen als Inhalt an, sie zählt nichts. Mit anderen Worten: Wenn Sie darauf angewiesen sind, in einer Liste immer genau Bescheid zu wissen, im wievielten Schleifendurchlauf Sie sich gerade befinden, dann müssen Sie hier noch manuell einen Zähler anlegen. Wenn jedoch die Anzahl der Schleifendurchgänge uninteressant ist, dann ist eine Schleife wie diese genau richtig. Genau genommen wird in die Schleifenvariable nicht ein Element der Liste übernommen, sondern nur eine Referenz auf den Wert in dieser Liste. Das kann dann durchaus überraschende Auswirkungen haben, wenn man nicht darüber informiert ist. Wenn Sie die Schleifenvariable mit einem Befehle wie log anzeigen, wird die Referenz in i automatisch aufgelöst und im Eventprotokoll wird der Wert angezeigt. Wenn Sie aber in der Schleife einen Test damit vornehmen, also einen Vergleichsoperator darauf anwenden, geschieht kein automatischer Rückverweis der Referenz: set oldList to {"a", "b", "c", "d", "e"} set oldListRef to a reference to oldList set newList to {} set newListRef to a reference to newList repeat with i in oldListRef set end of newListRef to i & i if i = "b" then say "I found character " & i -- wird niemals eintreten! end repeat 298
Die Sprache
Kapitel 4
Obige Prüfung auf den Inhalt von i wird nie wahr werden, denn i enthält tatsächlich nur die Adresse auf den Wert in der Schleife, nicht den Wert selber. Wenn in i aber die Adresse item 1 of oldList of «script» steht, wird das niemals gleich "b" sein. Der Beweis lässt sich leicht erbringen, indem Sie in dem Skript eine Liste mit den Werten von i anlegen, ohne eine Operation damit vorzunehmen. Lassen Sie jeglichen Operator weg, wird tatsächlich eine Liste mit den Referenzen auf die Elemente der Liste angelegt: set oldList to {"a", "b", "c", "d", "e"} set oldListRef to a reference to oldList set newList to {} set newListRef to a reference to newList repeat with i in oldListRef set end of newListRef to i -- Hier gibt’s nur Adressen, keine Werte! end repeat get newList -- Ergebnis: {item 1 of oldList of «script», item 2 of oldList of «script», item 3 of oldList of «script», item 4 of oldList of «script», item 5 of oldList of «script»} Sie sehen am Ergebnis, dass in der Schleifenvariablen i tatsächlich nur die Adressen auf die Listenelemente stecken. Das ist dann aber auch der Grund, warum diese Schleifenform relativ schnell ist. Ich konnte zumindest keine signifikanten Geschwindigkeitsunterschiede zu der repeat with-Schleife mit Start- und Stoppwert feststellen. Aber auch hier müssen Sie natürlich darauf achten, immer mit einer Referenz auf die Liste zuzugreifen und nicht direkt auf der Liste zu arbeiten. Wie kann man aber nun explizit auf den Inhalt zugreifen, ohne deswegen immer einen Befehl auf die Schleifenvariable anzuwenden? Fragen Sie explizit mit dem Schlüsselwort contents of nach dem Wert: set oldList to {"a", "b", "c", "d", "e"} set oldListRef to a reference to oldList repeat with i in oldListRef if contents of i = "b" then say "I found character " & i -- das klappt! end repeat Wenn Sie also nach contents of i fragen, funktionieren auch die Vergleichsoperatoren. Da in der Schleifenvariable die Adresse für das Element der Liste gespeichert ist, können Sie aber auch über diese Schleifenvariable die Elemente in der Liste direkt verändern.
299
SmartBooks
AppleScript
Das funktioniert so: set myList to {"a", "b", "c", "d", "e"} set myListRef to a reference to myList repeat with i in myListRef set contents of i to i & 1 end repeat get myList -- Ergebnis: {"a1", "b1", "c1", "d1", "e1"} Damit ist die Schleife noch mal wesentlich kompakter und übersichtlicher geworden. Durch den Operator & wird übrigens im Ausdruck i & i automatisch die Adresse aufgelöst, ansonsten müsste auch dort noch mal contents of i stehen. Statt einer Liste kann für dieses repeat auch eine Objektspezifikation angegeben werden, welche eine Liste ergibt. Zum Beispiel: set newList to {} set newListRef to a reference to newList repeat with i in words of "Bube Dame König Ass" set end of newListRef to "Herz " & contents of i end repeat get newList -- Ergebnis: {"Herz Bube", "Herz Dame", "Herz König", "Herz Ass"} Hier iteriert man also über die Wörter eines Textes. Tatsächlich wird natürlich intern aus der Objektreferenz zuerst eine Liste angelegt. Obige repeat-Zeile wäre also identisch mit: repeat with i in {"Bube", "Dame", "König", "Ass"} Wenn man sich die Adressen in i genauer anschaut, sehen die Referenzen dann so aus: set newList to {} set newListRef to a reference to newList repeat with i in words of "Bube Dame König Ass" set end of newListRef to i end repeat get newList -- Ergebnis: {item 1 of every word of "Bube Dame König Ass", item 2 of every word of "Bube Dame König Ass", item 3 of every word of "Bube Dame König Ass", item 4 of every word of "Bube Dame König Ass"} Dasselbe findet auch bei Referenzen auf Objekte in einer Anwendung statt. Hier zum Beispiel beim Finder:
300
Die Sprache
Kapitel 4
set newList to {} set newListRef to a reference to newList tell application "Finder" repeat with i in folder "Testordner" of desktop set end of newList to i end repeat end tell get newList - - Ergebnis: {item 1 of folder "Testordner" of desktop of application "Finder", item 2 of folder "Testordner" of desktop of application "Finder", item 3 of folder "Testordner" of desktop of application "Finder"} Wenn Sie einen Ordner angeben, wird also eine Schleife über alle Elemente in diesem Ordner gedreht. Wichtig hierbei: Das funktioniert nur bei Objekten, die auch Elemente beinhalten können. Außerdem gibt es keine Garantie dafür, was dabei herauskommt, wenn man über ein Objekt Schleifen dreht, welches andere Objekte beinhalten kann. Der Finder zählt zum Beispiel alle Elemente in dem Ordner, also nicht nur Dateien, sondern auch darin enthaltene Ordner. Je nachdem, welche Objekte in welcher Anwendung Sie steuern wollen, sollten Sie immer vorher ausprobieren, ob solch eine direkte Iteration auch funktioniert. Bei komplizierten Objekthierarchien kann es notwendig sein, das Hilfsverb get zu verwenden, um eine Objektliste mit den Referenzen für das repeat zu erzeugen. In folgendem Beispiel wird allen Dokumenten im Ordner Testordner auf dem Schreibtisch ein anderes Etikett verleihen. Ohne das get würde der Ausdruck nicht verstanden werden: tell application "Finder" repeat with i in (get document files in folder "Testordner" of desktop) set label index of i to 3 end repeat end tell Sie können aber auch eine Abfrage mit dem Filter whose erstellen, soweit es die Anwendung unterstützt: tell application "Finder" repeat with i in (items of folder "Testordner" of desktop whose class is document file) set comment of i to "Weihnachten 2008" end repeat end tell 301
SmartBooks
AppleScript
Da in obigen Beispielen die Terminologie vom Finder verwendet wird, muss dieses repeat auch in einem tell-Block an den Finder stehen! Das lässt sich hier nicht vermeiden, schließlich müssen Sie für jede Datei auch einen Befehl an den Finder senden, um die entsprechende Eigenschaft zu ändern. Naturgemäß ist dann auch die Geschwindigkeit der Ausführung gemächlich. Wenn Sie aber beim tell aufgepasst haben, wird Ihnen bestimmt auffallen, dass hier gar kein repeat benötigt wird, da Sie im Finder direkt mit whose die Etiketten aller Dateien ohne Schleife verändern können. Und das geht wesentlich schneller als eine Schleife: tell application "Finder" set label index of (items of folder "Testordner" of desktop ¬ whose class is document file) to 3 end tell Bevor Sie Schleifen über Objekte drehen, also immer erst einmal ausprobieren, ob sich diese vielleicht mit whose direkt in einem Rutsch verändern lassen! Allzu leicht vergisst man das im Eifer des Gefechts.
Optimierung durch System-Events statt Finder Der Finder als zentrale Anlaufstelle für alles, was das Betriebssystem betrifft, verliert zunehmend an Bedeutung. Mehr und mehr Möglichkeiten, auf das Betriebssystem Einfluss zu nehmen, werden nämlich auch in das Programm System-Events eingearbeitet. Im Gegensatz zum Finder handelt es sich um ein »gesichtsloses« Programm, es besitzt also keinerlei grafisches Benutzerinterface und wird nur bei Bedarf gestartet. Aus diesem Grund ist es aber auch schneller als der Finder. Allerdings lassen sich damit nicht die typischen Findereigenschaften wie zum Beispiel Etiketten verändern. Bei System-Events geht es mehr um das Betriebssystem an sich. Das Programm System-Events verbirgt sich im Ordner /System/Library/CoreServices/, wo sich auch noch andere für den Skripter sehr nützliche Programme verbergen, wie zum Beispiel die Image Events zur Bildbearbeitung direkt in AppleScript. Wenn Sie also nicht gerade eine Eigenschaft wie Etiketten oder Spotlight-Kommentare bearbeiten wollen, dann sollten Sie das Programm System-Events bevorzugen. Zusätzlich zu den System-Events gibt es zur Iteration über Dateien auch noch die Möglichkeit, die File commands aus den Standarderweiterungen zu nutzen. Sie können das Funktionsverzeichnis der Standarderweiterung von AppleScript über Ablage | Funktionsverzeichnis im Skripteditor öffnen. Doppelklicken Sie dort die Skripterweiterung Standard Additions und schauen Sie unter File commands nach. Die Befehle dort sind inzwischen allerdings als »deprecated«, also als veraltet markiert. Die Verwendung dieser Befehle wird daher irgendwann wohl nicht mehr unterstützt werden.
302
Die Sprache
Kapitel 4
Bei den System-Events finden Sie die Klassen und Befehle zum Dateisystem im Funktionsverzeichnis in der Disk-Folder-File-Suite. Hier ein Beispiel, wie man das Programm "System-Events" zur Umbenennung von Dateien in einem Ordner verwenden kann. Hier werden für das repeat nur sichtbare Dateien abgefragt, die kein Alias sind und den Dateityp tiff haben. Andere Dateitypen und Ordner bleiben daher unberücksichtigt und werden nicht umbenannt. set x to 1 tell application "System Events" set myFolder to folder "Testordner" of desktop folder repeat with i in (get files of myFolder whose (visible is true) and ¬ (kind is not "Alias") and (file type is "tiff")) set name of i to (x as text) & "_" & name of i set x to x + 1 end repeat end tell Die Dateien erhalten hier also eine durchgehende Nummerierung am Anfang des Namens. Fragen Sie einmal nach den Eigenschaften der Datei. Sie erhalten auch hier wieder einen Record zurück: tell application "System Events" properties of file ¬ "Macintosh HD:Users:Detlef:Desktop:Testordner:image4.tiff" end tell -- Ergebnis: {physical size:65536 container:folder "Macintosh HD:Users:Detlef:Desktop:Testordner:" POSIX path:"/Users/Detlef/Desktop/Testordner/image4.tiff" default application:alias "Macintosh HD:Applications:Adobe Photoshop:Adobe Photoshop.app:" product version:"" name:"image4.tiff" visible:true volume:"Macintosh HD" displayed name:"image4.tiff" modification date:date "Montag 26. Mai 2008 15:47:15 Uhr" package folder:false creator type:"8BIM" size:63185 303
SmartBooks
AppleScript
busy status:false stationery:false type identifier:"public.tiff" creation date:date "Montag 26. Mai 2008 15:47:15 Uhr" version:"" short version:"" file type:"TIFF" path:"Macintosh HD:Users:Detlef:Desktop:Testordner:image4.tiff" kind:"Adobe Photoshop TIFF file" URL:"file://localhost/Users/Detlef/Desktop/Testordner/image4.tiff" name extension:"tiff" class:file id:"image4.tiff,-100,4893846"} Der Filter whose funktioniert wunderbar auch direkt in einem tell. Beachten Sie nur im Funktionsverzeichnis, welche Eigenschaften der Klasse file sich auch ändern lassen. Viele sind schreibgeschützt. Im Folgenden wird der creator type aller sichtbaren Dateien mit dem Dateikürzel tiff auf den Typ des Programms GraphicConverter (GKON) umgestellt. Die Dateien öffnen sich damit ab sofort mit diesem Programm. tell application "System Events" set myFolder to folder "Testordner" of desktop folder tell (files of myFolder whose visible is true and name extension is "tiff") set creator type to "GKON" end tell end tell Das Ergebnis kann im Finder in der Dateiinformation unter Öffnen mit überprüft werden, oder indem man erneut die Propertys einer Datei abfragt.
Geschachtelte repeat Auch ein repeat lässt sich natürlich schachteln, und oft ist es sogar unumgänglich, nämlich immer dann, wenn Objekte wiederum Elemente eines Objekts sind. Einfachstes Beispiel wäre eine Liste, die Listen als Elemente enthält. In folgendem Beispiel soll allen Elementen in allen Listen der Hauptliste ein Buchstabe vorangefügt werden:
304
Die Sprache
Kapitel 4
set oldList to {{1, 2, 3}, {2, 4, 6}, {1, 3, 5}} set abclist to {"a", "b", "c"} set x to 1 repeat with i in oldList repeat with j in i set contents of j to item x of abclist & j end repeat set x to x + 1 end repeat get oldList -- Ergebnis: {{"a1", "a2", "a3"}, {"b2", "b4", "b6"}, {"c1", "c3", "c5"}} Doch was ist, wenn Sie nicht wissen, wie tief die Objekte verschachtelt sind? Ordner sind dafür ein klassisches Beispiel. Ein Ordner kann in einem Ordner stecken, welcher wiederum in einem Ordner steckt und so weiter. Für jede Verschachtelungsebene ein repeat anzulegen, das geht nicht, da man im Vorhinein nicht weiß, wie tief die Ordner verschachtelt sind. Solche Schleifen über eine unbekannte Verschachtelungstiefe nennt man »rekursiv« und man löst sie in AppleScript nicht mit einem repeat, sondern über den rekursiven Aufruf von Handlern. Die allgemeine Lösung für dieses Problem finden Sie daher im Kapitel Handler. Wenn es jedoch um den Finder geht, ist ein rekursiver Handler meist gar nicht nötig. Der Finder kennt nämlich die Klasse container, und diese besitzt die Eigenschaft entire contents. Wenn Sie einen folder, welcher von der Klasse container abstammt, nach seinem entire contents fragen, so erhalten Sie eine Liste mit allen Objekten in diesem Ordner und sämtlichen Unterordnern. Die Ordner selbst sind ebenfalls Elemente der Liste, nicht aber unsichtbare Dateien. Im nächsten Beispiel werden die POSIX-Pfade aller Dokumente eines Ordners und seiner Unterordner ermittelt, in eine Liste gespeichert und zum Schluss in einen Text mit Zeilenumbruch umgewandelt (zum Einfügen in eine Textverarbeitung): set pfadListe to {} tell application "Finder" set myFolder to folder "Testordner" of desktop set allItems to entire contents of myFolder repeat with i in allItems if (class of i is document file) then copy POSIX path of (i as text) to end of pfadListe end if end repeat end tell set text item delimiters to return get pfadListe as text 305
SmartBooks
AppleScript
Grundlagen Bevor Sie groß versuchen, Schleifen über mehrere Ebenen zu drehen, schauen Sie immer zuerst im Funktionsverzeichnis der Anwendung nach. Manchmal gibt es dafür auch eine Abkürzung in Form eines Befehls oder einer Eigenschaft. Diese liefert Ihnen dann das Gewünschte, nämlich eine Liste aller ineinander verschachtelten Elemente, in einem Rutsch, so dass Sie dann nur noch eine einzige Schleife über diese Liste benötigen.
considering/ignoring Mit den Schlüsselwörtern considering und ignoring nehmen Sie keine Verzweigung oder Schleife vor. Sie beeinflussen damit das Verhalten von AppleScript an sich. In diesem Kapitel geht es speziell um das Verhalten von AppleScript bei Textvergleichen. Wie Sie bereits wissen, beachtet AppleScript die Groß- und Kleinschreibung bei Textvergleichen nicht. Wenn Sie dieses Verhalten und andere ändern wollen, dann können Sie das mit einer considering- oder ignoring-Anweisung erreichen, die im Folgenden im Detail behandelt werden. Tipp Egal, wie das Standardverhalten in AppleScript auch ist, geben Sie immer explizit das von Ihnen gewünschte Verhalten mit considering oder ignoring in Ihrem Skript an. Sie erreichen dadurch eine größtmögliche Kompatibilität mit älteren Betriebssystemen und mit möglichen Änderungen von AppleScript in der Zukunft.
case Mit case können Sie Einfluss darauf nehmen, ob die Groß- und Kleinschreibung bei einem Textvergleich beachtet werden soll oder nicht. Standardmäßig wird die Groß- und Kleinschreibung bei Textvergleichen in AppleScript seit jeher nicht beachtet. "abc" = "ABC" -- Ergebnis: true Möchten Sie dieses Verhalten ändern, so müssen Sie den Textvergleich in eine considering case-Anweisung schachteln: considering case "abc" = "ABC" -- Ergebnis: false end considering Wenn Sie explizit ausschließen möchten, dass die Groß- und Kleinschreibung beachtet wird, so können Sie, obwohl dieses Verhalten ja bereits Standard in AppleScript ist, den Textvergleich in ein ignoring case schachteln:
306
Die Sprache
Kapitel 4
ignoring case "abc" = "ABC" -- Ergebnis: true end ignoring Dasselbe Verhalten betrifft auch die text item delimiters. Das schnelle Suchen und Ersetzen mit text item delimiters wird also Groß- und Kleinschreibung nicht unterscheiden. Mit einem considering case lässt sich das aber schnell ändern: set meinText to "Achtung, achtmal!" considering case set text item delimiters to "acht" set meinText to every text item of meinText set text item delimiters to "sieben" set meinText to meinText as text end considering -- Ergebnis: "Achtung, siebenmal!" Als Ergebnis erhalten Sie "Achtung, siebenmal!". Würden Sie das considering weglassen oder stattdessen ignoring verwenden (wie in den folgenden Zeilen) so erhielten Sie als Ergebnis "siebenung, siebenmal!". set meinText to "Achtung, achtmal!" ignoring case set text item delimiters to "acht" set meinText to every text item of meinText set text item delimiters to "sieben" set meinText to meinText as text end ignoring -- Ergebnis: "siebenung, siebenmal!" Beachten Sie, dass jedes considering oder ignoring auch immer ein end considering oder end ignoring erfordert. Es reicht dabei, wenn Sie einfach nur end schreiben. Das ignoring oder considering hinter dem end wird beim Kompilieren automatisch ergänzt. Nur die Codezeilen, die sich in dem considering- oder ignoring-Block befinden, richten sich nach der Groß- und Kleinschreibung. Außerhalb dieses Blocks gelten die Standardbedingungen von AppleScript.
307
SmartBooks
AppleScript
Aufgepasst Wenn ein Skript mit text item delimiters auf Tiger und Leopard gleichermaßen laufen soll, sollten Sie immer genau angeben, ob die Groß- und Kleinschreibung berücksichtigt werden soll, denn beide Betriebssysteme verhalten sich hier gegensätzlich. Lassen Sie das considering case oder ignoring case weg, wird unter Mac OS X 10.4 und früher bei den text item delimiters die Groß- und Kleinschreibung berücksichtigt, unter Leopard jedoch nicht. Mit anderen Worten: Das Skript wird auf einem der beiden Betriebssysteme fehlerhaft laufen. In Leopard wurde damit das Verhalten der text item delimiters bei Textvergleichen dem Verhalten von AppleScript bei einfachen Textvergleichen angeglichen. Man hatte sich zwar daran gewöhnt, dass die text item delimiters sich anders herum verhalten, nun aber gilt übergreifend generell: Textvergleiche aller Art beachten nicht die Groß- und Kleinschreibung, egal, ob es sich um einen einfachen direkten Vergleich von Text handelt oder ob er mittels text item delimiters stattgefunden hat.
diacriticals Sollen bei einem Vergleich ein e und ein é gleich behandelt werden? Dann müssen Sie ignoring diacriticals verwenden. Standardmäßig werden diakritische Zeichen bei Textvergleichen immer berücksichtigt. Das heißt, e und é wären nicht dieselben Buchstaben. "égalité" starts with "e" -- Ergebnis: false ignoring diacriticals "égalité" starts with "e" -- Ergebnis: true end ignoring Das gilt auch für den Fall von zusammengesetzten Unicode-Zeichen: set eAkut to character id {101, 769} -- eAkut enthält nun "é" "e" = eAkut -- Ergebnis: false Mit ignoring gelten beiden Texte als gleich: set eAkut to character id {101, 769} -- eAkut enthält nun "é" ignoring diacriticals "e" = eAkut -- Ergebnis: true end ignoring Die text item delimiters verhalten sich gleich. Im folgenden Code werden die diakritischen Zeichen berücksichtigt, infolgedessen wird nur Liberté gefunden und ersetzt, nicht jedoch Liberte.
308
Die Sprache
Kapitel 4
set meinText to "Liberté, Liberte" set text item delimiters to "Liberté" set meinText to every text item of meinText set text item delimiters to "Freiheit" set meinText to meinText as text --Ergebnis: "Freiheit, Liberte" Verwenden Sie daher ignoring, wenn der Akzent nicht berücksichtigt werden soll. set meinText to "Liberté, Liberte" ignoring diacriticals set text item delimiters to "Liberté" set meinText to every text item of meinText set text item delimiters to "Freiheit" set meinText to meinText as text end ignoring --Ergebnis: "Freiheit, Freiheit"
expansion Dieses Attribut für considerung und ignoring ist in Leopard weggefallen. Das heißt, es spielt nur noch in früheren Betriebssystemversionen eine Rolle. Skripts, die dieses Attribut verwenden, laufen unter Leopard nicht mehr! Was hat expansion dann eigentlich gemacht? Wenn man ignored expansion verwendete, wurden Ligaturen als identisch mit ihrer getrennten Schreibweise erkannt. Beispiel: ignoring expansion "AE" = " Æ " -- Ergebnis: true end ignoring
hyphens Wenn man Bindestriche im Text ignorieren möchte, sollte man ignoring hyphens vor dem Textvergleich verwenden. Standardmäßig werden Bindestriche also berücksichtigt. "email" is equal to "e-mail" -- Ergebnis: false
309
SmartBooks
AppleScript
Mit ignoring sind beide Texte aber gleich: ignoring hyphens "email" is equal to "e-mail" -- Ergebnis: true end ignoring Das funktioniert wunderbar, nur die text item delimiters halten sich leider nicht daran! Folgendes Suchen und Ersetzen funktioniert nicht: set meinText to "e-mail" ignoring hyphens set text item delimiters to "email" set meinText to every text item of meinText set text item delimiters to "E-Mail" set meinText to meinText as text end ignoring -- Ergebnis: "e-mail" Laut einem Hinweis im AppleScript Language Guide, Seite 199 sollten die text item delimiters aber considering- und ignoring-Attribute berücksichtigen. Ich betrachte das derzeitige Verhalten daher als Fehler.
punctuation Sollen Interpunktionszeichen bei einem Textvergleich nicht beachtet werden, so verwenden Sie ignoring punctuation. Standardmäßig werden diese berücksichtigt: "3.14" = "3,14" -- Ergebnis: false Wenn Sie diese Zeichen ignorieren, sind beide Zahlen im Text gleich: ignoring punctuation "3.14" = "3,14" -- Ergebnis: true end ignoring Auch die text item delimiters berücksichtigen diese Einstellung, solange Sie ein Interpunktionszeichen gegen ein anderes vergleichen: set meinText to "a.1" ignoring punctuation set text item delimiters to "a!1" set meinText to every text item of meinText set text item delimiters to "Gefunden!" set meinText to meinText as text end ignoring -- Ergebnis: "Gefunden!" 310
Die Sprache
Kapitel 4
Folgendes Suchen und Ersetzen schlägt aber fehl: set meinText to "a.1" ignoring punctuation set text item delimiters to "a1" set meinText to every text item of meinText set text item delimiters to "Gefunden!" set meinText to meinText as text end ignoring -- Ergebnis: "a.1" Hier ist also nichts passiert, obwohl der direkte Vergleich true ergibt: ignoring punctuation "a.1" = "a1" -- Ergebnis: true end ignoring Das gleiche Verhalten wie beim hyphen.
white space Bei Textvergleichen wird sogenannter white space (das sind die unsichtbaren Zeichen wie Leerstelle, Return, Tab, Linefeed und andere) berücksichtigt. Hier ein Vergleich mit einem Tabulator (\t): "eins\tzwei" = "eins zwei" -- Ergebnis: false Verwenden Sie daher ignoring, um diese Steuerzeichen bei einem Textvergleich zu ignorieren: ignoring white space "eins\tzwei" = "einszwei" -- Ergebnis: true end ignoring Mit den text item delimiters gibt es aber auch hier (wie bei hyphens und punctuation) ein Problem: Sie funktionieren nicht mit ignoring white space, und zwar auch dann nicht, wenn der Suchtext ebenfalls ein white space an der Stelle enthält: set meinText to "eins\tzwei" ignoring white space set text item delimiters to "eins zwei" set meinText to every text item of meinText set text item delimiters to "eins drei" set meinText to meinText as text end ignoring -- Ergebnis: "eins ⇒ zwei"
311
SmartBooks
AppleScript
numeric strings Diese Eigenschaft ist relativ neu und wurde mit Tiger eingeführt. Sie eignet sich vor allem, um Versionsnummern oder IP-Adressen zu vergleichen. "1.10" is greater than "1.9" -- Ergebnis: false Diese Aussage ergibt false, denn die 9 kommt nach der 1 im Alphabet. Hier müsste also die 10 als Zahl mit der 9 als Zahl verglichen werden. Früher müsste man solch eine Versionsnummer zuerst auseinandernehmen, um dann die einzelnen Bestandteile zu vergleichen. Da das etwas umständlich ist, vor allem aber, weil AppleScript in Tiger gerade die Version 1.10 erreichte, hat man dort numeric strings als Attribut für considering und ignoring eingeführt. Damit ist es nun möglich, solch eine Versionsnummer korrekt zu prüfen: considering numeric strings "1.10" is greater than "1.9" -- Ergebnis: true end considering Standardmäßig werden numeric strings also nicht beachtet. Von Bedeutung können numeric strings auch beim Vergleich von Zahlen mit führenden Nullen sein, falls einmal Postleitzahlen oder IP-Adressen in diesem Format vorliegen. Zum Beispiel: considering numeric strings "192.168.15.1" = "192.168.015.001" -- Ergebnis: true end considering Für die text item delimiters würde sich diese Art des Vergleichs am besten eignen, da hier auf Gleichheit geprüft wird: set meinText to "192.168.001.005" considering numeric strings set text item delimiters to "192.168.1.5" set meinText to every text item of meinText set text item delimiters to "Die IP Adresse ist identisch" set meinText to meinText as text end considering -- Ergebnis: "192.168.001.005" Doch am Ergebnis sehen Sie schon, numeric strings funktionieren ebenfalls nicht mit den text item delimiters!
312
Die Sprache
Kapitel 4
Kombinierte Anweisungen und Schachtelungen Verschiedene considering- und ignoring-Attribute lassen sich natürlich auch miteinander kombinieren oder sogar schachteln. Falls es also mehr zu ignorieren oder zu berücksichtigen gibt, so schreiben Sie zum Beispiel: considering case but ignoring white space and diacriticals --Anweisungen end considering Beachten Sie hier das Wörtchen but! Wenn Sie considering und ignoring gleichzeitig verwenden, müssen Sie beide mit but verbinden. Mehrere Anweisungen gleicher Art, wie zum Beispiel zwei ignoring-Anweisungen, werden mit and verbunden (ignoring white space and diacriticals). Eine Schachtelung ist auch möglich, wobei auf jeder Ebene der Schachtelung mehr considering oder ignoring-Anweisung berücksichtigt werden, da die inneren Blöcke immer auch die äußeren mit einschließen, aber nicht die äußeren die inneren. ignoring case log "A" = "a" -- Ergebnis:true ignoring punctuation log "A." = "a" -- Ergebnis true ignoring white space log "A. \t a" = "Aa" -- Ergebnis: true ignoring diacriticals log "A. Â" = "Aa" -- Ergebnis: true end ignoring end ignoring end ignoring end ignoring Auf jeder Ebene wird hier der Textvergleich immer liberaler, bis am Ende selbst der Text "A. \t Â" als identisch zu "Aa" erkannt wird. Natürlich müssen nicht alle Blöcke nur ignoring oder considering-Blöcke sein. Man kann beide auch gemischt verschachteln.
313
SmartBooks
AppleScript
considering/ignoring application responses Bei der Steuerung eines Programms ist es manchmal nicht erforderlich, auf die Antwort des Programms zu warten. Während das Programm mit der Abarbeitung der gegebenen Befehle beschäftigt ist, könnte das Skript nämlich schon mit anderen Tätigkeiten fortfahren – und zwar immer dann, wenn das Skript keinen Rückgabewert vom Programm benötigt. Wenn Sie aber den Rückgabewert benötigen oder derselben Anwendung noch weitere Anweisungen geben wollen, müssen Sie darauf warten, bis sie mit der Ausführung der ersten Befehle fertig ist. Wenn Sie nicht auf eine Antwort der Anwendung warten müssen, packen Sie die Anweisungen einfach in folgenden Block: ignoring application responses -- Anweisungen an die Anwendung end ignoring Alle Anweisungen innerhalb dieses Blocks werden gegeben, ohne auf Rückmeldung des Programms zu warten. Im folgenden Beispiel wird eine Sicherung vorgenommen, die einige Zeit in Anspruch nehmen kann – je nachdem, wie viel Megabyte oder Gigabyte sich in dem Ordner befinden. Ihr Skript muss hier nicht unbedingt auf die Beendigung der Sicherung warten (obwohl eine Rückmeldung nach erfolgreichem Kopieren natürlich beruhigender wäre) und könnte daher schon mit anderen Anweisungen fortfahren. In diesem Beispiel wird am Ende des Skripts die Rückmeldung gegeben, dass das Skript fertig ist. Je nachdem, wie groß der angegebene Ordner Projekte im Heimatverzeichnis ist, dauert der Kopiervorgang im Finder aber noch wesentlich länger an: ignoring application responses tell application "Finder" activate copy folder "Projekte" of home to folder "Sicherungen" of desktop end tell -- Weitere Anweisungen say "Script done" end ignoring (Zum Testen einen Ordner mit Namen Projekte auf oberster Ebene im Heimverzeichnis anlegen und mit einigen großen Dateikopien füllen, die etwas Zeit zum Kopieren benötigen!)
314
Die Sprache
Kapitel 4
Achten Sie darauf, nur die Befehle in den ignoring-Block zu packen, für die Sie auch wirklich keine Rückmeldung benötigen. Für Schleifen über Programmobjekte ist diese Anweisung daher nicht geeignet, da dort eine Rückmeldung erforderlich ist. Im folgenden Beispiel erhalten Sie beim Ausführen die Fehlermeldung, dass die Variable meinOrdner nicht definiert ist. ignoring application responses tell application "Finder" set meinOrdner to folder "Testordner" of desktop get meinOrdner end tell -- andere Anweisungen end ignoring Die Definition der Variablen meinOrdner ist auf eine Rückmeldung vom Finder angewiesen, schließlich handelt es sich bei dem Objekt folder um ein Objekt des Finders, und nur der Finder kann hierfür einen gültigen Wert an die Variable zurückliefern. Weisen Sie dieser Variablen daher außerhalb des ignoring-Blocks ihren Wert zu oder schachteln Sie diese Zuweisung innerhalb des ignoring-Blocks in einen consideringBlock, und schon funktioniert es: ignoring application responses tell application "Finder" considering application responses set meinOrdner to folder "Testordner" of desktop end considering get meinOrdner end tell -- andere Anweisungen end ignoring Auch diese Kontrollstruktur lässt sich also nach Belieben schachteln.
315
SmartBooks
AppleScript
using terms from Mit dieser Kontrollstruktur bestimmen Sie, mit welchem Funktionsverzeichnis die innerhalb dieses Blocks vorkommenden Begriffe und Anweisungen übersetzt werden sollen. Wie im Kapitel zum tell schon angeschnitten, kann ein Programm zwar in einer Variablen gespeichert, aber es kann nicht darüber angesprochen werden. Das Programm muss während der Kompilierung bekannt sein. Mit anderen Worten: Ein tell an die Anwendung ist immer erforderlich. Alternativ kann man stattdessen aber auch einen using terms from-Block verwenden: tell application "Finder" activate set myWindow to make new Finder window end tell using terms from application "Finder" tell myWindow set statusbar visible to true end tell end using terms from Im tell-Block wird hier ein Fenster des Finders in einer Variablen gespeichert. Im using terms-Block wird dann dieses Fenster angesprochen, um seine Statusleiste einzuschalten. Ohne dieses using terms würde der zweite Block nicht kompilieren, da die Eigenschaft statusbar visible zum Finder gehört und AppleScript diese Eigenschaft selbst nicht kennt. Wie Sie aber sicher erkennen, könnte man hier auch genauso gut einen weiteren tell-Block verwenden – und genau das wird bei solchen Beispielen auch meist gemacht. Selbst wenn sich die Anweisung in einem tell-Block an eine andere Anwendung befindet, können Sie darin ruhig einen zweiten tell-Block an eine andere Anwendung richten. Unverzichtbar wird ein using terms erst, wenn es darum geht, Handler, die von einem Programm zur Verfügung gestellt werden, anzusprechen. Ein Beispiel hierzu finden Sie im Abschnitt Mailregeln im Kapitel 6, wo es darum geht, ein Skript zu starten, wenn eine E-Mail eintrifft. Beachten Sie auch das Kapitel Handler.
316
Die Sprache
Kapitel 4
Dabei muss der vom Programm »Mail« zur Verfügung gestellt Handler on perform mail action mit dem Funktionsverzeichnis von Mail kompiliert werden, ansonsten erhalten Sie eine Fehlermeldung. using terms from application "Mail" on perform mail action with messages theMessages for rule theRule tell application "Mail" repeat with eachMessage in theMessages set theSender to sender of eachMessage say "Message received from " & theSender end repeat end tell end perform mail action with messages end using terms from Dieser Handler wird dann automatisch aufgerufen, sobald eine E-Mail eintrifft. Im obigen Beispiel wird mit say angesagt, von wem eine E-Mail eingetroffen ist. Dass Programme solche Handler als Schnittstelle für das Andocken von Skripts und anderen Anwendungen anbieten, kommt leider nicht häufig vor, und wenn, dann müssen diese Handler mit using terms from explizit mit dem Funktionsverzeichnis dieser Anwendung übersetzt werden.
with timeout Mit with timeout können Sie eine bestimmte Zeit vorgeben, die das Skript auf eine Antwort wartet und nach deren Ablauf es dann abbricht. Angegeben werden ganze Sekunden: with timeout of 10 seconds --Anweisungen end timeout Auch wenn die Angabe von seconds dazu verleitet, Sie können dort nicht minutes oder hours schreiben, hier wird immer das Wort seconds (oder second, wenn es nur um eine einzelne Sekunde geht) erwartet, und der Integer-Wert davor wird immer als Sekunden interpretiert. Nichts spricht jedoch dagegen, den Wert entsprechend hoch genug zu setzen und für den Integerwert die Zeitkonstanten zu verwenden wie in folgendem Beispiel. with timeout of (5 * minutes) seconds --Anweisungen end timeout Sie dürfen nur nicht vergessen, seconds dahinter zu schreiben.
317
SmartBooks
AppleScript
Wenn Sie with timeout nicht verwenden, gilt übrigens generell für alle Befehle in AppleScript immer ein timeout-Wert von 2 Minuten, also 120 Sekunden. Also auch ohne with timeout können Sie in einem Skript eventuell einen timeout-Fehler bekommen, wenn eine Anwendung nach 2 Minuten immer noch nicht auf einen Befehl reagiert hat. Wenn ein timeout auftritt, wird der Fehler event timed out erzeugt, der sich mit einem tryBlock leicht abfangen lässt. Wird der Fehler nicht in einem try abgefangen, wird die Ausführung des Skripts an dieser Stelle abgebrochen. Das with timeout funktioniert nur bei Programmobjekten, also nicht mit den Basisklassen von AppleScript oder seiner Standarderweiterung. Sie können also nicht das Arbeiten auf einer Liste mit einem timeout versehen, das hätte keine Wirkung. Überlegen Sie sich vorher, ob Sie wirklich ein with timeout benötigen oder nicht doch ein delay. Wenn das Skript einfach nur zu schnell ist mit seinen Anweisungen, so ist ein einfaches delay anzahlSekunden zwischen zwei Befehlen die richtige Wahl. Sie geben damit der Anwendung ein wenig mehr Zeit, zu einem geordneten Zustand zurückzukehren, in welchem es in der Lage ist, auf den nächsten Befehl zu hören. Wenn Sie der Anwendung allerdings soviel zu tun gegeben haben, dass Sie mehr als 2 Minuten Zeit bis zur Antwort braucht, sollten Sie den timeout-Wert mit with timeout hochsetzen, ansonsten stoppt das Skript eventuell, bevor die Anwendung die aufgetragene Arbeit erledigt hat und das Ergebnis zurückliefert. Im folgenden Beispiel wird das vordere Dokument in TextEdit gesichert. Wurde das Dokument schon einmal gesichert, geschieht das ohne weitere Rückfrage. Wurde das Dokument noch nie gesichert, erscheint natürlich der Sichern-Dialog. Hier wartet das Skript nun 10 Sekunden. Wenn dann das Dokument immer noch nicht vom Anwender gesichert wurde, wird das Skript gestoppt und erzeugt einen timeout-Fehler – den man normalerweise natürlich mit einem try und on error abfangen würde. with timeout of 10 seconds tell application "TextEdit" save window 1 end tell end timeout 318
Die Sprache
Kapitel 4
with transaction Diese Anweisung muss explizit von der betreffenden Anwendung unterstützt werden, um zu funktionieren. Damit wird sichergestellt, dass die Anweisungen in diesem Block vollständig oder gar nicht ausgeführt werden. Das heißt, wenn innerhalb des with transaction-Blocks auch nur ein einziger Befehl fehlschlägt, werden auch alle anderen Befehle in diesem Block nicht ausgeführt. Damit wird verhindert, dass Daten in einen inkonsistenten Zustand geraten. Einfaches Beispiel: Das Geld von Ihrem Konto darf bei einer Überweisung nur abgebucht werden, wenn die Einbuchung auf dem anderen Konto ebenfalls erfolgt. Schlägt nur eine der beiden Aktionen fehl, darf die andere Aktion nicht mehr ausgeführt werden, ansonsten haben Sie eine Abbuchung ohne Empfänger oder eine Einbuchung ohne Absender, was niemals sein darf. FileMaker war bisher immer ein gutes Beispiel für with transaction, scheint aber in seinen neuesten Versionen noch nicht wieder dazu in der Lage zu sein, zumindest gibt es widerstreitende Berichte darüber. Und auch ob with transaction in AppleScript überhaupt funktioniert, ist nicht ganz klar. Da ich bisher keine Anwendung kenne, die with transaction unterstützt, hier nur die Theorie; with transaction tell application "einProgramm" -- Erste Anweisungen -- Zweite Anweisung end tell end transaction In obigem Beispiel werden dem fiktiven Programm einProgramm zwei Anweisungen gegeben. Da beide Anweisungen sich innerhalb eines transaction-Blocks befinden, werden diese immer nur zusammen ausgeführt oder gar nicht. In keinem Fall aber wird nur eine der Anweisungen ausgeführt, ohne die andere ebenfalls auszuführen. Damit ist sichergestellt, dass die Anwendung ihre Daten in einem konsistenten Zustand behält. Wenn ein Programm transaction nicht unterstützt, und Sie Vergleichbares in eigenem Code umsetzen wollen, müssen Sie den Erfolg Ihrer Anweisung nach deren Ausführung unbedingt überprüfen. Für den Fall, dass auch nur eine Anweisung nicht erfolgreich war, sollten Sie dann Code bereitstellen, welcher den Ausgangszustand wiederherstellt.
319
SmartBooks
AppleScript
Laut Apple unterstützt with transaction auch einen sogenannten session parameter, welcher nach with transaction angegeben werden muss. Dieser Parameter soll das Objekt der »Sitzung« beinhalten. Natürlich muss es auch eine Anwendung geben, die das auch unterstützt. with transaction sessionparameter --Anweisungen end transaction Diese session id ist dann allen Anweisungen in diesem Block gemeinsam, womit wahrscheinlich mehrere gleichzeitig stattfindende transactions auseinander gehalten werden sollen.
error Mit error erzeugen Sie in Ihrem Skript Fehler. Das mag sich seltsam anhören, ist aber tatsächlich von größter Bedeutung. Sie sollten in Ihrem Skript nach Möglichkeit alle Eventualitäten berücksichtigen und in Fällen, in denen das Skript nicht richtig funktionieren würde, lieber bewusst einen Fehler erzeugen. Zum Beispiel, um den Benutzer auf den Fehler hinzuweisen oder um im Skript entsprechende Gegenmaßnahmen einleiten zu können. Diese selbst erzeugten Fehler (wie auch andere) lassen sich nämlich »abfangen«, was man nutzen kann, um dafür zu sorgen, dass sich das Skript nicht bei jedem Fehler gleich beendet. Um das Abfangen geht es später. Hier geht es erst einmal darum, wie man bewusst einen Fehler erzeugen kann. Einen Fehler erzeugen Sie, indem Sie an einer beliebigen Stelle in Ihrem Skript auf einer Zeile den Begriff error schreiben. Das Skript wird damit an dieser Stelle beendet. Error ist keine Blockanweisung, sondern ein schlichter Einzeiler. In folgendem Skript soll ein Fehler erzeugt werden, wenn in der Variable x keine Ganzzahl enthalten ist. Damit der Fehler nicht jedes Mal auftritt, wird der Wert per Zufall aus einer Liste entnommen, und nur einer der vier Werte darin ist keine Ganzzahl: set y to {1, 2, 3, "4"} set x to some item of y if class of x is not integer then error else log x -- mach was end if 320
Die Sprache
Kapitel 4
Führen Sie das Skript so oft aus, bis ein Fehlerdialog erscheint.
Abb. 4-11 Die allgemeine Fehlermeldung Diese Fehlermeldung gibt dem Benutzer natürlich überhaupt keinen Hinweis darauf, was genau falsch gelaufen ist. Deswegen gibt es die Möglichkeit, einem Fehler auch einen eigenen Fehlertext mitzugeben. Fügen Sie den Text einfach als Literal oder als Variable hinter error an: set y to {1, 2, 3, "A"} set x to some item of y if class of x is not integer then error "Die Variable x enthält »" & class of x & ¬ "«, es wird aber »integer« erwartet!" else log x -- mach was end if
Abb. 4-12 Eine Fehlermeldung mit eigenem Fehlertext Die Fehlermeldung ist damit schon besser beschrieben. Wenn Sie in Ihrem Skript ein umfangreiches Fehlermanagement einführen, empfiehlt es sich, außerdem den verschiedenen Fehlern eine Nummer zu geben. Fehlernummern können Sie mit dem Parameter number angeben. Hinter number wird dann eine Ganzzahl erwartet, als Literal oder Variable:
321
SmartBooks
AppleScript
set y to {1, 2, 3, "A"} set x to some item of y if class of x is not integer then error "Die Variable x enthält »" & class of x & ¬ "«, es wird aber »integer« erwartet!" number 501 else log x -- mach was end if Diese Fehlernummer wird allerdings nur dann im Fehlerdialog angezeigt, wenn kein Fehlertext vorliegt. Das heißt, erst wenn Sie den Fehlertext oben entfernen, so dass in der Zeile nur noch error number 501 steht, wird Ihnen im Fehlerdialog die Nummer angezeigt, und zwar als Meldung: »Es ist ein Fehler "501" aufgetreten.« Diese Art von Fehlermeldung sollten Sie aber generell vermeiden. Sie stellt den Anwender vor unlösbare Probleme, wenn Sie ihm nicht auch gleichzeitig eine Liste Ihrer Fehlernummern und deren Bedeutung mitgeben. Wenn Sie Fehlernummern vergeben, achten Sie bitte darauf, nur positive Fehlernummern im Bereich von 500 bis 10.000 zu verwenden. Die anderen Bereiche sind für Apple reserviert. Eine Liste bekannter Fehlernummer finden Sie im Anhang. Wenn Sie keine Fehlernummer angeben, hat ein selbst erzeugter Fehler die Fehlernummer -2700 (unknown error). Weitere mögliche Parameter von error sind partial result, from und to, die für eigene Fehlermeldungen jedoch eher selten gebraucht werden. Für partial result wird eine Liste mit Objekten angegeben. Dieser Parameter ist vor allem für Befehle gedacht, die für mehrere Objekte Ergebnisse zurückliefern. Hier werden diese Objekte dann aufgenommen, und Sie können verfolgen, inwieweit die Befehle auf diesen Objekten erfolgreich waren. Sinnvoll ist diese Angabe erst, wenn Sie den Fehler »abfangen«, um diese Angabe dann auszuwerten. In folgendem Beispiel wird partial result einfach dafür verwendet, die Werte der Variablen y und x sowie die Klasse von x zu speichern.
322
Die Sprache
Kapitel 4
set y to {1, 2, 3, "A"} set x to some item of y if class of x is not integer then error "noch'n Fehler" number 501 partial result {y, x, class of x} else log x -- mach was end if Ein weiterer möglicher Parameter ist from. Er ist dafür gedacht, eine Referenz auf das Objekt anzugeben, welches den Fehler erzeugt hat. Im obigen Fall wäre das also x oder die Liste y. Eine Referenz erzeugt man mit dem a reference to-Operator. Bei diesem einfachen Beispiel ist zwar keine Referenz nötig, wenn Sie aber mit Programmobjekten arbeiten, sollten Sie Referenzen bevorzugen. set y to {1, 2, 3, "A"} set x to some item of y if class of x is not integer then error "Fehler" number 501 partial result {y, x} from (a reference to y) else log x -- mach was end if Der letzte mögliche Parameter von error dient dazu, die Klasse anzugeben, die in der Operation erwartet wurde. In diesem Beispiel wäre das die Klasse integer. set y to {1, 2, 3, "A"} set x to some item of y if class of x is not integer then error "Fehler" number 501 partial result {y, x} from (a reference to y) ¬ to integer else log x -- mach was end if Damit wären in obigem Beispiel nun alle Parameter versammelt. Alle diese Parameter sind optional. Sie können sich davon also genau die aussuchen, die Sie brauchen, und die anderen weglassen. Bis auf den Fehlertext erscheinen all diese Parameter nicht in der Fehlermeldung, Sie dienen also nur dazu, Informationen von der Fehlerstelle aufzunehmen, um sie später zu verarbeiten.
323
SmartBooks
AppleScript
Ansonsten möchte ich darauf hinweisen, dass Sie für Ihre eigenen Fehler in diese Parameter natürlich hineinpacken können, was Sie wollen. Trotzdem ist es zu empfehlen, sich an das vorgegebene Konzept zu halten, ansonsten verlieren Sie irgendwann den Überblick. Damit haben Sie nun alle möglichen Parameter von error kennengelernt. Als Nächstes geht es darum, wie man diese Informationen über den aufgetretenen Fehler verwenden kann, um Gegenmaßnahmen einzuleiten.
try Mit try geben Sie AppleScript Bescheid, die folgenden Anweisungen »auszuprobieren«. Wenn in diesen Anweisungen ein Fehler auftritt, soll die Ausführung des Skripts deswegen aber nicht gleich abgebrochen werden. Mit try »fängt« man Fehler (to »catch« errors). Im einfachsten Fall fängt man den Fehler, macht dann aber nichts damit, sondern fährt einfach mit den Anweisungen nach dem try fort: try set y to 2 / 0 -- weitere Anweisungen end try beep Hier wird versucht, 2 durch 0 zu teilen, was ohne try sofort zum Abbruch des Skripts führen würde. Dadurch, dass diese Anweisung nun in einem try-Block steht, fährt das Skript aber einfach mit der nächsten Anweisung, einem beep, fort. Kommentieren Sie einmal das try und end try aus, um den Unterschied zu testen, und Sie werden sehen, dass Sie sofort eine Fehlermeldung erhalten und es damit erst gar nicht bis zum beep kommt. Wenn im try-Block ein Fehler auftritt, wird das Skript an dieser Stelle im try-Block unterbrochen. Alle dem Fehler folgenden Zeilen innerhalb des try werden nicht mehr ausgeführt. Das Skript fährt mit den Anweisungen nach dem try fort. Das beep in folgendem Beispiel wird daher nicht ausgeführt, wohl aber das say nach dem try-Block: try set y to 2 / 0 -- weitere Anweisungen beep end try say "Ready"
324
Die Sprache
Kapitel 4
Normalerweise möchte man ein Skript nach einem Fehler jedoch nicht einfach fortführen, sondern erst einmal auf den Fehler entsprechend reagieren. Um auf einen Fehler in einem try-Block reagieren zu können, müssen Sie diesem noch den error-Block hinzufügen: try set y to 2 / 0 -- … on error -- Aktion im Fehlerfall -- … end try beep Die Aktionen nach dem on error werden nur ausgeführt, wenn ein Fehler eingetreten ist! Wenn kein Fehler eintritt, wird der error-Block einfach übersprungen und mit den Anweisungen nach dem try fortgefahren. Tritt ein Fehler auf, wird die Abarbeitung der Befehle im try-Block (zwischen try und on error) abgebrochen, und das Skript springt sofort zur ersten Anweisung im error-Block. Doch wie kommt man im error-Block nun an Informationen über den Fehler heran? Ganz einfach. Fügen Sie einfach hinter on error alle Parameter ein, die Sie bereits bei error kennengelernt haben, nur dass Sie hier neue Variablen verwenden sollten, welche die Fehlerinformationen für Sie aufnehmen können: try set y to 2 / 0 on error errText number errNr partial result errList from errSource to errClass -- Aktion im Fehlerfall end try Die einzelnen Schlüsselwörter für die Parameter sind oben der leichteren Lesbarkeit wegen in fetter Schrift dargestellt. Natürlich brauchen Sie davon nur die Parameter anzugeben, die Sie dann auch wirklich benötigen. In obigem Beispiel landet der Fehlertext in der Variable errText, die Fehlernummer wird in der Variable errNr abgelegt, partial result wird in errList abgelegt, der Parameter from landet in errSource und die erwartete Klasse in errClass. Die Namen, die Sie für die Variablen verwenden, spielen natürlich keine Rolle. In folgendem Beispiel wird der Inhalt dieser Parameter mit log im Eventprotokoll des Skripteditors sichtbar gemacht – schließlich möchte man beim Testen wissen, was drin steht.
325
SmartBooks
AppleScript
try set y to 2 / 0 on error errText number errNr partial result errList from errSource to errClass log errText log errNr log errList log errSource log errClass end try Eventprotokoll:
(*„2.0“ kann nicht durch Null geteilt werden.*) (*-2701*) (**) (*2.0*) (**)
Sie sehen, dass hier alle Parameter Werte bis auf partial result und to gefüllt wurden. Der Versuch, durch 0 zu teilen, ergibt also die Fehlernummer -2701. Dieser Fehler wurde von AppleScript selber generiert, also nicht von Ihnen, deswegen handelt es sich um eine Fehlernummer im Minusbereich. Aus diesem Grund sollten Sie für eigene Fehler auch niemals eine Fehlernummer in diesem Bereich verwenden. Als Maßnahme können Sie nun die Fehlernummer in einem if abfragen, und wenn es sich um den Fehler -2701 handelt, zum Beispiel einen neuen Versuch wagen oder den Benutzer um einem anderen Wert bitten – oder Sie zeigen eine Fehlermeldung und beenden dann das Skript sauber. In folgendem Beispiel wird der Wert von y bei einem Fehler von -2701 auf 20 gesetzt, bei einem Fehler -2702 jedoch auf 200.000. Sie können also durch Abfrage der Fehlernummer auf jeden Fehler anders reagieren. (Fehler -2702 »The result of a numeric operation was to large«, siehe Anhang.) Außerdem wird hier im error-Block nur die Fehlernummer als Parameter angegeben, da die anderen Parameter nicht benötigt werden.
326
Die Sprache
Kapitel 4
set x to 0 try set y to 2 / x on error number errNr if errNr = -2701 then set y to 20 end if if errNr = -2702 then set y to 200000 end if end try Natürlich kann man statt der Fehlernummer auch den Fehlertext im if abfragen, aber da dieser eventuell in unterschiedlichen Sprachen vorliegt, je nachdem, in welcher Sprache Ihr Betriebssystem eingestellt ist, eignet sich das nicht für eine zuverlässige Identifikation. Der Text ist eher als beschreibende Ergänzung der Fehlernummer gedacht.
Fehler durchreichen Was passiert dann mit den anderen Fehlern, die nicht mit einem if und der Fehlernummer abgefangen werden? Diese werden einfach ignoriert, und das Skript fährt nach dem end try fort. Das sollten Sie natürlich unbedingt vermeiden. Je nachdem, was Ihr Skript vorhat, könnte es dadurch auch erheblichen Schaden anrichten. Sehen Sie daher am besten auch immer ein else vor: set x to 0 try set y to 2 / x on error errText number errNr partial result errList from errSource to errClass if errNr = -2701 then set y to 20 else if errNr = -2702 then set y to 200000 else error errText number errNr partial result errList from errSource to errClass end if end try In obigem Fall wird, wenn ein anderer Fehler als -2701 oder -2702 aufgetreten ist, im elseTeil manuell ein Fehler erzeugt, und zwar mit den Parametern des zuvor abgefangenen Fehlers. Der Fehler wird also, nachdem er zuvor abgefangen wurde, nach dessen Untersuchung einfach weitergereicht. Sie erklären sich damit sozusagen als nicht zuständig für alle anderen Fehlernummern und bitten AppleScript, sich darum zu kümmern.
327
SmartBooks
AppleScript
Dieses Vorgehen ist im Allgemeinen erwünscht. Wenn unbekannte Fehler auftreten, dann möchte man natürlich darüber informiert werden. Deswegen wird hier der Fehler mit all seinen Parametern erneut erzeugt und damit weitergereicht. Wer kümmert sich dann um einen Fehler, der im error-Block erzeugt wird? Wenn das try in einem weiteren try geschachtelt sein sollte, wird der im error-Block erzeugte Fehler im darüber stehenden try erneut abgefangen, ansonsten landet der Fehler im Skript als oberster Instanz, und der Anwender erhält die normale Fehlermeldung von AppleScript mit dem durchgereichten Fehlertext. Anhand dieser Fehlermeldung haben Sie oder der Anwender dann zumindest einen ersten Anhaltspunkt, um was für einen Fehler es sich handelt. Würden Sie den Fehler im errorBlock nicht auf obige Weise weiterreichen, würde er ignoriert. Sie würden nichts davon erfahren, dass ein unbekannter Fehler stattgefunden hat, und das Skript würde nach dem try fortfahren und wahrscheinlich an irgendeiner Stelle katastrophal fehlschlagen. Also immer daran denken, beim Abfangen der Fehler nicht einfach alle Fehler zu blockieren, sondern alle Fehler weiterreichen, um die man sich nicht selbst kümmern will! Tipp Alle Aktionen, die auf Objekte zugreifen, die dem direkten Zugriff des Anwenders unterliegen, also außerhalb des Skripts gelöscht, umbenannt oder verschoben werden können, sollten in ein try gepackt werden. Dazu gehören zum Beispiel Dateien im Betriebssystem oder Objekte in einer Anwendung. Provozieren Sie zum Testen ruhig absichtlich Fehler, indem Sie eine der Vorraussetzungen entfernen oder verändern. Merken Sie sich dann die Fehlernummer, die Sie dadurch im error-Block erhalten, und schreiben Sie für diese Fehlernummer eine Anweisung in den error-Handler. Auf diese Weise können Sie also Fehler abfangen, die in einem Skript aufgetreten sind. Doch wie fängt man nun einen Fehler auf, den man selbst erzeugt hat? Ähnlich, nur dass Sie den Fehler explizit mit error erzeugen, wenn eine bestimmte Bedingung wahr wird. Um auf das anfängliche Beispiel mit dem Zufallswert aus der Liste zurückzukommen:
328
Die Sprache
Kapitel 4
set y to {1, 2, 3, "A"} set x to some item of y -- Zufallsauswahl try if class of x is not integer then error "O weh, ein Fehler!" number 501 partial result {y, x} from y to integer else -- mach was mit x end if on error errText number errNr partial result errList from errSource to errClass log errText log errNr log errList log errSource log errClass if errNr = 501 then error "Tut mir leid, die Liste ist nicht sauber. Bitte überprüfen!" else if errNr = 502 then - else if errNr = 503 then - else error errText number errNr partial result errList from errSource ¬ to errClass end if end try Hier wird also der Fehler im try-Block manuell erzeugt, und auch dieser kann anhand der selbst definierten Fehlernummer im error-Teil abgefangen werden. Auch hier sollten Sie natürlich wieder daran denken, dort alle nicht behandelten Fehler in einem else weiterzuleiten. Probieren Sie obiges Skript bitte so oft aus, bis auch ein Fehler eingetreten ist, und halten Sie das Eventprotokoll im Skripteditor dabei geöffnet. Tipp Wenn Sie in Ihrem Skript an irgendeiner Stelle einmal das Skript unmittelbar und sofort beenden wollen, ohne einen weiteren Fehlerdialog zu zeigen, zum Beispiel, weil schon einer erschienen ist, dann »werfen« Sie einfach folgenden Fehler: error number -128 Damit wird das Skript an dieser Stelle sofort und ohne Rückmeldung beendet, zumindest solange Sie diesen Fehler nicht ebenfalls abfangen. Verwenden Sie diese Option aber wirklich nur als Notausstieg, nachdem andere Optionen fehlgeschlagen sind und Sie um die Integrität von Daten in den zu steuernden Anwendungen fürchten müssen. Diese Fehlermeldung nennt sich User cancelled und wird auch erzeugt, wenn man in einem Dialog wie zum Beispiel display dialog auf Abbrechen klickt und damit das Skript sofort beendet. 329
SmartBooks
AppleScript
Die log-Anweisungen im obigen Skript zeigen Ihnen die Werte der error-Parameter zum Testen auch im Eventprotokoll an:
(*O weh, ein Fehler!*) (*501*) (*1, 2, 3, A, A*) (*1, 2, 3, A*)
Was immer Sie an Informationen über den Fehler benötigen, können Sie also einfach durch Abfrage der entsprechenden Variablen ermitteln. Alle Informationen, die als Parameter beim Erzeugen des Fehlers im try angegeben wurden, sind also wohlbehütet im error-Teil angelangt und können dort für Auswertungen und Abfragen verwendet werden.
Fehler filtern Falls nötig, können Sie auch in einem error-Block nur einen ganz spezifischen Fehler abfangen. Sie brauchen dafür nur dem Parameter number statt einer Variablen direkt die Fehlernummer zu geben. Dann wird der error-Block nur bei diesem einen Fehler in Aktion treten. Der try-Block fängt also wirklich nur diesen einen Fehler ab, alle anderen werden weitergereicht, also nicht etwa blockiert. Ein if mit else-Teil erübrigt sich hier daher. set y to {1, 2, 3, "A"} set x to some item of y try if class of x is not integer then error "O weh, ein Fehler!" number 501 partial result {y, x} from y to integer end if on error number 501 beep 3 error "Ein Fehler" end try Alle Parameter, die Sie direkt als Literal in on error hineinschreiben, müssen passen! Würden Sie zum Beispiel auch den to-Parameter angeben, würde der error-Block nur ausgeführt werden, wenn die Fehlernummer und die erwartete Klasse identisch sind. Trifft das nicht zu, wird der Fehler nicht abgefangen! Im obigen Fall wird der Fehler "O weh, ein Fehler!" erfolgreich abgefangen, da die Nummer 501 mit number 501 im error-Teil übereinstimmt. Ändern Sie oben einmal die Fehlernummer im try auf 502 und führen Sie das Skript erneut so oft aus, bis ein Fehler auftritt. Nun wird der Fehler "O weh, ein Fehler!" erscheinen, da dieser Fehler nicht mehr abgefangen wird.
330
Die Sprache
Kapitel 4
Diese Art des Fehlerabfangens eignet sich also gut dafür, wenn Sie nur hin und wieder einzelne Fehler selbst behandeln wollen, Sie können nämlich nicht mehrere Fehlernummern als Parameter angeben. Sobald es mehrere Fehler werden, ist die Vorgehensweise zu empfehlen, alle Fehler abzufangen, zu untersuchen und dann nur die bekannten selbst zu behandeln und die unbekannten weiterzuleiten. Power User Ein try fängt auch alle Fehler eines im try-Block aufgerufenen Handlers auf! Es ist also nicht unbedingt erforderlich, in jedem Handler ein eigenes Fehlermanagement einzubauen. Siehe Kapitel Handler.
Eigene Fehlerdialoge Nutzen Sie auch die Möglichkeit, sich in selbst angelegten Fehlermeldungen alle Informationen hineinzupacken, die Ihnen beim Kampf gegen den Fehlerteufel helfen können. Erstellen Sie sich also Ihre Fehlermeldungen ganz nach eigenem Wunsch, indem Sie alle nötigen Parameter hineinpacken: set y to {1, 2, 3, "A"} set x to some item of y try if class of x is not integer then error "Falsche Klasse!" number 501 partial result {x} from "x" to integer else -- mach was mit x end if on error errText number errNr partial result errList from errSource to errClass if errNr = 501 then error errText & " Fehlernummer: " & errNr & ",\rWert des Objekts: "¬ & errList & ", Objekt: " & errSource & ",\rErwarteter Typ: " & ¬ errClass & ", aber nicht die Null!" else error errText number errNr partial result errList from errSource ¬ to errClass end if end try beep
331
SmartBooks
AppleScript
Abb. 4-13 Eine selbst erzeugte Fehlermeldung in einem als Programm gesicherten Skript. Speichern Sie das Skript im Format Programm-Bundle, wenn der Knopf »Edit« mit »Bearbeiten« beschriftet sein soll. Am obigen Bild ist auch zu sehen, dass Fehlermeldungen von AppleScript in einem als Programm gespeichertem Skript immer auch einen Knopf Edit oder Bearbeiten enthalten. Wenn Sie nicht möchten, dass dadurch jemand dazu verleitet wird, in den Code hineinzuschauen, ändern Sie die Fehlermeldung im error-Teil auf ein display alert und beenden Sie dann das Skript mit dem Fehler -128: … on error errText number errNr partial result errList from errSource to errClass if errNr = 501 then display alert errText & " Fehlernummer: " & errNr & ¬ ",\rWert des Objekts: " & errList & ", Objekt: " & ¬ errSource & ",\rErwarteter Typ: " & errClass & ¬ ", aber nicht die Null!" as warning error number -128 else error errText number errNr partial result errList from errSource ¬ to errClass end if end try
Abb. 4-14 Eine selbst erzeugte Fehlermeldung mit »display alert« aus den Standarderweiterungen
332
Die Sprache
Kapitel 4
Handler Ein Handler ist eine Gruppe von Anweisungen mit einem Namen. Anhand dieses Namens lassen sich diese Anweisungen dabei auf »Zuruf« ausführen. In anderen Programmiersprachen werden Handler als »Funktion« oder »Subroutine« bezeichnet. In einem Skript können mehrere Handler enthalten sein. Handler können aber nicht ineinander geschachtelt werden (nur indirekt über Skriptobjekte, siehe entsprechendes Kapitel). Jeder Handler in Ihrem Skript erscheint übrigens als Eintrag in der Steuerungsleiste des Skripteditors. Über die Steuerungsleiste können Sie damit schnell von einem zum anderen Handler navigieren.
Definition Eine Handlerdefinition wird mit dem Wörtchen on eingeleitet und endet, wie alle Blockstrukturen in AppleScript, mit dem Wörtchen end. on sayHello() say "Hello " & short user name of (get system info) end sayHello Alternativ können Sie auch to verwenden, wobei diese Form meist für Handler mit benannten Parametern verwendet wird, dazu gleich mehr: to sayHello() say "Hello " & short user name of (get system info) end sayHello Nach dem on oder to folgt direkt der Name des Handlers. Bei der Namensgebung sind wieder die üblichen Regeln in AppleScript zu beachten, also keine Sonderzeichen oder Interpunktionszeichen im Namen und keine Zahlen am Wortanfang. Nach dem Namen folgt unmittelbar und ohne Leerstelle ein Klammernpaar, welches die Namen von Variablen enthalten kann, aber nicht muss. Die Klammer muss auch geschrieben werden, wenn sie leer ist. Danach folgen die Anweisungen, also das Skript im Handler selbst. Obiger Handler enthält ein einfaches say-Kommando und begrüßt Sie mit dem Namen, mit dem Sie an Ihrem Rechner angemeldet sind – wenn Sie denn das Geheimnis kennen, wie man diesen Handler ausführt. (system info ist ein Befehl aus dem Funktionsverzeichnis der StandardAdditions und short user name eine Eigenschaft davon.)
333
SmartBooks
AppleScript
Der Handler endet mit einem end und der Wiederholung des Handlernamens. Sie brauchen den Handlernamen hier aber nicht erneut zu schreiben, da er nach dem Kompilieren automatisch eingefügt wird.
Aufrufen Nachdem Sie solch einen Handler in Ihrem Skript angelegt haben, können Sie diesen über die Angabe seines Namens mit anschließender Klammer an jeder Stelle in Ihrem Skript aufrufen. Schreiben Sie dafür einfach sayHello() irgendwo außerhalb des Handlers in das Skript. Das Skript sieht als Ganzes dann also so aus: on sayHello() say "Hello " & short user name of (get system info) end sayHello sayHello() Wenn Sie das Skript nun ausführen, werden Sie mit einem Hello und der Kurzform des Benutzer-Accounts Ihres Rechners begrüßt, bei mir zum Beispiel "Hello Detlef". Dabei spielt es übrigens keine Rolle, an welcher Stelle im Skript der Handler oder der Aufruf desselben steht. Die bisher vorbestimmte Reihenfolge, dass ein Skript von oben nach unten ausgeführt wird, ist für Handler also nicht gültig (wohl aber für die Anweisungen in dem Handler!). Ein Handler kann also auch erst nach dem Aufruf definiert werden. Von alleine wird ein Handler also niemals ausgeführt, Sie müssen ihn immer erst aufrufen – erst dann wird der Code im Handler gestartet (Ausnahmen folgen im Kapitel Die Standard-Handler einer Skriptanwendung). Mit einem einzigen Wort können Sie nun diesen say-Befehl ausführen, wo Sie vorher einen ganzen Satz schreiben mussten. Stellen Sie sich nun vor, Sie hätten wesentlich mehr zu tun und diese Anweisungen würden öfters in Ihrem Skript benötigt. Ohne Handler müssten Sie den Code an jeder Stelle im Skript erneut schreiben. Das ist natürlich unnötige Arbeit, und deswegen wurden Handler in Programmiersprachen erfunden, damit man Code in kleine Grüppchen packen kann, um ihn dann nach Wunsch mit einem einzigen Wort in Betrieb zu setzen. Außerdem kann man sich so mit der Zeit kleine Bibliotheken von Codebausteinen anlegen. Nun wäre es noch schön, wenn ich dem Handler Daten in die Hand drücken könnte mit der Anweisung »Verarbeite das mal!«.
334
Die Sprache
Kapitel 4
Genau das ist möglich, und zwar mit Parametern. Es gibt zwei Arten von Parametern in AppleScript-Handlern: Das sind zum einen die Positionsparameter, also Parameter, die anhand ihrer Position erkannt werden, und benannte Parameter. Diese beiden Typen können nicht gemischt werden. Um Positionsparameter dreht sich alles auf den folgenden Seiten.
Positionsparameter Um einem Handler etwas überreichen zu können, müssen Sie ihm als Erstes »Hände« zur Verfügung stellen. Die Hände eines Handlers sind seine Parameter, welche in die Klammer hinter dem Namen geschrieben werden. Wenn die Klammer also leer ist, heißt das, dass dieser Handler keine Daten annehmen kann. Er tut damit immer exakt dieselbe Aktion, ohne jede Variationsmöglichkeit. Wenn Sie in die Klammer aber einen Variablennamen schreiben, dann haben Sie dem Handler eine Hand – einen Parameter – geschenkt: on sayHello(param) say "Hello " & short user name of (get system info) end sayHello Den Namen für den Parameter können Sie sich frei aussuchen, er muss nur wieder den allgemeinen Regeln für die Benennung von Variablen entsprechen. Oben wurde der Parameter einfach param genannt. param ist dabei einfach nur eine Variable, die alle möglichen Objekte aufnehmen kann, welche, das bleibt ganz Ihnen überlassen. Damit diese Variable nun etwas aufnehmen kann, müssen Sie diesen Parameter auch beim Aufruf des Handlers angeben. Ein Aufruf mit leeren Klammern würde nun fehlschlagen. Wenn ein Handler eine Hand hat, dann muss diese in AppleScript immer etwas erhalten: on sayHello(param) say "Hello " & short user name of (get system info) end sayHello sayHello(param) Wenn Sie das so ausführen, erhalten Sie aber die Fehlermeldung, dass param noch nicht definiert ist. param ist einfach nur eine Variable und die hat natürlich noch keinen Inhalt.
335
SmartBooks
AppleScript
Also erstmal etwas hineintun: on sayHello(param) say "Hello " & short user name of (get system info) end sayHello set param to "John" sayHello(param) Nun enthält die Variable param den Text "John". Dieser Name wird an den Handler weitergereicht und landet dort in der Variable gleichen Namens. Dort wurde diese Variable bisher aber gar nicht verwendet. Ändern Sie daher die Anweisung im Handler noch so, dass dort der Wert von param Verwendung findet. Wenn der Handler nichts mit dem ihm übergebenen Wert macht, braucht man ihm auch keine Hand zu geben! on sayHello(param) say "Hello " & param end sayHello set param to "John" sayHello(param) Nun wird param als Argument für say verwendet. Wenn Sie das Skript nun ausführen, werden Sie mit »Hello John« begrüßt. Sie haben nun einen Handler erschaffen, der sich universell für jeden beliebigen Text als Begrüßung verwenden lässt. Der Variablenname muss dabei übrigens nicht identisch sein. Im Folgenden wird im Handler die Variable param verwendet, beim Aufruf aber eine Variable mit dem Namen toName. on sayHello(param) say "Hello " & param end sayHello set toName to "John" sayHello(toName) Beide Variablen sind unterschiedlich, trotzdem wird der Wert von toName an die Variable param im Handler übergeben. Damit soll gesagt werden, die Übergabe eines Wertes an den Handler sei nicht vom Namen der Variablen abhängig, sondern von der Position. In der Klammer können nämlich noch mehrere Werte und damit Parameter stehen:
336
Die Sprache
Kapitel 4
on sayHello(param1, param2) say "Hello " & param1 say "Hi " & param2 end sayHello set {toGreet1, toGreet2} to {"John", "Mike"} sayHello(toGreet1, toGreet2) Hier werden also zwei Variablen mit Namen gefüllt, toGreet1 und toGreet2. Beide werden an sayHello weitergereicht und landen dort in den Variablen param1 und param2, um dann im Handler als Namen für einen Gruß verwendet zu werden. In obigem Beispiel wird zuerst John und dann Mike gegrüßt. Wenn Sie die Reihenfolge ändern wollen, so tauschen Sie zum Beispiel den Platz der Variablen beim Aufruf: sayHello(toGreet2, toGreet1) Ganz wichtig also: Bei dieser Art des Aufrufs müssen Sie immer gut darauf achten, dass die Reihenfolge der Variablen auch der gewünschten Reihenfolge der Parameter im Handler entspricht. Das gilt auch für den Fall, dass Sie die Werte als Literale übergeben. Achten Sie dann nur darauf, diese mit Komma voneinander zu trennen: on sayHello(param1, param2) say "Hello " & param1 say "Hi " & param2 end sayHello sayHello("John", "Mike")
Abb. 4-15 Der Programmfluss beim Aufruf eines Handlers (1, 2 und 3) und die Übergabe der Parameter anhand ihrer Position
337
SmartBooks
AppleScript
Handlerparameter dokumentieren Aus den oben genannten Gründen sollte jeder Handler in seinen ersten Zeilen immer eine Erklärung der Parameter beinhalten. Dabei sollte auf deren Reihenfolge, als auch auf den erwarteten Typ, hingewiesen werden, schließlich kann man auch eine Zahl oder sogar ein Programmobjekt wie ein Fenster an den Handler übergeben, womit dieser dann herzlich wenig anfangen kann und schnell ins Straucheln käme. Hier ein Beispiel für eine Beschreibung der Parameter: on sayHello(param1, param2) -- Grüßt param 1 mit "Hello" und param2 mit "Hi". -- Beide Parameter müssen vom Typ text sein say "Hello " & param1 say "Hi " & param2 end sayHello Diese Beschreibung ist kein Muss. Sie dient nur dazu, Ihnen den Durchblick zu erleichtern. Wenn Sie die Arbeit an einem komplexen Skript nach längerer Zeit wieder aufnehmen, werden Sie für solche Kommentare dankbar sein.
Prüfung und Fehlerbehandlung Als Nächstes ist zu empfehlen, in jedem Handler die Klasse der Parameter zu prüfen. Wenn der Handler zum Beispiel Text erwartet, aber eine Zahl oder ein Objekt erhält, würde er nicht korrekt funktionieren, und dann ist es besser, eine Fehlermeldung zu erzeugen: on sayHello(param1, param2) -- Grüßt param 1 mit Hello und param2 mit Hi. -- Beide Parameter müssen vom Typ text sein if class of param1 = text and class of param2 = text then say "Hello " & param1 say "Hi " & param2 else error "Ich will Text!" number 501 end if end sayHello sayHello(3, "Mike") Hier wird ein Fehler erzeugt, wenn in einem der beiden Parameter nicht ein Wert von der Klasse text enthalten ist.
338
Die Sprache
Kapitel 4
Dieser Fehler kann schon beim Aufruf mit einem try abgefangen werden. Sie brauchen also nicht unbedingt einen try-Block in einem Handler anzulegen. Fehler, die in dem Handler auftreten, werden an das Skript durchgereicht. Und wenn der Aufruf des Handlers in einem try-Block steht, können die Fehler dort abgefangen werden. Im Folgenden ist der Aufruf des Handlers in ein try gepackt worden. Um einen Fehler zu provozieren, wurde dabei eine Zahl in toGreet1 eingeschmuggelt: on sayHello(param1, param2) -- Grüßt param 1 mit Hello und param2 mit Hi. -- Beide Parameter müssen vom Typ text sein if class of param1 = text and class of param2 = text then say "Hello " & param1 say "Hi " & param2 else error number 501 end if end sayHello set {toGreet1, toGreet2} to {3, "Mike"} try sayHello(toGreet1, toGreet2) -- Aufruf on error errTxT number errNr if errNr = 501 then display dialog "Der Handler sayHello erwartet nur Text!" else error errTxT number errNr end if end try In diesem Beispiel wird der im Handler selbst geworfene Fehler mit der Nummer 501 im try beim Aufruf des Handlers abgefangen, also nicht im Handler selbst. Im error-Block bekommt der Fehler dann eine detaillierte Fehlermeldung. Alle anderen Fehler werden im else-Teil an AppleScript weitergereicht. Es spricht aber auch nichts dagegen, in komplexeren Handlern ein eigenes Fehlermanagement mit try einzubauen und Fehler direkt dort abzufangen. In den folgenden Beschreibungen zum Thema Handler lasse ich die Fehlerbehandlung und auch die Dokumentation der Parameter weg. So ist der Code schneller zu lesen und nimmt nicht unnötig viel Platz im Buch ein.
339
SmartBooks
AppleScript
Variablen im Handler sind lokal Bisher wurde das Konzept lokaler und globaler Variablen nicht behandelt und wird es auch erst bei den Skriptobjekten. Hier jedoch bereits so viel: Sie können außerhalb des Handlers nicht auf Variablen im Handler zugreifen und umgekehrt. Wenn Sie in folgendem Beispiel versuchen, auf die Variable names außerhalb des Handlers zuzugreifen, so funktioniert das nicht: on sayHello() say "Hello " & names end sayHello set names to "Robert and Tim" sayHello() Hier wird zuerst names auf den Wert "Robert and Tim" gesetzt und dann wird der Handler sayHello aufgerufen. Das Skript schlägt jedoch fehl mit der Meldung, dass die Variable names nicht definiert ist. Dabei markiert der Skripteditor die Stelle mit names im Handler. Das heißt, der Handler kennt keine Variable dieses Namens. Umgekehrt genauso: on sayHello() set names to "Robert and Tim" say "Hello " & names end sayHello sayHello() get names Das Skript schlägt am Ende mit der Meldung fehl, dass die Variable names nicht definiert ist. Dabei wird names am Schluss markiert. Das heißt, die im Handler definierte Variable mit dem Namen names ist außerhalb des Handlers nicht bekannt! Sie können also im Handler nach Belieben Variablennamen verwenden, die auch außerhalb des Handlers verwendet werden. Beide Namen kommen sich nicht in die Quere. Tipp Wenn Sie unbedingt grenzenlos auf Variablen zugreifen wollen, so geht das nur über die Definition von globalen Variablen oder Propertys, wie bei den Skriptobjekten beschrieben. Sie brauchen sich im Handler also keine Sorgen zu machen, ob Sie einen Namen schon außerhalb des Handlers verwendet haben oder nicht.
340
Die Sprache
Kapitel 4
Anders verhält es sich jedoch mit Variablen, die Sie als Parameter an einen Handler übergeben und die keinen Text oder Zahlen enthalten.
Die Parameterübergabe geschieht per Referenz Dass Variablen in einem Handler lokal sind, heißt nicht unbedingt, dass alle Werte, für welche diese Namen stehen, generell von außerhalb unerreichbar wären. Eine Besonderheit gibt es nämlich zu beachten bei Parametern, welche in einem veränderbaren (mutable) Typ vorliegen. Das betrifft alle Objekte der Klassen list, record, date und script sowie alle Programmobjekte. Bei der Übergabe der Werte an einen Handler findet in AppleScript immer eine Wertübergabe per Referenz statt (pass by reference). Das heißt, es wird dem Handler gesagt, wo der Wert gespeichert ist. Der Wert wird also nicht in den Handler hinein kopiert. Bei Objekten wie Text oder Zahlen jedoch, die sich nicht ohne Kopieren verändern lassen, wird für jede Operation an ihnen ein neues Objekt erstellt, so dass die Referenz nach der ersten Operation darauf hinfällig ist. Dadurch fällt es bei diesen Objekten nicht auf, dass es sich um eine Übergabe per Referenz handelt. Wenn Sie zum Beispiel eine Liste als Parameter verwenden, wird eine Referenz auf die Originalliste an den Handler übergeben. Im Handler wird damit also die Originalliste verändert und keine Kopie. Zuerst mal eine neues Beispiel, anhand dessen Sie diese Besonderheit gleich erkunden können. Eine kleine Würfelmaschine: on wuerfeln(param1) -- Erwartet eine Liste mit zwei Zahlen -- Die erste Zahl stellt die Anzahl der Würfel dar -- Die zweite Zahl die Anzahl der Seiten eines Würfels set ergebnisListe to {} repeat with i from 1 to item 1 of param1 copy (random number from 1 to item 2 of param1) ¬ to end of ergebnisListe end repeat set text item delimiters to " - " -- Umwandlung Liste -> Text display dialog "Die Würfel sind gefallen: " & ¬ ergebnisListe as text buttons "OK" default button 1 end wuerfeln set mylist to {0, 0} 341
SmartBooks
set set
AppleScript
item 1 of mylist to (text returned of (display dialog ¬ "Wie viele Würfel?" default answer "3") as integer) item 2 of mylist to (text returned of (display dialog ¬ "Wie viele Seiten soll ein Würfel haben?" default answer "6")¬ as integer)
wuerfeln(mylist) Wenn Sie das Skript ausführen, erhalten Sie als Erstes zwei Dialoge, in denen Sie aufgefordert werden, die Anzahl der Würfel und die Anzahl der Seiten eines Würfels anzugeben – falls Sie mit Oktaedern (8 Seiten), Dodekaedern (12 Seiten) oder anderen platonischen Körpern würfeln wollen. Danach wird der Handler wuerfeln aufgerufen und in einem repeat für jeden Würfel eine Zufallszahl ermittelt. Wenn Sie nun myList im Skript verändern, so hat das unmittelbar Einfluss auf die Ausführung im Handler. Denn myList und param1 weisen auf dasselbe Objekt hin. Verändern Sie dieses Objekt über eine dieser beiden »Türen«, so verändern Sie damit das Objekt innerhalb und außerhalb des Handlers, da es ein und dasselbe Objekt ist. Hier in gekürzter Form (ohne Abfragedialoge) verdeutlicht. In Fett die Zeile, an der die Liste param1 im Handler verändert wird: on wuerfeln(param1) set ergebnisListe to {} set item 1 of param1 to 1 repeat with i from 1 to item 1 of param1 copy (random number from 1 to item 2 of param1) ¬ to end of ergebnisListe end repeat set text item delimiters to ", " display dialog "Die Würfel sind gefallen: " & ¬ ergebnisListe as text buttons "OK" default button 1 end wuerfeln set mylist to {3, 6} wuerfeln(mylist) get mylist -- Ergebnis {1,6} Am Schluss wird mit get myList der Wert von myList abgefragt, und Sie sehen, dass sich myList ebenfalls geändert hat und nun eine 1 als erstes Element enthält, obwohl im Handler die Variable param1 verändert wurde und nicht myList!
342
Die Sprache
Kapitel 4
Also noch mal: Bei Listen, Records, Dates, Skriptobjekten und Programmobjekten wird bei der Übergabe von Werten an Handler eine Referenz übergeben. Es wird keine Kopie des Objekts angelegt. Fortan lässt sich dieses Objekt also innerhalb des Handlers mit seinem Parameternamen ansprechen und verändern und außerhalb des Handlers mit dem Namen, den dieses Objekt außerhalb des Handlers trägt. Das Objekt, wie hier die Liste, bleibt also dasselbe, hat dann aber zwei verschiedene Namen. Innerhalb des Handlers kennt man die Liste unter dem Namen param1, außerhalb unter dem Namen myList! Aus diesem Grund empfiehlt es sich oft, bei wiederholtem Aufruf eines Handlers die Werte, die man ihm übergeben will, zu überprüfen oder erst direkt vor Aufruf des Handlers zu setzen, da die Variablennamen eventuell noch auf alte Objekte verweisen. Wenn Sie unbedingt das Original unangetastet lassen möchten, dann sollten Sie im Handler immer eine Kopie erstellen und dann nur mit dieser Kopie arbeiten und nicht mit dem überreichten Original: on wuerfeln(param1) set ergebnisListe to {} copy param1 to myCopy set item 1 of myCopy to 2 repeat with i from 1 to item 1 of myCopy copy (random number from 1 to item 2 of myCopy) ¬ to end of ergebnisListe end repeat set text item delimiters to ", " display dialog "Die Würfel sind gefallen: " & ¬ ergebnisListe as text buttons "OK" default button 1 end wuerfeln set mylist to {3, 6} wuerfeln(mylist) get mylist -- Ergebnis {3,6} Im obigen Beispiel wird im Handler (fette Zeilen) eine Kopie von param1 mit dem Namen myCopy erstellt. In dieser Kopie wird dann der erste Wert auf 2 gestellt, und mit dieser Liste wird dann gewürfelt. Am Ende des Skripts wird dann mit get myList nachgesehen, ob sich die Originalliste verändert hat – und tatsächlich, sie ist unberührt.
343
SmartBooks
AppleScript
Parametervariablen mit Programmobjekten Statt Texte, Listen oder andere eingebaute Objekttypen von AppleScript zu verwenden, können Sie auch Programmobjekte an einen Handler übergeben. Nicht, dass dies irgendwie etwas Besonderes wäre, es kann aber nicht oft genug wiederholt werden: Es ist einer Variablen völlig egal, was für ein Objekt in ihr steckt. Hier ein Beispiel mit Fenstern. Der Handler windowSort nimmt zwei Parameter entgegen, die beide vom Typ Finder window sein sollen. Dann ermittelt er die aktuelle Bildschirmgröße anhand der Größe des Schreibtisches (bounds of window desktop). Dann werden die beiden Fenster links und rechts auf dem Bildschirm so verteilt, dass sie sich nicht überlappen und den Bildschirm völlig unter sich aufteilen. Der Code nach dem Handler ist im Großen und Ganzen nur eine Überprüfung, ob bereits ein oder zwei Fenster geöffnet sind. Wenn ja, werden diese verwendet, ansonsten werden ein oder zwei neue Fenster geöffnet, die dann an den Handler windowSort überreicht werden. on windowSort(win1, win2) -- Beide Parameter müssen vom Typ "Finder window" sein tell application "Finder" set x to bounds of window of desktop activate set bounds of win1 to {0, 44, (item 3 of x) / 2, item 4 of x} set bounds of win2 to {(item 3 of x) / 2 + 1, 44, ¬ item 3 of x, item 4 of x} end tell end windowSort tell application "Finder" if (exists Finder window 1) and (exists Finder window 2) then set win1 to Finder window 1 set win2 to Finder window 2 else if exists Finder window 1 then set win1 to Finder window 1 set win2 to make new Finder window else set win1 to make new Finder window set win2 to make new Finder window end if end tell windowSort(win1, win2) 344
Die Sprache
Kapitel 4
Das Beispiel lässt sich noch beliebig »aufbohren«, um zum Beispiel auch horizontale Aufteilungen oder weitere Fenster zu ermöglichen oder um die Fenster auf eine bestimmte Darstellungsart umzustellen. Mit dem bisher erlangten Wissen über Handler und FinderFenster (siehe tell-Kapitel) wird das kein großes Problem mehr für Sie darstellen.
Rückgabewerte Bisher haben die Handler nur Werte angenommen und damit etwas gemacht. Um etwas von einem Handler zurückzubekommen, müssen Sie diesem in Ihrem Skript eine Variable als Behälter zur Verfügung stellen, in welche er das Ergebnis hineinpacken kann. Das geschieht einfach, indem Sie den Aufruf des Handlers in eine Variable packen. Statt den Handler so aufzurufen: wuerfeln(mylist) machen Sie das nun so: set rueckgabeWert to wuerfeln(mylist) Hier wird also der Handler würfeln der Variable mit dem Namen rueckgabeWert zugewiesen. Doch was landet dann in der Variable, wenn man ihr einen Handler zuweist? Der sogenannte Rückgabewert des Handlers! Welcher das jedoch ist, hängt von der Rückgabetechnik ab. Es gibt dafür zwei Möglichkeiten: die implizite Rückgabe über die Variable result und die explizite mit return.
Implizite Rückgabe Wie Sie ja bereits wissen, hat fast jede Anweisung (aber nicht alle!) in AppleScript ein Ergebnis zur Folge, und dieses Ergebnis wird in der Variablen result abgelegt und dort immer vom Ergebnis der nachfolgenden Anweisung überschrieben. Der implizite Rückgabewert eines Handlers ist immer das Ergebnis der letzten Aktion, die in dem Handler stattgefunden hat. Einem Handler über diese Variable etwas zurückgeben zu lassen, eignet sich daher nur für sehr einfache Handler, wie hier einem zum Berechnen des Volumens einer Kugel:
345
SmartBooks
AppleScript
on berechneVolumenEinerKugel(radius) set volumen to 4 / 3 * pi * (radius ^ 3) end berechneVolumenEinerKugel set radius to 8 set ergebnis to berechneVolumenEinerKugel(radius) -- Ergebnis: 2144.66058485063 Das letzte Ergebnis des Handlers (wobei es hier ja nur eines gibt) ist sein Rückgabewert, und der landet in der Variablen ergebnis. Klar ist, dass damit immer nur ein einziger Wert zurückgeliefert werden kann. Wenn Sie mehrere Werte benötigen, tragen Sie dafür Sorge, dass alle benötigten Werte am Schluss des Handlers in eine Liste gepackt werden. Deren Wert brauchen Sie dann nur einmal kurz mit get abzufragen, dann können Sie den Handler beenden und schon haben Sie diese Liste als impliziten Rückgabewert festgelegt. In der Praxis gibt man hier aber der expliziten Rückgabe mit return den Vorzug. Vorsicht mit der impliziten Rückgabe, wenn die letzte Aktion keinen Wert zurückliefert! In diesem Fall ist die Rückgabevariable undefiniert: on makeFinderWindow() tell application "Finder" make new Finder window activate end tell end startFinder set x to makeFinderWindow() get x Obiger Handler funktioniert durchaus, doch wenn Sie versuchen, auf die Rückgabevariable x zuzugreifen - hier mit get realisiert –, erhalten Sie die Fehlermeldung, dass die Variable noch nicht definiert ist. In der Variable ist also nichts enthalten, kann ja auch nicht, denn activate ist ein Befehl, der kein Ergebnis zurückliefert. Da er hier die letzte Anweisung ist, wird nichts zurückgeliefert. Wenn Sie das activate jedoch auskommentieren oder vor dem make einfügen, erhalten Sie als Rückgabewert das Fensterobjekt und können danach auf das Fenster über die Variable x zugreifen. Meist ist man als Skripter aber wenig geneigt, auf so etwas Rücksicht zu nehmen, und sorgt lieber für eine explizite Rückgabe, damit es auf keinen Fall zu Missverständnissen kommt. Vermeiden Sie implizite Rückgaben nach Möglichkeit und verlassen Sie sich lieber auf die Rückgabe mit return
346
Die Sprache
Kapitel 4
Explizite Rückgabe mit return Ich zeige Ihnen hier das Verfahren der expliziten Rückgabe an der vereinfachten Version des Würfel-Beispiels: on wuerfeln(param1) -- Erwartet eine Liste mit zwei Zahlen. -- Die erste Zahl stellt die Anzahl der Würfel dar, -- die zweite Zahl die Anzahl der Seiten eines Würfels. set ergebnisListe to {} repeat with i from 1 to item 1 of param1 copy (random number from 1 to item 2 of param1) ¬ to end of ergebnisListe end repeat return ergebnisListe end wuerfeln set mylist to {3, 6} set rueckgabeWert to wuerfeln(mylist) -- Ergebnis, zum Beispiel: {2,4,5} Die Rückgabe erfolgt mit dem Schlüsselwort return. Dem return folgt der Wert, hier die Variable ergebnisListe, den Sie zurückliefern möchten. Der Inhalt von ergebnisListe wird hier also in die Variable rueckgabeWert gesteckt. Nun können Sie das Ergebnis mit einem display dialog im Skript anzeigen lassen oder anderweitig damit verfahren. Der Handler hat seine Schuldigkeit getan und Ihnen das Ergebnis zurückgeliefert. Sie sind jedoch nicht gezwungen, mit return ein Ergebnis zurückzuliefern. Sie können return auch einfach nur dazu verwenden, den Handler an einer beliebigen Stelle zu beenden. Der Rückgabewert ist dann wieder das Ergebnis der letzten Aktion. Wenn Sie return ohne Angabe eines Wertes verwenden, brauchen Sie diesen impliziten Rückgabewert der letzten Aktion aber wahrscheinlich nicht. Sie können auch mehrere return einsetzen (mit oder ohne Rückgabewert), die von einem Entscheidungsprozess in einem if abhängig sind. Je nachdem, welche Bedingung wahr wird, wird ein anderes return ausgeführt:
347
SmartBooks
AppleScript
on makeFinderWindow() tell application "Finder" if (exists Finder window 1) then activate return else make new Finder window activate return end if beep 3 end tell end makeFinderWindow makeFinderWindow() Wenn Sie, wie oben, keinen Wert zurückliefern wollen, dann sollten Sie den Handleraufruf ohne Variable verwenden, wie in der letzten Zeile zu sehen. Wenn Sie dort set x to makeFinderWindow() schreiben würden, wäre x nach Aufruf des Handlers immer noch undefiniert, was bei einem späteren Zugriff auf x zu einem Fehler führen würde. Wenn in einem Handler ein return erfolgt ist, dann wird der Handler an dieser Stelle sofort beendet und verlassen, auch wenn nach dem return noch weitere Anweisungen stehen! Das beep im folgenden Beispiel kann daher nie ausgeführt werden: on makeFinderWindow() tell application "Finder" if not (exists Finder window 1) then return (make new Finder window) else return (Finder window 1) end if beep 3 end tell end makeFinderWindow set x to makeFinderWindow() An obigem Beispiel können Sie auch sehen, dass Sie als Rückgabewert von return nicht unbedingt immer eine Variable verwenden müssen, Sie können jeden beliebigen Ausdruck dafür nehmen. Das Ergebnis dieses Ausdrucks oder der Anweisung wird mit return zurückgeliefert. Sie können sich damit die eine oder andere Variable sparen. Denken Sie nur
348
Die Sprache
Kapitel 4
daran, dass dafür oft eine Klammerung des Ausdrucks notwendig ist und manchmal auch ein get in der Klammer.
Rückgabe mehrerer Variablen durch Pattern Die Frage wird sich sicher früher oder später ergeben: Kann man mehrere Variable zurückliefern? Schließlich ist es ja möglich, mehrere Werte an den Handler zu übergeben, und man möchte unter Umständen sicher auch mehrere Ergebnisse zurück erhalten. Die Antwort lautet: »Nein, nicht direkt, aber …« Sie können über die sogenannte Musterzuweisung (patterned parameters) erreichen, dass mehrere Variablennamen in einer Liste (es bleibt also ein einzelner Wert!), beim Aufruf einer Liste mit Variablen übergeben wird. Sie kennen diese Technik bereits als Massenzuweisung von mehreren Werten auf mehrere Variable: set {a, b, c} to {1, 2, 3} In Variable a landet also die 1, in Variable b die 2 und in Variable c die 3. Auf diese Weise können Sie auch die Werte mehrerer Variablen in geschweiften Klammern an ein return hängen: on patternMatch(a, b, c) set a to a + 1 set b to b + 1 set c to c + 1 return {a, b, c} end patternMatch set {a, b, c} to {1, 2, 3} set {x, y, z} to patternMatch(a, b, c) Wenn Sie danach mit log oder get den Inhalt prüfen, sehen Sie, dass die 3 Rückgabewerte fein säuberlich auf die Variablen aufgeteilt wurden: log x log y log z -- Event-Protokoll: (*2*) (*3*) (*4*) 349
SmartBooks
AppleScript
Bei dieser Art der Rückgabe muss nur beachtet werden, dass nicht mehr Rückgabevariablen angegeben, als Werte zurückgeliefert werden. Sie erhalten sonst eine Fehlermeldung. Umgekehrt gibt es kein Problem. Sie können zum Beispiel vier Werte mit return zurückliefern, aber nur drei Variablen zum Auffangen bereitstellen. Der vierte Wert wird dann einfach ignoriert, wie in folgendem Beispiel die Variable d: on patternMatch(a, b, c) set a to a + 1 set b to b + 1 set c to c + 1 set d to a + b + c return {a, b, c, d} end patternMatch set {a, b, c} to {1, 2, 3} set {x, y, z} to patternMatch(a, b, c) Sie können diese Technik also dafür verwenden, immer nur die Variablen aufzufangen, die Sie auch benötigen, wobei Sie natürlich immer nur vom Ende der Liste her weglassen können. Wenn Sie den Handler also mehrmals in Ihrem Skript benötigen, was ja einer der Gründe dafür ist, dass man Handler schreibt, so können Sie einmal nur die ersten Werte und ein anderes Mal alle Werte auffangen, je nach Bedarf. Unabhängig davon kann man natürlich jederzeit auch alle Werte, die man zurückgeben will, als Liste zurückliefern. Diese ist ja bekanntlich ein »Allesfresser« und nimmt nicht nur Zahlen und Texte auf, sondern auch Objekte aller Art. Sie müssen sich dann nur merken, an welcher Stelle was steht: on patternMatch(a, b, c) set a to a + 1 set b to "b" tell application "Finder" set c to make new Finder window end tell return {a, b, c} end patternMatch set {a, b, c} to {1, 2, 3} set x to patternMatch(a, b, c) -- Ergebnis: {2, "b", Finder window id 985 of application "Finder"}
350
Die Sprache
Kapitel 4
Der umgekehrte Weg, einen Handler mit unterschiedlicher Anzahl an Parametern aufzurufen - mal nur die ersten Parameter zu füllen, mal alle -, ist nicht möglich. Ein Handler braucht immer so viele Werte, wie er Hände hat, da gibt es keine Ausnahmen. Wenn Sie ihm weniger geben, verweigert er die Arbeit. Wenn Sie dem Handler einmal mehr und einmal weniger Parameter übergeben wollen, so verwenden Sie doch einfach eine Liste oder einen Record als Parameter. Diese können beliebig viele Elemente enthalten, die alle als Parameter dienen können. Power User Wenn Sie einen Handler mal mit zwei, mal mit drei Parametern brauchen, so können Sie statt einer Liste dem Handler auch gleich vier Parameter geben! (Das ist ernst gemeint!) Machen Sie den vierten zu einem Ja/Nein-Schalter. Je nachdem, ob dieser true oder false enthält, wird einmal mit 2 Parametern im Handler gearbeitet, ein anderes Mal werden alle drei verwendet. Hier eine angepasste Version des Würflers dazu: on wuerfeln(wuerfel, seiten, modifier, schalter) -- wuerfel: Anzahl der Würfel, integer + -- seiten: Anzahl der Würfelseiten, integer + -- modifier: Wert der zum Wurf addiert wird, integer +/ -- schalter: Soll mit Modifier gewürfelt werden? boolean set ergebnisListe to {} repeat with i from 1 to wuerfel if schalter = true then copy (random number from 1 to seiten) ¬ + modifier to end of ergebnisListe else copy (random number from 1 to seiten) ¬ to end of ergebnisListe end if end repeat return ergebnisListe end wuerfeln set {wuerfel, seiten, modifier, schalter} to {3, 6, -4, true} set rueckgabe to wuerfeln(wuerfel, seiten, modifier, schalter) -- Ergebnis, zum Beispiel: {2, -3, -1} In diesem Beispiel wird der Parameter modifier beim Würfeln nur verwendet, wenn schalter auf true steht, ansonsten wird im else-Teil ohne Addition von Modifier gewürfelt. Über solche Schalter können Sie bei jedem Aufruf anders entscheiden – und so kann ein Handler gleich mehrere ähnliche Jobs erledigen.
351
SmartBooks
AppleScript
Aufruf von Handlern mit Parameter-Pattern Auch der Aufruf eines Handlers kann über Muster wie bei der Rückgabe erfolgen. Hier ein Beispiel mit der Würfelmaschine aus dem Kasten. In fetter Schrift die entscheidenden Stellen: on wuerfeln({wuerfel:wu, seiten:se, modifier:mo, schalter:jn}) -- wuerfel: Anzahl der Würfel, integer + -- seiten: Anzahl der Würfelseiten, integer + -- modifier: Wert der zum Wurf addiert wird, integer +/ -- schalter: Soll mit Modifier gewürfelt werden? boolean set x to {} repeat with i from 1 to wu if jn = true then copy (random number from 1 to se)+ mo to end of x else copy (random number from 1 to se) to end of x end if end repeat return x end wuerfeln set wuerfelRecord to {modifier:2, schalter:true, wuerfel:6, seiten:6} set rueckgabe to wuerfeln(wuerfelRecord) -- Ergebnis zum Beispiel: {7, 6, 5, 8, 5, 7} In der Handlerdefinition stehen diesmal die Variablen nicht in einer Liste, sondern in einem Record. Dieser Record hat vier Werte definiert. Die Variablennamen nach dem Doppelpunkt sind die Parameter. Beim Aufruf des Handlers muss daher ein Record mit den Propertys wuerfel, seiten, modifier und schalter übergeben werden. Alles andere würde zu einem Fehler führen, da eine Zuordnung der Werte bei einem Record nur über den Namen und nicht die Position möglich ist. Der Aufruf mit Mustern geht auch mit kombinierten Elementen. Hier dasselbe Beispiel mit zwei Einzelvariablen und einer Pattern-Liste:
352
Die Sprache
Kapitel 4
on wuerfeln(wuerfel, seiten, {modifier, schalter}) set x to {} repeat with i from 1 to wuerfel if schalter = true then copy (random number from 1 to seiten) ¬ + modifier to end of x else copy (random number from 1 to seiten) to end of x end if end repeat return x end wuerfeln set wuerfelListe to {-4, true} set rueckgabe to wuerfeln(3, 6, wuerfelListe) -- Ergebnis zum Beispiel: {2, -1, 2} Hier besteht das Muster aus zwei Einzelvariablen und einer Liste mit zwei Variablen. Dementsprechend müssen bei der Übergabe drei Werte angegeben werden, zwei Einzelwerte und eine Liste mit zwei Elementen. Die Reihenfolge der Variablen in der Liste ist dabei im Gegensatz zu einem Record nicht egal, sondern von elementarer Wichtigkeit. Vertauschen Sie diese daher nicht, oder die Parameter werden falsch übergeben.
Aufruf in Ausdrücken Bisher wurde der Aufruf eines Handlers immer gesondert auf einer Zeile geschrieben, als wäre er etwas Besonderes, geradezu Heiliges, was unbedingt eine eigene Zeile benötigt. Eine Handleraufruf kann aber auch wie eine Variable in einem Ausdruck verwendet werden. An seiner Stelle wird dann der Wert, den der Handler zurückliefert, eingesetzt. Im folgenden Beispiel wird der Handleraufruf als Argument eines display dialog verwendet und sogar in Text umgewandelt, als wäre er eine Liste: on wuerfeln(param1) set ergebnisListe to {} repeat with i from 1 to item 1 of param1 copy (random number from 1 to item 2 of param1) ¬ to end of ergebnisListe end repeat return ergebnisListe
353
SmartBooks
AppleScript
end wuerfeln -- 1.Zahl: Anzahl Würfel; 2. Zahl: Seiten des Würfels set mylist to {3, 6} set text item delimiters to " - " display dialog "Die Würfel sprechen: " & ¬ wuerfeln(mylist) as text buttons "OK" default button 1 Tatsächlich verhält sich ein Handleraufruf in einem Ausdruck immer genauso wie sein Rückgabewert! So können Sie oben auch nach einem Item des Handlers fragen: item 1 of wuerfeln(mylist) Sie erhalten dann den ersten Wert der Rückgabeliste.
Aufruf mit my Der Aufruf eines Handlers ist also wie ein Platzhalter für sein Ergebnis. Liefert der Handleraufruf einen Text zurück, verwenden Sie den Aufruf des Handlers wie Text, liefert er ein Fenster zurück, sprechen Sie den Handler wie ein Fenster an: on makeFinderWindow() tell application "Finder" if not (exists Finder window 1) then return (make new Finder window) else return (Finder window 1) end if beep 3 end tell end makeFinderWindow tell application "Finder" set collapsed of (my makeFinderWindow()) to true end tell Hier wird Ihnen sicher auffallen, dass der Handleraufruf oben in einem tell an den Finder steht und dass ein my davor steht. Beides ist notwendig. Das tell ist notwendig, weil der Handler ein Programmobjekt zurückliefert, ein Fenster des Programms Finder, und nur der Finder kann mit dieser Art von Objekten etwas anfangen. Also müssen Sie mit diesem Objekt über den Finder sprechen. Im obigen Fall wird die Property collapsed dieses Fensters auf true gesetzt. Das Fenster wird damit ins Dock geschickt.
354
Die Sprache
Kapitel 4
Durch das tell weiß AppleScript Bescheid, dass es den Ausdruck collapsed im Funktionsverzeichnis des Finders nachsehen muss. Das führt dann aber auch dazu, dass der Handleraufruf makeFinderWindow() ebenfalls im Funktionsverzeichnis des Finders gesucht wird, wo er natürlich nicht steckt. Um hier deutlich zu machen, dass makeFinderWindow() kein Begriff des Finders ist, muss ein my vorangefügt werden. Damit wird der Handler dann im Skript gesucht und gefunden. Also: Ein Programmobjekt als Rückgabewert eines Handlers muss in einem tell an dieses Programm angesprochen werden. Ein Handler in einem tell an eine Anwendung muss mit my aufgerufen werden, damit klar ist, das es sich um einen von Ihnen definierten Befehl handelt und nicht um einen Befehl des Programms.
Ausdrücke als Parameter beim Aufruf Wenn der Aufruf eines Handlers selbst als Teil eines Ausdrucks gebraucht werden kann, wie steht es dann mit den Parametern? Können auch diese durch einen Ausdruck ermittelt werden? Wenn ja, würde das nämlich einige Variablen überflüssig machen. Ja, das geht und ist sogar zu empfehlen, wenn der Wert des Parameters ansonsten nicht im Skript direkt gebraucht wird. on wuerfeln(par1) set x to {} repeat with i from 1 to item 1 of par1 copy (random number from 1 to item 2 of par1) to end of x end repeat return x end wuerfeln set text item delimiters to " - " display dialog "Die Würfel sprechen: " & ¬ (wuerfeln({random number from 1 to 6, 6}) ¬ as text) buttons "OK" default button 1 Oben werden die Parameter beim Aufruf von wuerfeln() erst in den Klammern als Parameter von display dialog ermittelt. Die Anzahl der Würfel wird dabei per Zufall zwischen 1 und 6 ermittelt, die zweite Zahl (Anzahl Seiten) ist mit 6 vorgegeben.
355
SmartBooks
AppleScript
Beide Ausdrücke stehen in geschweiften Klammern, ergeben also zusammen die für den Handler benötigte Liste. Die Parameter, die bei der Definition des Handlers angegeben werden, müssen jedoch Variablen oder Muster von Variablen bleiben, können also nicht durch Ausdrücke ersetzt werden.
Rekursive Handler Bei den Schleifen wurde bereits darauf hingewiesen: Wenn Sie eine rekursive Schleife brauchen, die zum Beispiel eine Struktur von unbekannter Tiefe durchgeht, dann müssen Sie dafür Handler verwenden. Ein rekursiver Handler ist dabei nichts anderes als ein Handler, der sich selbst erneut aufruft. Bisher wurde ein Handler immer von außerhalb aufgerufen. Sie können aber auch in einem Handler einen anderen Handler aufrufen: on sayHello(someName) say "Hello " & someName greetSusan() beep end sayHello on greetSusan() say "Hello Susan" end greetSusan sayHello("Mike") In obigem Beispiel wird in der letzten Zeile der Handler sayHello aufgerufen. Im Handler sayHello wird dann nach dem eigenen Gruß der Handler greetSusan aufgerufen. Er wird an dieser Stelle ausgeführt. Wenn greetSusan fertig ist, wird die Kontrolle wieder an sayHello zurückgegeben. Dort fährt sayHello fort, die restlichen Zeilen Code auszuführen, und lässt mit beep einmal den Signalton erklingen. Merken Sie sich die Ausführungsreihenfolge. Die Stelle, an der der Handler greetSusan im Handler sayHello aufgerufen wird, ist wie ein Platzhalter. An dieser Stelle wird quasi der ganze Code des Handlers greetSusan eingefügt. Wenn dieser fertig ausgeführt wurde, geht die Ausführung mit den folgenden Codezeilen, hier ein beep, weiter. Statt einen anderen Handler aufzurufen, kann der Handler aber auch sich selbst aufrufen. Dabei müssen Sie wie bei einer Schleife nur darauf achten, dass dies zu keiner
356
Die Sprache
Kapitel 4
Endlosschleife führt, wie in folgendem Beispiel, welches Sie mit [esc] oder [Befehl]+[.] oder [Befehl]+[alt]+[esc] abbrechen müssen: on sayHello(someName) say "Hello " & someName sayHello("Susan") end sayHello sayHello("Mike") Damit solche endlosen Schleifen nicht passieren, muss man die erneute Ausführung des Handlers immer an Bedingungen knüpfen. In folgender abgeänderter Version wird sayHello nur solange erneut aufgerufen, wie der Name nicht Susan ist. Da der Name beim ersten Selbstaufruf auf Susan gesetzt wird, erfolgt kein weiterer Selbstaufruf: on sayHello(someName) say "Hello " & someName if someName is not "Susan" then sayHello("Susan") end if end sayHello sayHello("Mike")
Speicherung von Ergebnissen bei rekursiven Aufrufen Hier das nützlichere Beispiel eines Selbstaufrufs am Beispiel einer Liste. Die Liste besitzt eine unbekannte Verschachtelungstiefe, enthält also weitere Listen und Unterlisten, und soll vom Handler »geglättet« werden. Das heißt, alle Elemente aller Listen darin werden auf die oberste Ebene geholt, jede Schachtelung wird also aufgehoben, »flach gemacht«. Im Folgenden wird, immer wenn die Klasse des nächsten item in der Liste vom Typ list ist, der Handler erneut aufgerufen, ansonsten wird jedes Listenelement an das Ende einer neuen, anfangs leeren Liste gesetzt: on flattenList(myList, flatList) repeat with i in myList if class of i is list then flattenList(i, flatList) else set end of flatList to contents of i end if end repeat
357
SmartBooks
AppleScript
end flattenList set myList to {1, {2, 3, {4, 5, 6}}, 7, {8, 9, 10}, 11, 12} set flatList to {} flattenList(myList, flatList) flatList -- Ergebnis: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} Wenn in einem rekursiven Handler ein Ergebnis über alle Handleraufrufe gespeichert werden soll, wie in obigem Beispiel, können Sie dafür keine Variable verwenden, die im Handler definiert ist. Eine im Handler definierte Variable gilt nämlich nur für diesen einen Aufruf des Handlers und in keinem anderen. Bei jedem erneuten Aufruf des Handlers würde dort also eine weitere Variable gleichen Namens angelegt, in welche dann das Ergebnis dieses einen Aufrufs gesteckt werden kann. Sie müssen das Ergebnis eines Handlerselbstaufrufs also in einer Variablen abspeichern, die außerhalb des Handlers definiert wurde. Daraus ergibt sich dann aber das Problem, dass man in einem Handler nicht auf Variablen zugreifen kann, die außerhalb des Handlers definiert wurden! Was tun? Als Lösung bieten sich drei Möglichkeiten an: Erstens der Einsatz einer Property und zweitens die Verwendung von globalen Variablen. Diese beiden Möglichkeiten werden aber erst im Kapitel Skriptobjekte beschrieben. Als dritte Möglichkeit bietet es sich an, dem Handler noch eine zweite Liste mitzugeben. Das funktioniert nur, weil die Parameterübergabe eines Handlers per Referenz geschieht und weil es sich hier um eine Liste, also einen veränderbaren Wertetyp von AppleScript, handelt. In obigem Beispiel wird aus diesem Grund beim Aufruf des Handlers eine zweite Liste als Parameter mitgegeben. In dieser werden alle Elemente der Ursprungsliste angefügt. Mit Text oder Zahlen würde das aber nicht funktionieren! (Siehe auch Kapitel Arbeiten in der Liste, Der Unterschied zwischen set und copy.) Wenn Sie also zum Beispiel über alle Elemente eines rekursiven Handleraufrufs rechnen wollen, müssen Sie eine globale Variable oder Property verwenden, wie sie noch beschrieben werden. Trotzdem hier vorab ein kleines Beispiel, in welchem alle Elemente der verschachtelten Liste einfach addiert werden. Die globale Variable wird am Anfang mit dem Schlüsselwort global deklariert und danach durch eine Zuweisung von 0 initialisiert. Eine »Globale« ist dabei nichts anderes als eine Variable, nur mit dem Unterschied, dass sie von überall aus im Skript erreichbar ist. Die globale Variable braucht deswegen im Handler
358
Die Sprache
Kapitel 4
nicht mit return zurückgegeben zu werden, sie ist sowieso innerhalb und außerhalb des Handlers gleichermaßen zugänglich. global ergebnis set ergebnis to 0 on sumList(myList) repeat with i in myList if class of i is list then sumList(i) else set ergebnis to ergebnis + (contents of i) end if end repeat end sumList set myList to {1, {2, 3, {4, 5, 6}}, 7, {8, 9, 10}, 11, 12} sumList(myList) get ergebnis -- Ergebnis: 78
Rekursion über Programmobjekte Aufbauend auf diesen Beispielen können Sie diese Rekursion auch auf Ordner im Finder (oder beliebige andere Programmobjekte) anwenden, von denen Sie im Normalfall ebenfalls nicht wissen, wie tief sie geschachtelt sind. Wenn Sie jedoch direkt mit dem Finder arbeiten, ist solch eine Rekursion gar nicht nötig, da Sie dort über entire contents eine Liste aller Element in einem Ordner inklusive aller seiner Unterordner abfragen können. Beachten Sie hierzu Geschachtelte repeat im Kapitel Schleifen. Notwendig ist eine solche Rekursion über verschachtelte Ordner daher nur, wenn Sie aus irgendeinem Grund über die System Events gehen müssen, die bisher kein entire contents für Ordner kennen. Hier ein Beispiel, welches nichts anderes macht, als alle Dateien in den gefundenen Ordnern in eine Liste zu schreiben. Am Anfang des Skripts werden Sie in einem Dialog (choose folder aus den StandardAdditions) gebeten, einen Ordner auszuwählen. Achten Sie bitte darauf, nicht gleich das ganze Heimverzeichnis oder die ganze Festplatte auszuwählen. Das Skript wird sonst sehr lange beschäftigt sein. Ein kleinerer, verschachtelter Testordner ist angeraten.
359
SmartBooks
AppleScript
set pathList to {} set myFolder to choose folder with prompt "Bitte Ordner auswählen."¬ default location (path to desktop) without invisibles processFolder(myFolder, pathList) on processFolder(someFolder, pathList) tell application "System Events" set folderItems to every disk item of someFolder¬ whose (visible is true) repeat with i in folderItems if class of i is folder then my processFolder(i, pathList) else copy POSIX path of i to end of pathList end if end repeat end tell end processFolder tell application "TextEdit" activate make new document set my text item delimiters to return set text of document 1 to pathList as text end tell Am Ende des Skripts wird die Liste aller Pfade zur Weiterverarbeitung in ein neues Dokument von TextEdit kopiert. Da Sie in obigem Beispiel jedes Objekt in dem ausgewählten Ordner fragen müssen, ob es ein Ordner ist, lässt sich das Skript kaum durch Vermeidung des Sendens von Apple events optimieren. Jede Ermittlung einer Eigenschaft eines Objekts kostet Zeit! Die Tipps zur Optimierung von Schleifen gelten daher auch für rekursive Aufrufe von Handlern (siehe Kapitel Schleifen mit repeat). Wenn es schneller gehen muss, empfiehlt sich die Verwendung der Unix-Shell aus AppleScript heraus oder die Verwendung des leider als »deprecated« gekennzeichneten Befehls list folder aus den StandardAdditions. Mit ihm lässt sich der Inhalt eines Ordners auflisten und mit info for die Eigenschaft einer Datei ermitteln. Es ist jedoch damit zu rechnen, dass diese Möglichkeit in einer der kommenden AppleScript-Versionen nicht mehr unterstützt wird.
360
Die Sprache
Kapitel 4
Handler sind Objekte Ein Handler ist ein Objekt und als solches hat es eine Klasse. Wenn Sie herausfinden wollen, von welcher Klasse ein Handler ist, dann können Sie ihn mit class of danach fragen. Wenn Sie dabei aber den Handler mit Klammern schreiben, würden Sie ihn aufrufen, was in diesem Fall nicht gewollt ist. Was ich Ihnen bisher verschwiegen habe: Sie dürfen den Handler auch ohne Klammern schreiben. Er wird dann zwar nicht ausgeführt, aber dafür kann man andere interessante Sachen mit ihm anstellen. on sayHello(someName) say "Hello " & someName end sayHello class of sayHello -- Ergebnis: handler Wenn Sie nach dem Wert des Handlers fragen, erhalten Sie den Handler selbst: get sayHello -- Ergebnis: «handler sayHello» Wenn Sie also den Namen des Handlers ohne Klammer verwenden, können Sie den Handler wie eine ganz normale Variable behandeln und zum Beispiel in eine andere Variable packen. Dann können Sie den Handler über diese Variable genauso ausführen wie mit der vorigen Variablen: on sayHello(someName) say "Hello " & someName end sayHello set someVar to sayHello someVar("Kathrin") Wenn Sie noch einen Schritt weiter gehen, bedeutet das aber auch, dass Sie zum Beispiel mehrere Handler in eine Liste packen können. Sie erinnern sich: Eine Liste kann jedes Objekt aufnehmen, und auch ein Handler ist nur ein Objekt. on sayHello(someName) say "Hello " & someName end sayHello on sayGoodbye(someName) say "Goodbye " & someName end sayGoodbye set handlerlist to {sayHello, sayGoodbye} set someVar to item 2 of handlerlist someVar("Dave") 361
SmartBooks
AppleScript
Ob someVar nun den ersten oder zweiten Handler in der Liste aufruft, hängt jetzt ganz von der item-Zuweisung in der vorletzten Zeile ab. Eine solche Liste mit Handlern lässt sich daher gut als eine Art zentrales Register verwenden, über das unterschiedliche Handlungsalternativen zentral abgerufen werden. Ihrer Fantasie sind keine Grenzen gesetzt, genauso gut können Sie einen Handler auch einen Handler zurückliefern lassen. Im folgenden Beispiel wird eine Liste mit zwei Handlern an den Handler randomHandler übergeben. Dieser wählt per Zufall einen Handler aus der Liste aus, welcher dann am Ende ausgeführt wird. Als Ergebnis wird Dave mal begrüßt und mal verabschiedet, ganz wie der Zufall es will, und immer über ein und denselben Handleraufruf am Schluss des Skripts. on sayHello(someName) say "Hello " & someName end sayHello on sayGoodbye(someName) say "Goodbye " & someName end sayGoodbye on randomHandler(handlerlist) set zufall to random number from 1 to length of handlerlist if zufall = 1 then return item 1 of handlerlist else return item 2 of handlerlist end if end randomHandler set handlerlist to {sayHello, sayGoodbye} -- Liste mit zwei Handlern set someVar to randomHandler(handlerlist) someVar("Dave") Zur Erklärung: Die dritte Zeile von unten wird zuerst ausgeführt, da sie die erste ist, die in keinem Handler steckt. Darin wird der Variablen handlerlist eine Liste mit den zwei Handlern sayHello und sayGoodbye zugewiesen. Danach wird die Variable someVar auf das Ergebnis des Handleraufrufs randomHandler gesetzt. Dieser Handler randomHandler bringt als Parameter die Liste handlerlist mit den zwei Handlern mit. In diesem Handler wird dann gewürfelt, welcher der Handler
362
Die Sprache
Kapitel 4
aus randomList mit return zurückgeliefert wird. Danach steckt dieser zurückgelieferte Handler in der Variablen someVar. Wenn Sie dann in der letzten Zeile someVar mit Klammern aufrufen und einen Namen als Parameter angeben, wird entweder der Handler sayHello oder der Handler sayGodbye ausgeführt, je nachdem, welcher dieser beiden Handler in someVar steckt. Mit einem einzigen Handleraufruf können Sie so also unterschiedliche Handler auslösen, Sie müssen nicht einmal wissen, wie diese heißen. Nur die erwarteten Parameter müssen immer bekannt sein. Und natürlich werden Sie normalerweise den auszuführenden Handler nicht per Zufall bestimmen wollen, sondern an anderen Bedingungen festmachen.
Benannte Parameter Die folgende Art des Handleraufrufs ist mir sonst von keiner anderen Programmiersprache bekannt und ich übersetze den von Apple verwendeten Namen »Labeled Parameters« hier mit »Benannte Parameter«. Eigentlich sind es jedoch nicht richtige Namen, also Substantive, sondern Präpositionen, die es hier ermöglichen, die einzelnen Parameter zu unterscheiden und den Handler ohne Klammern auf eine mehr beschreibende Art und Weise zu verfassen. Handler mit benannten Parametern sind dadurch aber nicht unbedingt einfacher zu erstellen. Erstens muss man die Schlüsselwörter kennen, bevor man sie verwenden kann, und zweitens möchte man sich dann natürlich auch die Mühe machen, solche Präpositionen auszuwählen, die einen möglichst sinnvollen beschreibenden Satz ergeben, welcher etwas über die Tätigkeit des Handlers aussagt. Auch die Wahl der Variablenbezeichner spielt eine ungleich wichtigere Rolle als bei Positionsparametern. Bei benannten Parametern empfiehlt es sich, alle Variablen, die für Parameter verwendet werden, durch eine bestimmte Schreibweise klar abzuheben, zum Beispiel durch gemischte Groß-/ Kleinschreibung. Für Handler, die mit benannten Parametern arbeiten, wird dabei meist die Schreibweise mit to bevorzugt. Sie erinnern sich bestimmt noch, dass Sie die Definition eines Handlers statt mit on auch mit dem Wort to einleiten können. Diese Schreibweise hat keinen technischen, sondern nur den einen Vorteil, dass sich damit eine Handlerdefinition mehr wie ein englischer Satz mit Betonung auf der auszuführenden Handlung anhört. Mit ein bisschen Mühe bei der Wahl der zur Verfügung stehenden Präpositionen und Variablennamen braucht man dann kaum noch in den Handler hineinzusehen, um zu verstehen, was er macht und wofür die einzelnen Parameter dienen. Im Idealfall liest man die Handlerdefinition oder deren Aufruf und weiß Bescheid, was dort geschieht.
363
SmartBooks
AppleScript
Die einfachste Form eines Handlers mit benannten Parametern wäre einer ohne jeden Parameter. Da es dann aber auch nichts zu benennen gibt, ist die Form mit benannten Parametern logischerweise nur für Handleraufrufe mit Parametern möglich. Wenn Sie einen Handler definieren wollen, der keine Parameter benötigt, so verwenden Sie die bisherige Form mit Klammern am Ende des Handlernamens: to sayEnough() say "Enough is enough" end sayEnough sayEnough() Ansonsten haben Sie die Möglichkeit, benannte Parameter auf drei Arten zu definieren: über Benutzer-Parameter, den direkten Parameter und Benutzer-Parameter mit dem Schlüsselwort given. Parameter mit booleschen Werten lassen sich zudem mit with oder without aufrufen.
Benutzer-Parameter Dies ist die eigentliche und grundlegende Art benannter Parameter. Welche Variable oder Variablen Sie auch immer verwenden, Sie müssen dabei nur darauf achten, dass jeder dieser Variablen mit einem der folgenden Verhältniswörter eingeleitet wird und dass jedes dieser Wörter nur ein Mal in der Definition eines Handlers vorkommt: about above against apart from around aside from at below
beneath beside between by for from instead of into
on onto out of over since thru (oder through) to (undokumentiert!) under
So kann ein einfacher Aufruf zum Beispiel so aussehen: to getMessages out of someMailbox from somePerson tell application "Mail" set listOfMessages to every message of mailbox someMailbox ¬ whose sender contains somePerson end tell return listOfMessages end getMessages set someMailbox to "Projekte/2008" 364
Die Sprache
Kapitel 4
set somePerson to "Robert" set listOfMessages to getMessages out of someMailbox from somePerson -- Ergebnis: {message id 303929 of mailbox "Projekte/2008" of application "Mail", message id 292202 of …} Hier werden im Handler getMessages E-Mails zurückgeliefert, die aus der Mailbox someMailbox (out of someMailbox) und von der Person somePerson (from somePerson) stammen. Die resultierende Liste würde sich dann zum Beispiel für eine Schleife über diese Mails eignen, zum Beispiel, um deren Inhalt abzufragen und in eine Textverarbeitung, ein Layout-Programm oder eine Datenbank einzutragen. Wenn das Postfach verschachtelt ist, muss der Pfad wie hier mit Schrägstrichen verdeutlicht werden. Obiges Beispiel definiert zwei Parameter die anhand der Namen out of und from unterschieden werden. Das bedeutet, dass die Reihenfolge der Parameter beim Aufruf völlig egal ist. Sie können in dem Aufruf des Handlers die Parameter also durchaus auch in anderer Reihenfolge angeben. Also zum Beispiel: set listOfMessages to getMessages from somePerson out of someMailbox Merken Sie sich, dass eines der Verhältniswörter aus obiger Liste und ein Variablenname immer zusammengehören, wobei das Verhältniswort immer vor der Variable stehen muss. Wenn Sie die Reihenfolge vertauschen, dann immer ein Namen/Variablen-Paar zusammen und niemals getrennt. Sie können beliebig viele Parameter angeben, jede Präposition darf aber nur ein Mal vorkommen. Da es insgesamt nur 24 gibt, ist die Anzahl der Parameter also praktisch auf 24 begrenzt, aber es gibt ja noch selbst definierte, benannte Parameter, wie gleich zu sehen sein wird. Zusätzlich können Sie an jeder Stelle auch noch das Füllwort the verwenden. Es hat keine Bedeutung, kann einen Handler aber leichter lesbar machen. So können Sie obigen Handler zum Beispiel auch so definieren: to getMessages out of the mailBx from the person Da mailbox bereits ein Schlüsselwort von Mail ist wird es hier bewusst anders geschrieben, um einen Namenskonflikt zu vermeiden. Auch beim Aufruf eines Handlers kann
365
SmartBooks
AppleScript
überall the eingefügt werden, ohne zu stören, selbst wenn der Handler ohne the definiert wurde. Von Apple nicht dokumentiert ist in diesem Zusammenhang die Verwendung von to als Präposition zur Benennung eines Parameters. Auf Grund der fehlenden Dokumentation würde ich von dessen Verwendung dann auch eher abraten. Es könnte aber auch daran liegen, dass to an vielen anderen Stellen in AppleScript bereits eine wichtige Rolle spielt. To funktioniert bei mir jedenfalls problemlos als Benennung für einen Parameter: to sayHello to someOne from someOneElse say "Hello " & someOne & ", greetings from " & someOneElse end sayHello sayHello to "Robert" from "Susan"
Der direkte Parameter Ein direkter Parameter wird immer mit den Wörtern of oder in direkt nach dem Handlernamen eingeleitet. Der direkte Parameter muss also immer der erste Parameter sein. Seine Position ist damit im Gegensatz zu den Benutzer-Parametern fest. Außerdem kann der direkte Parameter nicht alleine verwendet werden, sondern es muss immer zumindest ein weiterer Parameter folgen. Hier ein Beispiel mit iTunes. Der Handler stellt für einen bestimmten Künstler in einer playlist die Equalizer-Einstellung auf ein Preset ein: to setEqualizer of somePlaylist for someArtist by EQPreset tell application "iTunes" set EQ of every track of playlist somePlaylist ¬ whose artist is someArtist to EQPreset -- weiterer Code -- … end tell end setEqualizer set myPlaylist to "Gurdjieff" set myArtist to "Alessandra Celletti" set myEqualizer to "Piano" setEqualizer of myPlaylist for myArtist by myEqualizer Der direkte Parameter ist keine Pflicht, er kann also auch weggelassen werden, wenn Sie stattdessen eine andere Parameterart verwenden.
366
Die Sprache
Kapitel 4
Eigene Benutzer-Parameter mit given Wenn Sie mit Benutzerparametern arbeiten, werden Sie schnell feststellen, dass die möglichen Präpositionen doch zu einer starken Beschränkung bei der Wortwahl führen und dass man daher oft zu Wörtern greift, die nicht so richtig passen, so dass sich der Handler recht holprig liest. Natürlich ist das rein kosmetisch und ändert nichts an seiner Funktionsweise, trotzdem wäre es schön, wenn man noch eigene Wörter definieren könnte. Nun, eigene Präpositionen kann man nicht erfinden, aber man kann sich mit dem für diesen Zweck reservierten Schlüsselwort given eigene Namen/Variablen-Paare ausdenken. Im folgenden Beispiel werden aus einer Liste von Zahlen alle Zahlen extrahiert, die durch eine Ganzzahl ohne Rest teilbar sind: to extractNumbers from someList given dividableThru:someInt set resultList to {} repeat with i in someList if i mod someInt = 0 then set end of resultList to contents of i end if end repeat return resultList end extractNumbers set someList to {1, 2, 3, 4, 8, 16, 23, 27, 32} set resultList to extractNumbers from someList given dividableThru:4 -- Ergebnis: {4, 8, 16, 32} Nach dem Schlüsselwort given folgt also immer der Name des Parameters, in obigem Fall ist dies dividableThru, danach folgen ein Doppelpunkt und der Inhalt des Parameters. Das kann ein Literal sein, ein Ausdruck oder eine Variable, oben ist dies die Zahl 4. Parameter mit given müssen immer am Schluss aller Parameter stehen. Ihre Reihenfolge ist also nicht egal. Wenn Sie jedoch mehrere Parameter mit given definieren, so ist deren Reihenfolge untereinander egal, Sie müssen diese einfach nur durch Komma voneinander trennen: to extractNums from mylist given divThru:someInt, except:exList set resultList to {} repeat with i in mylist if i mod someInt = 0 and contents of i is not in exList then set end of resultList to contents of i end if end repeat return resultList
367
SmartBooks
AppleScript
end extractNums set mylist to {1, 2, 3, 4, 8, 16, 23, 27, 32} set {someInt, exList} to {4, {4, 8}} set resultList to extractNums from mylist ¬ given divThru:someInt, except:exList -- Ergebnis: {16, 32}
with oder without beim Aufruf Wenn Sie in einem Handler einen Parameter verwenden, welcher einen booleschen Wert erwartet, entweder als Benutzerparameter oder mit given, so können Sie diesen mit den Wörtern with oder without beim Aufruf angeben. to roll around numDice onto numSides given mode:modifier, modifying:onOff -- numDice: Anzahl der Würfel, integer + -- numSides: Anzahl der Würfelseiten, integer + -- modifier: Wert der zum Wurf addiert wird, integer +/ -- onOff: Soll mit Modifier gewürfelt werden? boolean set ergebnisListe to {} repeat with i from 1 to numDice if onOff then copy (random number from 1 to numSides) ¬ + modifier to end of ergebnisListe else copy (random number from 1 to numSides) ¬ to end of ergebnisListe end if end repeat return ergebnisListe end roll set {numDice, numSides, modifier, modifying} to {3, 6, -4, true} set rueckgabe to roll around numDice onto numSides without modifying ¬ given mode:modifier Wenn Sie den Namen des given-Parameters mit without davor verwenden, wird false übergeben, verwenden Sie with, so wird true übergeben. Der boolesche Wert wird also im Aufruf durch with oder without auf true oder false gesetzt! Eine vorherige Zuweisung eines booleschen Wertes in eine Variable, die dann im Aufruf übergeben wird, ist also nicht notwendig. Wenn Sie mehrere solcher Wahrheitswerte haben, können Sie diese beim Aufruf hintereinander schreiben, wobei AppleScript beim Kompilieren eventuell etwas umstrukturiert.
368
Die Sprache
Kapitel 4
So wird das with immer zuerst genannt und dann erst folgt das without. Wenn mehrere with oder without hintereinander folgen, so werden diese mit and verbunden, wie in folgendem Beispiel: to roll around numDice given sixSides:sixSides, modifying:onOff, mode:modifier -- numDice: Anzahl der Würfel, integer + -- sixSides: Würfel mit 6 Seiten? Wenn false, Prozentwürfel mit 100 Seiten -- modifier: Wert der zum Wurf addiert wird, integer +/ -- onOff: Soll mit Modifier gewürfelt werden? boolean set ergebnisListe to {} if sixSides then set numSides to 6 else set numSides to 100 end if repeat with i from 1 to numDice if onOff then copy (random number from 1 to numSides) ¬ + modifier to end of ergebnisListe else copy (random number from 1 to numSides)¬ to end of ergebnisListe end if end repeat return ergebnisListe end roll set {numDice, modifier} to {3, -4} set rueckgabe to roll around numDice without sixSides and modifying¬ given mode:modifier Die letzte Zeile beim Aufruf ist also identisch zu: set rueckgabe to roll around numDice without sixSides without modifying¬ given mode:modifier Im Prinzip braucht man sich um die Schreibweise mit and aber nicht zu kümmern, da sie automatisch beim Kompilieren erfolgt.
369
SmartBooks
AppleScript
Laden von Bibliotheken mit load script Wen Sie ein und denselben Handler öfters in verschiedenen Skripts brauchen, können Sie ihn in ein anderes Skript auslagern, um dann von unterschiedlichen Skripts aus darauf zuzugreifen. Dieses Verhalten ist mit dem Befehl load script aus den Standarderweiterungen möglich. Schreiben Sie dafür einfach alle benötigten Handler in ein neues Skript und speichern Sie dieses im Format Skript mit der Endung scpt oder Skript-Bundle mit der Endung scptd. Damit haben Sie sich eine Bibliothek mit Handlern angelegt, die für sich alleine nichts tut, da die Bibliothek keinen Code außerhalb eines Handlers enthält. Dieses Skript kann aber von einem anderen Skript »geladen« werden. Danach können Sie die Handler verwenden, als befänden sie sich im Skript selber und nicht außerhalb. Solche als Bibliothek verwendete Skripts werden als library bezeichnet. Schreiben Sie zum Beispiel in einem Skript folgende Handler hinein und speichern Sie diese dann mit dem Namen library.scpt ab: on flattenList(myList, flatList) -- plättet eine verschachtelte Liste repeat with i in myList if class of i is list then flattenList(i, flatList) else set end of flatList to contents of i end if end repeat return flatList end flattenList on berechneVolumenEinerKugel(radius) set volumen to 4 / 3 * pi * (radius ^ 3) return volumen end berechneVolumenEinerKugel Nun können Sie in einem zweiten Skript das Skript library.scpt mit load script in eine Variable laden. Achten Sie dabei darauf, den Pfad korrekt anzugeben, oder verwenden Sie einen der Standardpfade mit path to aus den Standard-Erweiterungen.
370
Die Sprache
Kapitel 4
set lib to load script POSIX file ¬ "/Users/Detlef/Documents/Skripts/library.scpt" (*oder: set lib to load script alias (((path to documents folder) as text) & ¬ "Skripts:library.scpt") *) set someList to {1, {2, 3, {4, 5, 6}}, 7, {8, 9, 10}, 11, 12} set flatList to {} set newList to lib's flattenList({1, {2, 3, {4, 5, 6}}, 7, {8, 9, 10}}, {}) -- Ergebnis: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} berechneVolumenEinerKugel(5) of lib-- Ergebnis: 523.598775598299 Hier wird also ganz am Anfang des Skripts das Skript library.scpt mit den gesammelten Handlern in die Variable mit dem Namen lib geladen. In dieser Variablen steckt ab sofort ein ganzes Skript. Wenn Sie am Ende des obigen Skripts einmal class of lib ans Ende schreiben und das Skript dann ausführen, erhalten Sie als Ergebnis script. Das heißt, ein Skript an sich ist ebenfalls eine Klasse. Ab sofort können Sie alle Handler aus diesem Skript aufrufen. Sie müssen dabei nur darauf achten, beim Aufruf des Handlers anzugeben, dass es sich um einen Handler von lib handelt. Diese Besitzanzeige geschieht entweder mit of lib nach dem Handlernamen oder vor dem Handlernamen mit lib's. Alternativ können Sie auch tell verwenden, entweder als Einzeiler oder als Block. Alle Befehle in dem tell-Block richten sich dann an das Bibliotheksskript: tell lib set newList to flattenList({1, {2, 3, {4, 5, 6}}, 7, {8}}, {}) berechneVolumenEinerKugel(5) end tell Sichern Sie das Skript dann im Format Skript mit der Endung scpt oder als Skript-Bundle mit dem Dateikürzel scptd.
Laden von Bibliotheken aus dem Bundle des Skripts Wennn das Skript auf die beschriebene Art auf eine Bibliothek zugreift, hat das leider den Nachteil, dass man es nicht mehr so einfach weitergeben kann. Man muss dann jedes Mal darauf achten, das Library-Skript mitzugeben und auf dem anderen Rechner an die gleiche Stelle zu legen.
371
SmartBooks
AppleScript
Seit es Bundles gibt, können Sie solch eine Bibliothek aber auch in das Bundle legen. 1. Speichern Sie dafür ein neues, leeres Skript im Format Skript-Bundle und nennen Sie es Main.scptd. 2. Klicken Sie dann im Skripteditor auf die Schaltfläche Bundle-Inhalt und ziehen Sie die vorhin erstellte Bibliothek library.scpt in die Schublade, am besten direkt in den Ordner Skripts. Alternativ können Sie das Skript-Bundle Main.scptd auch im Finder über das Kontextmenü öffnen und die Bibliothek dann hinein ziehen. 3. Das Laden der Bibliothek erfolgt dann folgendermaßen: Schreiben Sie in das noch leere Skript Main.scptd folgenden Code: set myRes to path to resource "library.scpt" in directory "Scripts" set lib to load script myRes tell lib set newList to flattenList({1, {2, 3, {4, 5, 6}}, 7, {8, 9, 10}}, {}) berechneVolumenEinerKugel(5) end tell Wenn das Skript auf oberster Ebene in der Bundle-Schublade liegt, was im Finder dem Ordner Resources im Bundle entspricht, können Sie den Parameter in directory auch weglassen.
Abb. 4-16 Hinzufügen einer Bibliothek in ein Skript-Bundle und wie man diese im Skript »lädt«
372
Die Sprache
Kapitel 4
Der Befehl path to resource liefert dabei immer den kompletten Pfad bis in den Ordner Resources ab. Egal, auf welchem Rechner das Skript also läuft, es selbst und seine Ordner im Bundle lassen sich damit immer finden. Der Ordner Resources im Bundle eignet sich damit auch für andere Ressourcen, die vom Skript gebraucht werden, zum Beispiel TextDateien mit Daten, die vom Skript geladen werden, oder Log-Dateien, welche die Ausführung des Skripts und aufgetretene Fehler protokollieren. Nun können Sie das Skript ohne Probleme weitergeben. Aufgepasst Wenn Sie jedoch das Format wechseln wollen, zum Beispiel wenn das Skript nach Fertigstellung als Programm-Bundle gespeichert werden soll, dann speichern Sie das Skript unbedingt unter einem anderen Namen. Beim Wechsel des Formats werden nämlich hinzugefügte Skripts und Ressourcen im Bundle nicht mit übernommen. Sie müssen diese nach Speicherung als Programm-Bundle also noch mal aus dem Skript-Bundle holen und in das Programm-Bundle kopieren.
Die Standard-Handler einer Skriptanwendung Bisher haben Sie Handler selbst erzeugt. Es gibt jedoch einige Handler, die existieren bereits und können direkt von Ihnen verwendet werden. Um einen Handler nutzen zu können, der bereits existiert, muss man natürlich erstens wissen, wie er heißt, zweitens welche Parameter er benötigt und drittens was er eigentlich macht. Im Folgenden dreht sich alles um die Standardhandler eines Skripts. Sie können diese in wirklich jedem Skript verwenden. Das Besondere an ihnen ist, dass diese Handler automatisch bei einem bestimmten Ereignis aufgerufen werden. Das heißt, diese Handler werden normalerweise nicht von Ihnen aufgerufen, sondern von einem Ereignis in Ihrem Skript.
Der run-Handler Alles, was Sie bisher in einem Skript geschrieben haben und was nicht Teil eines Handlers war, ist Teil des run-Handlers. Im folgenden Skript gehören die erste und letzte Zeile zum Beispiel zum run-Handler. Der Handler sayHello in der Mitte gehört nicht dazu. Ein Handler darf ja nicht in einem anderen geschachtelt werden.
373
SmartBooks
AppleScript
set {toGreet1, toGreet2} to {"John", "Mike"} on sayHello(param1, param2) say "Hello " & param1 say "Hi " & param2 end sayHello sayHello(toGreet1, toGreet2) Diese Zeilen außerhalb jedes anderen Handlers im Skript werden jedes Mal automatisch ausgeführt, wenn Sie das Skript starten, also laufen (run) lassen. Der Handler wird also automatisch aufgerufen, wenn Sie ihm den run-Befehl geben. Das geschieht jedes Mal, wenn Sie im Skripteditor auf den Ausführen-Knopf klicken. Sie können diesen impliziten runHandler aber auch ganz bewusst als Handler schreiben: on run set {toGreet1, toGreet2} to {"John", "Mike"} sayHello(toGreet1, toGreet2) end run on sayHello(param1, param2) say "Hello " & param1 say "Hi " & param2 end sayHello Auffällig ist dabei, dass der Handler run keine Klammern am Ende trägt und damit keine Parameter kennt. Sie können ihm also nicht irgendwelche Informationen mitgeben. Power User Tatsächlich hat der run-Handler durchaus einen Parameter, der als Liste vorliegen muss. Dieser kann aber nur über den Befehl run script genutzt werden (siehe run script und der Aufruf des run-Handlers mit Parametern am Ende des Kapitels Skriptobjekte). Das Skript funktioniert mit diesem explizit definierten run-Handler genauso wie vorher. Der run-Handler wird automatisch aufgerufen, wenn Sie das Skript ausführen. Sie müssen ihn also nicht selber im Skript aufrufen wie bei Ihren selbst definierten Handlern. Dieser run-Handler, ob Sie ihn nun implizit oder explizit nutzen, bildet immer den Startpunkt eines jeden Skripts. Ohne einen run-Handler passiert beim Start eines Skripts gar nichts. Ob Sie bei der bisherigen Form bleiben, in welcher jede Zeile außerhalb eines Handlers zum impliziten run-Handler gehört, oder ob Sie die Form mit explizitem run-Handler bevorzugen, bleibt Ihnen überlassen. Den run-Handler bewusst zu schreiben, kann ein komplexes Skript auf jeden Fall leichter verständlich machen.
374
Die Sprache
Kapitel 4
Wenn Sie den run-Handler explizit definieren, dann müssen Sie aber wirklich darauf achten, dass Sie nichts mehr außerhalb eines Handlers schreiben dürfen. Ausnahmen sind nur property- und global-Deklarationen (siehe Kapitel Skriptobjekte). Es dürfen dann also keine Einzelzeilen irgendwo herrenlos im Skript herumliegen. Sie erhalten sonst sofort eine Fehlermeldung, wenn Sie das Skript kompilieren. Im Normalfall brauchen Sie den run-Handler also niemals selbst aufzurufen, da er ja automatisch aufgerufen wird, wenn das Skript startet. Wenn Sie den run-Handler in einem Skript aber bewusst erneut aufrufen, erhalten Sie eine Endlosschleife, wenn die erneute Ausführung von run nicht an eine Bedingung geknüpft ist, die irgendwann wahr wird. In folgendem Skript wird der run-Handler aus dem run-Handler heraus 3 Mal aufgerufen. Um die Anzahl zu zählen, ist dabei eine Property (siehe Kapitel Skriptobjekte) nötig, da jede Variablendefinition im run-Handler beim rekursiven Aufruf zurückgesetzt würde. property i : 1 on run set toGreet to {"John", "Susan", "Mike"} if i ≤ length of toGreet then sayHello(item i of toGreet) tell me to run else set i to 1 end if end run on sayHello(param) say "Hello " & param set i to i + 1 end sayHello Obwohl technisch also möglich, ist der rekursive Aufruf eines run-Handlers normalerweise zu vermeiden. Die Nebeneffekte, die dabei auftreten können, sind schlecht vorhersehbar und schwierig zu beherrschen. Benutzen Sie den run-Handler immer nur als Startpunkt. Für die rekursive Abarbeitung von Aufgaben sollten Sie Schleifen und, wenn nötig, andere Handler verwenden, aber nicht den run-Handler selbst.
375
SmartBooks
AppleScript
Wenn Sie den eigenen run-Handler explizit selber starten wollen oder müssen, dann denken Sie daran, dass Sie innerhalb von tell-Blöcken an andere Anwendungen, wie oben geschehen, mit tell me angeben müssen, dass der run-Handler des Skripts gemeint ist, ansonsten schicken Sie einen run-Befehl an die Anwendung.
Der quit-Handler Der quit-Handler ist quasi das Gegenstück zum run-Handler. Wenn ein Skript gestartet wird, wird ein run-Befehl an das Skript gesendet. Dieser Befehl wird vom Skript aufgefangen, und sein run-Handler fängt an zu arbeiten. Wenn sich ein Skript beendet, wird vorher ein quit-Befehl gesendet. Ein quit-Handler kann diesen Befehl abfangen und darauf reagieren, um zum Beispiel noch ein paar Aufräumarbeiten vor Abschluss zu erledigen. Besonders sinnvoll ist das bei Skripts, die mit der Option Nicht automatisch beenden gespeichert wurden. on run beep end run on quit say "Goodbye" continue quit end quit Wenn Sie dieses Skript ausführen, erfolgt nur ein beep, aber kein Goodbye. Der quitHandler wird also nicht ausgeführt. Das liegt daran, dass Sie im offenen Skripteditor arbeiten. Wenn Sie dieses Skript jedoch als Programm abspeichern und dieses dann per Doppelklick starten, erfolgt nach dem beep, dem Zeichen, dass der run-Handler ausgeführt wurde, ein Goodbye, das Zeichen, dass der quit-Handler vor dem Beenden des Skripts ausgeführt wurde. Dabei dürfen Sie niemals vergessen, im quit-Handler nach Erledigung aller Aufgaben das quit mit continue quit weiterzuleiten an das Skriptprogramm, damit sich dieses wirklich beenden kann. Mit einem quit-Handler »fangen« Sie das quit sozusagen ab. Es erreicht daher niemals das Skriptprogramm, was dazu führt, dass sich das Programm nur noch auf die harte Tour mit [Befehl]+[alt]+[esc] abbrechen lässt. Um das Verhalten eines Skriptprogramms in einem Skript im offenen Skripteditor zu simulieren, ohne das Skript jedes Mal als Programm zu speichern, können Sie ein quit auch selber senden. Im folgenden Skript wird das say im quit-Handler ausgeführt, weil der quit-Handler im run-Handler explizit aufgerufen wird:
376
Die Sprache
Kapitel 4
on run beep tell me to quit end run on quit say "Goodbye" --continue quit end quit Sie müssen dann im quit-Handler, zumindest solange das Skript noch nicht als Programm gesichert wurde, den continue quit-Befehl auskommentieren, da sonst der quit-Befehl an den Skripteditor weitergeleitet wird, welcher sich daraufhin beenden will. Wichtig ist auch das tell me. Wenn das quit nämlich in einem tell-Block an eine Anwendung steht, dann rufen Sie mit einem einfachen quit nicht den quit-Handler im Skript auf, sondern Sie senden der Anwendung einen quit-Befehl, wodurch diese dann beendet wird! Ein quit-Handler besitzt einen optionalen einzelnen Parameter: on run set toGreet to "Kathrin" tell me to quit toGreet end run on quit param say "Goodbye" & param --continue quit end quit Dieser Parameter benötigt keine Klammern, Sie brauchen den Wert einfach nur hinter quit zu schreiben. Achten Sie darauf, das continue quit vor dem Sichern als Programm wieder zu dekommentieren, ansonsten kann das Skriptprogramm nicht beendet werden.
Der idle-Handler Wie der quit-Handler, so ist auch der idle-Handler vor allem für Skripts sinnvoll, die geöffnet bleiben und auf Befehle warten. Im Gegensatz zum quit-Handler wird der idleHandler aber wirklich nur ausgeführt, wenn das Skript als Programm mit der Option Nicht automatisch beenden abgesichert wurde.
377
SmartBooks
AppleScript
Der run-Handler wird beim Start ausgeführt, der quit-Handler beim Beenden und der idle-Handler wird ausgeführt, wenn nichts geschieht. Hört sich komisch an, ist aber so. Auch das Nichtstun ist in AppleScript ein Ereignis. Das Wort »idle« bedeutet dabei soviel wie »Leerlauf«. AppleScript sendet in periodischen Abständen, standardmäßig alle 30 Sekunden, Skriptprogrammen ein idle-Event. Wenn das Skript gerade nichts anderes zu tun hat, kann es dieses Ereignis mit einem idle-Handler abfangen. Das lässt sich dann nutzen, um zum Beispiel regelmäßig Informationen abzufragen oder Arbeiten mit niedriger Priorität auszuführen, immer dann, wenn gerade nichts anderes zu tun ist. Das Abfragen der Zeit und das Auslösen eines Handlers zu einem bestimmten Zeitpunkt sind klassische Verwendungsmöglichkeiten hierfür. Da Befehle in einem idle-Handler nur dann ausgeführt werden, wenn gerade nichts anders zu tun ist, kann der idle-Handler nur in Skripts verwendet werden, die als Programm mit der Option Nicht automatisch beenden gespeichert wurden. Ohne diese Option beendet sich das Skript sofort nach Ausführung seiner Aufgabe, und es wird niemals zu einem Leerlauf kommen. Die folgenden Zeilen müssen Sie daher unbedingt mit dieser Option als Programm abspeichern: on run say "Run-Handler started" end run on idle say "Waiting" using "Trinoids" end idle on quit say "Goodbye" continue quit end quit Wenn dieses Skript startet, werden Sie zuerst darüber informiert, dass der run-Handler gestartet wurde. Dann wird der idle-Handler aufgerufen und es wird "Waiting" gesagt. Diese Ansage erfolgt nun ungefähr alle 30 Sekunden, so oft wie der idle-Handler also standardmäßig aufgerufen wird. Wenn Sie das Skript beenden, wird der quit-Handler ausgelöst und das "Goodbye" ertönt. Wenn Sie einen anderen Rhythmus benötigen, dann lassen Sie den idle-Handler mit return eine positive Integerzahl zurückliefern. Diese bestimmt dann die Anzahl der Sekunden, bis der Handler erneut aufgerufen wird:
378
Die Sprache
Kapitel 4
on run say "Run-Handler started" end run on idle say "Waiting" using "Trinoids" return 10 end idle on quit say "Goodbye" continue quit end quit Wenn der Rückgabewert keine Zahl ist oder sich im negativen Bereich befindet, wird das Intervall nicht geändert. Wenn Sie die Zahl 0 zurückgeben, ergibt sich wieder der Standardwert von 30 Sekunden. Da jeder Handler einen impliziten Rückgabewert hat, ist bei einem idle-Handler besonders darauf zu achten, explizit ein return am Ende des idle-Handlers anzugeben. Wennn die letzte Anweisung im idle-Handler gerade irgendwelche Berechnungen vornimmt, um dort zum Beispiel ein Ergebnis von 14400 zu erhalten, so wird der idle-Handler erst in vier Stunden wieder ausgeführt, und Sie werden sich dann wahrscheinlich wundern, warum er nach der ersten Ausführung stundenlang faulenzt. Im Kapitel 6 finden Sie weitere Beispiele zur Verwendung des idle-Handlers.
Der open-Handler und Droplets Dieser Handler wird ausgeführt, wenn Anwender Dateien oder Ordner auf das Icon eines Applets ziehen. Dabei spielt es keine Rolle, ob das Programm schon läuft, also mit der Option Nicht automatisch beenden gespeichert wurde, oder ob es dadurch erst gestartet wird. Dieser Handler funktioniert nur mit Skripts, die als Programm oder Programm-Bundle abgespeichert wurden. Sobald Sie eine oder mehrere Dateien oder Ordner auf das Icon des Skriptprogramms ziehen, empfängt das Skript den open-Befehl, womit der open-Handler im Skript ausgeführt wird. Dem open-Handler wird dabei an seinen einzigen Parameter eine Liste mit den Pfaden (als alias) der Ordner und Dateien, die auf das Skript gezogen wurden, übergeben. Die Verwendung dieses Parameters ist für die Funktionsfähigkeit also unbedingt erforderlich, da Sie sonst nicht erfahren, welche Dateien auf das Applet gezogen wurden.
379
SmartBooks
AppleScript
Der Handler selbst hat wieder keine Klammern. Der Parameter folgt als einzelner Wert direkt nach on open. Die Grundstruktur eines open-Handlers zur nicht-rekursiven Abarbeitung von Ordnern oder Dateien, die auf ihn gezogen werden, sieht wie folgt aus: on open pathList set itemList to {} tell application "System Events" repeat with i in pathList if class of disk item (POSIX path of i) is folder then -- Was mit einem Ordner zu tun ist, gehört hier hinein! -- Zum Beispiel: set end of itemList to (path of disk items of i ¬ whose visible is true) -- Unsichtbare Dateien ausschließen! else -- Was mit einer Datei zu tun ist, gehört hier hinein! -- Zum Beispiel: set end of itemList to path of i end if end repeat end tell my viewResult(itemList) end open on viewResult(itemList) -- Liste der Pfade anzeigen set AppleScript's text item delimiters to return tell application "TextEdit" make new document with properties {text:itemList as text} end tell end viewResult Hier wird am Schluss noch der Handler viewResult aufgerufen, der nur dazu dient, die ermittelten Pfade in TextEdit zu protokollieren. Er ist nur zur Veranschaulichung und Überprüfung des open-Handlers da. Sie müssen dieses Skript als Programm sichern und dann eine oder mehrere Dateien oder Ordner darauf ziehen, damit dieser Handler ausgelöst wird. Ein Applet (Programm) mit einem open-Handler bezeichnet man als »Droplet«. Ein Droplet ist im Finder an seinem Icon zu erkennen. Die Schriftrolle des AppleScript-Symbols trägt dort zur Verdeutlichung noch einen Pfeil. So können Sie schon im Finder erkennen, dass man auf dieses Icon Dateien oder Ordner ziehen kann.
380
Die Sprache
Kapitel 4
Abb. 4-17 Das Icon eines Droplets reagiert auf Dateien oder Ordner, die man darauf fallen lässt. Wenn solch ein Droplet keinen expliziten run-Handler enthält (oder keine Anweisungen außerhalb eines Handlers), dann wird es bei einem Doppelklick zwar gestartet, beendet sich aber sofort wieder, da keine Befehle im run-Handler vorliegen. Normalerweise gibt man einem Droplet daher noch alternative Befehle für den Fall mit, dass es zum Beispiel aus dem Dock oder per Doppelklick gestartet wird. Hier bieten sich etwa die Befehle choose file oder choose folder aus den Standarderweiterungen an. Dadurch wird der Anwender dann beim Start aufgefordert, Dateien oder Ordner auszuwählen, die das Droplet verarbeiten soll. Ein solches Droplet lässt sich also auch wie ein Programm verwenden. Eine ausgereifte Vorlage für solch ein Droplet, welches Ordner und Dateien verarbeiten kann und sich zudem per Doppelklick starten lässt, finden Sie im Folgenden aufgeführt. Beachten Sie die Kommentare im Code und experimentieren Sie ruhig damit herum. (Zur Erinnerung: Sie müssen das Skript nicht abtippen, laden Sie sich die Skripts von der Webseite www. skripteditor.de herunter.)
Vorlage für ein Droplet Folgende Vorlage für ein Droplet reagiert auf run und open gleichermaßen und geht zudem iterativ durch verschachtelte Ordnerstrukturen durch. Zur Abfrage der Eigenschaften einer Datei oder eines Ordners verlasse ich mich dabei auf die System-Events, wie von Apple empfohlen. Die Befehle info for und list folder aus den Standarderweiterungen, die bisher gerne dafür verwendet wurden, sind nunmehr von Apple als »deprecated« (abgelehnt, missbilligt, veraltet) markiert worden und werden damit wohl irgendwann nicht mehr unterstützt. Nachdem über den run- oder open-Handler die Dateien oder Ordner ermittelt wurden, wird der Handler distributeItems aufgerufen. Dieser macht nichts anderes, als zu schauen, ob es sich bei den Listenelementen, die von dem open- oder run-Handler kommen, um eine Datei oder einen Ordner handelt, und verteilt diese dann entsprechend auf die Handler – auf processFile, wenn es eine Datei ist und auf processFolder, wenn es ein Ordner ist.
381
SmartBooks
AppleScript
Im Handler processFolder wird ermittelt, welche sichtbaren Elemente im Ordner liegen, und das Ergebnis an distributeItems zurückgeliefert, welcher dann wiederum erneut mit der Verteilung für diesen Ordner beginnt. Das Skript ist also rekursiv und geht damit in unbekannte Tiefen oder bis der Speicher, der »Stack«, überläuft. Zum Testen immer kleinere Ordner oder Dateimengen verwenden! global resultList -- Ergebnisliste global overallCount -- Dateizähler on run -- Normaler Start set {overallCount, resultList} to {0, {}} -- Mehrfachauswahl von Ordnern mit Befehlstaste ist erlaubt set listItems to ¬ choose folder with multiple selections allowed distributeItems(listItems) -- weiter mit Verteiler viewResult() -- Ergebnisse anzeigen end run on open listItems -- Start über Drag und Drop set {overallCount, resultList} to {0, {}} distributeItems(listItems) -- weiter mit Verteiler viewResult() -- Ergebnisse anzeigen end open on distributeItems(pathList) -- Ordner und Dateien verteilen tell application "System Events" repeat with i in pathList if class of disk item (POSIX path of i) is folder then my processFolder(i) -- wenn Ordner else my processFile(i) -- wenn kein Ordner end if end repeat end tell end distributeItems on processFolder(aFolder) -- Anweisungen an Ordner tell application "System Events" -- Alle sichtbaren Elemente im Ordner ermitteln: set allItems to disk items of aFolder whose visible is true my distributeItems(allItems) -- Inhalt zurück an Verteiler end tell
382
Die Sprache
Kapitel 4
end processFolder on processFile(someFile) -- Anweisungen an Dateien tell application "System Events" -- Beispiel: Die Eigenschaft "POSIX path" abfragen: set end of resultList to POSIX path of someFile -- oder den Namen durchnummerieren zum Beispiel mit: -- set name of someFile to (overallCount as text) & "_" & (name of someFile) end tell set overallCount to overallCount + 1 -- Dateizähler hochsetzen end processFile on viewResult() -- Ergebnisse anzeigen tell application "TextEdit" activate make new document set AppleScript's text item delimiters to return set text of document 1 to (resultList as text) ¬ & return & "Anzahl Dateien: " & overallCount end tell end viewResult on quit -- Aufräumarbeiten vor Beendigung set AppleScript's text item delimiters to "" continue quit end quit Als Anregung empfiehlt es sich, auch die Droplet-Templates von Apple unter http://www.apple.com/applescript/resources.html zu studieren. Diese arbeiten jedoch noch mit den als »veraltet« markierten Befehlen info for und list folder aus den Standarderweiterungen, sind also nicht sehr aktuell.
Der reopen-Handler Ein weiterer Handler, den es schon seit Urzeiten gibt, welcher aber selten Verwendung findet, ist der Handler reopen. Dieser Handler wird nur ausgelöst, wenn das Programm erneut gestartet wird, obwohl es schon läuft. Das heißt, nur wenn Sie auf das Dock-Icon des Applets klicken oder es mit einem Doppelklick im Finder erneut öffnen, wird dieser Handler ausgelöst. Nur das Wechseln des Programms löst diesen Handler nicht aus. Das bedeutet aber auch, dass dieser Handler in der Regel nur bei Applets vorkommt, die offen bleiben, also mit der Option Nicht automatisch beenden gespeichert wurden.
383
SmartBooks
AppleScript
Speichern Sie folgendes Beispiel mit dieser Option und starten Sie es dann per Doppelklick. Beenden Sie das Applet nicht, sondern doppelklicken Sie es erneut, und Sie werden sehen, wie die Anweisung im reopen-Handler ausgeführt wird. Hier nur die Ansage, dass reopen läuft. Ziehen Sie das Applet ins Dock und starten Sie es. Auch wenn Sie nun im Dock erneut auf das Applet klicken, ertönt der Hinweis aus dem reopen-Handler. on run say "I'm running" end run on reopen say "reopen is running" end reopen Wenn Sie eine Verwendung für dieses Verhalten haben, dann nehmen Sie diesen Handler, ansonsten merken Sie sich nur, dass es so etwas gibt.
Applets sind skriptbar Ein als Programm abgespeichertes Skript ist selbst wiederum von einem anderen Skript steuerbar, damit quasi selbst »skriptfähig«, und zwar in Bezug auf die Handler, die es enthält. Wenn Sie darauf geachtet haben, beim Entwurf des Skripts alle Tätigkeiten sinnvoll auf Handler zu verteilen, dann können Sie diese Handler in einem als Applet gesicherten Skript auch von einem anderen Skript aus aufrufen. Sinnvoll ist das vor allem, wenn die Applets geöffnet bleiben, um genau auf diese Anfragen zu warten. Die Speicherung mit der Option Nicht automatisch beenden ist also Pflicht. Hier ein Beispiel eines Applets mit mehreren Handlern. Speichern Sie es als Programm mit der Option Nicht automatisch beenden und nennen Sie es callme.app. on run say "I'm running" end run on beepMe(x) beep x end beepMe on greet(someOne) say "Hello " & someOne end greet on mailMe(someSubject) 384
Die Sprache
Kapitel 4
tell application "Mail" activate set myMessage to make new outgoing message ¬ with properties {subject:someSubject, content:"Blah …"} tell myMessage make new to recipient at end of to recipients with properties ¬ {name:"Test", address:"[email protected]"} set sender to "IhrName <[email protected]>" set visible to true end tell -- set sendResult to send myMessage return myMessage end tell end mailMe on quit say "Goodbye" continue quit end quit Starten Sie das obige Skript, und während es geöffnet ist, schicken Sie dem Applet in einem neuen Skript im geöffneten Skripteditor einfach den Befehl, einen seiner Handler auszuführen. Da das Applet ein Programm wie jedes andere ist, wird das genauso gemacht, als wenn Sie zum Beispiel TextEdit einen Befehl senden würden. Probieren Sie dafür einfach einmal folgende Zeilen, eine nach der anderen, aus: tell application "callme" to run beepMe(5) of application "callme" application "callme"'s greet("John") tell application "callme" mailMe("Wichtige Informationen!") quit end tell Sie sehen, selbst der run- und der quit-Handler lassen sich von außerhalb erreichen. Außerdem sind oben die unterschiedlichen Möglichkeiten aufgelistet, wie man den Befehl an das Programm formulieren kann. Doch was macht man, wenn das Applet noch gar nicht läuft? Ganz einfach, wenn Sie einen Befehl an das Applet senden, obwohl es noch nicht gestartet ist, wird es beim ersten Aufruf automatisch gestartet. Einfach auszuprobieren, wenn Sie
385
SmartBooks
AppleScript
obigem Skript zuerst den quit-Befehl und danach einen anderen geben. Das Skript wird für den Befehl wieder neu gestartet. Der Nachteil dabei ist allerdings, dass dann immer zuerst der run-Handler ausgeführt wird, selbst wenn man einen ganz anderen Handler aufgerufen hat. Wenn Sie das nicht wollen, müssen Sie das Applet mit dem Befehl launch starten und dann erst den gewünschten Handler aufrufen: tell application "callme" to launch tell application "callme" to beepMe(3) Der run-Handler wird nun nicht mehr ausgeführt. Der Befehl launch startet ein Programm, ohne irgendeinen Handler auszuführen. Wenn der Handler einen Rückgabewert erbringt, wie zum Beispiel der Handler mailMe, dann können Sie diesen natürlich auch beim Aufruf einer Variablen zuweisen: tell application "callme" set myMessage to mailMe("Wichtige Informationen!") end tell -- Ergebnis: outgoing message id 176780128 of application "callme" Sie sehen hier, dass die neue E-Mail-Nachricht von callme stammt und nicht mehr vom Programm Mail. Sie können sich also mit diesem Rückgabewert nicht mehr direkt an Mail wenden – an callme vorbei, da Mail dieses Objekt nicht mehr kennt. Wenden Sie sich dann auch weiterhin an callme und hoffen Sie, dass dieses Applet noch mehr Methoden bereitstellt, um mit E-Mail-Nachrichten umzugehen. Wenn Sie die Standardwertetypen von AppleScript zurückliefern, gibt es aber keine Probleme. Lassen Sie sich daher besser immer nur eine id oder den Namen eines Objekts zurückliefern und nicht direkt das Objekt. return id of myMessage -- Ergebnis: 176780128 Obige Zeile zur Definition des Rückgabewertes am Ende des Handlers mailMe erledigt das schnell und unproblematisch. Danach können Sie mit outgoing message id integer darauf zugreifen. Auch Fehler, die in callme auftreten, werden an das aufrufende Skript weitergeleitet. Ein in ein try gepackter Aufruf fängt damit auch Fehler ab, die in dem entfernten Handler des Programms auftreten.
386
Die Sprache
Kapitel 4
Ordneraktionen Mit Ordneraktionen können Sie ein AppleScript an einen Ordner »binden«. Das Skript kann dadurch auf bestimmte Ereignisse im oder am Ordner reagieren. Es wird also bei einer Aktion im oder am Ordner ausgelöst. Für jede der möglichen Aktionen gibt es einen eigenen Handler, der genau für dieses eine Ereignis zuständig ist. Sie lösen diese Aktion also nicht selber aus, sondern der Handler im Skript startet automatisch ohne Ihr Zutun, wenn der Ordner beispielsweise geöffnet wird. Für diese Ordneraktionen gibt es ein eigenes kleines Hilfsprogramm, das zu Anfang des Buches bereits kurz vorgestellt wurde. Hier ist nun der Zeitpunkt gekommen, auf dieses Hilfsmittel näher einzugehen: 1. Öffnen Sie das Hilfsprogramm, indem Sie irgendwo im Finder das Kontextmenü aufrufen, zum Beispiel mit einem Rechtsklick auf dem Schreibtisch. Wählen Sie dort zuerst den Eintrag Mehr und dann Ordneraktionen konfigurieren. Alternativ können Sie das Programm auch unter /Programme/AppleScript/ im Finder aufsuchen und dort doppelklicken. 2. Kreuzen Sie in dem Hilfsprogramm den Punkt Ordneraktionen aktivieren an. 3. Legen Sie sich dann einen Testordner auf dem Schreibtisch an. 4. Wählen Sie diesen Ordner in Ordneraktionen konfigurieren unten links durch Klick auf das Pluszeichen aus. 5. Ein Dialog erscheint, in welchem Sie aufgefordert werden, ein Skript auszuwählen. Klicken Sie erst einmal auf Abbrechen. Die Skripts, die hier zur Wahl aufgelistet werden, liegen übrigens in den diversen LibraryOrdnern unter /Scripts/Folder Action Scripts/. Schauen Sie sich die Beispiele später einmal in Ruhe an. Auch Ihre Ordneraktions-Skripts müssen Sie dort ablegen, damit sie im Hilfsprogramm zur Verfügung stehen. Der Dialog sieht dann erst mal so aus wie in der folgenden Abbildung:
387
SmartBooks
AppleScript
Abb. 4-18 Ein Ordner wurde als Kandidat für Ordneraktionen hinzugefügt. Nachdem Sie einen Ordner ausgewählt haben, fehlt nur noch das Skript, welches nach Erstellung unten im Fenster über das rechte Pluszeichen dem Ordner zugewiesen werden kann. Dabei ist es auch durchaus möglich, einem Ordner mehrere Skripts zuzuweisen. Power User Die Bindung eines Skripts an einen Ordner wird von dem bereits bekannten Programm ohne Benutzeroberfläche, von den System-Events übernommen. Dabei ist dieser Vorgang selbst wiederum skriptbar. Die nötigen Befehle dafür finden Sie im Funktionsverzeichnis der System-Events in der Folder Actions Suite. Wenn Sie diese Bindung selber skripten wollen, statt das Hilfsprogramm Ordneraktionen konfigurieren zu verwenden, dann schauen Sie sich die Beispiele dazu unter Folder Actions im Skriptmenü an. Das Programm Ordneraktionen konfigurieren stellt aber in jedem Fall den einfacheren Weg dar. Ein Skript, welches für die Ordneraktionen eines Ordners herhalten soll, benötigt ganz bestimmte Handler. Jeder dieser Handler reagiert auf ein ganz bestimmtes Ereignis des Ordners und keiner liefert einen Wert zurück. Des Weiteren gibt es beim Auftreten von Fehlern keine Fehlermeldungen! Wenn also gar nichts passiert, ist sehr wahrscheinlich ein Fehler aufgetreten. Es ist daher unbedingt erforderlich, die Einzelbausteine für ein Ordnerskript vorher allein für sich außerhalb eines Ordnerskript-Handlers auszuprobieren. Im Einzelnen sind es folgende Ereignisse, auf die ein Skript reagieren kann – in Klammern stehen die entsprechenden Handler-Namen: << Den Ordner im Fenster öffnen (opening folder) << Das Fenster des Ordners schließen (closing folder window for) 388
Die Sprache
Kapitel 4
<< Bewegen oder Verändern des Ordnerfensters (moving folder window for) << Elemente dem Ordner hinzufügen (adding folder items to) << Elemente aus dem Ordner entfernen (removing folder items from)
opening folder Wenn Sie auf das Öffnen eines Ordners in einem Fenster reagieren wollen, dann brauchen Sie den opening folder-Handler. Beachten Sie die Wortwahl! Der Ordner muss in einem Fenster geöffnet werden, also nicht im Terminal oder auf einem anderen Weg. Sie müssen also in der Regel direkt oder indirekt über den Finder gehen. Dieser Handler wird auch nicht ausgelöst, wenn der Ordner in Listenansicht aufgeklappt wird oder wenn Sie den Ordner in Spaltenansicht auswählen. Der Ordner muss per Doppelklick in einem eigenen Fenster geöffnet werden. Ein opening folder-Handler besitzt einen einzelnen Parameter, welcher immer angegeben werden muss: on opening folder thisFolder display dialog "Achtung, dieser Ordner ist gefährlich!" ¬ buttons "OK" default button 1 with icon caution end opening folder 6. Speichern Sie dieses Skript als ganz normales Skript, also nicht als Programm, im Library-Ordner Ihres Heimverzeichnisses unter Scripts/Folder Action Scripts/. Wenn der Ordner Folder Action Scripts dort noch nicht existiert, so erzeugen Sie ihn und legen Sie das Ordnerskript dort ab. Das Skript zu einer Ordneraktion wird also nicht im oder am Ordner selbst gespeichert, sondern muss immer an diesem speziellen Platz in der Library liegen. 7. Nun können Sie wieder das Hilfsprogramm Ordneraktionen konfigurieren öffnen oder nach vorne holen. 8. Wählen Sie dort zuerst links Ihren Testordner aus und klicken Sie dann unten auf das rechte Pluszeichen. 9. Wählen Sie in der Liste Ihr Ordnerskript aus und bestätigen Sie die Auswahl. Damit haben Sie Ihrem Testordner nun ein Skript zugewiesen. Da dieses Skript nur einen einzigen Handler besitzt, der auf das Öffnen des Testordners reagiert, wird auch nur beim Öffnen des Ordners die Anweisung in dem Handler opening folder ausgeführt. Bei allen anderen Aktionen im und am Ordner passiert nichts.
389
SmartBooks
AppleScript
Abb. 4-19 Ein Skript wurde einem Ordner zugewiesen. 10. Doppelklicken Sie nun ein Mal den Testordner im Finder. Sie erhalten sofort einen Warndialog, dass dieser Ordner gefährlich ist. Das Öffnen des Ordners in einem Fenster hat also die Anweisung in dem Handler ausgelöst. Solange der Ordner geöffnet bleibt, wird der Handler im zugewiesenen Ordnerskript nicht erneut ausgeführt. Sie müssen das Fenster also noch mal öffnen, damit die Anweisung erneut ausgeführt wird.
Abb. 4-20 Das Öffnen des Ordners hat zu einer Warnung geführt - wie beabsichtigt.
390
Die Sprache
Kapitel 4
Der Parameter wurde in obigem Beispiel aber noch gar nicht benutzt. Schauen Sie sich daher zuerst einmal an, was eigentlich beim Aufruf des Handlers dort abgelegt wird. Ändern Sie dafür das Ordnerskript wie folgt ab: on opening folder thisFolder display dialog thisFolder as text end opening folder Im Dialog erhalten Sie nun den Pfad zu dem aktiven Ordner, zum Beispiel: Macintosh HD:Users:Detlef:Desktop:Achtung lebender Ordner!: Power User Genau genommen handelt es sich dabei um ein alias (siehe Die Klasse alias am Ende von Kapitel 4): alias "Macintosh HD:Users:Detlef:Desktop:Achtung lebender Ordner!:" Um es im Dialog anzeigen zu können, muss es daher mit as text in Text umgewandelt werden, wodurch nur der Pfad übrig bleibt. Hier noch ein längeres Beispiel unter Verwendung dieses Parameters. Zum Ausprobieren können Sie übrigens das Skript von vorhin im Programm Ordneraktionen konfigurieren anklicken und mit Klick auf den Knopf Skript bearbeiten erneut öffnen, das alte Skript darin löschen und dann das folgende Skript ohne Änderungen einfügen. Das Beispiel stellt das Fenster, in welchem der Ordner dargestellt wird, auf eine bestimmte Darstellungsform ein und eignet sich gut für Ordner mit Bildern, die man wie in iTunes durchblättern möchte. Da in dem Parameter aber nicht das Fenster, sondern der Ordner steckt, muss man zuerst herausfinden, wie man darüber das Fenster ermitteln und ansprechen kann. Glücklicherweise besitzt ein Ordner eine Eigenschaft namens container window. Darin steckt das Fenster, in welchem der Ordner gerade dargestellt wird. Gibt es mehrere, wird das weiter vorne liegende Fenster genommen:
391
SmartBooks
AppleScript
on opening folder thisFolder tell application "Finder" -- Die nächste Zeile ist zum Testen des Skripts -- außerhalb des Handlers gedacht, Pfad bitte anpassen: -- set thisFolder to alias "Macintosh HD:Users:Detlef:Desktop:Achtung lebender Ordner!:" -- Ermitteln der Bildschirmgröße set maxBounds to bounds of window of desktop -- Platzbedarf der Menüleiste + Fensterleiste set item 2 of maxBounds to 44 --Fenster ermitteln set thisWindow to container window of thisFolder --Fenster einstellen tell thisWindow set toolbar visible to false set statusbar visible to false set current view to flow view set bounds to maxBounds end tell end tell --Dock ausblenden tell application "System Events" set autohide of dock preferences to true end tell end opening folder Hilfe Ich habe Ihnen oben noch eine auskommentierte Testzeile am Anfang des Skripts stehen gelassen, die Ihnen einen Einblick darin gibt, wie man solch einen Handler während der Erstellung testen kann. Man kommentiert Handleranfang und -ende aus und schreibt dann den Ordner als alias in eine Variable. Für diesen Test muss das Fenster des Ordners dann allerdings schon geöffnet sein.
392
Die Sprache
Kapitel 4
Abb. 4-21 Das Fenster wird beim Öffnen des Ordners automatisch auf volle Größe in Cover-Flow-Ansicht eingestellt und das Dock ausgeblendet. Hier noch ein Beispiel dazu, wie Sie Eigenschaften des Ordners beim Öffnen ändern können. Beim Öffnen des Ordners werden der Benutzer und der Zeitpunkt des Öffnens als Spotlight-Kommentar in die Ordnerinformation eingetragen, so dass sich dort eine Art Protokoll ergibt, wann der Ordner von wem das letzte Mal geöffnet wurde. on opening folder thisFolder tell application "Finder" set comment of thisFolder to comment of thisFolder ¬ & short user name of (get system info) ¬ & ": " & (current date) & return end tell end opening folder
393
SmartBooks
AppleScript
Abb. 4-22 Protokollierung des Zugriffs auf den Ordner als Spotlight-Kommentar Hier ist allerdings zu bedenken, dass der Zugriff auf den Ordner über Listen- oder Spaltenansicht nicht registriert wird. Erst wenn der Ordner in einem eigenen Fenster geöffnet wird, wird die Ordneraktion ausgelöst.
closing folder window for Diese Aktion ist das Gegenstück zum Öffnen des Ordners und wird daher meistens in Verbindung mit dieser verwendet. In einem der obigen Beispiele wird Ihnen bestimmt aufgefallen sein, dass dort das automatische Ausblenden des Docks eingeschaltet wurde, damit dieses bei der Bildbetrachtung nicht stört. Jetzt wäre es natürlich sehr sinnvoll, wenn man hier den Ursprungszustand beim Schließen wiederherstellen würde. Für so etwas ist ein closing-Handler hervorragend geeignet. Dafür muss der opening-Handler aus dem vorigen Beispiel zuerst einmal den Zustand des Docks außerhalb des Handlers abspeichern, zum Beispiel in einer globalen Variablen. Dann kann der closing-Handler darauf zugreifen und den Ausgangszustand wiederherstellen. (Globale Variablen werden am Ende von Kapitel 4 beschrieben.)
394
Die Sprache
Kapitel 4
global dockHide on opening folder thisFolder tell application "Finder" -- Ermitteln der Bildschirmgröße set maxBounds to bounds of window of desktop -- Platzbedarf der Menüleiste + Fensterleiste set item 2 of maxBounds to 44 --Fenster ermitteln set thisWindow to container window of thisFolder --Fenster einstellen tell thisWindow set toolbar visible to false set statusbar visible to false set current view to flow view set bounds to maxBounds end tell end tell --Dock ausblenden tell application "System Events" set dockHide to autohide of dock preferences set autohide of dock preferences to true end tell end opening folder on closing folder window for thisFolder tell application "System Events" to ¬ set autohide of dock preferences to dockHide end closing folder window for Der kleine Handler am Schluss macht also nichts anderes, als den Ausgangszustand des Docks wiederherzustellen. Der Handler wird dabei ausgelöst, wenn das Fenster direkt geschlossen oder wenn durch das Wechseln einer Ansicht ein anderer Ordner im Fenster dargestellt wird. Natürlich können Sie diesen Handler auch für andere Aktionen verwenden. Der Parameter enthält wieder ein alias mit dem Pfad zum Ordner, so dass Sie zum Beispiel das Protokoll-Beispiel von eben auch beim Schließen des Ordners anwenden können.
395
SmartBooks
AppleScript
Auf das Fenster selbst können Sie in diesem Handler nicht mehr zugreifen, es existiert nach dem Schließen nicht mehr.
moving folder window for Mit diesem Handler können Sie auf Bewegungen des Fensters reagieren, in dem der Ordnerinhalt dargestellt wird. In folgendem Handler kommt eine Ansage, dass man das Fenster in Ruhe lassen soll, und dann wird die Position des Fensters vor und nach dem Bewegen angezeigt. on moving folder window for thisFolder from oldPos say "Hey, leave me alone!" set my text item delimiters to ", " display dialog "Bounds of last position: " & oldPos as text tell application "Finder" set newPos to bounds of container window of thisFolder end tell display dialog "Bounds of new position: " & newPos as text set my text item delimiters to "" end moving folder window for Das Besondere an diesem Handler ist, dass er zwei Parameter besitzt, die oben als thisFolder und oldPos angegeben wurden. Der Parameter nach dem for enthält wieder ein alias auf den Ordner. Der Parameter nach dem from enthält eine Liste mit vier Integerwerten, zum Beispiel {50, 100, 500, 800}. Diese Liste stellt die Koordinaten der Fensterposition vor der Veränderung dar. Sie bekommen damit also nicht die aktuelle Position des Fensters heraus, die wird oben im tell an den Finder ermittelt. Alle Werte stellen dabei Pixel dar: << Der erste Wert steht für den Abstand des linken Fensterrands zum linken Rand des Bildschirms. << Der zweite Wert steht für den Abstand des oberen Fensterrands zum oberen Rand des Bildschirms. << Der dritte Wert steht für den Abstand des rechten Fensterrands zum linken Rand des Bildschirms. << Der vierte Wert steht für den Abstand des unteren Fensterrands zum oberen Rand des Bildschirms. Diese Koordinaten dann aber direkt im Skript zu ändern und damit ein Fenster zum Beispiel wieder an seinen ursprünglichen Platz zu schicken, führt zu einem erneuten Ausführen des Handlers und damit zu einer Endlosschleife, da das Fenster ja gerade wieder verschoben wurde, wenn auch per Skriptanweisung.
396
Die Sprache
Kapitel 4
Diese Ordneraktion ist in Leopard als »Not currently available« gekennzeichnet, also als »Zur Zeit nicht verfügbar«, wie es im AppleScript Language Guide heißt. Von daher sollte man diesen Handler zurzeit besser nicht verwenden. Hilfe Wenn Sie bei einem Ordnerskript in eine Endlosschleife geraten, dann entfernen Sie währenddessen im Hilfsprogramm Ordneraktionen konfigurieren den Haken vor dem Skript, um es temporär zu deaktivieren.
adding folder items to Dies ist wohl der wichtigste Handler und meistens der Hauptgrund für die Einrichtung eines aktiven Ordners. Sie tun etwas in den Ordner hinein, und das Ordnerskript fängt sofort an, damit etwas zu machen. Dabei funktioniert das in fast allen möglichen Situationen: auf das Icon des Ordners, in das geöffnete Fenster des Ordners, in Listen-, Spalten- und Cover-Flow-Ansicht und sogar im Dock oder der Seitenleiste eines Finderfensters. Was mit den Dateien oder Ordnern darin gemacht wird, liegt dann ganz bei Ihnen. Jedenfalls sind auch komplexe Arbeitsabläufe durch solch einen Ordner auslösbar, zum Beispiel kann man Bilder in den Ordner hineinlegen, welche dann in einer Bildbearbeitung geöffnet und verarbeitet werden. Wenn das Bild dort fertig bearbeitet ist, wird es als Nächstes in einem Layout platziert und/oder auf dem Webserver abgelegt. Dieser Handler hat zwei Parameter, einmal das alias des aktiven Ordners nach dem Schlüsselwort to und einmal eine Liste der in den Ordner gelegten Objekte nach after receiving. Auch die Objekte in der Liste liegen als alias vor. Damit läst sich wunderbar eine Schleife über diese Liste anlegen, und die Objekte können direkt angesprochen werden. on adding folder items to thisFolder after receiving thisItems tell application "Finder" repeat with anItem in thisItems -- Mach was mit der Datei oder dem Ordner: set label index of anItem to 2 -- Weitere Befehle end repeat end tell end adding folder items to Obige Ordneraktion gibt jedem Objekt, das man hineinlegt, einfach nur das Etikett mit dem Index 2. Fortan sind diese Objekte also im Finder eingefärbt.
397
SmartBooks
AppleScript
Wenn man schon dabei ist, will man aber von den Dateien vor der Bearbeitung sicher noch eine Sicherungskopie anlegen und Ordner iterativ durchgehen. Für die Iteration können Sie zum Beispiel die Grundstruktur wie bei der Iteration im Droplet übernehmen, für die Sicherung erstellt man aus Gründen der Übersicht am besten einen eigenen Handler. Hier ein ausgereiftes Beispiel, welches Bilder, die man hineinlegt, mit den Image Events von Apple bearbeitet. Leider sind diese seit Leopard jedoch recht unzuverlässig. Sie funktionieren manchmal, manchmal nicht. Trotzdem füge ich das Beispiel bei, in der Hoffnung, dass diese bald wieder repariert sind. Wenn es bei Ihnen ebenfalls nicht zuverlässig funktioniert, dann tauschen Sie den Inhalt des Handlers onProcessFile bitte aus. Sie können die Dateien auch mit einem skriptbaren Bildbearbeitungsprogramm wie zum Beispiel dem GraphicConverter verarbeiten. Tipp Die Image Events sind, wie die System Events, eine Anwendung ohne grafische Benutzerschnittstelle. Sie beruhen auf sips (scriptable image processing system), einer Grafikbibliothek der Unix-Shell. Man kann sie daher auch mit einem do shell script von einem Appleskript aus aufrufen, aber die Image-Events sind als Schnittstelle viel intuitiver in der Anwendung. Für weitere Informationen man sips im Terminal eingeben. Sie finden die Image-Events im Ordner /System/Library/CoreServices/. Ein Blick in deren Funktionsverzeichnis lohnt sich. Beachten Sie zum Programm Image Events auch die Beispiele von Apple unter http://www.apple.com/applescript/imageevents/. global backupIn global errorList global successList on adding folder items to thisFolder after receiving thisItems set errorList to {} set successList to {} tell application "Finder" if not (exists folder "Archives") in desktop then set backupIn to make new folder at desktop ¬ with properties {name:"Archives"} else set backupIn to folder "Archives" in desktop end if end tell my archiveOriginals(thisItems) my distributeItems(thisItems) my viewLog()
398
Die Sprache
Kapitel 4
end adding folder items to on archiveOriginals(thisItems) -- Sicherung anlegen tell application "Finder" repeat with anItem in thisItems duplicate anItem to backupIn replacing yes end repeat end tell end archiveOriginals on distributeItems(thisItems) -- Ordner und Dateien verteilen tell application "System Events" repeat with i in thisItems if class of disk item (POSIX path of i) is folder then my processFolder(i) -- wenn Ordner else my processFile(i) -- wenn kein Ordner end if end repeat end tell end distributeItems on processFolder(aFolder) -- Anweisungen an Ordner tell application "System Events" -- Alle sichtbaren Elemente im Ordner ermitteln: set allItems to disk items of aFolder whose visible is true my distributeItems(allItems) -- Inhalt zurück an Verteiler end tell end processFolder on processFile(myImage) -- Anweisungen an Dateien tell application "Image Events" if file type of myImage is "JPEG" then set end of successList to POSIX path of myImage -- Öffnen set modImage to open myImage -- Bearbeiten scale modImage by factor 0.5 set someAngle to random number from -25 to 25 rotate modImage to angle someAngle -- Sichern save modImage as JPEG with icon
399
SmartBooks
AppleScript
close modImage else set end of errorList to POSIX path of myImage end if end tell end processFile on viewLog() tell application "TextEdit" make new document set AppleScript's text item delimiters to return set text of document 1 to ¬ "Nicht verarbeitet: " & return & (errorList as text) & return ¬ & return & "Verarbeitet: " & return & (successList as text) end tell end viewLog Wenn Sie einen Ordner mit diesem Skript versehen haben und die Ordneraktionen eingeschaltet sind, dann ziehen Sie ein paar Bilder im Format JPEG auf den Ordner. Die Bilder werden vor der Bearbeitung in den Ordner Archives auf dem Schreibtisch gesichert. Wenn der Ordner noch nicht existiert, wird er angelegt. Die Bilder im aktiven Ordner werden dann mit dem Faktor 0,5 skaliert und um einen Zufallswert zwischen -25 und +25 Grad gedreht. Zum Schluss wird in TextEdit ein Protokoll angezeigt, in welchem genau steht, welche Bilder verarbeitet wurden und welche nicht (zum Beispiel weil sie nicht als JPEG vorlagen oder wegen anderer Probleme).
Abb. 4-23 Die Bilder im aktiven Ordner sind skaliert und gedreht worden.
400
Die Sprache
Kapitel 4
removing folder items from Mit diesem Handler können Sie überwachen, ob etwas aus einem Ordner entfernt wurde. Diese Aktion eignet sich damit besonders gut für Ordner, deren Integrität gewahrt bleiben muss. Für den Fall, dass irgendjemand eine Datei aus dem Ordner entfernt oder löscht, kann ein Ordnerskript mit diesem Handler zum Beispiel dafür sorgen, dass diese wieder zurückgeschoben wird oder von einer anderen, möglichst gut versteckten Stelle (zum Beispiel aus der Library unter Application Support) die Originaldatei zurück kopiert wird. Auch dieser Handler hat wieder zwei Parameter, einmal für den überwachten Ordner selbst und einmal für eine Liste mit den aus dem Ordner entfernten Dateien. Die Objekte in beiden Parametern liegen wieder in Form eines alias vor, man kann also direkt mit dem Finder damit agieren. Der zweite Parameter ist immer eine Liste, auch wenn nur ein Item entfernt wurde. Wurden die Dateien komplett gelöscht, also auch der Mülleimer entleert, so kann von der Ordneraktion kein Pfad mehr zurückgeliefert werden, sondern nur der Name der ehemaligen Datei. Der Name liegt in Textform vor. Aus diesem Grund muss für diesen zweiten Parameter berücksichtigt werden, dass man mal einen Pfad, mal einen Text bekommt. Im folgenden Beispiel wird das durch Abfrage der Klasse in einem if-Block erledigt. Der spezielle Fall, dass nur der Name der Datei noch bekannt ist, folgt zuerst. Dort wird dann mit einem duplicate-Befehl die Datei gleichen Namens aus dem Backup-Ordner zurückkopiert. Der Backup-Ordner ist hier durch den Pfad in der Variablen secretFolder definiert. Liegt jedoch kein Text vor, sondern ein Alias, dann wird im else-Teil die herausbewegte Datei einfach mit einem move-Befehl zurück geschoben. Das kann dann ganz lustig sein, wenn die Datei, die man gerade herausgezogen hat, plötzlich wieder zurückhüpft, vor allem, wenn man nicht darüber informiert ist, das der Ordner eine Ordneraktion besitzt. Überwacht werden dabei nur die Dateien, von denen eine Kopie in dem Ordner secretFolder liegt. Andere Dateien können also ohne Folgen entfernt werden.
401
SmartBooks
AppleScript
on removing folder items from thisFolder after losing someItems tell application "Finder" set secretFolder to folder ¬ "Folder Actions Backup" of folder ¬ "Application Support" of folder "Library" of home set filePaths to files in secretFolder set fileNames to name of files in secretFolder repeat with anItem in someItems set i to 1 if class of anItem is text then -- Datei total gelöscht repeat with someName in fileNames if someName as text = anItem as text then duplicate (item i of filePaths) to thisFolder exit repeat end if set i to i + 1 end repeat else -- Datei nur verschoben move anItem to thisFolder end if end repeat end tell display dialog "Dieser Ordner darf nicht verändert werden!" ¬ buttons "OK" end removing folder items from Da Ordneraktionen mit niedriger Priorität laufen, erfolgt die Reaktion nicht immer augenblicklich. Wenn ein Ordner auf mehrere Aktionen reagieren soll, können Sie für jeden Handler ein eigenes Skript schreiben und dann alle Skripts dem Ordner zuweisen. Das hat den Vorteil, dass Sie dann einzelne Aktionen im Programm Ordneraktionen konfigurieren gezielt abschalten können. Wenn die einzelnen Handler jedoch Informationen austauschen müssen, zum Beispiel über Propertys oder globale Variablen, ist es besser, alle Handler in ein einziges Skript zu packen.
402
Die Sprache
Kapitel 4
Skriptobjekte An mehreren Stellen im Buch ist bereits erwähnt worden, dass ein Skript ebenfalls ein Objekt ist, wie jeder andere Wertetyp auch, seien es Zahlen, Zeiten, Listen, Text oder Handler. Wenn Sie in einem leeren Skript einfach das Wörtchen me schreiben und es ausführen, erhalten Sie «script» als Antwort. Fragen Sie mit class of me nach der Klasse, erhalten Sie script zur Antwort. Das Skript selbst kennt und versteht sich als Objekt der Klasse script und kann Ihnen sogar mit Hilfe der Wörter me oder my Auskunft über sich selbst geben. Der Begriff »Objekt« ist dabei nur ein anderer Name für den Begriff Klasse, wie er im Funktionsverzeichnis verwendet wird. Eine Klasse oder ein Objekt kann wiederum andere Klassen mit anderen Eigenschaften als Elemente enthalten. Im Funktionsverzeichnis einer Anwendung begegnen Sie dem Begriff »Elemente« daher ständig. Im Folgenden dreht sich alles um das Skript als Objekt. Wenn von einem Skript gesprochen wird, dann ist damit immer das im Skripteditor geöffnete Skript gemeint. Ist explizit von einem Skriptobjekt die Rede, dann ist damit ein im Skript definiertes Skriptobjekt gemeint.
Bestandteile eines Skriptobjekts Wann immer Sie im Skripteditor an einem Skript arbeiten, haben Sie bereits ein Skriptobjekt vor sich. Man nennt dies auch das implizite Skriptobjekt, da es nicht extra definiert werden muss. Dieses »Skriptobjekt«, welches ich wie bisher einfach als »Skript« bezeichnet habe, liegt als Datei auf der Festplatte vor, sobald Sie es im Skripteditor gesichert haben. Wie jede Klasse hat auch die Klasse script Eigenschaften. Manche dieser Eigenschaften werden von AppleScript und eventuell auch von einem anderen Skriptobjekt geerbt, andere können von Ihnen selbst bestimmt werden. Darüber hinaus kann ein Skriptobjekt aber, wie eine Liste oder ein record, auch Elemente anderer Klassen enthalten. Die Bestandteile eines Skriptobjekts lassen sich daher in Eigenschaften, Handler und Elemente unterteilen. Bis auf geerbte Bestandteile und den run-Handler sind alle Bestandteile optional: << geerbte Eigenschaften << mit property selbst definierte Eigenschaften << der implizit oder explizit definierte run-Handler 403
SmartBooks
AppleScript
<< weitere Handler << weitere Skriptobjekte Von einem grundlegenden Standpunkt aus betrachtet, kann man auch sagen, dass ein Skript nur aus zwei Bestandteilen besteht: aus Daten (Propertys, weitere Skriptobjekte) und aus Befehlen (Handlern), die darauf agieren.
Die Eigenschaften eines Skriptobjekts Ein Skript bringt bereits jede Menge Eigenschaften mit sich, die Sie in jedem Skript abfragen können. Diese Eigenschaften eines Skriptobjekts kann man nur im Script Debugger von Late Night Software sichtbar machen, aber nötig ist das eigentlich nicht, denn Sie kennen diese Eigenschaften größtenteils bereits, sie werden von Apple meist als Konstanten bezeichnet, obwohl es sich dabei eher um Eigenschaften handelt. Alle Konstanten, die AppleScript mit sich bringt, sind durch Vererbung auch Eigenschaften eines Skripts. Dabei handelt es sich im Einzelnen um die folgenden Eigenschaften der Klassen script und application: (Im Kommentar steht der Standardwert und eventuell ein »r/o«, wenn die Eigenschaft nicht veränderbar ist.) pi text item delimiters return space tab linefeed quote weeks days hours minutes result missing value true false version class it 404
-------------------
3.14159265359 "" "\r" "" "\t" "\n" "\"" 604800 86400 3600 60 60 (das Ergebnis der letzten Aktion) missing value (r/o) true (r/o) false (r/o) "2.0.1" (Version von AppleScript) script «script» (Ziel-Bezug) (r/o)
Die Sprache
me name parent AppleScript current application
Kapitel 4
------
«script» (Selbst-Bezug) (r/o) "Script Editor" «script AppleScript» «script AppleScript» current application (r/o)
Die Klasse script selbst hat dabei nur die Eigenschaften name und parent definiert, alle anderen Bestandteile in dieser Liste sind Eigenschaften der Klasse application, die über current application von einem Skriptobjekt geerbt werden. Alle diese Eigenschaften können Sie daher jederzeit nutzen, ohne deswegen ein tell an das Skript zu richten. me --«script» AppleScript --«script AppleScript» my version -- 2.0.1 AppleScript's minutes -- 60 quote of me -- "\"" In der ersten Zeile sehen Sie, dass me (oder my) tatsächlich das Skript als Objekt darstellt. Darunter sehen Sie, dass sich die Konstante AppleScript auf das Skriptobjekt "AppleScript" bezieht. Das Skript AppleScript steht über Ihrem Skript und ist sozusagen die Mutter aller Skriptobjekte, die von Ihnen erstellt werden. Danach folgen drei Zeilen mit Beispielen für Abfragen. Allen diesen drei Zeilen ist gemeinsam, dass es egal ist, ob Sie me, my oder AppleScript's verwenden, diese Begriffe können untereinander ausgetauscht werden oder sogar wegfallen. Selbst wenn in einem tell ein anderes Ziel vorliegt, ist es meist nicht nötig, die Zugehörigkeit dieser Konstanten und Eigenschaften zu spezifizieren. Ausnahmen, die in diesem Buch bisher besprochen wurden, sind die text item delimiters und der Aufruf von Handlern in tell-Blöcken. Da diese Eigenschaften in Ihrem Skript meist nicht abgeändert werden, wird ein Befehl an diese direkt an AppleScript durchgereicht. Ihr Skript hat diese Eigenschaften von AppleScript geerbt, braucht sie also nicht noch einmal zu definieren. Wenn Sie sie aber in Ihrem Skript umdefinieren (soweit das möglich ist), kümmert sich Ihr Skript selbst darum. Von alldem bekommen Sie aber in der Regel nichts mit. Über «script» steht also «script AppleScript» und darüber steht nur noch current application. Das ist die Anwendung, aus der das Skript gestartet wird. Wenn Sie im Skripteditor arbeiten, ist das der Skripteditor. Wenn das Skript aus einem Programm wie zum Beispiel RagTime heraus läuft, ist es RagTime. Wenn das Skript als Programm gespeichert wurde und gestartet wird, ist es das Applet selbst und damit sozusagen sein eigener Herr.
405
SmartBooks
AppleScript
Darüber hinaus kann ein Skript auch noch Elemente und Eigenschaften eines anderen Skripts erben, dazu mehr unter Vererbung und Delegation. Mehrere Skriptobjekte, die sich in einem als Datei abgespeicherten Skript oder Applet befinden, teilen sich die Eigenschaften und Konstanten von AppleScript. Ändern Sie zum Beispiel die text item delimiters in einem Skriptobjekt, dann gilt das auch für alle anderen Skriptobjekte in dieser Datei. Wenn Sie hier eine Trennung benötigen, müssen Sie die Skriptobjekte auf mehrere als Applet (Programm) abgespeicherte Dateien auslagern. Die Skripts können dann durch das Senden von Befehlen miteinander kommunizieren. Siehe hierzu auch Applets sind skriptbar im Kapitel Handler. Jedes als Programm laufende Appleskript hat seine eigene Laufzeitumgebung. Mehrere im Format Skript abgespeicherte Dateien teilen sich hingegen die Laufzeitumgebung, da sie alle aus einer einzelnen Anwendung wie dem Skripteditor heraus gestartet werden, welcher dieselbe Laufzeitumgebung für alle zur Verfügung stellt. Wenn man jedoch ein Skript aus dem Skripteditor heraus startet und ein anderes aus einem anderen Programm wie zum Beispiel dem Script Debugger, dann haben beide Skripts getrennte Umgebungen und kommen sich gegenseitig nicht ins Gehege.
Variablen und Handler als Elemente eines Skriptobjekts Jeder Bezeichner in Ihrem Skript ist ein Element des Skripts, egal, ob es sich dabei um Variablen, Handler oder weitere Skriptobjekte handelt. Wie auf die Eigenschaften eines Skripts, so können Sie auch auf seine Elemente gezielt mit my zugreifen, und müssen es teilweise sogar, wie bei einem Handler, der in einem tell-Block an eine Anwendung steht. Hier ein Beispiel mit iTunes, das alle Titel der aktuellen playlist in eine Liste packt und zum Schluss in TextEdit platziert. In fetter Schrift die hier erforderlichen my. on run tell application "iTunes" set somePlaylist to current playlist set titleList to my listTitles(somePlaylist) my displayResult(titleList) end tell end run on listTitles(somePlaylist) set titleList to {} tell application "iTunes" set listTracks to tracks of somePlaylist repeat with i in listTracks set end of titleList to name of i -- Versuchen Sie auch "artist of i", "album of i", etc. end repeat end tell 406
Die Sprache
Kapitel 4
return titleList end listTitles on displayResult(titleList) set text item delimiters to return tell application "TextEdit" activate make new document set text of document 1 to titleList as text end tell set text item delimiters to "" end displayResult Auch auf Variablen können Sie auf diese Weise zugreifen, nur macht man das normalerweise natürlich nicht, da jede Verwendung eines Bezeichners ohne eine Angabe der Objektzugehörigkeit automatisch als zum Skript gehörig betrachtet wird. Es ist aber nicht verkehrt, die Objektzugehörigkeit explizit mit anzugeben: set a to "Ich bin hier!" my a -- Ergebnis "Ich bin hier!" Wie später noch zu sehen sein wird, bezieht sich die Adressierung mit my immer auf das Skriptobjekt, in welchem es steht.
Selbst definierte Eigenschaften – Propertys Neben den Eigenschaften, die AppleScript bereits mitbringt, können Sie einem Skript auch selbst definierte Eigenschaften mitgeben. Diese Eigenschaften nennt man ebenfalls properties, genauso wie die Propertys eines Records oder die Propertys einer beliebigen Klasse, wie zum Beispiel eines Ordners im Finder.
Definition von Propertys Auf der obersten Ebene eines Skripts können Sie mit dem Schlüsselwort property eine Eigenschaft für das Skript deklarieren: property xColor : "green" display dialog (xColor) Sie können property beim Schreiben auch mit prop abkürzen. Nach dem Übersetzen wird dann automatisch property ergänzt. Nach property folgt der Name der Eigenschaft. Hier gelten wieder die allgemeinen Regeln für Bezeichner, wie im Kapitel Bezeichner zu Anfang von Kapitel 4 dargestellt. In diesem Beispiel heißt die Property xColor. Danach folgen ein Doppelpunkt und der Wert der Property. In diesem Beispiel ist es ein Text. Eine Property kann wie eine Variable jede Klasse beinhalten.
407
SmartBooks
AppleScript
In diesem Beispiel können Sie außerdem sehen, wie Sie anschließend auf diese property im Skript ganz normal zugreifen können wie auch auf eine Variable. Hier wird deren Inhalt mit display dialog angezeigt. Sie können eine Property auch jederzeit verändern: property xColor : "green" set xColor to "red" display dialog (xColor) Sie können beliebig viele Eigenschaften auf diese Weise definieren: property property property property
cColor : "cyan" mColor : "magenta" yColor : "yellow" kColor : "black"
Wenn Sie jedoch sehr viele Propertys definieren wollen, kann es hilfreich sein, einer einzelnen Property einen Record mit allen Werten zu geben: property processColors : {cColor:"cyan", mColor:"magenta", yColor:"yellow", kColor:"black"} get mColor of processColors -- Ergebnis: "magenta" Der Zugriff gestaltet sich dadurch natürlich mit einem weiteren of komplexer, ist deswegen aber nicht unlogisch, wenn die Propertys einen sinnvollen Zusammenhang besitzen wie hier die Prozessfarben des Offsetdrucks. Eine Möglichkeit, mehrere Propertys in einem Rutsch auf einer Zeile zu definieren, wie bei set über Listenzuweisungen, ist bei einer property-Definition nicht möglich. Sie können höchstens nachträglich den Propertys auf diese Weise einen anderen Wert zuweisen: property cColor : "" property mColor : "" property yColor : "" property kColor : "" set {cColor, mColor, yColor, kColor} to {"cyan", "magenta", "yellow", "black"}
Der richtige Platz für Propertys Eine property-Definition muss immer außerhalb eines Handlers geschehen. Sie ist also niemals Bestandteil eines Handlers und damit auch nicht Teil des impliziten run-Handlers, was Sie leicht ausprobieren können, wenn Sie den run-Handler explizit machen und dann versuchen, darin eine Property zu definieren. Der Versuch schlägt schon beim Kompilieren fehl:
408
Die Sprache
Kapitel 4
on run property xList : {"green", "red", "blue"} copy "yellow" to end of xList end run --Syntaxfehler: Es wurde „end“ erwartet, aber eine „property“ wurde gefunden. Propertys stehen niemals in irgendeinem Block, sei es ein tell-Block, ein Handler oder irgendein anderer Block (mit Ausnahme von Skriptobjektdefinitionen, wie später noch zu sehen sein wird). Wenn Sie mit expliziten run-Handlern arbeiten, müssen Propertys daher außerhalb davon definiert werden: property myColor : "cyan" on run get myColor -- Ergebnis: cyan end run Normalerweise definiert man Propertys immer ganz am Anfang des Skripts. Tatsächlich kann eine Property-Definition jedoch auch später im Skript erfolgen. Es gibt dabei keine Fehlermeldung: property a : 1 set c to a + b property b : 2 get c -- Ergebnis: 3 Wenn Sie jedoch einen Handler aufrufen, muss die Property vorher definiert sein: on addColor() copy "yellow" to end of xList end addColor property xList : {"green", "red", "blue"} addColor() get xList -- Fehler: Die Variable „xList“ ist nicht definiert. Der Fehler erscheint hier erst zur Laufzeit und nicht schon beim Kompilieren. Der Grund liegt ganz einfach darin, dass Sie hier einen impliziten run-Handler verwenden und AppleScript spätestens hier Probleme bei der Trennung der Bestandteile des run-Handlers von der Property-Definition bekommt. Die property-Definition darf ja nicht Teil des impliziten run-Handlers sein. Die Position der property-Definition im Skript ist also nicht so völlig egal, wie bei einem Handler, der problemlos am Anfang oder Ende oder in der Mitte des Skripts definiert werden kann.
409
SmartBooks
AppleScript
Aus diesem Grunde gilt, dass Propertys immer ganz an den Anfang des Skripts (oder Skriptobjekts) gestellt werden sollten. Nur dann können Sie sicher sein, dass es keine Probleme gibt. Auch wenn Sie explizite run-Handler verwenden und die Position der property-Definition keine Rolle spielt, gehört es zum guten Stil eines Appleskripters, property-Definitionen immer an den Anfang eines Skripts zu stellen.
Wertezuweisung in properties Generell gilt: Sie können für den Wert einer Property zwar einen beliebigen Wert oder Ausdruck verwenden, Sie können darin jedoch nicht auf andere Elemente des Skripts wie Variablen oder Handler zugreifen. Die properties eines Skriptobjekts werden immer als Erstes, also vor den Handlern und damit auch vor dem impliziten run-Handler, definiert. Die Variablen und Handler sind also zu diesem Zeitpunkt noch gar nicht bekannt, unabhängig davon, ob die Variable vor der Property im Skript erscheint. Wie Sie am folgenden Beispiel erkennen können, dürfen Sie in einer Property auch auf andere Propertys zugreifen, wobei dann die richtige Reihenfolge wichtig ist: property a : 1 set b to 3 property c : a + b -- Fehler: Die Variable „b“ ist nicht definiert. Würden Sie in der folgenden Zeile die Property c vor der von b definieren, würden Sie wieder die Fehlermeldung erhalten, dass die Variable b nicht definiert ist. property a : 1 property b : 2 property c : a + b get c -- Ergebnis: 3 Sie können beliebige Werte in einer Property speichern, also nicht nur die Standard-Wertetypen von AppleScript, sondern auch Programmobjekte. Bei einfachen Klassen wie window oder document funktioniert das sogar ohne einen tell-Bezug, da AppleScript diese Klassen von sich aus bereits kennt: property myWindow : window 1 of application "Finder" get myWindow -- Ergebnis: Finder window id 508 of application "Finder" Trotzdem müssen Sie danach mit der property im Kontext eines tell an das entsprechende Programm arbeiten:
410
Die Sprache
Kapitel 4
property myWindow : window 1 of application "Finder" get myWindow -- Ergebnis: Finder window id 508 of application "Finder" tell application "Finder" tell myWindow to set collapsed to true end tell Wenn Sie jedoch zum Beispiel versuchen, eine Mailbox aus dem Programm Mail in eine Property zu legen, schlägt das fehl, da AppleScript den Begriff mailbox nicht kennt und dafür im Funktionsverzeichnis von Mail nachsehen müsste. Dieses Nachsehen wird aber nur über ein tell oder ein using terms erreicht – bei der Definition einer Property schlägt die Zuweisung daher fehl: property myMailbox : mailbox "Accounts" of application "Mail" -- Fehler: Syntaxfehler Verwenden Sie statt "Accounts" den Namen eines Ihrer selbst angelegten Postfächer im Programm Mail. In solch einem Fall müssen Sie die property daher zuerst mit einem leeren Wert oder der Konstante missing value definieren und danach erst im Skript mit dem richtigen Wert füllen: property myMailbox : missing value tell application "Mail" set myMailbox to mailbox "Accounts" of application "Mail" end tell get myMailbox -- Ergebnis: mailbox "Accounts" of application "Mail"
Eine Property-Definition verhält sich wie set Mit Propertys kann ganz normal mit copy und set gearbeitet werden. Wenn es sich bei dem Inhalt der Property um einen veränderbaren Wertetyp handelt, also list, record, date oder script, dann wird mit set immer eine Referenz auf das Originalobjekt angelegt. Eine property-Definition verhält sich also wie eine Zuweisung mit set: property xList : {"green", "red", "blue"} property yList : xList set item 1 of yList to "yellow" get xList -- Ergebnis: {"yellow", "red", "blue"} Siehe auch Der Unterschied zwischen set und copy im Kapitel 4 unter Arbeiten in der Liste.
411
SmartBooks
AppleScript
Abfrage der Propertys Wenn Sie den Wert selbst angelegter Propertys in Ihrem Skript abfragen wollen, so machen Sie das einfach, indem Sie deren Namen verwenden. property xList : {"green", "red", "blue"} xList -- Ergebnis: {"green", "red", "blue"} Wenn Sie aber alle Propertys Ihres Skripts in einem Rutsch abfragen wollen, so wie Sie ja auch die Eigenschaften eines Programmobjekts (wie zum Beispiel einem Fenster) mit properties of window 1 abfragen können, so schlägt das fehl. Das heißt, es schlägt nicht ganz fehl, der Skripteditor fängt die Nachricht ab und liefert Ihnen seine properties zurück. Sie erhalten also schon ein Ergebnis, aber nicht das erwartete: properties of me -- Ergebnis: {frontmost:true, class:application, selection:insertion point after character 16 of text of document "Ohne Titel", version:"2.2", name:"Script Editor"} Eigentlich sollte man erwarten, dass sich die properties genauso einfach abfragen lassen wie im Finder. Der Grund, warum das hier nicht funktioniert, liegt ganz einfach darin, dass der Finder für die meisten Klassen eine Property namens properties definiert hat. Und tatsächlich wird genau diese abgefragt, und in dieser sind alle anderen Eigenschaften der Klasse enthalten. Wenn Sie sich einmal im Skripteditor die Klasse windows anschauen, werden Sie in dieser Klasse eine Eigenschaft namens properties finden. In der Beschreibung dahinter steht »every property of a window«. Diese Property enthält also alle Eigenschaften eines Fensters. Wenn Sie nach properties of window 1 fragen, erhalten Sie also tatsächlich nur eine einzelne Eigenschaft mit dem Namen properties zurück. Ein interessanter Trick, den Sie aber genauso gut auch für Ihr eigenes Skript anwenden können, Sie müssen die property nur exakt properties nennen und dann alle anderen properties Ihres Skripts darin aufnehmen: property property property property
startZahl : 1 startText : "a" startListe : {0, 1, 2, 3} properties : {startZahl:startZahl, startText:startText, startListe:startListe}
tell application "Finder" properties of window 1 -- Ergebnis:{class:Finder window, id:957,… properties of me -- Ergebnis: {startZahl:1, startText:"a", startListe:{0, 1, 2, 3}} end tell
412
Die Sprache
Kapitel 4
Das of me (oder my) ist natürlich nur erforderlich, wenn sich die Abfrage in einem tell an ein anderes Ziel als das Skript richtet, wie hier in einem tell an den Finder. Grundlagen Wenn sich in einer Anwendung die Eigenschaften eines Objekts nicht mit properties of ermitteln lassen, liegt das also nur daran, dass dieses Objekt keine Eigenschaft mit dem Namen properties besitzt! Leider kommt das recht häufig vor. In diesem Fall hilft dann nur das Nachschauen im Funktionsverzeichnis der Anwendung. Wenn Sie den Script Debugger von Late Night Software besitzen, haben Sie es besonders einfach. Mit seinem tell context-Inspector zeigt er Ihnen alle Eigenschaften und Elemente des Ziels eines beliebigen tell-Blocks an. Einfach nur die Einfügemarke in das entsprechende tell in Ihrem Code setzen und schon können Sie alle Elemente und Eigenschaften dieses Objekts im Inspector untersuchen.
Sichtbarkeit von Propertys Propertys sind ohne Ausnahme in allen Elementen des Skripts sichtbar. Das bedeutet konkret, dass Sie auch aus einem Handler heraus darauf zugreifen können, sei es der run-Handler oder andere selbst definierte Handler. property a : "All's well that ends well." on run display dialog "run-Handler: " & a disp() end run on disp() display dialog "disp-Handler: " & a end disp Würden Sie die Property als normale Variable definieren, könnten Sie zwar aus dem Handler, in dem sie definiert wurde, darauf zugreifen, nicht jedoch aus anderen Handlern. Deutlich sichtbar wird dies, wenn man den run-Handler explizit schreibt: on run set a to "All's well that ends well." display dialog "run-Handler: " & a disp() end run on disp() display dialog "disp-Handler: " & a end disp -- Fehler : Die Variable „a“ ist nicht definiert.
413
SmartBooks
AppleScript
Da ein Handler nicht in einem anderen definiert sein kann, gibt es keine tiefere Schachtelung. Wie Sie später noch sehen werden, geht das aber auch aus einem im Skript definierten Skriptobjekt und darin enthaltenen Handlern heraus, zumindest solange diese property nicht »überschrieben« oder die Abstammung verändert wird. Siehe Kapitel Vererbung und Delegation und Der Gültigkeitsbereich von Variablen und Propertys.
Persistenz von Propertys Neben der Tatsache, dass eine Property überall im Skript sichtbar ist, unterscheiden sich Propertys noch in einem weiteren Punkt von Variablen: Eine Property merkt sich ihren Wert über mehrere Ausführungen des Skripts hinaus. Führen Sie einmal das folgende Skript mehrmals hintereinander aus: property xList : {"green", "red", "blue"} copy "yellow" to end of xList get xList -- 1. Ergebnis: {"green", "red", "blue", "yellow"} -- 2. Ergebnis: {"green", "red", "blue", "yellow", "yellow"} -- 3. Ergebnis: {"green", "red", "blue", "yellow", "yellow", "yellow"} --… Die Liste wird immer länger, da sich die Property ihren letzten Wert merkt. Mit anderen Worten: Die Property-Definition in der ersten Zeile setzt den Ausgangswert nicht zurück! Mit einer Variablen ist es nicht möglich, den letzten Wert für den Start des nächsten Laufs zu verwenden. Eine Variable wird mit set oder copy definiert, und Befehle werden bei jeder Ausführung erneut ausgeführt, wodurch Variablen sich keine Werte über mehrere Ausführungen merken können. Führen Sie das folgende Skript mehrmals aus und Sie werden sehen, der Wert bleibt immer gleich: set xList to {"green", "red", "blue"} copy "yellow" to end of xList get xList -- Alle Ergebnisse: {"green", "red", "blue", "yellow"} Propertys eignen sich damit hervorragend, um sich Werte der letzten »Sitzung« zu merken. So können Sie sich zum Beispiel einen Zähler basteln, welcher sich merkt, wie oft das Skript bereits gestartet wurde: property runCounter : 0 set runCounter to runCounter + 1 -- Ergebnisse: 1, 2, 3, 4, … 414
Die Sprache
Kapitel 4
Dabei ist jedoch zu beachten: << Eine Property wird zurückgesetzt, wenn das Skript kompiliert wird. Solange Sie also noch am Skript arbeiten und ständig Änderungen vornehmen, wird die Property bei jeder erneuten Übersetzung, auch wenn Sie nur ein einzelnes Wort geändert haben, auf ihren Anfangswert zurückgesetzt. << Ein als Applet gesichertes Skript muss sich selbst sichern können. Denn nach jeder Ausführung des Skripts wird der letzte Wert im übersetzten Skript gespeichert. Ein Applet mit einer Property ändert damit also bei jedem Ausführen sein Änderungsdatum. Starten Sie ein Applet von einem nicht beschreibbaren Medium wie einer CD, so wird der Wert der Property bei jeder Ausführung gleich sein! << Wenn das Skript nicht als eigenständiges Applet gestartet wird, muss das Programm, aus dem heraus das Skript gestartet wird, das Zurückschreiben auch unterstützen. Der Skripteditor, das Skriptmenü und auch Programme wie RagTime machen das ohne Probleme. Das Skriptmenü in iTunes (Version 7.7) aber zum Beispiel nicht! Dort müssen Sie das Skript als Applet abspeichern und in den Scripts-Ordner von iTunes ablegen (~/Library/iTunes/Scripts/). Dann kann sich das Applet selbst darum kümmern, seine Propertys abzuspeichern.
Skriptobjekte als Element eines Skripts Neben Handlern und Propertys kann ein Skript auch weitere Skriptobjekte enthalten. Das hört sich etwas seltsam an, denn bisher war ein Skript ja immer eine Datei auf der Festplatte, die im Skripteditor zum Bearbeiten geöffnet werden konnte. Wie kann aber diese Datei nun weitere Dateien enthalten? Die Antwort ist: Erstens können Sie in Ihrem bestehenden Skript Skriptobjekte definieren, die nur in Ihrem Skript leben und mit ihm auf der Festplatte gespeichert werden, und zweitens können Sie ein anderes Skript als Datei von der Festplatte in Ihr Skript als Skriptobjekt »laden« und dort dann benutzen. Ein Skriptobjekt ist in AppleScript also nicht zwingend eine Datei auf der Festplatte. Ein Skript oder Skriptobjekt kann also weitere Skriptobjekte als Elemente enthalten. Diese Skriptobjekte können wiederum Skriptobjekte enthalten und so weiter, bis zu einer beliebigen Verschachtelungstiefe.
Skriptobjekte definieren Ein Skriptobjekt wird in einem bestehenden Skript mit dem Schlüsselwort script und einem beliebigen Namen für eine Variable eingeleitet. Das Skriptobjekt endet mit einem
415
SmartBooks
AppleScript
end script. Das script in end script braucht nicht geschrieben zu werden, es wird automatisch beim Kompilieren ergänzt. script meinSkript -- Anweisungen end script Das Skriptobjekt selbst wird dabei in dem angegebenen Variablennamen meinSkript gespeichert. Sie können es später also über diesen Namen ansprechen, so wie man auch einen Handler über seinen Namen ansprechen kann. Dieser Bezeichner ist übrigens optional, kann also auch weggelassen werden. Wenn Sie das aber tun, haben Sie keine Möglichkeit, auf das Skriptobjekt direkt zuzugreifen. Also besser niemals den Variablennamen vergessen! Dieses Skriptobjekt ist natürlich noch leer. Sie können nun die Zeilen innerhalb dieses script-Blocks so füllen, als wenn das Skriptobjekt eine eigene Datei im Skripteditor darstellen würde: script meinSkript property someName : "John" say "Hello " & someName on changeName(x) set someName to x end changeName end script Auch ein solchermaßen angelegtes Skriptobjekt hat dabei einen impliziten run-Handler, der in obigem Fall aus der say-Zeile besteht. Obige Schreibweise mit implizitem runHandler ist daher identisch zu der folgenden Schreibweise mit explizitem run-Handler: script meinSkript property someName : "John" on run say "Hello " & someName end run on changeName(x) set someName to x end changeName end script Solch ein Skriptobjekt kann in friedlicher Koexistenz mit den Bestandteilen des obersten Skriptobjekts leben, also mit den Elementen desjenigen Skripts, welches im Skripteditor geöffnet ist:
416
Die Sprache
Kapitel 4
property lastTrack : missing value tell application "iTunes" to set lastTrack to (get name of current track) sayTrack(lastTrack) on sayTrack(x) say x end sayTrack script meinSkript property someName : "John" on run say "Hello " & someName end run on changeName(x) set someName to x end changeName end script Das Skript meinSkript ist oben ein völlig autarker Block. Das obige Beispiel sagt Ihnen übrigens einfach nur den Titel des aktuell in iTunes laufenden Tracks an. Alternativ könnten Sie dafür auch ein display dialog verwenden, wenn Sie ein plötzlich erscheinender Dialog mit dem Titel nicht stört. Das script meinSkript tritt dabei gar nicht in Aktion. Skriptobjekte werden nicht automatisch ausgeführt, man muss ihnen Befehle geben, damit sie etwas machen. Ein solchermaßen in einem Skript definiertes Skriptobjekt kann wiederum Skriptobjekte enthalten: property lastTrack : missing value tell application "iTunes" to set lastTrack to (get name of current track) sayTrack(lastTrack) on sayTrack(x) say x end sayTrack script meinSkript property someName : "John" on run 417
SmartBooks
AppleScript
say "Hello " & someName end run on changeName(x) set someName to x end changeName script meinSkript2 property someName : "Gerda" on run say "Hello " & someName end run on changeName(x) set someName to x end changeName end script end script Hier sind nun also schon drei Skriptobjekte vorhanden: das oberste Skript im Skripteditorfenster, welches immer ohne script und end script geschrieben wird, dann das script meinSkript und darin dann das script meinSkript2. Ein Skript kann dabei beliebig viele Skriptobjekte definieren, welche alle beliebig viele Handler, Skriptobjekte und Propertys enthalten dürfen. Ein Skriptobjekt kann auch in einem beliebigen Handler definiert werden. Diese spezielle Anordnung wird später im Abschnitt Konstruktoren und Instanzen behandelt. Alles in allem macht das so definierte Skriptobjekt natürlich noch gar nichts. Es ist zwar definiert, enthält Daten in Form von properties und Handlungsmöglichkeiten in Form von Handlern, braucht jedoch einen Anstoß von außen, um aktiv zu werden.
Mit Skriptobjekten arbeiten Um ein Skriptobjekt zu irgendeiner Reaktion zu bewegen, müssen Sie ihm Befehle geben. Von sich aus tut ein Skriptobjekt nämlich gar nichts.
Aufruf von Handlern in Skriptobjekten Die einfachste Art eines Befehls ist, dem Skriptobjekt zu sagen, es soll starten. Das wird mit dem run-Befehl gemacht, der den run-Handler in diesem Skript aufruft:
418
Die Sprache
Kapitel 4
run sayHello script sayHello property someName : "John" on run say "Hello " & someName end run on changeName(x) set someName to x end changeName end script Hier wird mit run und einer darauf folgenden Variable, die ein Skript oder Skriptobjekt enthalten muss (sayHello), der run-Handler des entsprechenden Skriptobjekts aufgerufen, was hier dazu führt, dass das Skriptobjekt sayHello gestartet wird und John begrüßt. Alternativ können Sie auch ein tell verwenden: tell sayHello to run Bei anderen Handlern müssen Sie immer den Handlernamen und das Skriptobjekt angeben: changeName("Mike") of sayHello run sayHello script sayHello property someName : "John" on run say "Hello " & someName end run on changeName(x) set someName to x end changeName end script Hier wird in der ersten Zeile der Handler changeName des Skriptobjekts sayHello aufgerufen. Die Zugehörigkeit wird mit of gekennzeichnet. Alternativ können Sie die Zugehörigkeit auch mit Apostroph-s kennzeichnen: sayHello's changeName("Mike") oder mit einem tell: tell sayHello to changeName("Mike")
419
SmartBooks
AppleScript
Wenn Sie mehrere Befehle an das Skriptobjekt geben möchten, können Sie auch einen tellBlock verwenden: tell sayHello changeName("Mike") run changeName("Susan") run end tell script sayHello property someName : "John" on run say "Hello " & someName end run on changeName(x) set someName to x end changeName end script Hier wird zuerst Mike und danach Susan begrüßt. Sind Skriptobjekte ineinander verschachtelt, gilt es zu beachten, dass ein in einem Skriptobjekt angelegtes Skriptobjekt nicht ebenfalls gestartet wird, wenn das darüber liegende Skript mit run gestartet wird: run sayHello script sayHello property someName : "John" say "Hello " & someName on changeName(x) set someName to x end changeName script writeMe property someOne : "Merlin" display dialog "Hello " & someOne on changeSomeOne(x) set someOne to x end changeSomeOne end script end script
420
Die Sprache
Kapitel 4
Das Script writeMe wird hier nicht ausgeführt, wenn das script sayHello startet. Wenn Sie einen Handler im Skript writeMe aufrufen wollen, dann müssen Sie diese Schachtelung der Skriptobjekte auch mit of, tell oder Apostroph-s kennzeichnen: run writeMe of sayHello oder tell writeMe of sayHello to run Bei anderen Handlern als dem run-Handler: tell writeMe of sayHello to changeSomeOne("Peter") oder tell sayHello's writeMe to changeSomeOne("Peter") oder changeSomeOne("Peter") of writeMe of sayHello oder writeMe's changeSomeOne("Peter") of sayHello In einem tell-Block: tell writeMe of sayHello changeSomeOne("Peter") run end tell Alle diese Aufrufe müssen natürlich in demselben Skript stehen wie das Skriptobjekt sayHello.
Zugriff auf Propertys eines Skriptobjekts In den vorangegangenen Beispielen konnten Sie auch sehen, wie über den Aufruf eines Handlers eine Property in dem Skriptobjekt geändert wurde. Der Handler changeName() oder changeSomeOne() macht nichts anderes, als die Property für den zu Grüßenden zu setzen. Über diesen Handler ist diese property also der Außenwelt zugänglich gemacht worden. Diese Art des Zugriffs auf eine Pproperty in einem Skriptobjekt sollte immer der bevorzugte Weg sein. Wenn Sie Propertys in einem Skriptobjekt von außen ändern wollen, so erschaffen Sie dafür immer einen dedizierten Handler:
421
SmartBooks
AppleScript
setName("Peter") of sayHello run sayHello script sayHello property someName : "John" say "Hello " & someName on setName(x) set someName to x end setName end script Das ist auch für die bloße Abfrage einer Property zu empfehlen. Erschaffen Sie immer einen eigenen Handler für jede Aktion, die das Skript ausführen soll. Im Folgenden hat das Skriptobjekt einen weiteren Handler namens getName erhalten, der nur dazu dient, die Property someName abzufragen: set x to getName() of sayHello -- Ergebnis: "John" setName("Peter") of sayHello set x to getName() of sayHello -- Ergebnis: "Peter" script sayHello property someName : "John" say "Hello " & someName on setName(x) set someName to x end setName on getName() return someName end getName end script Der Zugriff ist aber auch direkt möglich, wenn man den Namen der Property kennt, was aber dem Gedanken der Kapselung in der objektorientierten Programmierung widerspricht: set someName of sayHello to "Kathrin" run sayHello script sayHello property someName : "John" say "Hello " & someName on changeName(x) set someName to x end changeName end script
422
Die Sprache
Kapitel 4
Wenn Sie in einem tell-Block auf Propertys zugreifen wollen, müssen Sie das Ziel nochmal explizit mit its bestätigen, ansonsten wird in dem tell eine Variable mit dem Namen der Property angelegt: script sayHello property someName : "John" say "Hello " & someName end script tell sayHello set its someName to "Mike" run set its someName to "Susan" run end tell Sie können auch problemlos auf Propertys aller übergeordneten Skriptobjekte zugreifen: property myName : "William" run sayHello script sayHello property someName : "John" say "Hello " & someName say "Hello " & myName on changeName(x) set someName to x end changeName end script Wenn Sie aber in einem Skriptobjekt eine Property mit dem gleichen Namen wie eine übergeordnete Property definieren, ist damit die property des übergeordneten Skriptobjekts nicht mehr zugänglich. Die Property ist »überschrieben« worden: property myName : " William " set someName of sayHello to "Kathrin" run sayHello script sayHello property someName : "John" property myName : "Peter" say "Hello " & someName say "Hello " & myName on changeName(x) set someName to x end changeName end script Statt William wird jetzt Peter begrüßt. 423
SmartBooks
AppleScript
Skriptobjekte als Werte Die Variable, die bei einer Skriptdefinition angegeben wird, ist eine ganz normale Variable. Fragen Sie diese nach ihrem Wert, um zu sehen, welches Skriptobjekt darin steckt: script sayHello say "Hello" end script get sayHello -- Ergebnis: «script sayHello» Sie können dabei jederzeit auch einer anderen Variablen den Wert aus der SkriptobjektVariablen zuweisen: set saySomething to sayHello run sayHello run saySomething get saySomething -- Ergebnis: «script sayHello» script sayHello property myName : "John" say "Hello " & myName on changeName(x) set name to x end changeName end script In diesem Fall wird der Variablen saySomething der Wert von sayHello zugewiesen. Danach weisen beide auf das gleiche Skriptobjekt. Das Skriptobjekt lässt sich danach also entweder über saySomething oder sayHello ansprechen. Die beiden Variablen verhalten sich wie zwei Türen, die in dasselbe Zimmer führen. Die Zuweisung eines Skriptobjekts in eine Variable mit set verhält sich damit genauso wie bei den Klassen list, record und date. Bei den vier eingebauten AppleScript-Klassen list, record, date und script wird mit set immer eine Referenz angelegt und keine Kopie des Objekts. Möchten Sie ein Kopie des Skriptobjekts erzeugen, müssen Sie das mit copy machen: copy sayHello to sayHello2 tell sayHello2 to changeName to "Wilbur" run sayHello run sayHello2 script sayHello property myName : "John" say "Hello " & myName on changeName to x 424
Die Sprache
Kapitel 4
set myName to x end changeName end script Hier haben Sie nun aus einer einzigen Skriptobjektdefinition zwei Skriptobjekte erzeugt. Jedes Skriptobjekt hat seine eigene Property myName, da der Kopie über den Aufruf des Handlers changeName ein anderer Name zugewiesen wurde. Die Skriptobjektdefinition verhält sich hier also wie eine Blaupause, von der Sie beliebig viele Kopien »abziehen« können. Außerdem wird Ihnen hier sicher auffallen, dass für den Handler changeName diesmal benannte Parameter verwendet wurden. Wenn Sie einer Variablen mit einem Skriptobjekt einen anderen Wert zuweisen, bedeutet das aber auch: Zeigt keine Variable mehr auf das Skriptobjekt, ist es danach nicht mehr ansprechbar und für immer verloren: set sayHello to "No more greetings" run sayHello -- Ergebnis: „"No more greetings"“ versteht die Nachricht „run“ nicht. script sayHello property someName : "John" say "Hello " & someName on changeName(x) set someName to x end changeName end script Die Variable sayHello enthält nach der Zuweisung in der ersten Zeile nur noch einen Text und nicht mehr das Skriptobjekt sayHello. Auf das Skriptobjekt sayHello kann daher nicht mehr zugegriffen werden. Ein Text kann dann mit dem Befehl run natürlich nichts anfangen, und es gibt einen entsprechenden Fehler. Verwenden Sie also nicht aus Versehen denselben Bezeichner für eine Variable wie ein Skriptobjekt. Obwohl das Skriptobjekt hier am Ende des Skripts steht, bedeutet das nicht, dass dort der Text im sayHello wieder ausgetauscht wird gegen das Skriptobjekt. Ein Skriptobjekt wird, egal, wo es im übergeordneten Skriptobjekt steht, immer ganz zu Anfang initialisiert, direkt nach den Propertys des übergeordneten Skriptobjekts. Jede Zuweisung eines anderen Wertes in die Variable, die für das Skriptobjekt steht, hat damit den Verlust des Skriptobjekts zur Folge, wenn nicht zuvor der Inhalt noch in eine andere Variable gesichert wurde. Das Skriptobjekt verhält sich dann wie ein Raum ohne Tür. Es gibt keine Möglichkeit mehr, den Raum zu betreten.
425
SmartBooks
AppleScript
Dass man einer Variablen ein Skriptobjekt zuweisen kann, lässt sich auch gut ausnutzen, um zum Beispiel mehrere Skriptobjekte in eine Liste zu packen, um dann über die Skriptobjekte in dieser Liste eine Schleife mit Anweisungen an die Skriptobjekte zu drehen. Im folgenden Skript wird ein kleines Spiel veranstaltet: on run set players to {personA, personB, personC} repeat with i in players tell i to setScore(random number from 1 to 6) end repeat say "Total results:" using "Alex" say (getName() of personA) & " has a score of " & ¬ (getScore() of personA) using "Alex" say (getName() of personB) & " has a score of " & ¬ (getScore() of personB) using "Alex" say (getName() of personC) & " has a score of " & ¬ (getScore() of personC) using "Alex" end run script personA property myName : "John" property score : 0 on setScore(x) say "Hello, its " & myName using "Bruce" say "I rolled a bloody" & x using "Bruce" set score to score + x end setScore on getScore() return score end getScore on getName() return myName end getName end script script personB property myName : "Sarah" property score : 0 on setScore(x) say "Hello, I'm " & myName using "Vicki" say "I rolled a " & x using "Vicki" set score to score + x 426
Die Sprache
Kapitel 4
end setScore on getScore() return score end getScore on getName() return myName end getName end script script personC property myName : "Albert" property score : 0 on setScore(x) say "Its me, " & myName using "Albert" say "I got a " & x using "Albert" set score to score + x end setScore on getScore() return score end getScore on getName() return myName end getName end script Zur Erklärung: Das Skript enthält drei Skriptobjekte und einen expliziten run-Handler auf oberster Ebene ganz zu Anfang des Skripts. Jedes Skriptobjekt von personA bis personC enthält (neben dem leeren impliziten runHandler) drei Handler (oder Methoden, wie man in der objektorientierten Programmierung sagt). Eine, um den Spielstand score zu erhöhen (setScore), und zwei Zugriffsmethoden, die für die Abfrage der Propertys myName und score dienen (getName, getScore). Der implizite run-Handler ist leer. Jedes Skriptobjekt soll dabei eine Person mit Name und Spielstand darstellen. Der Name der Person steckt in myName und ist unveränderlich, da keine Methode implementiert wurde, die dessen Veränderung erlauben würde. (Es ist zwar über den direkten Zugriff möglich, was aber vermieden werden sollte.) Der Spielstand in der Property score kann aber über die Methode getScore um den Wert von x erhöht werden. Jede »Person« kann also auf Anfrage Auskunft über ihren Namen und den Spielstand geben und kann ihren Spielstand um x erhöhen.
427
SmartBooks
AppleScript
Das Skript, in dem diese drei Skriptobjekte oder »Personen« definiert sind, besteht eigentlich nur aus dem run-Handler. Hier finden sich alle Anweisungen versammelt. Am Anfang wird eine Liste namens players angelegt, in welcher alle drei Skriptobjekte abgelegt werden: set players to {personA, personB, personC} Alle drei Skriptobjekte (Personen) sind nun in dieser Liste versammelt. Danach beginnt ein repeat über diese Liste, in welcher für jede Person ein Mal die Methode setScore aufgerufen wird. repeat with i in players tell i to setScore(random number from 1 to 6) end repeat Dabei wird ein zufälliger Würfelwurf zwischen 1 und 6 als Parameter zur Erhöhung des Spielstands an den Spieler (in i) mitgegeben. In der Methode setScore jeder Person stellt sich dann jede Person kurz mit ihrer eigenen Stimme vor und sagt an, was sie gewürfelt hat. Danach folgt nur noch eine Reihe Schlussansagen, die den augenblicklichen Spielstand über alle Runden mitteilt. Diese Ansagen haben es nochmal in sich, Sie können daran nämlich sehen, wie Sie die Handler eines Skriptobjekts auch als Ausdruck verwenden können. Hier wird der Name der Person mit getName abgefragt und dann mit dem & Operator mit dem Text " has a score of " und dem Ergebnis des Handleraufrufs getScore verbunden. say (getName() of personA) & " has a score of " & (getScore() of personA) using "Alex" Sie können einen Handleraufruf eines Handlers in einem Skriptobjekt also überall wie eine Variable verwenden. Der Rückgabewert des Handleraufrufs ergibt sich durch den im Handler mit return zurückgelieferten Wert oder durch den impliziten Rückgabewert (siehe auch Kapitel Handler). Da die Personen keinen Handler zum Zurücksetzen der score-Property besitzen, erhöht sich der Spielstand ständig um den neuen Wurf, da eine Property sich ja ihren letzten Wert merkt, zumindest so lange, wie das Skript nicht erneut kompiliert wird. Skriptobjekte eignen sich hervorragend, um Objekte aus der realen Welt nachzubilden, was zusätzlich auch den Vorteil hat, dass die objektorientierte Programmierung mit AppleScript dadurch leichter verständlich wird.
428
Die Sprache
Kapitel 4
Die Property name Jedes Skriptobjekt, welches einen Bezeichner erhalten hat, besitzt auch eine Property mit dem Namen name. Diese Property enthält den Variablennamen des Skriptobjekts als Text: set anotherName to sayHello get anotherName -- Ergebnis: «script sayHello» get name of anotherName -- Ergebnis: "sayHello" script sayHello property someName : "John" say "Hello " & someName on setName(x) set someName to x end setName end script Sie können diese Eigenschaft nicht mit set verändern, sie kann also nur gelesen werden. Sie eignet sich gut dafür, um herauszufinden, welches Skriptobjekt sich nun wirklich gerade in einer Variablen befindet. Sie könnten zwar das Skriptobjekt auch direkt mit get abfragen, erhalten dann aber das Skriptobjekt direkt, welches als «script sayhello» im Ergebnisbereich des Skripteditors angezeigt wird. Und ein Skriptobjekt lässt sich nicht in Text und auch in keine andere Klasse umwandeln (außer in eine Liste mit dem Skriptobjekt als einzigem Element). Bei der Abfrage des Namens erhalten Sie aber einen Text zurück, den Sie dann problemlos auf seinen Wert vergleichen können.
Vergleichen von Skriptobjekten Zwei Skriptobjekte können Sie nur auf Gleichheit vergleichen. Zwei Skriptobjekte sind dann gleich, wenn es sich um exakt dasselbe Skriptobjekt handelt: set anotherName to sayHello anotherName = sayHello -- Ergebnis true script sayHello property someName : "John" say "Hello " & someName on setName(x) set someName to x end setName end script Wenn die Skriptobjekte nur die gleiche Definition haben, es sich also um Kopien eines Skriptobjekts handelt, reicht das nicht für einen positiven Test auf Gleichheit:
429
SmartBooks
AppleScript
copy sayHello to sayHello2 sayHello = sayHello2 -- Ergebnis false script sayHello property someName : "John" say "Hello " & someName on setName(x) set someName to x end setName end script Ansonsten können Sie noch den Namen der Skriptobjekte vergleichen: name of sayHello2 starts with "sayHello" -- Ergebnis true script sayHello property someName : "John" say "Hello " & someName name on setName(x) set someName to x end setName end script script sayHello2 property someName : "John" say "Hello " & someName name on setName(x) set someName to x end setName end script Oder Sie greifen auf den Inhalt der verschiedenen Propertys zu und vergleichen diese. Definieren Sie dafür eigene Handler im Skriptobjekt, welche die Eigenschaft zurückliefern: getName() of sayHello = getName() of sayHello2 -- Ergebnis true script sayHello property someName : "John" say "Hello " & someName on getName() return someName end getName end script script sayHello2 property someName : "John" 430
Die Sprache
Kapitel 4
say "Hello " & someName on getName() return someName end getName end script
Zugriff auf Elemente im übergeordneten Skript Wenn Sie in einem Skriptobjekt auf Elemente des Skripts zugreifen wollen, so können Sie dafür wieder einen Handler schreiben oder, wie bei den Propertys besprochen, direkt darauf zugreifen: property myName : "Kathrin" run sayHello script sayHello say "Hello " & myName end script Möchten Sie auf Variablen des übergeordneten Skripts zugreifen, so erhalten Sie einen Fehler: set x to "Mike" run sayHello script sayHello say "Hello " & x -- Fehler: Die Variable „x“ ist nicht definiert. end script Wenn Sie jedoch mit my angeben, dass mit x die Variable des Skripts gemeint ist, funktioniert es: set x to "Mike" run sayHello script sayHello say "Hello " & my x end script Tatsächlich wird mit my die Vererbung genutzt. My bezieht sich immer auf das Skriptobjekt, in dem es steht. Da dort aber kein x definiert ist, wird die Anfrage an die Eltern des Skriptobjekts weitergeleitet, das ist das Skript der obersten Ebene, und das kennt natürlich x. Bei dem Aufruf eines Handlers des übergeordneten Skripts ist die Verwendung von my nicht notwendig, aber möglich: run sayHello script sayHello say "Hello " & my getaName() end script 431
SmartBooks
AppleScript
on getaName() set somenames to {"Mike", "Robert", "Sarah"} return some item of somenames end getaName
Zugriff auf Elemente im übergeordneten Skriptobjekt Wenn das übergeordnete Skriptobjekt nicht das Skript selber ist, sondern ein anderes Skriptobjekt, ist der Zugriff auf Propertys weiterhin kein Problem, auch wenn das Skript dieselbe Property enthalten sollte: property myName : "Wilbur" run writeMe of sayHello script sayHello property myName : "Holger" beep script writeMe display dialog "Hello " & myName end script end script -- Ergebnis: Hello Holger Als Ergebnis wird Holger gegrüßt. Würde sayHello keine Property dieses Namens enthalten, würde die Property myName des Skripts gefunden und verwendet. Wenn Sie diese explizit haben möchten, können Sie das mit einem my im Aufruf kenntlich machen, wie eben bereits erwähnt: display dialog "Hello " & my myName Sie können auch mit parent explizit auf der Abstammungsleiter nach oben gehen: property myName : "Wilbur" run writeMe of sayHello script sayHello property myName : "Holger" beep script writeMe display dialog "Hello " & myName of parent end script end script Hier fällt auf, dass Wilbur zurückgeliefert wird. Tatsächlich stellt das Skript die Eltern dar, ist also parent für alle Skriptobjekte, die in ihm definiert werden, egal, wie tief diese in anderen Skriptobjekten geschachtelt wurden. Da Sie parent auch verändern können, lässt sich dieses Verhalten aber auch beliebig ändern. Beachten Sie hier unbedingt das Kapitel Vererbung und Delegation.
432
Die Sprache
Kapitel 4
Auf Variablen in einem übergeordneten Skriptobjekt können Sie nicht direkt zugreifen, wohl aber auf Handler: run beepHello of sayHello script sayHello set myName to "Wilbur" on beepMe(x) beep x end beepMe script beepHello sayHello's beepMe(3) end script end script
Zugriff auf Elemente in untergeordneten Skriptobjekten Der Zugriff auf Propertys in Skriptobjekten unterhalb eines Skriptobjekts ist möglich durch die exakte Angabe der Objekthierarchie: run sayHello script sayHello beep (howOften of hello) script hello property howOften : 3 display dialog "Hello" end script end script Auf Variablen funktioniert der Zugriff nicht direkt, wohl aber auf Handler: run sayHello script sayHello beep (chooseX() of chooseOne) script chooseOne on chooseX() some item of {1, 2, 3} end chooseX end script end script Sie sehen, es gibt einige Möglichkeiten, auf Elemente in einem Skriptobjekt zuzugreifen. In allen Fällen ist es immer besser, den Handler eines Skriptobjekts aufzurufen, welcher einem den Wert zurückliefert, oder durch Abstammungsregeln ein gewünschtes Zugriffsverhalten zu ermöglichen. Bitte beachten Sie hier das Kapitel Vererbung und Delegation. Bezüglich der Reichweite von Propertys, lokalen Variablen und globalen Variablen
433
SmartBooks
AppleScript
beachten Sie bitte das Kapitel Der Gültigkeitsbereich von Variablen und Propertys und die entsprechenden Tafeln im Anhang.
Initialisierung von Skriptobjekten in Handlern Jedes Skriptobjekt ist letztlich immer Teil eines Handlers. Wenn das Skriptobjekt scheinbar in keinem Handler steht, dann ist es immer Teil des impliziten run-Handlers. Ein Skriptobjekt wird dabei initialisiert, also ins Leben gerufen, wenn dieser Handler aufgerufen wird. Hier gibt es einen wichtigen Punkt zu beachten: Wird von außen auf den Handler zugegriffen, wird das Skriptobjekt darin in diesem Moment erschaffen. Wird der Handler später erneut aufgerufen, wird ein neues Skriptobjekt erschaffen. Propertys in der Skriptobjektdefinition halten sich daher nicht über mehrere Aufrufe des Handlers hinweg, da der Handler ja jedes Mal ein neues Skriptobjekt erstellt: greet() on greet() script sayHello property counter : 0 display dialog counter set counter to counter + 1 end script run sayHello end greet Der Dialog zeigt immer eine 0 an, da jedes Mal ein neues Skriptobjekt mit den Ausgangswerten erzeugt wird. Wird jedoch das Skriptobjekt innerhalb des übergeordneten Handlers aufgerufen, so wird immer das beim Aufruf des Handlers erzeugte Skriptobjekt für alle Aufrufe verwendet. Propertys bewahren damit ihren Inhalt über mehrere Aufrufe hinweg: greet() on greet() script sayHello property counter : 0 display dialog counter set counter to counter + 1 end script repeat with i from 1 to 3 run sayHello end repeat end greet 434
Die Sprache
Kapitel 4
Hier wird mit einem repeat im Handler greet() dreimal der run-Handler des Skriptobjekts sayHello aufgerufen. Dabei handelt es sich dann immer um dasselbe Skriptobjekt, und im Dialog wird folgerichtig immer um eins hochgezählt. Wenn Sie in einem Handler so auf ein Skriptobjekt zugreifen, müssen Sie nur beachten, dass der Zugriff nach der Definition des Skriptobjekts stehen muss. Würde der repeatBlock oben zwischen on greet() und script sayHello stehen, erhielten Sie die Fehlermeldung, dass die sayHello-Eigenschaft mehr als ein Mal angegeben wurde. Im expliziten run-Handler erhalten Sie die Meldung, dass die Variable sayHello nicht definiert ist: on run repeat with i from 1 to 3 run sayHello end repeat script sayHello property counter : 0 display dialog counter set counter to counter + 1 end script end run -- Fehler: Die Variable „sayHello“ ist nicht definiert. Dass Skriptobjekte immer gleich als Erstes evaluiert werden, gilt also nur, wenn sie im impliziten run-Handler auf der obersten Ebene des Skripts stehen. Setzen Sie daher den Aufruf eines Skriptobjekts in einem Handler immer nach dessen Definition. Im impliziten run-Handler spielt die Reihenfolge keine Rolle. Folgender Aufruf funktioniert daher problemlos: repeat with i from 1 to 3 run sayHello end repeat script sayHello property counter : 0 display dialog counter set counter to counter + 1 end script Die Eigenschaft, dass ein Handler mit einem Skriptobjekt bei jedem Aufruf ein neues Skriptobjekt anlegt, kann man sich auch für andere Zwecke zunutze machen wie im folgenden Abschnitt beschrieben.
435
SmartBooks
AppleScript
Konstruktoren und Instanzen Einige Seiten zuvor wurden in einem Skript drei Skriptobjekte angelegt, welche für die drei Teilnehmer eines Würfelspiels standen. Wenn sich die Spieleranzahl öfters ändert, muss dort jedes Mal die Anzahl der Skriptobjekte im Code angepasst werden. Hier wäre es schöner, wenn das Skript auf flexible Weise mit einer unterschiedlichen Anzahl an Personen klarkäme. Auch das ist natürlich möglich, wobei es zwei unterschiedliche Vorgehensweisen gibt: einmal durch Kopieren eines Skriptobjekts mit copy und einmal mit einem Handler, der ein Skriptobjekt zurückliefert.
Konstruktor mit copy Wie bereits kurz erwähnt, können Sie, wenn Sie copy statt set verwenden, auch jede Menge Kopien eines Skriptobjekts erzeugen. Jede Kopie wird dabei mit den Standardwerten dieses einen Skriptobjekts erzeugt. Das heißt, jedes Skriptobjekt hat danach exakt dieselben Werte für seine Propertys. Aus diesem Grund muss jedes Skriptobjekt nach dem Kopieren noch individualisiert werden. Dieses Erzeugen und Individualisieren von Skriptobjekten nennt man in der objektorientierten Programmierung »Instanzen erzeugen«. Ein Codeblock, der Instanzen erzeugt, ist dabei ein Konstruktor, sozusagen eine Kopiermaschine im Code. In der einfachsten Form sieht das wie in den folgenden Zeilen aus. Die sechs Zeilen am Anfang erstellen dabei eine Kopie des Skriptobjekts und geben jeder Kopie über den Handler setName einen anderen Namen für die Property myName: copy person to personA setName("John") of personA copy person to personB setName("Sarah") of personB copy person to personC setName("Albert") of personC script person property myName : "John" on setName(x) set myName to x end setName end script Bei dieser manuellen Methode, Kopien eines Skriptobjekts zu erzeugen, können Sie jedem einzelnen Skriptobjekt eine andere Variable geben, hier sind es die Variablen personA, personB und personC.
436
Die Sprache
Kapitel 4
Im folgenden Skript wurden die Codezeilen des Konstruktors in einen eigenen Handler namens initializePlayers() gelegt. Er könnte aber auch genauso gut an der Stelle seines Aufrufs direkt im run-Handler stehen. Des Weiteren werden die Spieler dort in einer Schleife angelegt, wodurch die Anzahl der Spieler noch leichter anpassbar ist, einfach durch Änderung der Liste mit den Spielernamen am Anfang des Skripts. Die Skriptobjekte existieren hier nur als Elemente in einer Liste: in fetter Schrift die Stellen, an denen das Skriptobjekt kopiert und mit einem Namen versehen wird. property players : {} property playerNames : {"John", "Sarah", "Albert"} on run initializePlayers() set nameList to {} get players -- Ergebnis: {«script», «script», «script»} end run on initializePlayers() set players to {} repeat with i from 1 to length of playerNames copy my person to end of players tell item -1 of players to setName(item i of playerNames) ¬ of item -1 of players end repeat end initializePlayers script person property myName : "John" on setName(x) set myName to x end setName end script Am Schluss haben Sie drei Kopien des Scripts person angelegt, auf die Sie über die Liste players zugreifen können, wie mit get players oben überprüft wird. Da die Skriptobjekte durch das Kopieren in eine Liste keinen Namen erhalten, können Sie nicht über einen Variablennamen auf sie zugreifen. Die Liste players sieht so aus: {«script», «script», «script»} Die Liste enthält also drei Skriptobjekte, und welches Skript welches ist, lässt sich so nicht erkennen. Sie müssen daher die Skriptobjekte in der Liste entsprechend nach einer Eigenschaft fragen, anhand derer sie sich identifizieren lassen. In diesem Beispiel also nach der Property myName.
437
SmartBooks
AppleScript
Wenn Sie an das Ende des run-Handler einmal folgende Zeilen einfügen und ausführen, eine nach der anderen, können Sie überprüfen, ob sich die drei Skriptobjekte wirklich in ihren Eigenschaften unterscheiden: get myName of item 1 of players -- Ergebnis: "John" get myName of item 2 of players -- Ergebnis: "Sarah" get myName of item 3 of players -- Ergebnis: "Albert" Mit dieser Technik des Kopierens lässt sich die Würfelrunde aus dem Kapitel Skriptobjekte als Werte so abändern, dass nur noch ein einziges Skriptobjekt definiert werden muss. Das wird dann allerdings etwas länger, da man außer dem Namen auch noch eine Methode braucht, um die Stimme zu individualisieren: property property property property
players : {} playerNames : {"John", "Sarah", "Albert"} playerVoices : {"Bruce", "Vicki", "Albert"} playerScores : {0, 0, 0}
on run initializePlayers() -- Spieler erzeugen repeat with i in players -- Jeder Spieler würfelt tell i to setScore(random number from 1 to 6) end repeat say "Total results: " using "Alex" -- Endergebnisse ansagen repeat with i from 1 to length of players set (item i of playerScores) to (item i of playerScores) + ¬ (getScore() of item i of players) --Scores abspeichern say (getName() of item i of players) & " has a score of " & ¬ (item i of playerScores) using "Alex" --Scores ansagen end repeat end run -- Eine Liste mit individualisierten Skriptobjekten erzeugen on initializePlayers() set players to {} repeat with i from 1 to length of playerNames copy my person to end of players tell item -1 of players to setName(item i of playerNames) of ¬ item -1 of players tell item -1 of players to setVoice(item i of playerVoices) of ¬ item -1 of players end repeat end initializePlayers -- Der Bauplan für ein Spieler-Skriptobjekt 438
Die Sprache
Kapitel 4
script person property myName : "John" property score : 0 property voice : "Bruce" on setScore(x) say "Hello, its " & myName using voice say "I rolled a " & x using voice set score to x end setScore on setName(x) set myName to x end setName on setVoice(x) set voice to x end setVoice on getScore() return score end getScore on getName() return myName end getName end script Da hier die Skriptobjekte erst zur Laufzeit durch Kopieren erzeugt werden, würden alle Personen bei jeder Runde wieder mit einem Score von null anfangen. Um das zu ändern, werden die Ergebnisse jeder Runde im run-Handler vor der Ansage der Endergebnisse zu playerScores addiert, damit diese für den Beginn des nächsten Laufs wieder als Ausgangsbasis zur Verfügung stehen.
Konstruktor mit dediziertem Handler Dies ist die Methode, die Apple selbst als Beispiel in seinem Language Guide angibt. Sie ist die mit Abstand eleganteste. Sie legen hier einfach einen Handler an und in diesen Handler packen Sie eine Definition eines Skriptobjekts. Wenn Sie den Handler aufrufen und ihm Parameter mitgeben, können diese Parameter gleich von dem Skriptobjekt zur Individualisierung seiner Propertys verwendet werden. Als Rückgabewert erhalten Sie ein bereits fertig individualisiertes Skriptobjekt. Wenn Sie beim Aufruf eine Rückgabevariable angeben, steckt die neue Instanz des Skriptobjekts sogar in einer Variablen, so dass man darüber darauf zugreifen kann. Aber auch die Abspeicherung in einer Liste als Index-Skriptobjekt ist natürlich möglich.
439
SmartBooks
AppleScript
Zuerst ein Beispiel im übersichtlichen Kurzformat: set newPerson to initMe("Hannibal") getName() of newPerson -- "Hannibal" on initMe(someName) script person property myName : someName on getName() return myName end getName end script return person end initMe Hier steht das Skriptobjekt direkt in einem Handler mit dem Namen initMe, welcher einen Parameter erwartet. Dieser Parameter someName wird in der Skriptdefinition für eine Property verwendet. Wenn Sie den Handler also mit einem beliebigen Namen als Parameter aufrufen, initMe("Hannibal), dann wird im Handler initMe ein Skriptobjekt mit dem übergebenen Namen in dessen Property myName angelegt. Am Ende des initMe-Handlers wird das Skriptobjekt mit return person zurückgeliefert. Grundlagen Das return person ist nicht unbedingt notwendig, da das Skriptobjekt auch implizit zurückgeliefert wird, wenn keine weiteren Anweisungen folgen. Ebenfalls unnötig ist hier die Angabe des Bezeichners für das Skriptobjekt (script person), über die auf das Skript zugegriffen werden kann. Dieses Skript liefert nur noch Kopien von sich zurück. Ein Zugriff erfolgt nicht mehr über den Namen, sondern nur noch über den Handler. Sie können den Konstruktor daher auch verkürzt so schreiben: on initMe(someName) script property myName : someName on getName() return myName end getName end script end initMe Als Ergebnis erhalten Sie in der Variablen newPerson ein Skriptobjekt, in dem myName gleich "Hannibal" ist. Auf diese Weise können Sie einzelne Skriptobjekte erzeugen,
440
Die Sprache
Kapitel 4
welche in Variablen abgespeichert werden, über die Sie bequem auf das Objekt zugreifen können. Wenn die Anzahl der zu erzeugenden Skriptobjekte jedoch nicht bekannt ist, ist eine Schleife zu bevorzugen. Und dann empfiehlt es sich, die Skriptobjekte in eine Liste zu packen und über den Index auf die Skriptobjekte zuzugreifen: property players : {} property playerNames : {"John", "Sarah", "Albert"} on run set players to {} repeat with i from 1 to length of playerNames copy initMe(item i of playerNames) to end of players end repeat getName() of some item of players end run on initMe(someName) script person property myName : someName on getName() return myName end getName end script return person end initMe Als Beispiel wird hier am Ende des run-Handlers mit some item von einem beliebigen Skriptobjekt in players die Property myNames abgefragt, woran Sie erkennen können, dass diese Person tatsächlich mit eigenem Namen initialisiert wurde. Zum Abschluss dieses Abschnitts nun noch einmal die komplette Würfelrunde inklusive Stimmenanpassung in der elegantesten und kürzesten Form mit Handler-Konstruktor: property property property property
players : {} playerNames : {"John", "Sarah", "Albert"} playerVoices : {"Bruce", "Vicki", "Albert"} playerScores : {0, 0, 0}
on run set players to {} repeat with i from 1 to length of playerNames copy initPlayers(item i of playerNames, item i of playerVoices) ¬ 441
SmartBooks
AppleScript
to end of players end repeat repeat with i in players tell i to setScore(random number from 1 to 6) end repeat say "Total results: " using "Alex" repeat with i from 1 to length of players set (item i of playerScores) to (item i of playerScores) + ¬ (getScore() of item i of players) say (getName() of item i of players) & " has a score of " & ¬ (item i of playerScores) using "Alex" end repeat end run on initPlayers(someName, someVoice) script person property myName : someName property score : 0 property voice : someVoice on setScore(x) say "Hello, its " & myName using voice say "I rolled a " & x using voice set score to x end setScore on setName(x) set myName to x end setName on setVoice(x) set voice to x end setVoice on getScore() return score end getScore on getName() return myName end getName end script return person end initPlayers
442
Die Sprache
Kapitel 4
Vererbung und Delegation Skriptobjekte können sich Eigenschaften und Handler teilen, indem diese vererbt werden. Das hat den Vorteil, dass ein neu zu definierendes Skriptobjekt bereits auf bestehende Skriptobjekte als Basis zugreifen kann und nicht noch einmal von vorne beginnen muss. Sinnvoll ist dies vor allem dort, wo thematische und strukturelle Verwandtschaften vorliegen. Zur Vererbung ist es notwendig, genau anzugeben, wer vererbt und wer erbt. Das wird mit einer Eigenschaft namens parent geregelt.
Die Property parent Jedes Skript und Skriptobjekt hat eine Eigenschaft namens parent. Diese Eigenschaft gibt an, wer die »Eltern« des Skriptobjekts sind, von wem das Skript oder Skriptobjekt also abstammt. Dabei gibt es in AppleScript immer nur einen Elternteil, also nicht etwa zwei. (Eine Mehrfachvererbung ist in AppleScript nicht möglich.)
Implizite Eltern Fragen Sie in einem leeren Skript einmal nach den Eltern: parent of me -- Ergebnis: «script AppleScript» Als Ergebnis wird das Skript mit dem Namen AppleScript zurückgeliefert. AppleScript selbst ist für jedes Skript die übergeordnete Klasse und liefert auf diesem Weg, wie zu Anfang besprochen, auch die ganzen Konstanten als Eigenschaften des Skripts mit. Doch AppleScript selbst ist noch nicht die letzte Instanz. Fragen Sie einmal nach den Großeltern: parent of parent of me -- Ergebnis: current application Die current application ist der Urgrund in AppleScript. Darunter kommt nichts mehr. Eine weitere Nachfrage nach den Urgroßeltern schlägt daher fehl: parent of parent of parent of me -- Fehler : „parent“ kann nicht gelesen werden. Wenn Sie nach der Klasse von current application fragen, erhalten Sie application als Antwort: class of current application -- Ergebnis: application Fragen Sie nach dem Namen der current application, erhalten Sie bei einem Skript im Skripteditor als Antwort:
443
SmartBooks
AppleScript
name of current application -- Ergebnis: "Script Editor" Die letzte Instanz in AppleScript ist also ein Programm. Wenn Ihr Skript aus dem Skripteditor gestartet wird, ist der Skripteditor diese current application, wird das Skript aus iTunes heraus gestartet, ist es iTunes. Haben Sie das Skript jedoch als Programm gesichert, ist das Applet selber die current application. Um das zu überprüfen, müssen Sie Ihrem Skript noch eine Eigenschaft namens name geben, da ein als Datei vorliegendes Skript diese Eigenschaft nicht besitzt – im Gegensatz zu Skriptobjekten mit Bezeichnern. Sichern Sie das folgende Skript als Programm und starten Sie es: property name : "TestScript" display dialog (get name of current application) Als Antwort erhalten Sie den Wert der Property name der current application. Da current application das Applet selber ist, wird seine eigene property mit dem Namen name zurückgeliefert. In diesem Fall also TestScript. Wenn das Applet keine Property name hat, gibt es eine Fehlermeldung, da nach dem Applet keine Autorität mehr folgt, die Antwort geben könnte. Die Eigenschaft parent kann aber nicht nur abgefragt werden, sie kann auch gesetzt werden – und hier fängt es an, richtig spannend zu werden. Zuerst aber stellt sich noch die Frage, wer standardmäßig parent eines gerade neu erstellten Skriptobjekts in einem Skript ist. Wenn Sie die Eigenschaft parent nicht ändern, ist jedes im Skript definierte Skriptobjekt ein Kind des Skripts, egal, wie tief es in anderen Skriptobjekten verschachtelt ist. Hier noch einmal die komplette Abstammungsübersicht inklusive Kindern und Enkeln. Bauen Sie dieses Skript zeilenweise auf, um die Ergebnisse zu überprüfen: property name : "Objekthierarchie.scpt" -- Ich me -- «script» name of me -- "Objekthierarchie.scpt" -- Eltern: parent of me -- «script AppleScript» -- get name of parent of me -- "AppleScript" (Bug!) -- Großeltern: parent of parent of me -- current application 444
Die Sprache
Kapitel 4
name of parent of parent of me -- "Script Editor" -- Kinder: parent of sub -- «script» name of parent of sub --"Objekthierarchie.scpt" parent of subsub of sub -- «script» name of parent of subsub of sub -- "Objekthierarchie.scpt" script sub beep script subsub beep end script end script In diesem Skript sehen Sie, dass die Abfrage nach me das Skript selbst ergibt. Wenn man nach dem Namen von me fragt, erhält man den Inhalt der im Skript zu Anfang definierten Property name. -- Ich me -- «script» name of me -- "Objekthierarchie.scpt" Als Nächstes wird mit parent of nach den Eltern des Skripts gefragt: -- Eltern: parent of me -- «script AppleScript» -- get name of parent of me -- "AppleScript" (Bug!) Hier sieht man, dass parent des Skripts ein Skript namens AppleScript ist. Das ist AppleScript selbst. Die Abfrage nach dem Namen der Eltern mit (get name of parent of me) ist hier auskommentiert. Sie bringt den Skripteditor bei mir in einen unkontrollierbaren Zustand, der sich nur durch zwangsweises Beenden und Neustart des Skripteditors beheben lässt! Auf einem anderen Rechner gibt es nur eine Fehlermeldung. Im Script Debugger funktioniert es hingegen, und AppleScript wird als Ergebnis zurückgeliefert. Als Nächstes wird nach den Großeltern gefragt: -- Großeltern: parent of parent of me -- current application name of parent of parent of me -- "Script Editor" Die Großeltern, oder parent des script AppleScript, sind die Anwendung, aus der heraus ein Skript gestartet wird. Ist das Skript als Applet gesichert worden, ist das Skript dann
445
SmartBooks
AppleScript
übrigens selber seine current application. Das Skript ist damit sozusagen erwachsen geworden. Die current application ist also der Urvater oder die Urmutter aller Skriptobjekte, die in AppleScript geschrieben werden, und ist damit die letzte Instanz und für alles zuständig, was nicht schon vorher von den Urenkeln, Enkeln und Kindern selbstständig erledigt wurde. Das Skriptobjekt sub, welches am Ende definiert wird, ist ein Kind des Skripts: parent of sub -- «script» name of parent of sub --"Objekthierarchie.scpt" Das wirklich Überraschende aber ist, dass auch das Skriptobjekt subsub, welches im Skriptobjekt sub definiert ist, ein Kind des Skripts ist und nicht etwa des Skriptobjekts sub. parent of subsub of sub -- «script» name of parent of subsub of sub -- "Objekthierarchie.scpt" Jedes Skriptobjekt in Ihrem Skript ist standardmäßig ein Kind des Skripts selber. Die Verschachtelung eines Skriptobjekts sagt also nichts über seine Abstammung aus. Sie bestimmt nur, wer Element von wem ist, wodurch sich die Objekthierarchie in einem tell definiert: tell subsub of sub to run script sub display dialog "I'm running" script subsub beep end script end script Die Abstammung hingegen wird nur (und wirklich nur) durch die Eigenschaft parent bestimmt! Ein Skriptobjekt kann damit Element eines anderen Skriptobjekts sein, ohne deswegen mit ihm verwandt sein zu müssen. Standardmäßig sind also alle Skriptobjekte erst einmal Kinder des aktuellen Skripts.
Explizite Eltern Da die Eigenschaft parent aber auch geändert werden kann, können Sie die Abstammung bewusst nach Herzenslust ändern. Warum sollte man das tun? Nun, ein Kind hat Zugang auf die Propertys und Handler seiner Eltern, ja sogar seiner Großeltern, Urgroßeltern und so weiter, so tief Sie auch immer
446
Die Sprache
Kapitel 4
die Abstammung führen wollen. Einem Skriptobjekt steht das gesammelte und angehäufte Erbe aller Vorfahren zur Verfügung. Hier ein Skriptobjekt mit dem Namen styleTemplate, welches eine Stilvorlage für Formen darstellen soll. Es definiert zwei Propertys, eine für die Farbe des Objekts und eine für die Entscheidung, ob es einen Rand erhalten soll. Dazu kommen Handler, um diese Werte von außen zu verändern. Wenn man streng objektorientiert vorgehen möchte, wird man auch noch Methoden (Handler) für den Zugriff auf die Instanzvariablen (properties) implementieren. script styleTemplate property shapeColor : {65535, 65535, 65535} -- RGB white property hasBorder : false -- mit Rand? on setShapecolor(rgbValue) set shapeColor to rgbValue end setShapecolor on setHasBorder(trueOrFalse) set hasBorder to trueOrFalse end setHasBorder end script on makeRect(x, y) script rectangle property parent : styleTemplate property xWidth : x property yHeight : y on setWidth(inCentimeters) set xWidth to inCentimeters end setWidth on setHeight(inCentimeters) set yHeight to inCentimeters end setHeight end script end makeRect set myRect to makeRect(5, 6) get shapeColor of myRect -- Ergebnis: {65535, 65535, 65535} Das zweite Skriptobjekt nennt sich rectangle, steht für ein Rechteck und gibt als Erstes über das Setzen der Property parent an, dass es von styleTemplate abstammt. Dann definiert es zwei Propertys für die Breite und Höhe des Rechtecks und die dazugehörigen Handler zum Setzen dieser Werte.
447
SmartBooks
AppleScript
Wichtig ist hier die Reihenfolge der Skriptobjekte: Die Eltern müssen im Skript immer vor der Definition des Kindes stehen, da ansonsten der Bezug auf die Eltern nicht klappt. Also immer erst die Eltern definieren und dann die Kinder. Des Weiteren ist darauf zu achten, dass Kinder nicht in ihren Eltern geschachtelt sein können. Sie müssen immer außerhalb von ihnen definiert werden. Die Schachtelung eignet sich zur Darstellung von Elementen eines Skriptobjekts, aber nicht zum Darstellen ihrer Abstammung. Am Ende wird eine Instanz vom Skriptobjekt rectangle erzeugt und in der Variablen myRect gespeichert. Dann wird die Farbe von myrect abgefragt (shapeColor of myRect). Obwohl die Farbe in rectangle gar nicht definiert wurde, hat rectangle sie von den Eltern geerbt. Als Antwort erhalten Sie daher die Farbe Weiß. Das Skriptobjekt styleTemplate dient hier als eine abstrakte Klasse für alle möglichen Formen. Abstrakt in dem Sinne, dass Sie nicht »eine weiße Vorlage mit oder ohne Rand« erzeugen können. Alles, was Sie im realen Leben erzeugen können, ist eine Spezifizierung davon, zum Beispiel ein Rechteck oder ein Kreis. Die Elternklasse styleTemplate definiert hier nur die Elemente, die alle Formen, die davon abstammen, später gemeinsam haben sollen. Hier sollen alle Kinder weiß sein und keine Randlinie besitzen.
Eine Property für alle Kinder Darin liegt nun das Besondere, egal, wie viele Kinder Sie nun von dem Skriptobjekt styleTemplate definieren oder wie viele Kinder des Typs rectangle Sie erzeugen, sie teilen sich alle dieselbe Farbe und denselben Rand. Erzeugen Sie noch ein weiteres Skriptobjekt am Ende des obigen Skripts: set myRect2 to makeRect(3, 3) Fragen Sie nun nacheinander nach der Farbe von myRect und myRect2: get shapeColor of myRect -- {65535, 65535, 65535} get shapeColor of myRect2 --{65535, 65535, 65535} Sie fragen hier nach der Farbe der Skriptobjekte vom Typ rectangle. Wenn Sie jedoch in das Skript rectangle hinein schauen, werden Sie sehen, dieses Objekt hat gar keine Eigenschaft namens shapeColor. Diese Property kommt also tatsächlich von den Eltern. Die Kinder liefern die Farbe der Eltern zurück. Ändern Sie nun die Farbe des Skriptobjekts styleTemplate (einfach ans Ende des Skripts anfügen): setShapecolor({0, 0, 0}) of styleTemplate Fragen Sie dann erneut nach der Farbe der beiden Rechtecke:
448
Die Sprache
Kapitel 4
get shapeColor of myRect -- {0, 0, 0} (black) get shapeColor of myRect2 -- {0, 0, 0} Die Farbe der beiden Rechtecke hat sich geändert, und zwar indem die Farbe der Eltern geändert wurde. Diese Eigenschaft der Vererbung lässt sich daher gut für Vorlagen aller Art verwenden, in denen es möglich sein muss, alle Objekte derselben Art in einem Rutsch zu ändern. Ohne Vererbung müssten Sie eine Schleife über alle Skriptobjekte drehen und für ein Skriptobjekt nach dem anderen die Farbe ändern. So ändern Sie die Farbe eines einzigen Objekts, und alle Objekte, die davon abstammen, ändern ebenfalls ihre Farbe.
Ein Handler für alle Kinder und implizite Delegation Im obigen Fall wurde die Farbe der Eltern geändert und die Farbe aller Kinder änderte sich mit, da die Kinder diese von den Eltern gerbt hatten. Interessant ist, dass Sie gar nicht wissen müssen, wer die Eltern sind, es reicht, die Methode zu kennen, mit der man die Farbe ändern kann. Sie können dann auch einem beliebigen Kind sagen, das es die Farbe ändern soll. Als Folge ändern alle Geschwister ebenfalls die Farbe. Hier das Skript nochmal in voller Länge: script styleTemplate property shapeColor : {65535, 65535, 65535} -- white property hasBorder : false -- mit Rand? on setShapecolor(rgbValue) set shapeColor to rgbValue end setShapecolor on setHasBorder(trueOrFalse) set hasBorder to trueOrFalse end setHasBorder end script on makeRect(x, y) script rectangle property parent : styleTemplate property xWidth : x property yHeight : y on setWidth(inCentimeters) set xWidth to inCentimeters end setWidth on setHeight(inCentimeters) set yHeight to inCentimeters 449
SmartBooks
AppleScript
end setHeight end script end makeRect set myRect to makeRect(5, 6) set myRect2 to makeRect(3, 3) setShapeColor({65535, 0, 0}) of myRect get shapeColor of myRect -- {65535, 0, 0} --rot get shapeColor of myRect2 -- {65535, 0, 0} get shapeColor of styleTemplate -- {65535, 0, 0} Schreiben Sie die letzten drei Zeilen nacheinander oder kommentieren Sie sie nacheinander aus und führen Sie das Skript jedes Mal erneut aus, um das Ergebnis zu überprüfen. Obwohl hier nur die Farbe von myRect geändert wurde, hat auch das Geschwisterobjekt myRect2 die Farbe geändert und sogar das Elternobjekt styleTemplate! Das Verrückte jedoch ist, dass das Kind myRect gar keinen Handler namens setShapeColor besitzt! Trotzdem wird dieser hier aufgerufen. Was tatsächlich aufgerufen wird, und zwar über das Kind, ist hier der Handler der Eltern styleTemplate. Diese besitzen einen Handler mit dem Namen setShapeColor, und den dürfen per Vererbung alle Kinder benutzen. Ein Kind führt hier die Anweisung über die Eltern für alle aus. Jedes Kind hat das Recht, sein Erbe zu nutzen. Dazu gehört auch der Zugriff auf sämtliche Handler der Eltern. Das Kind delegiert jeden Befehl automatisch an die Eltern, wenn es ihn nicht versteht. Es ist sehr wichtig, das zu verstehen. Wenn ein Kind einen Befehl bekommt, den es nicht versteht, sei es ein Befehl, um einen Handler auszuführen, oder einfach nur die Abfrage einer Property, dann reicht das Kind diesen Befehl an die Eltern weiter. Verstehen die Eltern den Befehl, dann führen sie ihn aus, kennen sie ihn ebenfalls nicht, reichen sie den Befehl wiederum an ihre Eltern weiter. Und so weiter, bis der Befehl im ungünstigsten Fall irgendwann in der current application landet und einen Fehler verursacht, wenn er auch dort nicht bekannt ist.
Rückgabewerte der Eltern Wenn der Handler der Eltern einen Wert zurückliefert, dann wird dieser Wert nur an das Kind zurückgeliefert, welches den Aufruf getätigt hat. Im folgenden Beispiel wurde das
450
Die Sprache
Kapitel 4
Skriptobjekt styleTemplate um einen Handler erweitert, welcher die Fläche eines Rechtecks berechnet und zurückliefert: script styleTemplate property shapeColor : {65535, 65535, 65535} -- white property hasBorder : false -- mit Rand? to setShapecolor to rgbValue set shapeColor to rgbValue end setShapecolor to setHasBorder to trueOrFalse set hasBorder to trueOrFalse end setHasBorder to getArea from sideA to sideB return sideA * sideB end getArea end script on makeRect(x, y) script rectangle property parent : styleTemplate property xWidth : x property yHeight : y property myArea : getArea of me from xWidth to yHeight to setWidth to xCentimeters set xWidth to xCentimeters end setWidth to setHeight to yCentimeters set yHeight to yCentimeters end setHeight end script end makeRect set myRect to makeRect(5, 6) set myRect2 to makeRect(3, 3) log myArea of myRect -- (*30*) log myArea of myRect2 -- (*9*) Das Kind rectangle hat nur eine einzige weitere Property erhalten. Deren Wert bestimmt sich durch den Ausdruck: getArea of me from xWidth to yHeight
451
SmartBooks
AppleScript
Hier wird bereits bei der Erstellung des Skriptobjekts ein Handler der Eltern aufgerufen. Der Rückgabewert landet in der Property myArea des Skriptobjekts myRect. Da diese Property vom Kind selbst definiert ist, kann sie für jedes Kind einen anderen Wert enthalten. Die Ermittlung dieses Wertes ist jedoch für alle Kinder gleich. Bei der Erschaffung eines Kindes wird ja die Breite und Höhe mit angegeben, und aus dieser ermitteln die Eltern dann die Fläche des Rechtecks und geben sie dem Kind in der Property myArea mit. Der Rückgabewert ist also nur für das eine Kind bestimmt. Das gilt aber nicht nur während der Erschaffung eines Skriptobjekts, sondern auch im Nachhinein. Im Folgenden ändert ein Kind zum Beispiel seine Breite und Höhe. Damit danach auch die Fläche in myArea angepasst wird, muss erneut der Handler der Eltern aufgerufen werden, um die Fläche zu berechnen. In fetter Schrift die Änderung der Breite und Höhe und der Aufruf an die Eltern. Am Schluss das Resultat, welches im Event-Protokoll verifiziert werden kann: script styleTemplate property shapeColor : {65535, 65535, 65535} -- white property hasBorder : false -- mit Rand? to setShapecolor to rgbValue set shapeColor to rgbValue end setShapecolor to setHasBorder to trueOrFalse set hasBorder to trueOrFalse end setHasBorder to getArea from sideA to sideB return sideA * sideB end getArea end script on makeRect(x, y) script rectangle property parent : styleTemplate property xWidth : x property yHeight : y property myArea : getArea of me from xWidth to yHeight to setWidth to xCentimeters set xWidth to xCentimeters end setWidth to setHeight to yCentimeters set yHeight to yCentimeters end setHeight end script 452
Die Sprache
Kapitel 4
end makeRect set myRect to makeRect(5, 6) set myRect2 to makeRect(3, 3) log myArea of myRect -- (*30*) log myArea of myRect2 -- (*9*) tell myRect set its xWidth to 2 set its yHeight to 2 set its myArea to getArea from its xWidth to its yHeight end tell log myArea of myRect -- (*4*) log myArea of myRect2 -- (*9*) Danach hat myRect eine Fläche von 4, myrect2 aber immer noch seine Fläche von 9, was im Event-Protokoll durch die log-Anweisung verifiziert wird. Rückgabewerte landen also nur bei dem Kind, welches den Handler aufgerufen hat.
Me und my in Skriptobjekten mit explizitem parent Wenn Sie sich die fett dargestellten Stellen im Code des vorigen Abschnitts ansehen, wird Ihnen dort sicher die Verwendung des Wortes me und die inflationäre Verwendung von its auffallen. Diese sind dort tatsächlich so oft nötig. Die Verwendung von its beim Aufruf wurde bereits im Kapitel Zugriff auf Propertys eines Skriptobjekts beschrieben. Kurz zusammengefasst brauchen Sie its, sobald Sie in einem tell-Block an das Skriptobjekt auf dessen Propertys zugreifen wollen, ansonsten wird vermutet, dass es sich bei dem Bezeichner um eine neue Variable handelt. Sie brauchen es nicht für den Zugriff auf dessen Handler. Ein me oder my bezieht sich immer auf das Skriptobjekt, in dem es steht: script robert property parentsHome : "Berlin" on setHome to someTown set parentsHome to someTown end setHome return me end script script child 453
SmartBooks
AppleScript
property parent : robert return me end script set x to run robert -- «script robert» set x to run child -- «script child» Wenn Sie also in einem Skriptobjekt einem Befehl of me anfügen oder ein my davor schreiben, dann wird dieser Befehl an das Skriptobjekt selbst geschickt, und nur falls das Skriptobjekt diesen Befehl nicht kennt, wird es an dessen Eltern weitergeleitet. Ist die Property parent nicht vorhanden, dann ist das wieder das Skript. Im folgenden Beispiel würden Sie die Fehlermeldung erhalten, dass die Variable myHome nicht definiert ist, wenn Sie das my davor weglassen: script robert property parentsHome : "Berlin" on setHome to someTown set parentsHome to someTown end setHome end script script child property parent : robert return my parentsHome end script setHome of robert to "Dresden" run child -- "Dresden" Greifen Sie auf einen Handler des Elternobjekts zu, so ist das my oder of me nicht erforderlich, egal, ob es sich um den impliziten run-Handler oder einen anderen Handler handelt: script robert property parentsHome : "Berlin" on setHome to someTown set parentsHome to someTown end setHome end script script child property parent : robert setHome to "München" 454
Die Sprache
Kapitel 4
end script run child get parentsHome of robert -- "München" Umgekehrt können auch die Eltern mit my auf Propertys des Kindes zugreifen, wenn von diesen eine Anfrage kommt: script robert property parentsHome : "Berlin" on getHomeOfChild() display dialog my childsHome end getHomeOfChild end script script child property parent : robert property childsHome : "Dresden" end script tell child to getHomeOfChild() -- Dresden Der Befehl muss dabei an das Kind gerichtet werden. Das Kind kennt diesen Befehl nicht und leitet ihn an die Eltern weiter. Da der Befehl vom Kind kommt, können die Eltern mit my auf dessen Propertys zugreifen.
Überschreiben oder »Eigensinnige Kinder« Bisher scheint es so, als habe das Kind eines Skriptobjekts bezüglich seiner Erbschaft keine große Wahl. Wenn die Eltern rot sind, dann sind auch alle Kinder rot, ob sie es wollen oder nicht. Nun, ganz so schlimm ist es nicht. Jedes Kind hat durchaus die Möglichkeit, sich die Erbschaft der Eltern umzudefinieren. Sie können nicht darauf verzichten, aber sie können sich von der Erbschaft lösen, indem sie diese umdefinieren. Die drastischste Methode würde eigentlich darin bestehen, einem Skriptobjekt einfach andere Eltern, die besser zu ihm passen, zuzuweisen. Das ist jedoch nicht möglich, da die Property parent nach der Erstellung des Skriptobjekts schreibgeschützt ist. Jeder Versuch, diese zu ändern, wird daher fehlschlagen. Die Eltern lassen sich also nur in der Skriptobjektdefinition selbst ändern. Nachdem aber ein Objekt davon erzeugt wurde, muss ein Skriptobjekt mit seinen Eltern leben und auskommen. Es liegt an Ihnen als Programmierer, durch gute Planung ein harmonisches Miteinander zu ermöglichen.
455
SmartBooks
AppleScript
Ansonsten, wenn Sie nichts zu verlieren haben, können Sie natürlich jederzeit dem Variablennamen, der bisher für das Skriptobjekt stand, ein anderes Skriptobjekt zuweisen. Wenn diese Variable der einzige Bezeichner war, mit dem man darauf zugreifen konnte, ist das Skriptobjekt danach für immer verloren, und ein völlig anderes Skriptobjekt mit dem gleichen Namen tritt an dessen Stelle. Im folgenden Beispiel wird dem Bezeichner für das Skriptobjekt rectangle das Skriptobjekt dummy zugewiesen. Das Skriptobjekt rectangle ist damit tot und nicht mehr erreichbar: script shape property shapeColor : {65535, 65535, 65535} get me --… end script script dummy property name : "dummy" get me --… end script script rectangle property parent : shape get me --… end script get rectangle -- «script rectangle» set rectangle to dummy get rectangle -- «script dummy» Eigentlich handelt es sich hierbei um einen Selbstmord. Die äußere Hülle wird danach aber wieder von jemand anderem mit Leben erfüllt. Jedenfalls ist es hier wohl eher der Bezeichner rectangle, der ein neues Leben beginnen kann. Das, was das Skriptobjekt rectangle vorher ausmachte, ist verloren. Aufgepasst Erstellen Sie niemals ein Skriptobjekt ohne Handler. Geben Sie diesem nämlich einen run-Befehl, so bekommen Sie den Fehler „der Stack ist übergelaufen“. Das ist nicht weiter schlimm, könnte aber für Verwirrung sorgen. Um nicht in diese Fehlermeldung hineinzulaufen, gebe ich leeren Skriptobjekten immer eine sinnlose Anweisung mit, zum Beispiel get me, log me oder beep, wodurch der implizite run-Handler im Skriptobjekt erwacht. Normalerweise geht man nicht so drastisch vor, sondern man wählt aus.
456
Die Sprache
Kapitel 4
Ihr Skriptobjekt soll grün werden und nicht rot? Dann müssen Sie nur die Eigenschaft der Eltern »überschreiben«. Sie können diese Eigenschaft niemals loswerden, Sie können sie aber vereinnahmen und sich damit zumindest in Bezug auf diese eine Eigenschaft von der Abhängigkeit zu den Eltern lösen. Das geht, indem Sie die Eigenschaft der Eltern im Kind selber definieren, mit exakt demselben Namen wie bei den Eltern, und ab sofort ist das Kind diesbezüglich emanzipiert. Es wird die Eigenschaft auf diese Weise zwar nicht los, aber es kann nun, unabhängig von den Geschwistern, seine eigene Farbe tragen: script shape property shapeColor : {65535, 65535, 65535} get me --… end script on makeRect(x, y) script rectangle property parent : shape property xWidth : x property yHeight : y property shapeColor : {0, 0, 0} get me --… end script end makeRect set myRect to makeRect(8, 5) shapeColor of myRect -- {0, 0, 0} Wenn das Skript wie oben in einem Konstruktor steht, werden von nun an natürlich alle Skriptobjekte dieser Art ihre eigene Farbe haben. Normalerweise wird daher zuerst ein Kind von rectangle erzeugt, also der erste Enkel von shape, welches dann seine eigene Farbe bekommt: script shape -- Der Großvater property shapeColor : {65535, 65535, 65535} get me --… end script on makeRect(x, y) script rectangle property parent : shape 457
SmartBooks
AppleScript
property xWidth : x property yHeight : y get me --… end script end makeRect -- rectSoloFather – Der Vater set rectSoloFather to makeRect(1, 1) on makeRectSolo(x, y) script rectSoloColor property parent : my rectSoloFather property shapeColor : {0, 0, 0} -- Eigene Farbe! end script end makeRectSolo -- myRect – Der Sohn set myRect to makeRectSolo(8, 5) -- Farbe des Sohnes: shapeColor of myRect -- {0, 0, 0} -- Farbe der Eltern: shapeColor of parent of myRect -- {65535, 65535, 65535} Da beide Skriptobjektdefinitionen in Handlern stecken, muss man natürlich erst einmal eine Instanz von rectangle erschaffen, die dann als Vater für das neue Rechteck mit eigener Farbe dienen kann. Oben ist dies rectSoloFather. Die Kehrseite der Medaille ist nun aber, dass dieses Kind nicht mehr auf eine Änderung der Elternfarbe reagiert. Fügen Sie zum Testen einfach die folgenden Zeilen an das Ende des Codes oben an: -- myRect – Das farbunabhängige Kind set myRect to makeRectSolo(8, 5) -- myRect2 – Das farbabhängige Kind set myRect2 to makeRect(2, 3) -- Ändern der Farbe des Großvaters: set shapeColor of shape to {65535, 65535, 0} set text item delimiters to ", " -- Farbe des farbabhängigen Kindes: 458
Die Sprache
Kapitel 4
log "myRect2's Farbe: " & shapeColor of myRect2 -- Farbe des farbunabhängigen Kindes: log "myRect's Farbe: " & shapeColor of myRect -- Event-Protokoll: (*myRect2's Farbe: 65535, 65535, 0*) (*myRect's Farbe: 0, 0, 0*)
Überschreiben von Handlern Dieses Überschreiben von Eigenschaften funktioniert aber nicht nur mit Propertys, sondern auch mit Handlern: script shape on calcArea(xWidth, yHeight) return xWidth * yHeight end calcArea end script on makeCircle() script circle property parent : shape on calcArea(x) pi * (x ^ 2) end calcArea end script end makeCircle set newCircle to makeCircle() tell newCircle to calcArea(5) -- 78.5398... Hier wird ein Skriptobjekt für Kreise angelegt, es erbt die Methode calcArea von shape. Diese ist aber nicht für Kreise geeignet. Aus diesem Grund wird der Handler calcArea hier im Kind circle einfach noch einmal definiert und auf die Formel zur Flächenberechnung eines Kreises angepasst. Wichtig ist hierbei nur, dass der Name des Handlers exakt derselbe ist wie der des Elternobjekts. Oben ist dies calcArea. Wie viele Parameter diese haben, ist dabei uninteressant. Hier wird vom Kreisobjekt eine Fläche bei einem Radius von 5 korrekt berechnet. Man sagt auch, der Handler der Eltern wurde »überschrieben«. Der Handler der Eltern ist damit mit normalen Mitteln vom Kind aus nicht mehr zugänglich.
459
SmartBooks
AppleScript
Grundlagen Würden Sie den Aufruf mit zwei Parametern machen, wird dabei nicht etwa das Elternobjekt aufgerufen, nein, die restlichen Parameter werden vom Kreisobjekt verworfen. Dies ist also keine Möglichkeit, Handler zu implementieren, die sich mit einer unterschiedlichen Anzahl an Parametern »überladen« lassen. Das ist in AppleScript generell nicht möglich und kann am besten noch durch die Übergabe einer Liste mit unterschiedlicher Anzahl an Elementen imitiert werden.
Polymorphismus Wenn Sie ein und denselben Befehl an verschiedene Skriptobjekte senden und jedes Skriptobjekt auf seine Weise darauf reagiert, dann nennt man das in der objektorientierten Programmierung »Polymorphismus«. Hier ein Beispiel mit einer Auto-Klasse. Die Methoden sind dabei alle im Elternteil definiert, da sie für alle Autos gleichermaßen gelten. Die Werte dafür kommen jedoch vom Kind. Je nachdem, welches Kind Sie fragen, erhalten Sie unterschiedliche Antworten, obwohl die Ausführung durch die Eltern erfolgt, welche mit my auf die Eigenschaften des Kindes zugreifen: script cars property beepTimes : 1 property maxSpeed: 120 property wheels : 4 on honk() beep my beepTimes end honk on getMaxSpeed() display dialog "Höchstgeschwindigkeit: " & my maxSpeed end getMaxSpeed end script on someSportscar(col, speed, xtim) script sportscar property parent : cars property itsColor : col property maxSpeed : speed property beepTimes : xtim end script end someSportscar set newCar to someSportscar("red", 240, 3)
460
Die Sprache
Kapitel 4
set newCar2 to someSportscar("yellow", 320, 5) tell newCar to getMaxSpeed() tell newCar to honk() tell newCar2 to getMaxSpeed() tell newCar2 to honk() Als Ergebnis wird zuerst ein Dialog mit dem Text »Höchstgeschwindigkeit 240« angezeigt, und danach ertönt dreimal ein beep. Danach folgt das zweite Auto und es zeigt eine Höchstgeschwindigkeit von 320 an und hupt fünfmal. Welches Kind Sie auch immer fragen, Sie werden von jedem die richtige Antwort bekommen, obwohl die Eltern sich um die Ausführung kümmern. Aktionen, die für alle Objekte eines Typs charakteristisch sind, sollten daher nach Möglichkeit schon in den Eltern implementiert werden, dadurch können Sie sicher sein, für alle Kinder dieselben Befehle zur Verfügung zu haben. Wenn Sie in obigem Beispiel direkt die Mutter fragen würden: tell cars to getMaxSpeed() tell cars to honk() erhielten Sie deren Werte, nämlich eine Höchstgeschwindigkeit von 120 und ein einfaches beep als Antwort. Je nachdem, von wem die Anfrage kommt, werden dessen Werte verwendet. Vorraussetzung ist dafür nur, dass bei den Eltern explizit mit my auf diese Eigenschaften zugegriffen wird. Hier noch ein Beispiel zu den bisherigen Rechteck-Beispielen: script rectangle property width : 1 property height : 1 on getArea() (my width) * (my height) end getArea end script on makeRect(xWidth, yHeight) script property parent : rectangle property width : xWidth 461
SmartBooks
AppleScript
property height : yHeight end script end makeRect set newRect to makeRect(5, 3) set newRect2 to makeRect(8, 8) tell newRect to getArea() -- 15 tell newRect2 to getArea() -- 64 tell rectangle to getArea() -- 1 Die Methode zur Berechnung der Fläche gehört also in die Eltern, denn diese ist für alle Kinder gleich. Das Kind muss nichts darüber wissen, wie sich die Fläche eines Rechtecks berechnen lässt. Sie senden einfach den Befehl getArea an ein Rechteck, und Sie erhalten die Fläche dieses Rechtecks. Senden Sie den Befehl an ein anderes Rechteck-Objekt, so erhalten Sie dessen Fläche. Sie senden den Befehl an die Eltern selbst und Sie erhalten deren Fläche. Sie müssen nur den Befehl und die Parameter kennen. Jedes Objekt wird sich beim Erhalten des Befehls seinen Daten entsprechend korrekt verhalten. Wenn Sie jedoch im Kind den Handler der Eltern überschreiben, ist kein my notwendig. Wessen Handler dann ausgeführt wird, hängt nur vom verwendeten Ziel ab: script cars property maxSpeed : 120 on getMaxSpeed() display dialog "Höchstgeschwindigkeit: " & my maxSpeed end getMaxSpeed end script on someSportscar(speed) script property parent : cars property maxSpeed : speed on getMaxSpeed() say "I can run at " & speed & " kilometers an hour" end getMaxSpeed end script end someSportscar set newCar to someSportscar(240) tell newCar to getMaxSpeed() tell cars to getMaxSpeed() 462
Die Sprache
Kapitel 4
In diesem Beispiel wird der Sportwagen newCar seine Höchstgeschwindigkeit mit say ansagen, das Elternobjekt jedoch mit display dialog.
Delegation an die Eltern und der Befehl continue Der Handler der Eltern ist aber nicht unerreichbar für ein Skript, welches diesen Handler überschreibt. Normalerweise wird das Kind immer seinen eigenen Handler verwenden, trotzdem kann es den Handler der Eltern noch explizit aufrufen, zum Beispiel durch die Angabe of parent: script cars property maxSpeed : 120 on getMaxSpeed() display dialog "Höchstgeschwindigkeit: " & my maxSpeed end getMaxSpeed end script on someSportscar(speed) script sportscar property parent : cars property maxSpeed : speed on getMaxSpeed() say "Yeah, I'm really fast!" getMaxSpeed() of parent end getMaxSpeed end script end someSportscar set newCar to someSportscar(240) tell newCar to getMaxSpeed() -- 120 Als Folge erhalten Sie die Höchstgeschwindigkeit der Eltern und nicht die des Kindes. Der ursprüngliche Befehl getMaxSpeed, der an das Kind newCar gerichtet wurde, wurde also unterbrochen, aus diesem Grund ist der Polymorphismus hier zerstört. Um das zu vermeiden, gibt es den continue-Befehl. Sie geben dafür einfach das Wort continue ein, gefolgt von einem vollständigen Handleraufruf mit sämtlichen Parametern. Bei Verwendung von continue wird der ursprüngliche Befehl weitergeleitet, und der Polymorphismus wird nicht unterbrochen: script cars property maxSpeed : 120 on getMaxSpeed() 463
SmartBooks
AppleScript
display dialog "Höchstgeschwindigkeit: " & my maxSpeed end getMaxSpeed end script on someSportscar(speed) script sportscar property parent : cars property maxSpeed : speed on getMaxSpeed() say "Yeah, I'm really fast!" continue getMaxSpeed() end getMaxSpeed end script end someSportscar set newCar to someSportscar(240) tell newCar to getMaxSpeed() -- 240 Als Ergebnis erhalten Sie nun tatsächlich die eigene Geschwindigkeit und nicht die der Eltern. Der Polymorphismus bleibt also intakt. An diesem Beispiel können Sie auch sehen, wie Handler der Eltern auf diese Weise im Kind erweitert werden können. Sie müssen nicht den gesamten Handler der Eltern erneut schreiben. Nehmen Sie Ihre Ergänzungen vor und delegieren Sie den Befehl dann einfach mit continue. Im folgenden Beispiel wird für die Erstellung eines Rechtecks nur noch ein einziger Wert benötigt. Dieser kann eine einzelne Zahl sein, in welchem Fall es sich um ein Quadrat handelt, oder eine Liste mit zwei Zahlen. Dann handelt es sich um ein Rechteck mit unterschiedlicher Seitenlänge. Dementsprechend werden im Handler getArea des Kindes, dessen Eigenschaften width und height gesetzt und dann erst zur Berechnung an die Eltern weitergeleitet: script rectangle property width : 1 property height : 1 on getArea() (my width) * (my height) end getArea end script on makeRect(x) script 464
Die Sprache
Kapitel 4
property parent : rectangle property param : x property width : missing value property height : missing value on getArea() if class of x is in {integer, real} then set width to param set height to param continue getArea() else if class of param is list then if class of item 1 of param is in {integer, real} and ¬ class of item 2 of param is in {integer, real} then set width to item 1 of param set height to item 2 of param continue getArea() end if end if end getArea end script end makeRect set newRect to makeRect(5) -- Quadrat set newRect2 to makeRect({8, 5}) -- Rechteck tell newRect to getArea() -- 25 tell newRect2 to getArea() -- 40 Wenn ein Handler der Eltern Parameter besitzt, können Sie diese im continue auch noch verändern. Im folgenden Beispiel wird die Höchstgeschwindigkeit durch das Alter des Automobils modifiziert – je älter das Auto, je mehr wird von der Höchstgeschwindigkeit abgezogen: script cars property maxSpeed : 120 on getMaxSpeed(age) display dialog "Höchstgeschwindigkeit: " & (my maxSpeed) - (age * 4) end getMaxSpeed end script on someSportscar(speed, age) script sportscar property parent : cars property maxSpeed : speed 465
SmartBooks
AppleScript
property myAge : age on getMaxSpeed() say "Yeah, I'm really fast!" continue getMaxSpeed(myAge - 3) -- wegen Motoraustausch 3 Jahre vom Alter abgezogen! end getMaxSpeed end script end someSportscar set newCar to someSportscar(240, 5) tell newCar to getMaxSpeed() -- 232
Befehle von Skripterweiterungen oder Anwendungen überschreiben Sie können einem Skriptobjekt auch einen Befehl aus den Skripterweiterungen oder aus einer Anwendung senden. Dieser Befehl wird von dem Skriptobjekt empfangen und kann von ihm geblockt, verändert und weitergeleitet werden. Hier ein einfaches Beispiel: script catchCmds on beep say "Beep" end beep on display dialog sometext continue display dialog sometext & ¬ " *** controlled by script catchCmds" end display dialog end script tell catchCmds beep display dialog "Hallo Welt" end tell Der beep-Befehl aus den Standard-Erweiterungen wird hier komplett überschrieben und nicht mit continue weitergeleitet. Das heißt, er wird niemals ausgeführt, stattdessen implementiert das Script catchCmds ein beep auf gesprochener Basis. Das display dialog wird mit continue weitergeleitet, allerdings wird ein Parameter davon verändert, indem immer ein weiteres Stück Text angehängt wird.
466
Die Sprache
Kapitel 4
Abb. 4-24 Ein Display-Dialog wird abgefangen und verändert. Auf diese Weise können Sie Befehle von einer Erweiterung mit eigenen Aktionen koppeln, sei es, um sie zu verändern, zu erweitern oder einfach nur, um sie zum Beispiel zu protokollieren. Sie müssen alle diese Befehle dann jedoch immer an das Skriptobjekt richten. Einen der wenigen Grundbefehle von AppleScript selbst abzufangen, das ist sehr viel schwieriger, da sich diese nicht an ein tell halten: script catchCmds on count x beep continue count x end count end script tell catchCmds to count {1, 2, 3} Das beep wird hier niemals ausgeführt werden, da count im Aufruf immer zuerst ausgeführt wird. Daraus ergibt sich hier eine 3, und diese 3 ist es, die an das Skriptobjekt gesendet wird. Wenn Sie count jedoch keine zählbare Menge mitgeben tell catchCmds to count 8 funktioniert der Aufruf.
467
SmartBooks
AppleScript
Aufgepasst Die grundlegenden Befehle wie set, copy, get und count sollten Sie immer in Ruhe lassen. Eine solche Verwendung ist von Apple nicht vorgesehen. Sie sägen damit an den Grundlagen der Sprache und sich vielleicht den Ast ab, auf dem Sie sitzen. Befehle an Anwendungen können Sie nicht direkt an ein Skriptobjekt senden, da diese ja in einem tell-Block an die Anwendung stehen müssen, um verstanden zu werden, und ein Handler kann nicht in einem tell-Block stehen. Wenn Sie Befehle an Anwendungen an ein Skriptobjekt senden wollen, um sie dort abzufangen, müssen Sie daher using terms from verwenden: script catchCmds property defaultPath : path to desktop using terms from application "Finder" on make new Finder window tell application "Finder" set x to make new Finder window set target of x to defaultPath set current view of x to list view end tell end make end using terms from end script using terms from application "Finder" tell catchCmds to make new Finder window end using terms from Das Senden des Befehls an catchCmds in den letzten Zeilen des Skripts muss wieder in einem using terms from stehen, da sonst der Begriff Finder window nicht übersetzt werden kann. Die Ausführung des Befehls im Skriptobjekt muss in einem tell-Block stehen. Ohne diesen erhalten Sie sonst eine Fehlermeldung. Der Befehl using terms from gibt nur an, mit welcher Terminologie die folgenden Zeilen übersetzt werden sollen, nicht jedoch das Ziel des Befehls. Das wird hier mit tell bestimmt. Eine continue-Anweisung können Sie hier nicht verwenden, es sei denn, dem Finder wird das Skriptobjekt als Kind untergeschoben, wie im Folgenden beschrieben.
Ein Programm als parent In folgendem Beispiel wird das Programm Pages aus der iWork-Suite als parent für das Skriptobjekt eingesetzt. Das hat zur Folge, dass das tell im Skriptobjekt entfallen kann (nicht jedoch beim Aufruf). Entsprechend der Vererbung landen die Befehle dann automatisch, auch ohne tell, bei den Eltern: 468
Die Sprache
Kapitel 4
script catchCmds property parent : application "Pages" using terms from application "Pages" on make new shape set x to continue make new shape with properties ¬ {shape type:rectangle} at end of page 1 of document 1 tell x set height to 2 set width to 3 set horizontal position to 1 set vertical position to 1 set fill type to color set single color to {65535, 0, 0} set opacity to 75 end tell end make end using terms from end script using terms from application "Pages" tell catchCmds to make new shape end using terms from Oben wird der Befehl in Pages, eine neue Form zu zeichnen, im Skriptobjekt mit continue weitergeleitet. Das Ergebnis (die Referenz auf das Zeichenobjekt) wird dabei in x gespeichert, worüber sich dann die Form anpassen lässt. Danach werden Größe, Position, Farbe und Transparenz des Objekts eingestellt. (In Pages vorher ein neues, am besten leeres Dokument öffnen.)
Abb. 4-25 Ein Skriptobjekt dient als Mittler zum Programm Pages und zeichnet dort ein Rechteck. 469
SmartBooks
AppleScript
In diesem Beispiel müssen Sie die Befehle an die Anwendung immer explizit an das Skriptobjekt senden, wo diese dann abgefangen und erweitert werden können, bevor sie weitergeleitet werden. Um Befehle an eine Anwendung direkt abzufangen, muss diese Anwendung einem Skript auch die Möglichkeit bieten, an ein Programmobjekt anzukoppeln. Beispiel hierfür sind die Ordneraktionen im Finder oder der Handler on perform mail action des Programms Mail.
Beliebige Objekte als parent Wenn man sogar eine Anwendung als parent für ein Skriptobjekt angeben kann, ergibt sich unweigerlich auch die Frage, ob man auch noch andere Klassen als Eltern angeben kann. Ja, das ist tatsächlich mit jeder beliebigen Klasse möglich. Im Folgenden wird zum Beispiel eine Liste als parent für ein Skriptobjekt eingesetzt, mit der Folge, dass Sie die Eigenschaften einer Liste (length, rest, reverse) auf das Skriptobjekt anwenden können, neben dem Aufruf seiner eigenen Methoden: script z property parent : {"red", "green", "blue"} on beep (x) beep x end beep end script get item 2 of z -- "green" length of z -- 3 rest of z -- {"green", "blue"} reverse of z -- {"blue", "green", "red"} Alle diese Anfragen werden dabei natürlich an die Eltern weitergeleitet, da das Skriptobjekt keinen Handler dafür besitzt, die Elternliste aber schon. Wenn Sie dieses Skriptobjekt aber in einem Ausdruck verwenden, wird nicht auf die Liste zugegriffen, sondern das Skriptobjekt selbst wird zurückgeliefert: script z property parent : {"red", "green", "blue"} on beep (x) beep x end beep end script set newList to z & "yellow" -- {«script z», "yellow"} set newList to contents of z & "yellow" -- {"red", "green", "blue", "yellow"} Wie Sie an der letzten Zeile sehen, funktioniert der Zugriff dann aber doch durch die explizite Verwendung von contents of. 470
Die Sprache
Kapitel 4
Skriptobjekte speichern und laden Die Scripting Commands aus den Standarderweiterungen (StandardAdditions) definieren zwei Befehle, die es erlauben, Skriptobjekte auch auf die Festplatte zu schreiben und wieder einzulesen.
store script Verwenden Sie den Befehl store script, um ein Skriptobjekt auf der Festplatte abzuspeichern. Damit können Sie den Zustand von Skriptobjekten sozusagen einfrieren und später mit load script jederzeit wieder laden. In der einfachsten Form fragt store script Sie in einem Dialog, wo das Skriptobjekt abgespeichert werden soll: on createScript(myList) script property itsList : myList on setList(x) set itsList to x end setList end script end createScript set newList to createScript({"ABC", "DEF", "GHI"}) store script newList
Abb. 4-26 Eine einfache »store script«-Anweisung führt zu einem Sichern-Dialog.
471
SmartBooks
AppleScript
Nach dem Befehl store script wird also ein Skriptobjekt als Parameter erwartet. Hier ist es das Skriptobjekt newList. In diesem Sichern-Dialog ist die Angabe des Dateikürzels von großer Wichtigkeit, diese bestimmt nämlich das Format, in welchem das Skript gespeichert wird. Normalerweise sollten Sie hier scpt für ein Skript oder scptd für ein Skript-Bundle verwenden. Aber auch die Angabe von app oder text ist möglich, wodurch das Skript als Applet (und zwar in Form eines Programm-Bundles) oder als reiner Text gespeichert wird. Das Format Programm ohne Bundle steht hier also nicht zur Verfügung, da dieses kein eigenes Dateikürzel besitzt. Im Textformat ist allerdings zu beachten, dass die Werte der Propertys darin nicht gespeichert werden können. Wenn Sie das Skript solchermaßen abgesichert haben, schauen Sie mal im Finder danach und öffnen Sie es per Doppelklick im Skripteditor. Der Inhalt des Skripts sieht so aus: property itsList : myList on setList(x) set itsList to x end setList Darin befindet sich also exakt die Definition des Skriptobjekts ohne Konstruktor und ohne script-Block. Aus dem Skriptobjekt ist also ein Skript der obersten Ebene geworden. Davon, dass dort die Liste {"ABC", "DEF", "GHI"} gespeichert sein soll, ist hier nichts zu erkennen. Die Liste ist aber tatsächlich in der Property gespeichert, allerdings in kompilierter Form – nur zu finden, wenn man das Skript zum Beispiel auf TextEdit zieht und dort im Buchstabensalat danach sucht. Wenn Sie das Skript separat im Skripteditor öffnen, müssen Sie nur aufpassen, es nicht erneut zu kompilieren und zu sichern. Jede Property wird durch Kompilieren zurückgesetzt. Der Befehl store script kennt noch zwei weitere Parameter. Der erste bestimmt den Ort, an dem das Skript gespeichert werden soll, der zweite, ob ein dort bereits existierendes Skript gleichen Namens ohne zu fragen überschrieben werden soll. Der Ort und der Namen der Datei wird mit in file bestimmt. Wenn Sie diesen Parameter angeben, erscheint kein Sichern-Dialog: set scriptFile to "Drehteller:Users:Detlef:Desktop:skript1.scpt" store script newList in file scriptFile Wenn an diesem Ort aber bereits eine Datei mit gleichem Namen existiert, werden Sie gefragt, ob diese überschrieben werden soll, wie in folgender Abbildung ersichtlich.
472
Die Sprache
Kapitel 4
Abb. 4-27 Abfrage vor dem Überschreiben eines gesicherten Skriptobjekts Klicken Sie in diesem Dialog auf Ersetzen, wenn das bereits existierende Skriptobjekt überschrieben werden soll, ansonsten klicken Sie auf Abbrechen, um es gar nicht zu sichern und das Skript an dieser Stelle abzubrechen, oder auf Sichern unter, um Namen und Ort für das Skriptobjekt zu ändern. Wenn Sie unter allen Umständen einen Dialog vermeiden wollen, sollten Sie noch den dritten Parameter hinzunehmen. Dieser folgt immer als Letztes und wird mit dem Wort replacing kenntlich gemacht. Er kann drei verschiedene Werte annehmen, die als Konstanten implementiert sind. Wenn Sie keinen Dialog möchten, wählen Sie yes als Parameter: store script newList in file scriptFile replacing yes Folgende drei Werte sind möglich: << yes: Wenn Sie yes schreiben, wird ein bereits bestehendes Skript gleichen Namens immer ohne Rückfrage überschrieben. Damit vermeiden Sie also jeden Dialog und damit jede Unterbrechung im Skriptfluss. Die richtige Wahl, wenn Sie vermeiden wollen, dass der Anwender Sicherungsdialoge erhält, die ihm nichts bedeuten. << no: Bei dieser Wahl erscheint bei bereits vorhandenem Skript die Fehlermeldung »Doppelter Dateiname für…«. Es gibt darin keine Möglichkeit zum Sichern unter einem anderen Namen, und das Skript bricht an dieser Stelle ab. Existiert das Skript noch nicht, erscheint kein Dialog. Das Skriptobjekt wird dann gesichert und das Skript läuft weiter. << ask: Bei dieser Wahl erscheint die Warnung aus obiger Abbildung, wenn bereits eine Datei gleichen Namens existiert. Dort können Sie dann auf Sichern unter klicken, um das Skriptobjekt unter einem anderen Namen zu sichern. Existiert der Dateiname an
473
SmartBooks
AppleScript
dieser Stelle noch nicht, erscheint die Warnung nicht, und das Skriptobjekt wird still gesichert. Dies ist die Standardeinstellung, die auch verwendet wird, wenn Sie den replacing-Parameter weglassen.
Skriptobjekte im Bundle speichern Wenn Sie Ihr Skript in einem Bundleformat gespeichert haben, bietet es sich an, Skriptobjekte auch gleich im Bundle zu speichern. Das ist relativ leicht, da der Befehl path to me aus den File Commands der StandardAdditions Ihnen den Pfad zum Skript zurückliefert. Und da alle Bundles den gleichen Ordnungskriterien unterliegen, sollten Sie alle eigenen Ressourcen immer im Ordner Contents/Resources/ abspeichern. Dieser Ordner ist immer vorhanden. Den Pfad zu diesem Ordner können Sie auf folgende Weise zusammenbauen: set myPath to path to me as text -- "Macintosh HD:Users:Detlef:Desktop:storeScript.scptd:" set myPath to myPath & "Contents:Resources:" -- "Macintosh HD:Users:Detlef:Desktop:storeScript.scptd:Contents:Resources:" Der Befehl path to me liefert ein alias zurück. Da Sie aber den Pfad noch verlängern müssen, wird hier path to me mit as text in einen String konvertiert. Danach werden an den Pfad noch die Ordner Contents und Resources aus dem Bundle angehängt. Das lässt sich dann natürlich auch auf einer Zeile schreiben: set myPath to (path to me as text) & "Contents:Resources:" -- "Macintosh HD:Users:Detlef:Desktop:storeScript.scptd:Contents:Resources:" Nun können Sie das Skriptobjekt mit store script an diesem Ort abspeichern. Hier das Beispiel als Ganzes: on createScript(myList) script property itsList : myList on setList(x) set itsList to x end setList end script end createScript set newList to createScript({"ABC", "DEF", "GHI"}) set myPath to (path to me as text) & "Contents:Resources:" store script newList in file (myPath & "script1.scpt") replacing yes
474
Die Sprache
Kapitel 4
Der Name des Skripts wird hier als Textliteral "script1.scpt" eingefügt. Wenn Sie mehrere Skriptobjekte verwalten, verwendet man natürlich eine Variable mit dem Dateinamen. Für die Verwendung von path to me muss das Skript natürlich bereits gesichert sein, ansonsten erhalten Sie nämlich den Pfad zum Skripteditor. Aufgepasst Unter Mac OS X 10.4 »Tiger« funktioniert path to me (und path to resource) anders als unter Leopard. Dort wird bei geöffnetem Skript im Skripteditor mit path to me immer der Pfad zum Skripteditor zurück geliefert. Hier funktioniert obige Anweisung nur, wenn das Skript als Programm gespeichert und laufen gelassen wird oder indem Sie mit path to resource arbeiten und dabei das gewünschte Programmbundle des Skripts mit dem Parameter in bundle angeben. Wenn Ihr Skript auch unter Tiger immer als Skript und nicht als Programm laufen soll, sollten Sie das berücksichtigen, oder kenntlich machen, dass Ihr Skript nur unter Leopard funktioniert.
load script Ein Skriptobjekt, welches auf der Festplatte abgespeichert wurde, lässt sich in jedem Skript wieder mit load script laden. Der Code aus dem Skriptobjekt wird dabei nicht real in das Skript eingefügt, Sie können nur über den Namen auf das Skriptobjekt zugreifen. Als Argument benötigt load script nur die Angabe des genauen Pfades zu der Datei. Der Pfad kann im Format alias oder file vorliegen. Das Skript selber muss das Format Skript oder Skript-Bundle haben. Da der Pfad hier nur als Text vorliegt, ist die explizite Angabe von file oder alias vor dem Text erforderlich. (Wenn der Pfad im Unix-Format mit Schrägstrichen vorliegt, muss POSIX file vor dem Text mit dem Pfad stehen.) on createScript(myList) script property itsList : myList on setList(x) set itsList to x end setList end script end createScript set newList to createScript({"ABC", "DEF", "GHI"}) set myPath to (path to me as text) & "Contents:Resources:" store script newList in file (myPath & "script1.scpt") replacing yes set newList2 to load script file ((path to me as text) & "Contents:Resources:" & "script1.scpt") get itsList of newList2 -- {"ABC", "DEF", "GHI"} 475
SmartBooks
AppleScript
In der letzten Zeile wird dann die Property itsList des Skriptobjekts überprüft. Der Wert, mit dem das Skriptobjekt ursprünglich gesichert wurde, ist tatsächlich immer noch vorhanden. Das Skriptobjekt wird hier in die Variable newList2 geladen. Wenn Sie es nicht beim Laden einer Variable zuweisen würden, könnten Sie nicht darauf zugreifen! Natürlich kann das Skriptobjekt nicht nur im Bundle liegen, sondern überall auf der Festplatte, und es muss nicht einmal zuvor mit store script gesichert sein – Sie können wirklich jedes Ihrer Skripts laden, Hauptsache, es hat das Dateikürzel scpt oder scptd. Folgende Schreibweisen sind für die Pfadangabe in store script und load script möglich, wenn Sie den Pfad im Textformat vorliegen haben: Klassische Schreibweisen: file "Macintosh HD:Users:Detlef:Desktop:script1.scpt" alias "Macintosh HD:Users:Detlef:Desktop:script1.scpt" Unix-Schreibweise: POSIX file "/Users/Detlef/Desktop/script1.scpt" Das Laden von Skripts wurde auch schon unter Laden von Bibliotheken mit load script im Kapitel Handler behandelt.
run script Der Befehl run script startet ein Skriptobjekt oder eine Skriptdatei. Wenn ein Skript bereits mit load script ins Hauptskript geladen wurde, reicht auch ein einfaches run an das Skript. Wenn das Skript aber als Text vorliegt, können Sie mit run script diesen Text als Skript behandeln und laufen lassen. Damit ist es dann zum Beispiel möglich, sich Skripte zur Laufzeit zusammenzubasteln: set myFolders to run script "tell app \"Finder\" to get folders of desktop" Hier werden alle Ordner auf dem Schreibtisch aufgelistet, und das Ergebnis wird der Variablen myFolders zugewiesen. Der Vorteil dieser Konstruktion ist, dass Sie das Skript so auch aus Textbauteilen zusammenstellen können, die zur Laufzeit noch nicht bekannt sind, zum Beispiel, weil Sie aus einer Anwendung oder einer Textdatei eingelesen werden.
476
Die Sprache
Kapitel 4
Wenn Sie ein im Skript stehendes Skriptobjekt oder ein mit load script geladenes Skriptobjekt starten wollen, brauchen Sie diesem nur ein run zu senden. run script funktioniert aber auch: script hello display dialog "Hiho" end script run hello run script hello Wenn das Skript auf der Festplatte liegt und gestartet werden soll, dann schicken Sie der Datei einen run script-Befehl, und sie wird direkt gestartet, unabhängig davon, in welchem Format das Skript vorliegt. Sichern Sie zum Beispiel folgende Zeile auf den Schreibtisch, egal, ob im Format Skript, Programm oder Text: display dialog "Hiho" Schließen Sie dann das Skript und rufen Sie es in einem zweiten Skript mit run script und Angabe des Pfades auf. Das Skript wird direkt ausgeführt: set scriptFile to (path to desktop as text) & "runMe.applescript" run script file scriptFile Als Argument erwartet run script ein alias oder ein file-Objekt. Da hier der Pfad wieder als Text zusammengebaut wird, muss beim Aufruf noch ein alias oder file (oder POSIX file bei Unix-Schreibweise) vor dem als Text vorliegenden Pfad stehen. Wenn Sie das Skript mit seinem Standardprogramm öffnen wollen, können Sie es mit dem Finder öffnen: set scriptFile to (path to desktop as text) & "runMe.scpt" tell application "Finder" to open file scriptFile Dann öffnet sich das Skript sehr wahrscheinlich im Skripteditor, wenn es nicht in einem Programm-Format vorliegt. Wenn es als Applet vorliegt, wird es direkt ausgeführt. Um ein Applet zu starten, ohne dass sein run-Handler ausgeführt wird, müssen Sie ihm den launch-Befehl senden. set scriptFile to (path to desktop as text) & "runMe.app" launch application scriptFile
477
SmartBooks
AppleScript
Ein Applet ist ein Programm und muss dementsprechend mit application adressiert werden. Statt des Pfades können Sie auch nur den Namen des Applets angeben, zumindest solange Sie nicht mehrere Versionen mit gleichem Namen vorliegen haben. Wenn Sie nun mit Befehlstaste und Tabulator in die Liste der geöffneten Programme schauen, werden Sie sehen, dass das Applet tatsächlich geöffnet ist. Nun können Sie dem Applet den run-Befehl senden: tell application scriptFile to run Besonders nützlich ist das Senden von Befehlen an Applets aber vor allem, wenn diese mit der Option Nicht automatisch beenden gespeichert wurden. Dann steht das Skript mit all seinen Handlern (und damit auch Konstruktoren für Skriptobjekte) stets zur Verfügung. Sichern Sie einmal folgenden Konstruktor als Programm mit der Option Nicht automatisch beenden auf dem Schreibtisch, und zwar mit dem Namen constructor.app: on makeobject(x, y) script property xValue : x property yValue : y on calcArea() display dialog "Das Ergebnis ist: " & xValue * yValue return xValue * yValue end calcArea end script end makeobject Schreiben Sie dann in einem zweiten Skript folgende Anweisungen: set scriptFile to (path to desktop as text) & "constructor.app" tell application scriptFile launch set x to makeobject(4, 5) end tell tell x to calcArea() -- 20 Statt ein Skript als Skriptobjekt zu laden und dann zu verwenden, ist es also auch möglich, ein laufendes Skript als Bibliothek zu verwenden. Beachten Sie hierzu auch den Abschnitt Applets sind skriptbar im Kapitel Handler.
478
Die Sprache
Kapitel 4
run script und der Aufruf des run Handlers mit Parametern Wie bereits bei der Beschreibung des run-Handlers im Kapitel Handler erwähnt, kann ein run-Handler durchaus einen einzelnen Parameter annehmen. Die Übergabe funktioniert aber nur mit dem Befehl run script. Dieser kennt nämlich einen Parameter mit dem Namen with parameters, der genau dafür gedacht ist, einem run-Handler Werte zu übergeben. Der Parameter eines run-Handlers ist dabei ein einzelner Wert in Form einer Liste. Schreiben Sie in einem neuen Skript folgenden run-Handler und sichern Sie es im Formt Skript auf dem Schreibtisch mit dem Namen run.scpt: on run {x, y} display dialog x * y end run Die Schreibweise des Parameters weicht von der üblichen ab. Sie können das aber auch ruhig wie bisher on run(x, y) schreiben. Beim Kompilieren wird dann aber in die obige Schreibweise gewechselt. Schließen Sie das Skript, erzeugen Sie ein neues Dokument im Skripteditor und schreiben Sie folgende Zeilen: set testScript to (path to desktop as text) & "run.scpt" set {x, y} to {5, 8} run script file testScript with parameters {x, y} -- 40 Wenn Sie das Skript ausführen, erhalten Sie sofort einen Dialog mit der Anzeige des Ergebnisses von 5 * 8, also 40. Der Parameter with parameters erwartet eine Liste mit beliebig vielen Werten. Geben Sie mehr Werte mit, als der run-Handler benötigt, werden die restlichen ignoriert, umgekehrt gibt es eine Fehlermeldung.
run script mit anderen OSA-Sprachen Der Befehl run script kann auch Skripts in anderen OSA-Sprachen ausführen. Um zu sehen, welche OSA-Sprachen auf Ihrem System installiert sind, sollten Sie zuerst einmal im Skripteditor folgenden Befehl schreiben: scripting components Wenn Sie den Script Debugger installiert haben oder hatten, erhalten Sie folgende Liste: {"JavaScript", "AppleScript Debugger X", "AppleScript"} Ansonsten steht bei Ihnen wahrscheinlich nur "AppleScript" in der Liste. Das ist die Liste der OSA-Sprachen, die auf Ihrem Rechner installiert sind.
479
SmartBooks
AppleScript
Bevor Sie also versuchen, mit run script ein Skript einer anderen OSA-Sprache zu starten, sollten Sie zuerst mit dem Befehl scripting components prüfen, ob die Sprache auch vorhanden ist: if (get scripting components) contains "JavaScript" then display dialog "JavaScript ist als OSA-Sprache installiert!" else beep end if Wenn Sie nur "AppleScript" installiert haben, können Sie die Komponente für JavaScript als OSA-Sprache auch von Late Night Software herunterladen. Sie ist kostenlos unter http://www.latenightsw.com/freeware/JavaScriptOSA/jsDownload.html erhältlich. Wenn die Prüfung positiv verläuft, können Sie mit run script auch ein in JavaScript vorliegendes Skript starten. Das folgende kleine Beispiel wurde der Dokumentation zu JavaScriptOSA entnommen. 1. Öffnen Sie ein neues Skript im Skripteditor und schalten Sie die Steuerung über das Menü Darstellung ein, falls diese noch nicht sichtbar ist. 2. Wählen Sie in der Steuerung JavaScript im ersten Einblendmenü. 3. Schreiben Sie das folgende JavaScript hinein und führen Sie es aus: var names = ""; with (MacOS.finder()) { numFiles = file.length; for (i = 1; i <= numFiles; ++i) { if (names != "") names += ", "; names += file[i].name; } } Als Ergebnis erhalten Sie einen kommagetrennten Text mit den Namen der auf Ihrem Schreibtisch liegenden Dateien. Eine Syntaxfärbung gibt es dabei nicht. In AppleScript entspricht das in etwa dem folgenden, wesentlich leichter verständlichen, Code:
480
Die Sprache
Kapitel 4
set names to "" tell application "Finder" set numFiles to count files repeat with i from 1 to numFiles if names is not "" then set names to names & ", " set names to names & (name of file i) end repeat end tell Wenn Sie dem Finder keine Angabe über einen Ort mitgeben, geht er übrigens immer vom Schreibtisch aus. Dieses Standardverhalten wird hier ausgenutzt, indem der Befehl count files ohne Angabe eines Ordners verwendet wird. Tipp Dieses Skript ist auf Grund der Eins-zu-eins-Übersetzung aus dem JavaScript nicht optimal. Sie erreichen die Auflistung aller Namen wesentlich schneller mit nur drei Zeilen Code, wenn Sie in AppleScript mit every nach den Namen fragen, die text item delimiters auf ein Komma umstellen und dann die Namensliste in einen Text umwandeln: tell application "Finder" to set names to name of every file set my text item delimiters to ", " set names to names as text Wenn Sie nicht gerade in JavaScript zu Hause sind, ist AppleScript wesentlich leichter und eleganter zu handhaben. Das gilt auch für andere Programmiersprachen, die versuchen, sich an OSA anzukoppeln um dieselbe Funktionalität wie AppleScript zu erreichen.
Abb. 4-28 Ein JavaScript fragt Informationen vom Finder ab.
481
SmartBooks
AppleScript
4. Nachdem Sie sich vergewissert haben, dass das JavaScript funktioniert, speichern Sie es einmal im Skript-Format unter dem Namen javascript.scpt, einmal im Textformat unter dem Namen javascript.applescript und einmal im Format Programm unter dem Namen javascript.app auf dem Schreibtisch ab und schließen Sie dann das Dokument. 5. Schreiben Sie in einem zweiten Skript folgende Zeilen und führen Sie das Skript aus: set scriptFile to (path to desktop as text) & "javascript.scpt" if (get scripting components) contains "JavaScript" then set x to run script file scriptFile tell application "TextEdit" make new document set text of document 1 to x end tell else beep end if Das JavaScript im Format Skript wird sofort ausgeführt und das Ergebnis in TextEdit angezeigt. Ändern Sie nun den Dateinamen in der ersten Zeile auf javascript.app und führen Sie das Skript erneut aus. Auch das JavaSkript im Programm-Format wird direkt ausgeführt. Wenn Sie nun den Dateinamen auf javascript.applescript ändern und das Skript erneut ausführen, gibt es eine Fehlermeldung. Bei einem OSA-Skript, welches nur als Text auf der Festpatte vorliegt, muss run script über einen weiteren Parameter gesagt werden, in welcher Sprache der Text vorliegt. Dieser Parameter muss den Namen der OSA-Sprache als Text enthalten und nach in folgen: set scriptFile to (path to desktop as text) & "javascript.applescript" if (get scripting components) contains "JavaScript" then set x to run script file scriptFile in "JavaScript" tell application "TextEdit" make new document set text of document 1 to x end tell else beep end if
482
Die Sprache
Kapitel 4
Aufgepasst Wenn Sie ein JavaScript im Skripteditor im Format Skript oder Programm abspeichern, kann dieser anschließend diese Datei nicht mehr öffnen. Sichern Sie die Datei daher immer auch als Text, um eine Sicherungskopie zu haben! Mit dem Script Debugger von Late Night Software gibt es das Problem nicht. Smile kann JavaScriptOSA-Skripts ebenfalls nur im Textformat öffnen. Weitere Informationen zu JavaScript als OSA-Sprache finden Sie beim Hersteller unter: http://www.latenightsw.com/freeware/JavaScriptOSA/index.html
Der Gültigkeitsbereich von Variablen und Propertys Auf eine Variable oder Property kann man im Skript nicht überall so einfach zugreifen. Wenn Sie eine Variable in dem einen Handler definieren, dann ist sie zum Beispiel in anderen Handlern nicht sichtbar. Sie können dort also eine Variable gleichen Namens verwenden, ohne mit der anderen Variable in Konflikt zu kommen. Möchten Sie an mehreren Stellen auf eine Variable zugreifen, so müssen Sie dafür globale Variablen oder Propertys verwenden. Der Wirkungsbereich von Variablen und Propertys hängt von zwei Faktoren ab: Erstens von der Stelle, an der diese definiert wurde, und zweitens von der Art der Variable. Wenn im Folgenden von Skript die Rede ist, dann ist damit immer das Skript auf der obersten Ebene gemeint, also das im Skripteditor geöffnete Skript. Ist von einem Skript als Element eines Skripts die Rede, dann wird immer von Skriptobjekt gesprochen. AppleScript unterscheidet wie die meisten Programmiersprachen zwischen lokalen und globalen Variablen. Zusätzlich gibt es aber noch die Propertys (Instanzvariablen) und die Variablen, die ohne Deklaration einfach durch ihre Verwendung definiert werden. << Lokale Variablen werden mit dem Wort local deklariert, bevor ihnen ein Wert zugewiesen wird. Sie gelten nur in dem Handler, in welchem sie definiert wurden. Der Ort der Definition unterliegt keiner Beschränkung, außer der, dass sie immer in einem Handler stehen müssen. Wenn sie in keinem Handler stehen, sind sie Teil des impliziten run-Handlers. Tiefer verschachtelte Skriptobjekte oder Handler haben genauso wenig Zugriff darauf wie übergeordnete Objekte. Lokale Variablen stellen die stärkste Stufe der Reichweitenbegrenzung dar und sind daher optimal dafür geeignet, Namensräume abzugrenzen und Code modular zu gestalten. Der Wert einer lokalen Variablen wird bei jedem Aufruf des Skripts erneut zugewiesen, die Variable wird also zurückgesetzt und merkt sich ihren Wert nicht für die nächste Ausführung des Skripts.
483
SmartBooks
AppleScript
<< Einfache Variablen: Wenn Sie eine Variable einfach verwenden, indem Sie einem beliebigen Bezeichner einen Wert zuweisen, handelt es sich dabei ebenfalls um eine Variable, welche nur in dem Handler, in welchem sie zuerst definiert wurde, erreichbar ist. Ist die Variable jedoch im impliziten oder expliziten run-Handler des Skripts definiert worden, können andere Handler auf sie zugreifen, indem sie denselben Bezeichner als global deklarieren. Diese Form von Variablen muss immer in einem Handler stehen oder es gibt eine Fehlermeldung. Stehen sie in keinem Handler, sind sie Teil des impliziten run-Handlers. Auch diese Variablen werden bei jedem Aufruf des Skripts zurückgesetzt. << Globale Variablen: Variablen dieses Typs werden mit dem Wort global deklariert. Sie müssen nach der Deklaration noch initialisiert werden, indem ihnen ein Wert zugewiesen wird. Eine globale Variable zeichnet sich durch einen erweiterten Wirkungsbereich aus, der schrankenlos in die Tiefe des Skripts oder des Skriptobjekts reicht, in dem sie definiert wurde. Normalerweise können übergeordnete Objekte nicht auf eine globale Variable, die in einem untergeordneten Objekt definiert wurde, zugreifen. Bei Bedarf kann eine globale Variable aber ihren Wirkungsbereich im Skript nach hinten, das heißt über die Grenzen des eigenen Handlers oder Skriptobjekts hinaus erweitern, bis auf die oberste Ebene des Skripts hinauf, indem dort die Deklaration der globalen Variable wiederholt wird. Eine globale Variable kann überall im Skript deklariert werden, in Handlern genauso wie in Skriptobjekten. Außerdem kann sie, wie Propertys, auch außerhalb jedes Handlers, also auch außerhalb des impliziten oder expliziten run-Handlers am Anfang des Skripts stehen. Der Wert einer globalen Variable wird nur zurückgesetzt, wenn die Initialisierung ausgeführt wird. Wenn man einer globalen Variable also nur beim ersten Start des Skripts einen neuen Wert zuweist und danach nicht mehr, verhält sich eine Globale wie eine Property, die sich ihren letzten Wert merkt. << Propertys sind die Eigenschaften eines Skriptobjekts. Sie werden mit dem Schlüsselwort property deklariert. Sie können nur in einem Skript oder Skriptobjekt außerhalb jedes Handlers definiert werden. Propertys sind damit auch niemals Teil des impliziten run-Handlers. Ihr Wirkungsbereich durchzieht das gesamte Skript oder Skriptobjekt, in dem sie definiert wurden. Außerhalb des eigenen Skripts oder Skriptobjekts kann nur durch Angabe der kompletten Objekthierarchie darauf zugegriffen werden. Letztlich sind Propertys damit überall zugänglich, wenn ihre Namen und die der Skriptobjekte bekannt sind. AppleScript hat dabei einige Besonderheiten, die sich für mich nur aus dem Bemühen heraus erklären lassen, es dem Anfänger besonders einfach zu machen. Alle »Tricks«, die im Folgenden besprochen werden, sollten Sie daher tunlichst wieder vergessen, wenn Sie objektorientiert arbeiten wollen, was ich nur empfehlen kann. Die Beschreibung dient daher nur der reinen Dokumentation und stellt keine Anleitung dar, wie man es unbedingt machen muss. Im Allgemeinen gilt:
484
Die Sprache
Kapitel 4
Greifen Sie niemals direkt auf Variablen außerhalb ihres normalen Geltungsbereichs zu und definieren Sie für den Zugriff auf Skriptobjekte immer Handler in diesen Skriptobjekten, auch wenn der Zugriff nur lesend sein soll. So erreichen Sie ein Optimum an Kapselung und Transportabilität Ihrer Skriptobjekte, Handler und Codeschnipsel. Beachten Sie zu allen folgenden Abschnitten auch die grafische Übersicht zur Reichweite von Variablen im Anhang.
Lokale Variablen Eine lokale Variable stellt die stärkste Form einer Einschränkung des Wirkungsbereiches dar und ist somit auch die sicherste Variable. Sie können bei lokalen Variablen ruhigen Gewissens die Namen anderer lokaler Variablen aus anderen Handlern oder Skriptobjekten wieder verwenden. Der Name einer lokalen Variable gilt immer nur in dem Handler, in dem sie definiert wurde. Sie ist weder in darin enthaltenen Skriptobjekten oder Handlern aufrufbar, noch kann in darüber liegenden Objekten auf die lokale Variable zugegriffen werden. Eine lokale Variable muss mit dem Schlüsselwort local zuerst deklariert werden: local a Damit ist bekannt, dass die Variable a eine lokale Variable werden soll. Sie ist damit aber noch nicht initialisiert, das heißt, sie hat noch keinen Wert. Im Gegensatz zu den einfachen Variablen, bei denen einem Bezeichner einfach ein Wert zugewiesen wird, wodurch die einfache Variable in einem Zug deklariert und initialisiert wird, erfolgt hier die Deklaration immer separat, und erst danach kann der Variablen ein Wert zugewiesen werden. local a set a to "Hello" Sie können auch mehrere lokale Variablen in einem Rutsch deklarieren, indem Sie diese nach local mit Komma voneinander trennen: local a, b, c Hier werden drei lokale Variablen mit dem Namen a, b und c definiert. Alle drei Variablen müssen danach natürlich noch durch Zuweisung eines Wertes initialisiert werden. Wenn Sie das vergessen, erhalten Sie spätestens beim ersten Zugriff auf die Variable die Fehlermeldung, dass die Variable nicht definiert ist. Wenn Sie in einem Skriptobjekt eine lokale Variable definieren, dann können Sie weder in anderen Handlern des Skriptobjekts darauf zugreifen noch aus anderen Skriptobjekten
485
SmartBooks
AppleScript
oder aus dem übergeordneten Skript heraus. Diese Variable kann wirklich nur in dem Handler des Skriptobjekts verwendet werden, in dem sie definiert wurde. Im folgenden Fall ist es der implizite run-Handler des Skriptobjekts test: run test run test2 script test local a set a to "Hello" display dialog a -- Funktioniert! sayHello() on sayHello() say a -- Fehler! Die Variable a ist nicht definiert! end beepMe display dialog a -- Funktioniert! end script script test2 property parent : test display dialog a -- Fehler! Die Variable a ist nicht definiert! end script display dialog a -- Fehler! Die Variable a ist nicht definiert! Kommentieren Sie in obigem Beispiel immer alle display dialog bis auf einen aus und probieren Sie diese dann einzeln nacheinander aus. Im Gegensatz zu den anderen Variablentypen gibt es hier auch keine Hintertür, um doch noch irgendwie an die Variable heranzukommen. Auch wenn Sie in einem Handler versuchen, mit my auf eine Variable auf oberster Ebene zuzugreifen – was normalerweise funktioniert –, wird der Zugriff auf eine mit local definierte Variable nicht gestattet: local a set a to "Hello" run test script test display dialog my a -- Fehler: a kann nicht in Typ string umgewandelt werden end script Kommentieren Sie hier die erste Zeile mit der local-Deklaration aus, dann funktioniert der Zugriff. Ansonsten erhalten Sie eine Fehlermeldung. Die Fehlermeldung erscheint dabei
486
Die Sprache
Kapitel 4
etwas seltsam. Man sollte meinen, hier käme die Meldung, dass die Variable a im Skriptobjekt test nicht definiert ist. Tatsächlich wird die Variable a aber durchaus auf der obersten Ebene gefunden, der Zugriff auf den Inhalt wird aber nicht gestattet. Deshalb kann a nicht in einen Text umgewandelt werden, wie es für display dialog erforderlich ist. Wenn Sie in einem Skript an untergeordneter Stelle ebenfalls eine lokale Variable mit gleichem Namen definieren, erhalten Sie eine zweite Variable mit demselben Namen. Jede Variable a ist nur in dem Handler gültig, in dem sie definiert wurde, und kann weder in darunter liegenden noch darüber liegenden Handlern gesehen werden: local a set a to "Hello" display dialog a -- Hello run test script test local a set a to "Auf Wiedersehen" display dialog a -- "Auf Wiedersehen" end script display dialog a -- Hello Die lokale Variable a der obersten Ebene ist hier Teil des impliziten run-Handlers des Skripts und nur dort gültig. Die Variable a im Skriptobjekt test ist Teil seines impliziten run-Handlers. Beide kommen sich nicht ins Gehege und sind völlig eigenständig. Die erste lokale Variable a gilt nur im impliziten run-Handler des Skripts und reicht nicht in darin enthaltene Skriptobjekte hinein, die zweite gilt nur im Skriptobjekt test und reicht nicht in das Skript hinauf. Eine lokale Variable muss nicht am Anfang eines Blocks definiert werden, Sie müssen dann allerdings bedenken, dass Sie erst nach der Definition der Variablen darauf zugreifen können: display dialog a local a set a to "Hello" Hier erhalten Sie beim Ausführen die Fehlermeldung, dass a nicht als local deklariert werden kann, da es sowohl eine lokale wie globale Variable ist. Diese Fehlermeldung erscheint verwirrend, klärt sich aber bei der Erklärung der einfachen Variablen. Fakt ist, das eine einfache Variable, die auf der obersten Ebene des Skripts definiert wurde, also in seinem impliziten oder expliziten run-Handler, überall im Skript durch Verwendung von my
487
SmartBooks
AppleScript
aus zugänglich ist, sich also wie eine globale Variable verhält. Hier wird in der ersten Zeile bereits eine Variable mit dem Namen a verwendet. Durch die Verwendung eines Bezeichners wird dieser Bezeichner sofort implizit deklariert, und zwar als einfache Variable. Aus diesem Grund können Sie in der nächsten Zeile diese Variable nicht nachträglich als local definieren. Setzen Sie lokale Variablen immer ganz an den Anfang des Handlers, in welchem die Variable gebraucht wird, und Sie werden keine Probleme haben. Wenn Sie aber diese Meldung erhalten, wissen Sie, dass irgendwo bereits eine Variable dieses Namens existiert. Ändern Sie dann den Namen der lokalen Variable, um den Konflikt zu vermeiden. Lokale Variablen sollte man immer dort verwenden, wo eine Variable mit Sicherheit nur auf einer Ebene eines Handlers oder eines Skriptobjekts gebraucht wird, und dann, wenn man ausschließen will, dass diese Variable auf irgendeine Weise von außen zugänglich ist. Beachten Sie auch die grafische Darstellung im Anhang.
Einfache Variablen Dies sind die gebräuchlichsten Variablen in AppleScript. Man denkt sich einfach einen Namen als Etikett aus und weist ihm einen Wert zu, fertig ist die Variable in AppleScript: set a to 1 Die Variable ist damit in einem Rutsch deklariert und initialisiert worden. Durch die Verwendung eines Bezeichners ohne eine vorherige Deklaration als local oder global wird diese Variable als einfache Variable gehandhabt. Diese Variablen verhalten sich mit einer Ausnahme exakt wie lokale Variablen. Beachten Sie daher auch die Beschreibung zum Wirkungsbereich dort. Eine einfache Variable ist so etwas wie eine implizite lokale Variable. Sie gilt immer nur in dem Handler oder Skriptobjekt, in dem sie definiert wurde, und zwar nur auf derselben Ebene. Sie reicht keine Verschachtelungsebene nach oben und auch keine nach unten. Die eine Ausnahme ist jedoch diese: Auf Variablen, die auf der obersten Ebene des Skripts definiert wurden, also im impliziten oder expliziten run-Handler, kann von überall aus zugegriffen werden. Sie müssen nur explizit mit my darauf hinweisen, dass Sie eine Variable des Skripts selber meinen. Eine Variable auf dieser Ebene verhält sich also wie eine Property oder eine globale Variable des Skripts:
488
Die Sprache
Kapitel 4
set a to "Hello" disp() on disp() display dialog my a & " Mike" end disp run test run test2 of test script test display dialog my a & " Henry" script test2 disp() on disp() display dialog my a & " Charlotte" end disp end script end script Das funktioniert dabei nur, wenn die Variable auf der obersten Ebene definiert ist. Sobald sie in einem untergeordneten Skriptobjekt oder in einem anderen Handler als dem runHandler steht, ist die Variable geschützt und nur noch dort zugänglich, ganz wie eine lokale Variable. Dass dieser Trick mit my funktioniert, deutet darauf hin, dass die einfachen Variablen eines Skripts, genau so wie die globalen Variablen, ähnlich wie Propertys implementiert sein müssen. Das Wörtchen my weist ja, wenn parent nicht geändert wurde und das Skriptobjekt nicht selbst eine Property dieses Namens besitzt, immer auf das Skript auf der obersten Ebene hin. Die Reihenfolge spielt hier ebenfalls eine große Rolle. Wird die Variable a oben erst nach dem Aufruf von disp() definiert, erhalten Sie eine Fehlermeldung, weil dann in disp() die Variable a noch nicht bekannt sein kann. Auf einfache Variablen, die auf der obersten Ebene des Skripts definiert wurden, kann auch durch eine erneute Deklaration dieser Variablen als eine globale Variable zugegriffen werden. Damit erschaffen Sie seltsamerweise keine neue Variable mit demselben Namen, sondern Sie bohren sozusagen ein »Loch« auf die oberste Ebene und haben fortan in diesem Handler überall freien Zugang auf diese Variable:
489
SmartBooks
AppleScript
set a to "Hello Mike" disp() on disp() global a display dialog a -- "Hello Mike" set a to "Hello Roland" end disp display dialog a -- "Hello Roland" Wenn Sie diesen Zugriff nicht zulassen wollen, so müssen Sie die Variable des Skripts explizit als local deklarieren: local a set a to "Hello Mike" disp() on disp() global a display dialog a -- Die Variable a ist nicht definiert. end disp Jetzt erhalten Sie im Handler disp die Fehlermeldung, dass a nicht definiert ist. Es kann also kein Bezug mehr zur Variablen a des Skripts hergestellt werden. Die oberste Ebene des Skripts hat ihre Besonderheiten bei einfachen Variablen, die ohne explizites local oder global definiert wurden. Wenn Sie es aber vermeiden, mit my oder global »Löcher« zu ihnen zu bohren, ist kein Unterschied zu Variablen mit local-Deklaration vorhanden und deren Verwendung ist absolut in Ordnung und vor allem sehr bequem.
Überschreiben von einfachen Variablen Sie können einfache Variablen der obersten Ebene des Skripts nicht dadurch »überschreiben«, dass Sie eine Variable gleichen Namens erneut definieren, da Sie in jedem Fall ja immer noch mit my auf die Variable gleichen Namens zugreifen können, unabhängig davon, ob die Neudefinition dort mit Deklaration von local oder ohne erfolgt: set a to "Hello Mike" disp() on disp() local a -- Diese Zeile kann auch wegfallen set a to "Hello Rose" 490
Die Sprache
Kapitel 4
display dialog a -- "Hello Rose" display dialog my a -- "Hello Mike" end disp Hier können Sie im Handler also zwei Variablen gleichen Namens verwenden, nur unterschieden durch das Vorhandensein oder Fehlen des Wörtchens my. Würden Sie die Variable a im Handler mit global deklarieren, würde es sich, wie eben gezeigt, um dieselbe Variable handeln wie die auf der obersten Ebene. Dann hätten Sie das »Loch« nach oben gebohrt und damit überall in diesem Handler Zugriff darauf. Definieren Sie aber a in einem Skriptobjekt als Property, ist die Variable gleichen Namens im Skript darüber tatsächlich unzugänglich geworden: set a to "Hello Mike" run disp script disp property a : "Hello Rose" display dialog a -- "Hello Rose" display dialog my a -- "Hello Rose" end script display dialog a -- "Hello Mike" Oben wird auch bei vorangestelltem my die Property mit dem Namen a verwendet und nicht die Variable a des Skripts. Diese wurde damit im Skriptobjekt disp komplett überschrieben und ist dort nun auch mit Tricks nicht mehr zugänglich.
Propertys Auf Propertys und auch auf deren Reichweite wurde schon ausgiebig am Anfang des Kapitels Skriptobjekte hingewiesen. Hier daher nur noch einmal eine kurze Zusammenfassung: Propertys des Skripts selber sind überall im Skript sichtbar, also auch in Handlern und Skriptobjekten des Skripts. Sind Propertys jedoch verschachtelt, ist bei deren Aufruf die Angabe der Objekthierarchie notwendig:
491
SmartBooks
AppleScript
property a : "Hello John" script test property b : "Hello Martha" display dialog b script test2 property c : "Hello Joe" display dialog c set b of test to "Moin Moin" run test end script end script set c of test2 of test to "Hallihallo" run test2 of test --Ergebnis: zuerst "Hallihallo" und dann "Moin Moin" Propertys sind damit, zusammen mit den globalen Variablen, ziemlich offene Strukturen. Wenn Sie objektorientiert arbeiten wollen, sollten Sie den direkten Zugriff auf Propertys oder Variablen des Skriptobjekts bewusst vermeiden.
Überschreiben durch properties Propertys der Eltern eines Skriptobjekts können durch erneute Deklaration überschrieben werden, so dass diese nicht mehr direkt zugänglich sind: property a : "Hello Joe" run test script test property a : "Hello Mike" display dialog a -- "Hello Mike" end script display dialog a -- "Hello Joe" Das Skript und das Skriptobjekt test verwenden hier beide eine Property a. Ohne die property-Deklaration im Skriptobjekt würde automatisch die Property des Skripts verwendet. Möchten Sie trotzdem auch auf die Property des Skripts zugreifen, so müssen Sie das mit of parent/parent's kenntlich machen. My können Sie nicht verwenden, da dann wieder die eigene Property verwendet wird:
492
Die Sprache
Kapitel 4
property a : "Hello Joe" run test script test property a : "Hello Mike" display dialog a -- "Hello Mike" display dialog parent's a -- "Hello Joe" end script display dialog a -- "Hello Joe"
Überschreiben durch globals So wie Sie mit einer global-Deklaration ein Loch auf die oberste Ebene des Skripts brennen können, um dort auf eine einfache Variable zuzugreifen, so funktioniert das mit global auch auf Propertys. property a : "Hello Joe" run test script test global a set a to "Hello Mike" display dialog a -- "Hello Mike" end script display dialog a -- "Hello Mike" Hier wird durch die global-Deklaration im Skriptobjekt test eine direkte Verbindung zur Property des Skripts geschaffen. Die folgenden Zuweisungen eines Wertes verändern daher die Property des Skripts, wie am letzten display dialog ersichtlich wird. Wie bei den einfachen Variablen funktioniert das aber nur mit Propertys auf der obersten Ebene des Skripts, also nicht mit Propertys von Skriptobjekten im Skript.
Überschreiben durch einfache und lokale Variablen Eine Property ist in allen verschachtelten Handlern und weiteren Skriptobjekten sichtbar. Wenn Sie dort jedoch eine einfache oder lokale Variable gleichen Namens anlegen, ist der Zugriff nicht mehr automatisch gewährleistet. Im folgenden Beispiel wird die Property des Skripts verwendet:
493
SmartBooks
AppleScript
property a : "Hello Joe" test() on test() --set a to "Hello Mike" display dialog a -- "Hello Joe" end test display dialog a -- "Hello Joe" Innerhalb und außerhalb des Handlers greifen Sie hier auf dieselbe Property a des Skripts zurück. Wenn Sie die auskommentierte Zeile wieder aktivieren, wird damit nicht eine neue Variable erzeugt, sondern der Wert der Property nur geändert. Eine Überschreibung von Propertys mit einfachen Variablen ist also nicht möglich. Mit einer lokalen Variable aber schon: property a : "Hello Joe" test() on test() local a set a to "Hello Mike" display dialog a -- "Hello Mike" end test display dialog a -- "Hello Joe" Jetzt können Sie auf die Property des Skripts nicht mehr zugreifen, es sei denn, Sie verwenden den Trick mit my: property a : "Hello Joe" test() on test() local a set a to "Hello Mike" set my a to "Good Morning from property a" display dialog a -- "Hello Mike" end test display dialog a -- "Good Morning from property a"
494
Die Sprache
Kapitel 4
Wenn die Property aber nicht auf der obersten Ebene des Skripts liegt, müssen Sie, wie bereits gezeigt, unter Angabe der exakten Objekthierarchie auf sie zugreifen oder mittels of parent unter Ausnutzung der Vererbung – wenn denn ein Skriptobjekt parent des anderen ist. Eine Property lässt sich also niemals vollständig abdecken, so dass sie überhaupt nicht mehr zugänglich ist. Eine Property ist damit der offenste Variablentyp von allen.
Globale Variablen Wie Sie bei den vorigen Variablentypen bereits sehen konnten, kann mit einer Variable, die als global deklariert wird, der Wirkungsbereich einer Variable gezielt erweitert werden, auch im Nachhinein. Eine als global deklarierte Variable zeichnet sich aber erst einmal dadurch aus, dass sie in dem Skriptobjekt, in dem sie definiert wurde, und in allen darin geschachtelten Skriptobjekten und Handlern, die nach ihrer Definition erfolgen, sichtbar ist. Eine globale Variable wird deklariert, indem der Bezeichner dieser Variablen dem Schlüsselwort global folgt: global a Sie können dabei auch mehrere globale Variablen mit Komma voneinander getrennt auf einer Zeile deklarieren: global a, xKoord, yKoord Hier werden drei globale Variablen mit den Namen a, xKoord und yKoord definiert. Einer globalen Variablen kann dabei nicht während der Deklaration gleich ein Wert zugewiesen werden. Das muss später erfolgen: global a, xKoord, yKoord set a to 1 set {xKoord, yKoord} to {5, 3} Die Zuweisung von Werten unterscheidet sich dabei nicht von anderen Variablen. Massenzuweisungen über Listen sind also auch hier, wie bei allen anderen Variablentypen möglich, wie in der letzten Zeile dargestellt.
495
SmartBooks
AppleScript
Globale Variablen sind persistent Eine globale Variable merkt sich ihren Wert auch über mehrere Skriptaufrufe hinweg. Dies ist nur nicht auf den ersten Blick ersichtlich, da die Initialisierung den Wert normalerweise bei jedem Durchlauf zurücksetzt. Wenn Sie die globale Variable jedoch mit einem try nur beim ersten Aufruf eines Skripts initialisieren, so wird das offensichtlich: global zaehler zaehlMal() on zaehlMal() try set zaehler to zaehler + 1 -- Fehler bei 1. Ausführung! on error set zaehler to 1 end try end zaehlMal -- Ergebnis: 1, 2, 3… Bei der ersten Ausführung wird im try ein Fehler auftreten. Da die Globale zaehler noch keinen Wert enthält, kann man ihr im try nichts hinzuaddieren, deswegen wird dann die Anweisung im on error-Teil ausgeführt und die Variable bekommt die 1 als Startwert zugewiesen. Damit ist die Globale initialisiert. In den folgenden Durchläufen gibt es bei der Anweisung im try keinen Fehler mehr. Die Anweisung im error-Block wird also nicht mehr ausgeführt. Damit wird die Globale nicht mehr neu initialisiert und damit nicht mehr zurückgesetzt. Da dies etwas umständlich ist für den täglichen Gebrauch, verwendet man hierfür natürlich besser gleich eine Property. Eine globale Variable ist nicht für diesen Einsatz gedacht. Daran lässt sich aber gut erkennen, dass globale Variablen (wie auch einfache Variablen) in AppleScript offensichtlich auf derselben Basis wie Propertys implementiert wurden und sich nur durch eine andere Form der Beschränkung auszeichnen.
Ort der Deklaration Eine globale Variable kann überall im Skript deklariert werden. Sie kann damit als einzige Anweisung neben einer Property auch außerhalb jedes Handlers deklariert werden, also auch außerhalb des run-Handlers:
496
Die Sprache
Kapitel 4
property zaehler : 0 global a on run set a to "Hallo Welt" display dialog a set zaehler to zaehler + 1 end run Die Initialisierung, also Zuweisung eines Wertes, kann jedoch nur in einem Handler erfolgen. Wenn Sie die Zuweisung von "Hallo Welt" aus dem Handler direkt hinter die Deklaration verschieben, erhalten Sie die Fehlermeldung, dass die Routine run mehr als einmal definiert ist. Eine Zuweisung mit set gehört halt immer einem Handler, und auf der obersten Ebene ist es immer der implizite run-Handler. Da der aber schon explizit definiert ist, haben Sie nunmehr zwei, einen expliziten und einen impliziten – was natürlich nicht sein darf. Wenn die Deklaration der Globalen wie oben am Anfang des Skripts steht und außerhalb des expliziten run-Handlers, ist diese globale Variable wie eine Property überall im Skript erreichbar. Sie können die Deklaration aber genauso gut in jedem anderen Handler vornehmen. Die Deklaration muss dabei nicht einmal direkt am Anfang eines Handlers stehen, sondern kann auch mitten drin erfolgen. Dabei müssen Sie jedoch darauf achten, dass Sie erst nach der Deklaration auf die Globale zugreifen können. Im Folgenden gibt es daher eine Fehlermeldung: display dialog a -- Fehler: Die Variable a ist nicht definiert. global a set a to "Hallo Welt" set zaehler to zaehler + 1 Wenn Sie jedoch zuerst eine Zuweisung eines Wertes in den Bezeichner a vornehmen, so haben Sie damit eine einfache Variable deklariert und initialisiert. Wenn Sie danach eine Globale mit gleichem Namen deklarieren, machen Sie diese einfache Variable nachträglich ab dieser Stelle überall im Skript zugänglich. Das ist dann also das Verhalten, was ich salopp als »Löcher brennen« bezeichne: set a to "Hallo Welt" display dialog a -- "Hallo Welt" global a getMe() on getMe() display dialog a end getMe 497
SmartBooks
AppleScript
Wenn der run-Handler aber nicht implizit ist, muss die Deklaration mit global in jedem Handler wiederholt werden, welcher auf die nachträgliche Globale zugreifen will: on run set a to "Hallo Welt" display dialog a -- "Hallo Welt" global a getMe() end run on getMe() global a display dialog a -- "Hallo Welt" end getMe Am besten, man deklariert eine Globale daher immer gleich ganz am Anfang eines Skripts oder Skriptobjekts und man vermeidet damit die eventuell sogar aus Versehen geschehene Nachdeklaration einer einfachen Variablen zu einer Globalen.
Reichweite in die Tiefe Die Reichweite globaler Variablen ist nach den Propertys die offenste. Eine globale Variable kann ihre Erreichbarkeit dabei in zwei Richtungen zur Geltung bringen. Zum einen wirkt sich die Globale ab dem Punkt, an dem sie deklariert wurde, in die Tiefe aus. Sie ist ab dem Punkt ihrer Deklaration überall in diesem Skript oder Skriptobjekt zugänglich bis in die letzte Ecke der darin verschachtelten Elemente. global a set a to "Hello World" run sayHello script sayHello getMe() on getMe() say a -- "Hello World" end getMe end script Eine Globale ist damit gut für Variablen geeignet, die überall im Skript oder Skriptobjekt erreichbar sein müssen und deren Wert bei jeder Ausführung zurückgesetzt werden soll. Die Globale sollte dafür immer am Anfang des Skripts oder Skriptobjekts stehen.
498
Die Sprache
Kapitel 4
Reichweite nach oben und in Laufrichtung des Skripts Die zweite Wirkrichtung einer globalen Variable reicht nach oben herauf statt in die Tiefe. Das ist das Verhalten, was ich zuvor bereits als »Löcher brennen« bezeichnet habe. Hier gibt es wiederum zwei zu beobachtende Effekte: 1. Ausdehnung nach oben Eine globale Variable ist in dem Handler, in dem sie definiert wurde, und in allen Skriptobjekten und Handlern darin sichtbar. Wenn dieser Handler auf der obersten Ebene des Skripts erst einmal aufgerufen wurde, ist danach diese globale Variable auch auf der obersten Ebene des Skripts erreichbar: on test() global a set a to "Hello Peter" display dialog a end test test() -- "Hello Peter" display dialog a -- "Hello Peter" Kommentieren Sie hier den Aufruf von test in der vorletzten Zeile aus, erhalten Sie beim nächsten Lauf in der letzten Zeile die Meldung, dass die Variable a nicht definiert ist. Der Aufruf des Handlers initialisiert die Globale! Ist der Bezeichner, der für die Globale verwendet wird, auf der obersten Ebene bereits in Gebrauch, so wurde durch die erneute global-Deklaration aus dem Handler heraus eine Brücke auf die Variable a gebaut. Der Wert dieser Variablen steht damit ab sofort im Handler test als Globale zur Verfügung. Wenn dort der Wert von a geändert wird, ändert sich auch der Wert von a auf der obersten Ebene, da beide tatsächlich ein und dasselbe Objekt sind: set a to "Hello John" on test() global a set a to "Hello Peter" display dialog a end test test() -- "Hello Peter" display dialog a -- "Hello Peter"
499
SmartBooks
AppleScript
Die Variable a auf der Skriptebene wird hier also nicht überschrieben, sondern eher vereinnahmt. Auf der Skriptebene ist dies weiterhin eine lokale Variable, im Handler, wo sie als global definiert wurde, ist es aber eine Globale, wie im folgenden Beispiel ersichtlich wird: set a to "Hello John" test() on test() global a script hello display dialog a -- "Hello John" Globaler Zugriff ! end script run hello end test display dialog a -- "Hello John" Lokaler Zugriff ! sayHello() on sayHello() say a -- Fehler: Die Variable a ist nicht definiert! end sayHello Innerhalb des Handlers test kann auf die Variable a global zugegriffen werden und damit auch aus dem Skriptobjekt hello heraus, welches ein Objekt dieses Handlers ist. Am Ende des Skripts erhalten Sie bei dem Aufruf des Handlers sayHello jedoch einen Fehler. In diesem Handler ist die Variable a nicht bekannt. Hier handelt es sich also weiterhin um eine lokale Variable. 2. Ausdehnung in Laufrichtung des Skripts Eine globale Variable kann durch erneute Deklaration in folgenden Handlern oder Skriptobjekten ihre Reichweite in Schreibrichtung nach unten ausdehnen. So gibt es in folgendem Skript eine Fehlermeldung, weil die global a nicht im zweiten Handler sichtbar ist. Sie ist im ersten Handler definiert und daher nur dort eine globale Variable: script test global a set a to "Hello Joe" hello() on hello() display dialog a end hello
500
Die Sprache
Kapitel 4
end script on sayHello() display dialog a -- Fehler: Die Variable a ist nicht definiert. end sayHello run test -- "Hello Joe" sayHello() Wenn Sie aber die Deklaration in dem zweiten Handler wiederholen, so ist die Variable ab sofort auch im zweiten Handler global. Wenn Sie dort a verändern, dann wirkt sich das auch wieder auf den ersten Handler im Skriptobjekt test aus: script test global a set a to "Hello Joe" hello() on hello() display dialog a end hello end script on sayHello() global a display dialog a set a to "Hello John" end sayHello run test -- "Hello Joe" sayHello() -- "Hello Joe" hello() of test -- "Hello John" get a -- "Hello John" Es werden hier also nicht zwei unterschiedliche globale Variablen mit dem Namen a definiert! Hier wird eine einzige Variable für beide Objekte verwendet. Gemäß der Regel, dass eine Globale nach ihrem ersten Aufruf im Skript auch auf der obersten Skriptebene bekannt ist, kann im obigen Beispiel in der letzten Zeile auf a zugegriffen werden. Die Wirkung der Globalen hat sich also gezielt in dem Handler nach unten in Laufrichtung des Skripts erweitert und mehr oder weniger unbeabsichtigt auch auf die obere Ebene des Skripts ausgeweitet.
501
SmartBooks
AppleScript
Obwohl die Globale nun auf der oberen Ebene des Skripts bekannt ist, muss sie trotzdem in allen folgenden Handlern erneut deklariert werden, wenn diese ebenfalls Zugriff auf diese Globale erhalten wollen. Dieses Verhalten von globalen Variablen lässt sich für mich noch am leichtesten damit erklären, dass diese auf der obersten Ebene des Skripts ähnlich wie Propertys implementiert sein müssen. Die Dokumentation von Apple geht leider nicht näher darauf ein. Hilfe Man kann das auf den ersten Blick seltsame Verhalten der globalen Variablen vielleicht am leichtesten mit der Telefonzentrale eines großen Hauses vergleichen. Das Skript stellt ein Haus dar. In diesem Haus befinden sich viele Zimmer (Skriptobjekte und Handler) verteilt auf mehrere verschachtelte Geschosse. Die Telefonzentrale des Hauses (die oberste Ebene des Skripts) befindet sich im Erdgeschoss. Sie sitzen nun als Handler in einem Zimmer und können nur die Variablen sehen, die Sie selbst deklariert haben, und tun so Ihre Arbeit. Jede Deklaration einer beliebigen Variablen müssen Sie dabei per Telefon der Vermittlungszentrale mitteilen, die diese dann für Sie abspeichert. Möchten Sie die Globalen von anderen Skriptobjekten oder Handlern aus den Nachbarzimmern sehen, so müssen Sie das der Vermittlung im Erdgeschoss mitteilen (den Variablennamen des anderen ebenfalls mit global deklarieren). Die Vermittlungszentrale erlaubt Ihnen dann ab sofort den Zugriff auf diese Variable des anderen Handlers oder Skriptobjekts. (Sie stuft Sie dabei als vertrauenswürdig ein, da Sie den Namen der Variablen nennen konnten.) Ab sofort steht Ihnen per Draht auch in Ihrem Zimmer (Handler) die Variable des anderen zur Verfügung. Wenn Sie diese ändern, ändern Sie damit auch die Variable des anderen Skriptobjekts oder Handlers. Im Erdgeschoss selbst, der obersten Ebene des Skripts, steht eine globale Variable aus den anderen Zimmern und Stockwerken erst zur Verfügung, wenn sie dort zum ersten Mal aufgerufen und verwendet wurde (ein Handler mit der Globalen im Skript aufgerufen wurde). .
Überschreiben von globalen Variablen Eine globale Variable kann von einer explizit definierten lokalen Variable oder auch einer Property gleichen Namens auf einer tieferen Ebene überschattet werden, so dass die globale Variable dort nicht mehr direkt zugänglich ist: global a set a to "Hello" on
test() local a set a to "Good Night" display dialog a 502
Die Sprache
Kapitel 4
end test test() -- "Good Night" display dialog a -- "Hello" Wenn die Globale aber wie hier auf der obersten Ebene des Skripts definiert ist, können Sie diesen Umstand noch mit my umgehen: global a set a to "Hello" on test() local a set a to "Good Night" display dialog my a end test test() -- "Hello" display dialog a -- "Hello" Bei einer Property ist dieser Trick aber nicht mehr möglich, da Sie dort mit my wieder auf die Property des Skriptobjekts zeigen und nicht auf das Skript: global a set a to "Hello" script test property a : "Good Night" display dialog a end script run test -- "Good Night" display dialog a -- "Hello"
503
SmartBooks
AppleScript
Weitere Klassen In diesem Kapitel werden die Klassen aus dem Sprachschatz von AppleScript behandelt, die bisher nicht zur Sprache gekommen sind. Zuerst folgen die Klassen, die mit dem Dateisystem zu tun haben. Beachten Sie dort auch den in Kapitel 5 beschriebenen Befehl path to, der Ihnen helfen kann, Pfade zu Ordnern im Betriebssystem zu ermitteln.
Die Klasse alias Ein alias ist in AppleScript eine Referenz auf eine Datei, einen Ordner oder ein eingebundenes Laufwerk. Viele Befehle von AppleScript, den Standarderweiterungen oder auch von anderen Anwendungen, die mit Dateien zu tun haben, liefern oft ein alias als Referenz auf eine Datei zurück. Dazu gehören zum Beispiel auch die User-Interface-Befehle aus den Standarderweiterungen (siehe Kapitel 5): set myFile to choose file -- Ergebnis: alias "Macintosh HD:Users:Detlef:Desktop:test.rtf" Sie können ein alias aber auch von Hand mit einem Text erstellen, der einen Pfad darstellt, indem Sie einfach alias davor schreiben. Der Pfad muss dabei in HFS-Schreibweise dargestellt werden, also mit Doppelpunkt als Trenner: set myFile to alias "Macintosh HD:Users:Detlef:Desktop:test.rtf" Ein Ordner kann mit einem Doppelpunkt am Ende abschließen: set myFolder to alias "Macintosh HD:Users:Detlef:Desktop:" tell application "Finder" to make new Finder window to myFolder Für absolute Pfade ist der Startpunkt immer der Name des Laufwerks, auf dem sich die Datei befindet, in obigem Fall also die Festplatte mit dem Namen Macintosh HD. Befindet sich die Datei auf einem anderen Laufwerk, dann muss dementsprechend dessen Name als Startpunkt verwendet werden. Relative Pfade beginnen mit einem Doppelpunkt, ihr Gebrauch wird aber nicht empfohlen, da es kein spezifiziertes Arbeitsverzeichnis gibt. Generell gilt: Pfade in AppleScript sind nicht lokalisiert. Sie müssen also die englischen Namen deutsch lokalisierter Ordner verwenden. Statt des Ordners Dokumente also Documents, statt Schreibtisch Desktop, statt Benutzer User usw.
504
Die Sprache
Kapitel 4
Der Originalname eines Ordners kann in der Finderinformation im Bereich Allgemein unter Ort nachgesehen werden. Tipp Wenn Sie den Skripteditor geöffnet haben, können Sie auch einfach die Datei, zu der Sie den Pfad wissen möchten, in den Skripteditor hineinziehen. Dadurch wird der Pfad zu dieser Datei in POSIX-Schreibweise eingefügt. Sie müssen dann nur noch die Schrägstriche gegen Doppelpunkte austauschen und den Laufwerksnamen vorne anfügen. Besser noch, Sie lassen den POSIX-Pfad stehen und konvertieren diesen auf die folgende Weise in die alias-Klasse: set myFile to alias (POSIX file "/Users/Detlef/Desktop/test.rtf") Tipp Als Skripter können Sie sich aber natürlich auch ein Skript erstellen, welches Ihnen den Pfad einer im Finder ausgewählten Datei oder eines Ordners in HFS-Schreibweise in die Zwischenablage kopiert, von wo aus Sie diesen dann überall einfügen können. Sichern Sie dafür das folgende Skript als einfaches Skript und legen Sie es in den Programmordner für den Finder des Skriptmenüs (siehe Kapitel 3) tell application "Finder" set the clipboard to selection as string end tell Ab sofort brauchen Sie nur die Datei oder den Ordner im Finder anzuklicken, im Skriptmenü das Skript auszuwählen und danach den Pfad im Skripteditor einzufügen. Das Besondere an der Klasse alias ist, dass die Datei auch gefunden wird, wenn sie umbenannt oder verschoben wurde. Die Klasse alias verhält sich damit genauso wie ein im Finder des Betriebssystems angelegtes Alias und ist damit nur dafür geeignet, auf Dateien zu weisen, die auch bereits existieren. Für Dateien, die erst noch erschaffen werden müssen, ist die file- oder POSIX file-Klasse zu verwenden. Aufgepasst Verwechseln Sie ein Alias im Betriebssystem nicht mit der Klasse alias in AppleScript. Sie können mit der Klasse alias nicht eine Datei-Verknüpfung im Finder anlegen. Dafür müssen Sie den Finder steuern und ihm den Auftrag geben, von einer Datei ein Objekt der Klasse alias file zu erzeugen: set myFile to choose file tell application "Finder" set myAlias to make new alias file at desktop to myFile end tell Der Befehlsparameter nach at gibt an, wo das Alias abgelegt werden soll, und nach to steht das Ziel für das Alias. 505
SmartBooks
AppleScript
Mit folgendem kleinem Skript können Sie testen, wie ein alias eine verschobene Datei wiederfindet. Beim ersten Lauf des folgenden Skripts werden Sie aufgefordert, eine Datei auszuwählen. Wählen Sie hier zum Beispiel eine Textdatei auf dem Schreibtisch aus. Die Datei wird als alias in der Property myfile abgespeichert, und das Skript endet. property myFile : missing value if myFile = missing value then set myFile to choose file else tell application "Finder" to open myFile end if Wenn Sie das Skript dann erneut ausführen, wird die vorher ausgewählte Datei in Ihrem Standardprogramm geöffnet, zum Beispiel TextEdit. Schließen Sie die geöffnete Datei wieder und verschieben Sie sie nun auf der Festplatte. Lassen Sie das Skript erneut laufen, ohne es noch einmal zu kompilieren. Die Datei wird gefunden und geöffnet, obwohl sie nun woanders liegt.
Eigenschaften eines alias Ein Objekt der Klasse alias hat nur zwei Propertys, class und POSIX path. Wenn Sie nach der Klasse eines alias fragen, erhalten Sie alias als Antwort. Fragen Sie danach, wenn Sie vor Ausführung einer Operation sichergehen wollen, dass die Variable auch einen Wert der richtigen Klasse enthält: set myFile to choose file class of myFile -- alias Wenn Sie nach POSIX path fragen, erhalten Sie den absoluten Pfad der Datei in POSIXSchreibweise als Text: set myFile to choose file POSIX path of myFile -- "/Users/Detlef/Desktop/test.rtf" Wurde die Datei vollständig gelöscht, erhalten Sie eine Fehlermeldung, wenn das Skript läuft. Ob die Datei (noch) existiert, wird erst in der Laufzeit des Skripts untersucht. Dieses Verhalten ist neu in AppleScript 2.0. Zuvor wurde ein alias schon beim Kompilieren evaluiert.
Umwandlungsmöglichkeiten Ein alias kann nur in einen Text oder eine Liste mit dem alias als einzigem Element umgewandelt werden: set myFile to alias "Macintosh HD:Users:Detlef:Desktop:test.rtf" myFile as text -- "Macintosh HD:Users:Detlef:Desktop:test.rtf" myFile as list -- {alias "Macintosh HD:Users:Detlef:Desktop:test.rtf"} 506
Die Sprache
Kapitel 4
Um ein alias in einen Text mit dem POSIX-Pfad umzuwandeln, brauchen Sie nur nach seiner Eigenschaft POSIX path zu fragen: set myFile to alias "Macintosh HD:Users:Detlef:Desktop:test.rtf" POSIX path of myFile -- "/Users/Detlef/Desktop/test.rtf" Um ein alias in die Klasse file umzuwandeln, müssen Sie über POSIX file gehen: set myFile to alias "Macintosh HD:Users:Detlef:Desktop:test.rtf" set myFile to POSIX path of myFile -- "/Users/Detlef/Desktop/test.rtf" set myFile to POSIX file myFile -- Ergebnis: file "Macintosh HD:Users:Detlef:Desktop:test.rtf" Oder gekürzt: set myFile to alias "Macintosh HD:Users:Detlef:Desktop:test.rtf" set myFile to POSIX file (POSIX path of myFile) Zur Pseudo-Klasse POSIX file gleich mehr. Wenn Sie im Finder arbeiten, haben Sie jedoch oft noch mit einer ganz anderen Art der Referenz zu tun. Der Finder merkt sich die Objekte anhand ihrer Objekthierarchie mit seiner eigenen Terminologie: tell application "Finder" set myFolder to folder "Test" of desktop end tell In myFolder steckt dann folgende Referenz: -- folder "Test" of folder "Desktop" of folder "Detlef" of folder "Users" of startup disk of application "Finder" Wie kann man solch eine Referenz dann in einen normalen HFS-Pfad als Text umwandeln? Das ist glücklicherweise ganz einfach. Wandeln Sie die Referenz des Finders einfach in Text um und Sie haben den HFS-Pfad: tell application "Finder" set myFolder to folder "Test" of desktop end tell set myFolder to myFolder as text -- "Macintosh HD:Users:Detlef:Desktop:Test:" Der Finder wiederum kann direkt mit einem alias umgehen, aber auch vielerorts direkt mit einem als HFS-Pfad vorliegenden Text:
507
SmartBooks
AppleScript
set myFolder to "Macintosh HD:Users:Detlef:Desktop:Test:" tell application "Finder" to open myFolder Um aus einem HFS-Pfad wieder eine Finder-Referenz zu machen, brauchen Sie nur die gewünschte Objektklasse vor den Pfad zu schreiben: set myFile to "Macintosh HD:Users:Detlef:Desktop:test.rtf" tell application "Finder" to set myFile to file myFile -- document file "test.rtf" of folder "Desktop" of folder "Detlef" of folder "Users" of startup disk of application "Finder"
Die Klassen file und POSIX file Ein Objekt der Klasse file ist wie ein alias eine Referenz auf eine Datei, einen Ordner oder ein eingebundenes Laufwerk. Im Gegensatz zu einem alias ist der Bezug jedoch starr, und das Objekt muss während der Laufzeit nicht unbedingt existieren. Im Gegensatz zu einem alias wird ein verschobenes oder umbenanntes file-Objekt jedoch nicht mehr gefunden. Der Pfad in einem file-Objekt ist also fest und unveränderlich gespeichert. Diese Klasse spielt eine große Rolle bei den File Read/Write-Befehlen der Standarderweiterung (siehe Kapitel 5). Sie können ein file dabei nicht direkt selbst erzeugen, wie Sie ein alias anlegen und einer Variablen zuweisen. Wenn Sie Folgendes versuchen, erhalten Sie seltsamerweise eine Fehlermeldung: set myFile to file "Macintosh HD:Users:Detlef:test.rtf" -- „file "Macintosh HD:Users:Detlef:test.rtf"“ kann nicht gelesen werden. Das war schon in Tiger so, nur dass die Fehlermeldung sich inzwischen geändert hat. Unter Tiger hieß es noch, dass der Wert nicht in eine Referenz umgewandelt werden könnte. Der Weg zum Erzeugen eines file-Objekts führt daher über a reference to: set myFile to a reference to file "Macintosh HD:Users:Detlef:test.rtf" -- file "Macintosh HD:Users:Detlef:test.rtf" of «script» oder über POSIX file unter Angabe des POSIX-Pfades: set myFile to POSIX file "/Users/Detlef/test.rtf" -- file "Macintosh HD:Users:Detlef:test.rtf" POSIX-file erzeugt dasselbe Objekt, einen Wert von der Klasse file. Aus diesem Grund bezeichnet man POSIX file auch als Pseudo-Klasse. Sie dient nur dazu, auch einen POSIX-Pfad zum Erstellen eines file-Objekts verwenden zu können.
508
Die Sprache
Kapitel 4
Eigenschaften von file und POSIX file Wie die Klasse alias so besitzen auch file und POSIX file die Eigenschaften class und POSIX path. set myFile to POSIX file "/Users/Detlef/Desktop/test.rtf" -- file "Macintosh HD:Users:Detlef:Desktop:test.rtf" class of myFile -- «class furl» POSIX path of myFile -- "/Users/Detlef/Desktop/test.rtf" Der Klassenname hat dabei keinen übersetzten Namen und wird daher mit seinem Apple Event-Code angezeigt «class furl».
Umwandlungsmöglichkeiten Ein file-Objekt kann in Text umgewandelt werden. Heraus kommt dabei der HFS-Pfad: set myFile to POSIX file "/Users/Detlef/Desktop/test.rtf" -- file "Macintosh HD:Users:Detlef:Desktop:test.rtf" set myFile to myFile as text -- "Macintosh HD:Users:Detlef:Desktop:test.rtf" Ansonsten lässt sich file noch in eine Liste mit dem file-Objekt als einzigem Wert umwandeln: set myFile to POSIX file "/Users/Detlef/Desktop/test.rtf" -- file "Macintosh HD:Users:Detlef:Desktop:test.rtf" set myFile to myFile as list -- {file "Macintosh HD:Users:Detlef:Desktop:test.rtf"} Wenn Sie von einem file-Objekt den POSIX-Pfad benötigen, so brauchen Sie nur nach der Eigenschaft POSIX path zu fragen, die jedes file-Objekt besitzt: set myFile to POSIX file "/Users/Detlef/Desktop/test.rtf" -- file "Macintosh HD:Users:Detlef:Desktop:test.rtf" set myFile to POSIX path of myFile -- "/Users/Detlef/Desktop/test.rtf" Auf folgendem Weg können Sie file in alias umwandeln: set myFile to POSIX file "/Users/Detlef/Desktop/test.rtf" -- file "Macintosh HD:Users:Detlef:Desktop:test.rtf" set myFile to alias (myFile as text) -- alias "Macintosh HD:Users:Detlef:Desktop:test.rtf" Um aus einer Finder-Referenz ein file-Objekt zu machen: tell application "Finder" set myFolder to folder "Test" of desktop end tell set myFolder to a reference to file (myFolder as string) 509
SmartBooks
AppleScript
Zurück ist eine Umwandlung nicht nötig, da der Finder direkt mit file-Objekten, genauso wie mit alias-Objekten, umgehen kann: set myFolder to POSIX file "/Users/Detlef/Desktop/" -- file "Macintosh HD:Users:Detlef:Desktop:" tell application "Finder" to open myFolder
Relative Pfade Wenn Sie mit POSIX-Pfaden arbeiten, ist zu beachten, dass die üblichen Abkürzungen für POSIX-Pfade nicht unterstützt werden. Die Verwendung der Tilde ~ als Abkürzung für das Heimverzeichnis in POSIX-Pfaden funktioniert in AppleScript nicht: Folgendes Verzeichnis wird daher nicht korrekt in ein file-Objekt umgewandelt: set myFolder to POSIX file "~/Desktop/" -- file ":~:Desktop:" -- Unsinniges Ergebnis! POSIX-Pfade ohne einen Schrägstrich am Anfang, welcher für das Wurzelverzeichnis steht, werden in Unix relativ zum Arbeitsverzeichnis aufgelöst. Da das Arbeitsverzeichnis in AppleScript aber nicht definiert ist, spielt das höchstens eine Rolle, wenn man das Terminal steuert. Bei der Arbeit mit Anwendungen wie dem Finder ist das Arbeitsverzeichnis unspezifiziert: set myFolder to POSIX file "Desktop/" -- file ":Desktop:" -- Unsinniges Ergebnis! Auch die Verwendung von zwei Punkten, um relativ zum Arbeitsverzeichnis einen Ordner nach oben zu springen, funktioniert daher nicht: set myFolder to POSIX file ".." -- file ":..:" -- Unsinniges Ergebnis! Sie können POSIX-Pfade in AppleScript daher, abhängig von der Anwendung, hauptsächlich als absolute Pfade vom root-Verzeichnis beginnend aus verwenden. Wenn Sie aber einen Unix-Befehl mit do shell script ans Terminal senden, können Sie den führenden Schrägstrich weglassen, der angegebene Pfad bezieht sich dann relativ auf das aktuelle Unix-Arbeitsverzeichnis: do shell script "pwd" -- "/" -- Arbeitsverzeichnis einer neuen Shell in sh do shell script "cd Applications/;ls -la Utilities/" Mehr zu diesem Thema beim Befehl do shell script in Kapitel 5 und im Kapitel Unix.
510
Die Sprache
Kapitel 4
Sie können aber natürlich jederzeit innerhalb Ihres Skripts mit relativen Pfaden arbeiten, wenn Sie diese als Text vorliegen haben, und dann entsprechend zusammenbauen: set myWD to "/Users/Detlef/Desktop/" set myFile to POSIX file (myWD & "test.rtf") tell application "Finder" to open myFile
Steuerung von Anwendungen auf entfernten Rechnern Sie können mit AppleScript auch Programme steuern, die auf anderen Rechnern im Netzwerk laufen. Vorraussetzung dafür ist allerdings, dass diese den Zugriff auch erlauben. Um auf einen Rechner mit AppleScript zugreifen zu können, ist es nötig, dass auf ihm in den Systemeinstellungen unter Sharing links der Dienst Entfernte Apple-Events aktiviert wird und rechts, für welche Benutzer der Zugriff freigeschaltet werden soll.
Abb. 4-29 Der Dienst »Entfernte Apple-Events« ermöglicht es, auf diesen Rechner mit AppleScript-Befehlen zuzugreifen.
511
SmartBooks
AppleScript
Diese Öffnung des Rechners stellt natürlich auch ein Sicherheitsrisiko dar und sollte nur auf Rechnern in einem sicheren lokalen Netzwerk geschehen. Schalten Sie diese Option nicht auf Rechnern frei, die direkt im Internet hängen. Man braucht nur das Passwort des Benutzers herauszufinden und schon ist man drin! Auf dem Rechner, von dem aus Sie zugreifen wollen, muss der Dienst nicht aktiviert werden. Aus Sicherheitsgründen ist dabei das Starten von Programmen per AppleScript nicht möglich. Die Programme, die Sie auf dem anderen Rechner steuern wollen, müssen also bereits laufen. Diese Art der entfernten Steuerung eignet sich vor allem zur Steuerung von Skripts, die weitestgehend automatisch ihren produktiven Dienst auf dem Rechner verrichten. Das Senden von Befehlen an laufende Appleskripts wurde bereits im Kapitel Handler und im Kapitel Skriptobjekte behandelt. Eine weitere Sicherheitsbeschränkung liegt darin, dass Sie Administratorrechte für den entfernten Rechner benötigen, um ein Skript kompilieren und laufen lassen zu können. Nachdem Sie den Zugriff freigeschaltet haben, sollten Sie sich noch den Gerätenamen des Rechners merken. Achten Sie dabei darauf, dass dieser keine Sonderzeichen oder Leerzeichen enthält, ansonsten müssen diese Zeichen später in URL-Kodierung geschrieben werden. In obiger Abbildung steht zum Beispiel, dass man auf diesen Rechner über macmaximi.local zugreifen kann. Die Kommunikation erfolgt über das IP-Protokoll (früher AppleTalk) und funktioniert damit auch über das Internet.
Die eppc-URL Um auf ein laufendes Programm eines anderen Rechners zuzugreifen, bedient man sich einer EPPC-URL. Das sieht zum Beispiel so aus: tell application "Finder" of machine "eppc://macminimi.local" get every file end tell Das Programm Finder eignet sich sehr gut als erster Anlaufpunkt, da dieses Programm immer läuft. Sie sprechen also nicht direkt mit dem anderen Rechner, sondern immer nur mit Anwendungen auf dem anderen Rechner! Zu welcher Maschine diese Anwendungen gehören, wird mit of machine gekennzeichnet. Nach machine muss dabei die EPPC-URL folgen. Diese URL ist ein reiner Text, der mit eppc:// beginnt. Die weiteren Bestandteile können variieren. Im obigen Beispiel wird nur der Gerätename des Rechners angefügt.
512
Die Sprache
Kapitel 4
Hilfe Wenn Sie viel mit unterschiedlichen eppc-Adressen herumspielen, kann es manchmal notwendig sein, den Skripteditor zu beenden und neu zu starten. Er merkt sich einmal eingegebene Adressen, so dass eine Änderung nicht immer gleich die gewünschte Auswirkung zeigt. Sobald Sie diese Zeilen kompilieren, erhalten Sie eine Passwortabfrage. Hier werden der Benutzer und das Passwort eines Administrators des entfernten Rechners benötigt.
Abb. 4-30 Das Passwort eines Administrator-Accounts ist für den entfernten Zugriff erforderlich. Erst nachdem Sie Benutzername und Passwort eines Administrators eingegeben haben, wird das Skript kompiliert, und Sie können es ausführen. Im diesem Beispiel werden Ihnen die Dateien auf dem Schreibtisch zurückgeliefert. Statt des Gerätenamens können Sie aber auch die IP- oder Serveradresse verwenden: "eppc://192.168.1.4" oder "eppc://server.firma.de" Falls in dem Gerätenamen oder der Serveradresse Leerzeichen oder andere Sonderzeichen vorkommen, so müssen diese in URL-Kodierung geschrieben werden. Für das Leerzeichen in dem Gerätenamen Heikes Mac also zum Beispiel: "eppc://Heikes%20Mac.local" Wenn Sie den Passwortdialog vermeiden wollen, können Sie vor dem Gerätenamen oder der IP-Adresse auch den Benutzernamen und das Passwort mit angeben, wie in folgendem Fall, wo sich jemand als Benutzer Hans mit dem Passwort trukuduk anmeldet: tell application "Finder" of machine "eppc://Hans:[email protected]" activate set myWin to make new Finder window set collapsed of myWin to true end tell 513
SmartBooks
AppleScript
Der Name des Benutzers folgt zuerst, dann kommen ein Doppelpunkt und das Passwort im Klartext. Danach folgt das Zeichen @ mit folgendem Gerätenamen oder IP-Adresse. Sie können die machine auch in eine Variable speichern und diese dann darüber ansprechen: set remMachine to machine "eppc://Hans:[email protected]" using terms from application "Finder" tell application "Finder" of remMachine set myWin to make new Finder window end tell end using terms from Wie oben zu sehen, wird es dann aber notwendig, using terms from zu verwenden, damit die folgenden Anweisungen an das Programm mit dem Funktionsverzeichnis des lokalen Finders generiert werden können. Das hat neben dem Nachteil, mehr schreiben zu müssen, aber auch den Vorteil der größeren Bearbeitungsgeschwindigkeit, da dann nicht das Funktionsverzeichnis des externen Finders übers Netz abgefragt werden muss. Man sollte aber darauf achten, dass auf beiden Rechnern dieselbe Version des angesprochenen Programms verwendet wird. Wenn Sie schon using terms from verwenden, können Sie übrigens auch gleich die Anwendung mit in die Variable packen: set rem to app "Finder" of machine "eppc://Hans:[email protected]" using terms from application "Finder" tell rem set myWin to make new Finder window end tell end using terms from
Anwendungen und Benutzer Wenn Sie erst einmal herausfinden wollen, welche Programme überhaupt auf dem Rechner laufen, so könnten Sie nach den Prozessen des Rechners fragen. Seit Leopard ist dieser Weg aber aus Sicherheitsgründen gesperrt. Der Finder weigert sich, über get name of every process eine Auflistung der laufenden Anwendungen zu liefern. Alternativ bleibt daher nur noch die Möglichkeit über choose remote application. Dabei handelt es sich um einen Dialog aus den Standarderweiterungen von AppleScript. Er ist zu finden in der User Interaction-Suite. Schreiben Sie dafür einfach Folgendes in ein neues, leeres Skript: set myRemApp to choose remote application
514
Die Sprache
Kapitel 4
Sie erhalten den Dialog aus der folgenden Abbildung. Auf der linken Seite können Sie über Bonjournamen oder IP-Adresse einen Rechner auswählen. Auf der rechten Seite werden dann die Anwendungen aufgelistet, die auf diesem Rechner zurzeit laufen. Rechts daneben steht die Benutzer-ID. Falls mehrere Benutzer angemeldet sind, stehen dort Programme auch mehrmals, jeweils mit einer anderen Benutzer-ID. Dazu gleich mehr.
Abb. 4-31 Eine laufende Anwendung auf dem entfernten Rechner auswählen Nach Auswahl des Finders erhalten Sie zum Beispiel folgenden Rückgabewert: application "Finder" of machine "eppc://192.168.1.4/?uid=501&pid=168" Sie können nun über diese Variable dem Finder direkt Befehle geben: set myRemApp to choose remote application using terms from application "Finder" tell myRemApp make new Finder window end tell end using terms from Wie Sie an dem Rückgabewert von choose remote application auch sehen, steckt dort zusätzlich sowohl die uid, das ist die Nummer des Benutzers im Betriebssystem, als auch die Prozess-ID (pid). Das bedeutet, dass Sie beides auch selbst in der EPPC-URL angeben können: set myRemApp to application "Finder" of machine "eppc://192.168.1.4/?uid=501&pid=168" 515
SmartBooks
AppleScript
using terms from application "Finder" tell myRemApp make new Finder window end tell end using terms from Da sich die Prozess-ID aber bei jedem Start des Programms ändert, ist die User-ID schon interessanter. Sind auf dem anderen Rechner mehrere Benutzer gleichzeitig angemeldet, können Sie einen Befehl nacheinander an beide Benutzer senden. tell application "Finder" of machine "eppc://192.168.1.4/?uid=502" make new Finder window end tell tell application "Finder" of machine "eppc://192.168.1.4/?uid=501" make new Finder window end tell Natürlich müssen Sie dafür die User-ID herausfinden, am einfachsten über das Terminal mit dem Befehl id -u. Da das Terminal dort aber sehr wahrscheinlich nicht läuft, verwenden Sie besser wieder choose remote application. Sind mehrere Benutzer angemeldet, so erscheinen dort die Programme mehrfach mit unterschiedlichen UID-Nummern hinter dem Programmnamen. Welche Nummer aber zu wem gehört, ist damit natürlich immer noch nicht klar. Sie können das aber zum Beispiel herausfinden, indem Sie sich mit get every file die Dateien auf dem Schreibtisch eines Benutzers ansehen und dann mit get owner of document file "somedocument" nach dem Eigentümer fragen. Dateien, die auf dem Schreibtisch liegen, gehören üblicherweise dem angemeldeten Benutzer. Der Befehle choose remote application besitzt noch zwei weitere Parameter. Einen für den Titel (with title) des Dialogs – dieser erscheint in der Fensterzeile – und einen für den Aufforderungstext (with prompt). Beide Parameter erwarten Text als Wert: set remApp to choose remote application with prompt "Welches Programm soll ein neues Dokument anlegen?" with title "Neues Dokument" if name of remApp is "TextEdit" then tell application "TextEdit" to make new document else --… end if Natürlich muss hier der folgende Befehl auch von den verschiedensten Programmen verstanden werden, deswegen wird oben in einem if der Name von remApp abgefragt, um dann entsprechend auf verschiedene Programme zu reagieren. Wenn Sie übrigens nach den Propertys der entfernten Anwendung fragen, erhalten Sie auch die Propertys des
516
Die Sprache
Kapitel 4
Programms. Die Klasse machine besitzt nur die Eigenschaft class, welche den Wert machine als Konstante ergibt!
Keine Dialoge Neben der Tatsache, dass Sie keine Programme starten können, ist auch die Verwendung der User-Interface-Dialoge aus den Standarderweiterungen im Remote-Zugriff nicht möglich, was ja durchaus Sinn hat, da ja wahrscheinlich niemand da ist, der diese beantworten könnte: tell application "Finder" of machine "eppc://192.168.1.4" display dialog "Hello machine" end tell -- Fehler: Keine Aktion vom Benutzer erlaubt!
Die Klasse RGB color Diese Klasse ist ein Wertetyp wie eine Liste und verhält sich auch genauso. Der einzige Unterschied: Diese Liste enthält nur drei Werte in Form von Ganzzahlen aus dem Bereich von 0 bis 65535. Die Ganzahlen stehen für den jeweiligen Wert der RGB-Farben Rot, Grün und Blau: set myRed to {65535, 0, 0} ergibt zum Beispiel ein reines RGB-Rot. Wenn Sie die Farbe auch sehen wollen, empfiehlt sich deren Darstellung in einem Programm, das zeichnen kann, zum Beispiel Pages. Öffnen Sie für das folgende Beispiel ein neues, leeres Dokument in Pages und führen Sie dann das Skript aus. Es erzeugt ein Rechteck, dem in der letzten Zeile im tell-Block eine RGB-Farbe zugewiesen wird: tell application "Pages" tell document 1 set newrect to make new shape with properties ¬ {shape type:rectangle} at end of page 1 tell newrect set width to 8 set height to 5 set horizontal position to 1 set vertical position to 1 set fill type to color set single color to {65535, 0, 0} end tell end tell end tell 517
SmartBooks
AppleScript
Power User Wenn Sie über Adobe Illustrator verfügen, erzeugen Sie auf folgende Weise ein Rechteck und ermitteln Sie dann dessen Eigenschaften. Achten Sie darauf, dass Sie vorher ein Dokument in Illustrator geöffnet haben: tell application "Adobe Illustrator 10" set rect1 to make new rectangle at document 1 properties of rect1 end tell Mit den so ermittelten Propertys könnnen Sie das obige Skript für Pages auch leicht für Illustrator anpassen. Wenn Sie bereits eine bestimmte Farbe in Pages vorliegen haben, zum Beispiel in einem Rechteck auf der Seite, dann können Sie dieses Rechteck auch mit der Maus auswählen und dessen RGB-Farbe mit dem folgenden Skript abfragen: tell application "Pages" get single color of item 1 of (get selection) end tell -- Ergebnis: {65535, 30375, 0} Pages muss man mit einem expliziten get auf die Sprünge helfen. selection liefert dann eine Liste zurück, da ja auch mehrere Elemente ausgewählt sein können. Aus diesem Grund muss dann mit item 1 auf das erste Element dieser Liste zugegriffen werden. Darin befindet sich ein Record mit der Property single color, die hier abgefragt wird. Falls Sie also mehrere Elemente ausgewählt haben, wird nur die Farbe des ersten ausgewählten Elementes zurückgeliefert. Ansonsten können Sie in AppleScript auch jederzeit die Farbpalette des Systems aufrufen, dort eine Farbe auswählen und den Rückgabewert in eine Variable speichern. Tippen Sie dafür in ein leeres Skript folgende Zeile und führen Sie es aus. set myColor to choose color Die Farbpalette von Mac OS X erscheint. Wählen Sie eine Farbe aus und bestätigen Sie mit OK. Sie erhalten den RGB-Farbwert, zum Beispiel {65535, 30375, 0}. Tipp Mit der Lupe in der Palette Farben können Sie übrigens auch Farben auf dem Bildschirm ermitteln. Einfach auf die Lupe links oben klicken und danach mit der statt des Mauszeigers eingeblendeten Lupe auf die Farbe irgendwo auf dem Monitor klicken. Die Lupe vergrößert den Bereich, so dass man gezielt ein einzelnes Pixel auswählen kann.
518
Die Sprache
Kapitel 4
Abb. 4-32 RGB-Werte ermittelt man am besten mit dem Befehl »choose color« und der Farbpalette.
Die unit types So wie die Klasse RGB color nur eine Sonderform der Liste darstellt, so sind die folgenden Klassen der Kategorie unit types Sonderformen der Klasse real. Ihre Besonderheit liegt darin, dass der Wert, den sie repräsentieren, auch gleich mit einer Maßeinheit gekoppelt ist. Folgende Maßeinheiten existieren in AppleScript: Längen
Flächen
Volumen
Flüssigvol.
Gewicht
Temperatur
centimetres
square feet
cubic centimetres
gallons
grams
degrees Celsius
centimeters
square kilometres
cubic centimeters
litres
kilograms
degrees Fahrenheit
feet
square kilometers
cubic feet
liters
ounces
degrees Kelvin
inches
square metres
cubic inches
quarts
pounds
kilometres
square meters
cubic metres
kilometers
square miles
cubic meters
metres
square yards
cubic yards
meters miles yards
519
SmartBooks
AppleScript
Wie Ihnen sicher auffällt, gibt es für viele Maßeinheiten Varianten bezüglich der Schreibweise für amerikanisches oder britisches Englisch. So können Sie metres und litres (britisches Englisch) oder auch meters und liters (amerikanisches Englisch) schreiben. Die Maßeinheiten selber sind identisch. Sie können alle Werte vom Typ integer oder real mit dem as-Operator in einen Wert vom Typ einer der obigen Maßeinheiten umwandeln: set temp to 25 set temp to temp as degrees Celsius -- Ergebnis: degrees Celsius 25.0 Das geht auch direkt bei der Zuweisung eines Wertes: set verbrauch to 18 as gallons -- Ergebnis: gallons 18.0 Wenn Sie nach der Klasse eines solchen Wertes fragen, erhalten Sie die Maßeinheit als Klassennamen: set verbrauch to 18 as gallons class of verbrauch -- Ergebnis: gallons Mit diesen Maßeinheiten können Sie sich Umrechnungen aller Art ersparen, indem Sie einen Wert einer Maßeinheit mit as in einen anderen umwandeln: set tempCel to 30 as degrees Celsius set tempFahr to tempCel as degrees Fahrenheit -- Ergebnis: degrees Fahrenheit 86.0 set tempFahr to tempCel as degrees Kelvin -- Ergebnis: degrees Kelvin 303.15 Eine Temperatur von 30 Grad Celsius entspricht also 86 Grad Fahrenheit oder 303,15 Grad Kelvin. Wenn Sie die Umwandlung vorgenommen haben, können Sie die Variable wieder in einen integer- oder real-Wert umwandeln, um dann damit weiter zu rechnen: set tempCel to 30 as degrees Celsius set tempFahr to tempCel as degrees Fahrenheit set tempFahr to tempFahr as real -- Ergebnis 86.0
520
Die Sprache
Kapitel 4
Beim Umwandeln ist natürlich darauf zu achten, dass Sie innerhalb einer der oben dargestellten Kategorien bleiben. So können Sie natürlich nicht eine Längeneinheit in eine Flächeneinheit umwandeln. Das wäre wenig sinnvoll.
Umwandlungsmöglichkeiten Die Maßeinheiten können jederzeit in die Klassen integer, real, text oder list umgewandelt werden: set frontLength to 20 as yards -- yards 20.0 frontLength as integer -- 20 frontLength as real -- 20.0 frontLength as text -- "20" frontLength as list -- {yards 20.0}
Rechnen mit unit types Sie können mit Werten, die als unit type vorliegen, nicht direkt rechen: set frontLength to 20 as yards set sideLength to 12 as yards set buildArea to (frontLength * sideLength) as square yards -- Fehler: yards 20.0 kann nicht in Typ number umgewandelt werden. Sie müssen die unit-type-Klassen beim Rechnen daher immer explizit in den Typ number, real oder integer umwandeln: set frontLength to 20 as yards set sideLength to 12 as yards set buildArea to ((frontLength as real) * (sideLength as real)) as square yards -- Ergebnis: square yards 240.0
521
SmartBooks
AppleScript
XML-RPC und SOAP AppleScript hat eine eingebaute Unterstützung für die Protokolle XML-RPC und SOAP. Beide dienen dazu, Informationen in verschiedenen Umgebungen über das HTTP-Protokoll anzubieten. Das können Wetterinformationen sein, Börsendaten, Flugpläne und so weiter. Als erste Anlaufstelle für Webseiten, die solche Dienste zur Verfügung stellen, bietet sich die Webseite http://www.xmethods.com an. Für grundlegende Informationen zu XML-RPC besuchen Sie die Webseite http://www.xmlrpc.com/spec, für SOAP http://www.w3.org/TR/. Die Apple-Dokumentation finden Sie unter http://developer.apple.com/documentation/AppleScript/Conceptual/soapXMLRPC. Beispiele von Apple finden sich auch im Skriptmenü unter Internet Services. Mit der eingebauten Unterstützung für diese Protokolle können Sie eine Anfrage an einen Server, der einen XML-RPC oder SOAP-Dienst bereitstellt, richten und erhalten von ihm die entsprechende Antwort. Das klingt so einfach wie der Aufruf eines Handlers in AppleScript, und tatsächlich ist es im Prinzip genau das. RPC ist die Abkürzung für remote procedure call, was auf Deutsch soviel heißt wie »entfernter Aufruf einer Methode«, oder in AppleScript-Terminologie »entfernter Aufruf eines Handlers«. Dem Dienst wird dabei eine XML-Datei mit Ihrer Anfrage zugeschickt, AppleScript wartet auf die Antwort, erhält diese ebenfalls als XML-Datei und liefert Ihnen das Ergebnis als Liste oder Record zurück. Sie brauchen dabei nichts über das XML-Format zu wissen, AppleScript erledigt das für Sie. Obwohl es in AppleScript denkbar leicht gestaltet wurde, diese Protokolle zu verwenden, besteht noch eine große Schwierigkeit darin, dass Sie erstmal herausfinden müssen, welche Parameter der Dienst benötigt. Jeder Server, der solch einen Dienst bereitstellt, erwartet bestimmte Parameter, und genau diese müssen Sie kennen. Meist sind diese auf der Webseite auch dokumentiert, wenn nicht, muss man oft ein wenig experimentieren. Vielleicht findet man die Informationen auch auf der Webseite von http://www.xmethods.com. So weit die Theorie. In der Praxis sind Webseiten, die Dienste über XML-RPC anbieten, inzwischen sehr selten, und es wird fast nur noch SOAP in diversen neueren Varianten und Implementierungen (inklusive Zertifizierung) verwendet, die den Zugriff mit AppleScript erschweren oder sogar ganz verhindern, zumal Apple hier mit der Entwicklung nicht Schritt gehalten hat. Aus diesem Grunde sind leider sowohl viele der aufgelisteten Dienste unter den obigen Links als auch die Beispiele von Apple nicht mehr funktionsfähig.
522
Die Sprache
Kapitel 4
Am besten testen kann man es daher noch, wenn man sich einen eigenen XML-RPC- oder SOAP-Server einrichtet. Die einfachste Möglichkeit besteht darin, sich den kleinen in Java geschriebenen Sample XML-RPC Server von Mark Alldritt unter http://www.latenightsw.com/freeware/Sample Server/index.html herunterzuladen und damit zu testen. Wenn man sich einen eigenen SOAP-Dienst einrichten will, um zum Beispiel im internen Netz Dienste anzubieten, empfiehlt sich das Studium der SOAP-Implementierungen in PHP, Perl, Ruby oder Python.
XML-RPC Eine Anfrage an einen XML-RPC-Dienst wird in einem normalen tell gestellt, so als wenn der entfernte Dienst ein Programm ist, was er ja letztlich auch ist, nur der Kommunikationswerg verläuft halt über das HTTP-Protokoll. Die grundlegende Syntax für eine XML-RPC Anfrage sieht so aus: tell application "http://url-zum-xmlrpc-service" call xmlrpc {method name: "methodenname", parameters:{parameterListe}} end tell Alles, was Sie von dem Dienst nun noch in Erfahrung bringen müssen, sind erstens die URL des Dienstes, die im tell angegeben werden muss, zweitens der Methodenname und drittens die notwendigen Parameter. Die Parameter sind dabei positionelle Parameter. Deren Reihenfolge muss also wie bei den Handlern mit Positionsparametern eingehalten werden. Wenn diese drei Werte korrekt angegeben sind, erhalten Sie nach erfolgreicher Anfrage eine Liste mit der Antwort zurück. Wie diese Liste strukturiert ist, hängt dabei ebenfalls wieder vom verwendeten Dienst ab. Beispiele dafür zu finden, ist schwierig, da dieses einfache Protokoll immer mehr zugunsten der SOAP Nachfolger verschwindet. Apple bringt in seinem Introduction to XML-RPC and SOAP Programming Guide (Link siehe oben) folgendes Beispiel, das irgendwann einmal funktioniert hat. Inzwischen ist der Server, wie viele andere auch, nicht mehr aktiv: set myText to "My frst naem is John" tell application "http://www.stuffeddog.com/speller/speller-rpc.cgi" set returnValue to call xmlrpc {method name:"speller.spellCheck",¬ parameters: {myText} } end tell
523
SmartBooks
AppleScript
Hierbei handelt es sich um einen Dienst, der die Rechtschreibung prüft. Als Argument wird nur der zu prüfende Text in der Liste der Parameter erwartet. Als Rückgabewert erhalten Sie dann folgende Liste mit zwei Records mit Wortvorschlägen für die falsch geschriebenen Wörter: {{suggestions:{"fast", "fest", "first", "fist", "Forst", "frat", "fret", "frist", "frit", "frost", "frot", "fust"}, location:4, |word|:"frst"}, {suggestions:{"haem", "na em", "na-em", "naam", "nae", "nae m", "nae-m", "nael", "Naim", "nam", "name", "neem"}, location:9, |word|:"naem"}} Beachten Sie hier, dass der Bezeichner word in dem Record mit senkrechten Strichen umfasst worden ist. Das dient dazu, Konflikte mit dem gleich lautenden AppleScript-Begriff zu vermeiden.
SOAP SOAP ist der Nachfolger von XML-RPC. Er hat damit eine wesentlich weitere Verbreitung und ist in seinen diversen Nachfolgeversionen und unterschiedlichen Implementierungen bis heute in Gebrauch. Statt einfacher zu werden, wurde jedoch immer mehr in SOAP hineingepackt, so dass neuere Implementierungen und Versionen sich nicht mehr unbedingt mit der AppleScriptImplementierung ansprechen lassen, zumal wenn auch noch an der XML-Grundlage oder der HTTP-Übermittlung etwas geändert wurde. Die AppleScript-Implementierung verwendet zum Beispiel immer eine HTTP-POST-Anfrage. Die Parameter sind im Gegensatz zu XML-RPC immer benannt. Deren Position ist also nicht entscheidend. Die grundlegende Struktur einer SOAP-Anfrage in AppleScript sieht so aus: tell application "http://url-zum-SOAP-service" call soap {method name:"Methodenname", ¬ method namespace uri:"someURN", ¬ parameters:{parameter1Name:parameter1Wert, ¬ parameter2Name:parameter2Wert, …}, ¬ SOAPAction:"ActionURN"} end tell Im Gegensatz zu einer einfachen XML-RPC-Anfrage muss hier neben der URL, dem Methodennamen und den Parametern noch ein Wert für method namespace uri und SOAPAction angegeben werden. Beides erhält man am einfachsten wieder vom Anbieter des Dienstes oder, wie im folgenden Beispiel, von xmethods.net. Der folgende Dienst ist allerdings auf maximal 10 Anfragen pro Tag begrenzt, neben einer nötigen Zertifizierung
524
Die Sprache
Kapitel 4
eine übliche Strategie, um zuviel Datenverkehr zu vermeiden und die eigenen Dienste vornehmlich den eigenen Kunden zur Verfügung zu stellen. set theIBAN to "DE86640901001111111111" tell app "https://www.unifiedsoftware.co.uk/cgi-bin/freeservicedispatcher.cgi" set theQuote to call soap {method name:"ibanvalidate",¬ method namespace uri:"urn:freeservices",¬ parameters:{params:theIBAN},¬ SOAPAction:"urn:freeservices#ibanvalidate"} end tell Hier können Sie eine IBAN (International Bank Account Number), also eine internationale Kontonummer, auf deren Gültigkeit überprüfen. Als Antwort erhalten Sie ein VALID oder INVALID als Text. Obiger Test liefert zum Beispiel »INVALID - Modulus Check Failed« zurück. Die Bankleitzahl 640 901 00 darin (Stellen 5-12) entspricht zwar der Volksbank Reutlingen. Die Kontonummer danach ist aber nicht gültig. Wenn die Antwort aus einer SOAP-Anfrage aus mehreren Teilen besteht, erhalten Sie einen Record zurück, wie bei dem folgenden Dienst für ein Zufallszitat: tell application "http://www.boyzoid.com/comp/randomQuote.cfc" set theQuote to call soap {method name:"getQuote", ¬ method namespace uri:"http://comp", ¬ parameters:{HTMLformat:false}, SOAPAction:""} end tell Der Rückgabewert sieht beispielsweise so aus: {|item|:{{value:"Yoda", |key|:"AUTHOR"}, {value:"Anger, fear, aggression; the dark side of the Force are they. Easily they flow, quick to join you in a fight. If once you start down the dark path, forever will it dominate your destiny...", |key|:"QUOTE"}}} Er besteht aus einem Record mit einem Element namens item. Da item auch ein Begriff von AppleScript ist, wird es hier in senkrechte Striche eingefasst, damit es keinen Konflikt im Namensraum gibt. Dieser eine Record namens item enthält wiederum eine Liste mit zwei Records. Im ersten wird der Name einer Person und dahinter deren Eigenschaft, hier als Autor des Zitats, angegeben. Im zweiten Record folgt dann nach dem Bezeichner value das eigentliche Zitat. Um den Autor und das Zitat in einfacher Textform herauszuholen, müssen Sie daher folgendermaßen danach fragen: get (value of item 2 of |item| of theQuote) & return & (value of item 1 of |item| of theQuote) 525
SmartBooks
AppleScript
Das Ergebnis sieht dann so aus: "Anger, fear, aggression; the dark side of the Force are they. Easily they flow, quick to join you in a fight. If once you start down the dark path, forever will it dominate your destiny... Yoda"
526
Die Standarderweiterungen
5
In diesem Kapitel werden die Klassen und Befehle der Erweiterung StandardAdditions von AppleScript erklärt.
SmartBooks
AppleScript
Die Standarderweiterungen Sie können das Funktionsverzeichnis dieser Erweiterung öffnen, indem Sie in die Bibliothek des Skripteditors schauen (Menü Fenster | Bibliothek) und dort diese Erweiterung doppelklicken. Falls die StandardAdditions dort nicht aufgelistet sind, öffnen Sie diese manuell über Ablage | Funktionsverzeichnis öffnen. Diese Standarderweiterung ist auf jedem Mac vorhanden, und die Befehle daraus können, wie von jeder Skripterweiterung, ohne ein tell verwendet werden. Wenn Sie Befehle in dieser Erweiterung vermissen, können Sie zusätzliche Erweiterungen installieren, welche diese Befehle enthalten, oder Sie steuern AppleScript-gemäß ein Programm, welches die vermissten Befehle und Fähigkeiten besitzt, das schließt den Finder, die System Events und viele weitere Programme des Betriebssystems mit ein. Beachten Sie auch die Programme im Ordner /System/Library/ CoreServices/, die sich teilweise ebenfalls mit AppleScript steuern lassen. Um eine andere Skripterweiterung zu installieren, brauchen Sie diese nur in einem Library-Ordner in den Ordner ScriptingAdditions zu legen (siehe Kapitel 2). Die Auflistung der Befehle in diesem Kapitel richtet sich nach den Suites, das ist eine thematische Gruppierung im Funktionsverzeichnis. Schalten Sie dafür im Funktionsverzeichnis die Darstellung nach Gruppen ein (erster Knopf der drei Darstellungsknöpfe), und der Inhalt wird nach den Suites sortiert. In der Beschreibung der Befehle der Standarderweiterung stellt kursive Schrift einen Platzhalter für den damit angegebenen Typ dar. Der folgende Parameter erwartet zum Beispiel einen Wert der Klasse text: with prompt text Statt text müssen Sie hier ein Textliteral, eine Variable oder einen Ausdruck angeben, der Text enthält oder sich dahingehend evaluieren lässt. Werden mehrere Wörter mit einem senkrechten Strich getrennt, so ist nur ein einziger der Begriffe zu verwenden. Im folgenden Beispiel muss man entweder application oder alias schreiben, aber in keinem Fall beides: as application|alias
528
Die Standarderweiterungen
Kapitel 5
User Interaction Im Bereich User Interaction dreht sich alles darum, wie man Kontakt mit dem Benutzer aufnehmen kann. Mit den hier versammelten Befehlen stellt Apple dabei nur das Notwendigste zur Verfügung. Wenn Sie mehr als die hier verwendeten grafischen Elemente benötigen, empfiehlt sich eine Erweiterung wie zum Beispiel 24U Appearance OSAX (http:// www.24usoftware.com) oder die Verwendung des Editors Smile. Oder Sie nehmen gleich eine Entwicklungsumgebung wie FaceSpan oder das in Xcode integrierte AppleScript Studio. Hier finden Sie die folgenden Befehle versammelt: << beep
Einfacher Signalton
<< choose application
Dialog zur Auswahl eines Programms
<< choose color
Dialog zur Auswahl einer Farbe
<< choose file
Dialog zur Auswahl einer Datei
<< choose file name
Dialog zur Auswahl eines Dateinamens
<< choose folder
Dialog zur Auswahl eines Ordners
<< choose from list
Dialog zur Auswahl eines Listenelements
<< choose remote application Dialog zur Auswahl eines Programms auf einem anderen Rechner << choose URL
Dialog zur Eingabe oder Auswahl eines Netzwerk- dienstes
<< delay
Befehl für bewusste Verzögerungen oder Pausen
<< display alert
Anzeige einer Warnung
<< display dialog
Anzeige eines Dialogs mit oder ohne Eingabe von Text
<< say
Befehl zum Vorlesen von Text
beep Der Befehl beep lässt den Warnton des Macs erklingen. Welcher das ist, hängt vom eingestellten Warnton in den Systemeinstellungen | Ton | Toneffekte ab.
529
SmartBooks
AppleScript
Optional kann beep ein Integerwert als Argument folgen, welcher angibt, wie oft der Warnton abgespielt wird. beep 3 Wenn Sie die Lautstärke abfragen oder setzen wollen, so beachten Sie auch die Befehle get volume settings und set volume aus der Suite Miscellaneous Commands. Der Befehl beep hat keinen Rückgabewert.
choose application Mit choose application können Sie einen Dialog aufrufen, der alle Programme auflistet, die auf dem Rechner installiert sind. Wenn das sehr viele sind, kann die Anzeige daher durchaus schon mal ein bisschen dauern. Ohne jedes Argument erscheint der Dialog mit dem Titel und der Aufforderung Programm auswählen.
Abb. 5-1 Der Dialog zur Programmauswahl Der Dialog enthält drei Knöpfe. Mit Auswählen wird das ausgewählte Programm bestätigt und der Dialog beendet. Mit Abbrechen wird der Dialog abgebrochen und damit auch das Skript.
530
Die Standarderweiterungen
Kapitel 5
Mit einem Klick auf Durchsuchen können Sie die Liste aller Anwendungen verlassen und einen normalen Öffnen-Dialog zur Auswahl der Anwendung aufrufen.
Parameter Der Befehl choose application verfügt über vier optionale Parameter, die den in kursiver Schrift dargestellten Wertetyp benötigen: << with title text << with prompt text << multiple selections allowed boolean << as application|alias Der Parameter with title gibt den Text an, der im Fenstertitel erscheint. Hier wird Text als Wert erwartet. Wenn Sie diesen Parameter nicht verwenden, wird der Text Programm auswählen für den Fenstertitel verwendet. Der Parameter with prompt ist für den Aufforderungstext unter der Fensterleiste zuständig. Auch hier wird Text benötigt. Wenn Sie diesen Parameter nicht verwenden, wird der Text Programm auswählen für die Aufforderungszeile verwendet. Wenn für den Parameter multiple selections allowed der boolesche Wert true angegeben wird, dann ist die Auswahl mehrerer Anwendungen in dem Dialog erlaubt (mit gedrückter Befehls- oder Umschalttaste auswählen). Wenn Sie diesen Parameter weglassen oder auf false setzen, kann nur eine einzige Anwendung ausgewählt werden. Der Parameter as gibt an, in welchem Typ der Rückgabewert geliefert werden soll. Wenn Sie diesen Parameter nicht angeben, wird standardmäßig eine application zurückgeliefert. Verwenden Sie as alias, wenn Sie lieber mit einem alias arbeiten wollen. Die Reihenfolge der Parameter spielt keine Rolle, da es sich um benannte Parameter handelt. Beim Kompilieren erfolgt gegebenenfalls eine Umsortierung. Boolesche Werte werden dann in die entsprechende Formulierung mit with oder without umgewandelt.
Rückgabewert Standardmäßig wird ein Programm von der Klasse application zurückgeliefert: set myApp to choose application -- application "TextEdit" Wird als letzter Parameter as alias gewählt, wird ein alias auf das Programm zurückgeliefert. set myApp to choose application as alias -- alias "Macintosh HD:Applications:TextEdit.app:" 531
SmartBooks
AppleScript
Ist multiple selections allowed auf true gesetzt, erhalten Sie immer eine Liste, auch wenn nur eine einzige Anwendung ausgewählt wurde: set myApp to choose application with multiple selections allowed -- {application "TextEdit"} Wenn Sie in dem Dialog auf Abbrechen klicken, wird das Skript abgebrochen und Sie erhalten die Fehlernummer -128, die sich in einem try abfangen lässt.
Beispiel set myApp to choose application with title "Textverarbeitung auswählen"¬ with prompt "Bitte wählen Sie eine Textverarbeitung aus:" ¬ as alias without multiple selections allowed
choose color Mit choose color wird eine Farbe aus dem Standard-Farbwähler des Mac OS X-Betriebssystems ausgewählt.
Abb. 5-2 Eine Farbauswahl mit AppleScript
Parameter Der Befehl choose color hat nur einen optionalen Parameter: << default color RGB color Als Wert wird ein Wert der Klasse RGB color erwartet. Beachten Sie hierzu die Beschreibung der Klasse RGB color am Ende von Kapitel 4.
532
Die Standarderweiterungen
Kapitel 5
Die mit default color angegebene Farbe wird im Farbwähler als Standardfarbe ausgewählt. Der einzige Unterschied ist, dass im Farbwähler für RGB-Farben eine Skala von 0 bis 255 verwendet wird, in der Klasse RGB color aber eine Skala von 0 bis 65535. Die Umrechnung geschieht automatisch.
Rückgabewert Der Rückgabewert ist vom Typ RGB color. Sie erhalten eine Liste mit drei Integer-Werten im Bereich von 0 bis 65535, zum Beispiel: set myCol to choose color -- {32896, 65535, 0} Wenn Sie in dem Dialog auf Abbrechen klicken, wird das Skript abgebrochen, und Sie erhalten die Fehlernummer -128, die sich in einem try abfangen lässt.
Beispiel set myCol to choose color default color {32896, 65535, 0} -- "Lime" -- Ergebnis: z.B. die Buntstiftfarbe "Plum": {32896, 0, 32896}
choose file Dieser Befehl stellt Ihrem Skript einen normalen Öffnen-Dialog zur Auswahl von Dateien auf der Festplatte zur Verfügung.
Abb. 5-3 Der ganz normale Öffnen-Dialog kann auch aus AppleScript heraus aufgerufen werden.
533
SmartBooks
AppleScript
Parameter Der Befehl choose file kennt insgesamt sechs optionale Parameter: << with prompt text << of type { text,…} << default location alias << invisibles boolean << multiple selections allowed boolean << showing package contents boolean Der Text, der für den Parameter with prompt angegeben wird, erscheint direkt unter der Fensterleiste. Wenn Sie diesen Parameter weglassen, erscheint dort kein Text. set myFile to choose file with prompt "Bitte Protokoll auswählen:" Der Titel in der Fensterleiste kann nicht verändert werden. Der Parameter of type ermöglicht Ihnen die Beschränkung auf bestimmte Dateitypen. Der Parameter erwartet eine Liste, welche einen oder mehrere Dateitypen enthält. Die Dateitypen müssen als file type oder type identifier vorliegen. Um den file type einer Datei zu erfahren, müssen Sie den Finder fragen, zum Beispiel so: set myFile to choose file tell app "Finder" to get file type of (get properties of myFile) Sehr oft werden Sie dabei jedoch auf den Wert missing value stossen. Das heißt, diese Datei hat keinen file type. Der file type ist ein altes Konzept des klassischen Mac OS und im Aussterben begriffen. Wenn Sie trotzdem file types verwenden, kann es Ihnen daher passieren, dass sich zum Beispiel das eine PDF auswählen lässt und das andere nicht. Dann liegt das einfach daran, dass das eine PDF einen file type hat und das andere nicht. Ein file type besteht immer aus vier Zeichen, beachten Sie daher eventuell vorkommende Leerstellen zwischen den Anführungszeichen, wie zum Beispiel beim file type "PDF " für PDFDateien. Andere Beispiele sind "W8BN" für Word- oder "C#+D" für RagTime-Dokumente: set myFile to choose file of type {"C#+D", "W8BN"} Aufgrund der zunehmenden Seltenheit von file types sollten Sie besser type identifier für diesen Parameter verwenden. Um den type identifier einer Datei zu erfahren, müssen Sie das Programm System Events fragen: set myFile to choose file tell app "System Events" to get type identifier of (get properties of myFile) 534
Die Standarderweiterungen
Kapitel 5
Folgendes choose file beschränkt den Anwender auf die Auswahl von Dokumenten, die im TIFF-, JPEG- oder PDF-Format vorliegen: set myFile to choose file of type {"public.jpeg", "public.tiff", "com.adobe.pdf"} Es gibt jedoch auch generelle type identifier wie zum Beispiel public.image für alle Bilddateien oder public.text für alle Dateien, die auf reinem Text basieren (inklusive RTF, HTML und XML-Dateien), public.content für alle Dokumentdateien oder public.movie für alle Filme. Für alle, die des Englischen sicher sind und sich dafür interessieren, ist die Dokumentation von Apple zu den Uniform Type Identifiers (UTI) zu empfehlen. Sie finden diese unter folgender Adresse: http://developer.apple.com/documentation/Carbon/Conceptual/understanding_utis Wenn Sie ganz bestimmte type identifier suchen, empfiehlt sich ein Klick am Ende des Dokuments auf den Link System-Declared Uniform Type Identifiers. Dieser Link führt Sie zu einer Tabelle mit einer Liste aller type identifier, die bereits ab Werk auf dem System eingerichtet sind. Da jede Anwendung für ihre Dokumente auch noch eigene type identifier mitbringt, stellt diese Liste natürlich nur eine Ausgangsbasis dar. Der Parameter default location kann dafür verwendet werden, den Auswahldialog bereits auf einen bestimmten Ordner einzustellen. Wenn der Dialog öfters verwendet wird, kann das dem Anwender unnötiges Navigieren durch die Dateihierarchie ersparen. Der Parameter muss als alias vorliegen. Folgendes choose file verwendet voreingestellt einen Ordner Briefe als Ausgangspunkt: set myFile to choose file default location alias ¬ "Macintosh HD:Users:Hans:Documents:Briefe:" Ohne Angabe wird der zuletzt verwendete Ordner angezeigt. Der Parameter invisibles gibt an, ob unsichtbare Dateien im Auswahldialog angezeigt werden sollen. Er erwartet einen booleschen Wert. Standardmäßig stehen unsichtbare Dateien ebenfalls zur Auswahl. Wenn Sie das nicht wollen, dann müssen Sie invisibles auf false setzen: set myFile to choose file invisibles false Nach dem Übersetzen wird diese Form in die Schreibweise mit with/without umgewandelt: set myFile to choose file without invisibles Sie können das daher auch gleich so schreiben.
535
SmartBooks
AppleScript
Wenn für den Parameter multiple selections allowed der boolesche Wert true angegeben wird, dann ist die Auswahl mehrerer Dateien erlaubt (mit gedrückter Befehls- oder Umschalttaste auswählen). Wenn Sie diesen Parameter weglassen oder auf false setzen, kann nur eine einzige Datei ausgewählt werden. set myFile to choose file multiple selections allowed true Nach dem Übersetzen wird diese Form wieder mit with/without geschrieben: set myFile to choose file with multiple selections allowed Der Parameter showing package contents erwartet einen booleschen Wert: set myFile to choose file showing package contents true Wenn der Wert auf true steht, ist es möglich, in Bundles hineinzuschauen. So können Sie zum Beispiel Ressourcen in einem Bundle auswählen, hier ein Bild aus dem Bundle des Programms Adressbuch: set myFile to choose file with showing package contents -- alias "Macintosh HD:Applications:Address Book.app:Contents:Resources:ABActionGear.tif" Wenn Sie diesen Parameter weglassen oder auf false setzen, können Sie nicht in Bundles hineinsehen.
Rückgabewert Der Rückgabewert von choose file ist ein alias auf die ausgewählte Datei: set myFile to choose file -- alias "Macintosh HD:Users:Hans:Desktop:ASLG.pdf" Wenn Sie multiple selections allowed auf true setzen, erhalten Sie eine Liste mit allen ausgewählten Dateien als alias, auch wenn nur eine einzelne Datei ausgewählt wurde: set myFile to choose file with multiple selections allowed -- {alias "Macintosh HD:Users:Hans:Desktop:ASLG.pdf"} Wenn Sie auf Abbrechen klicken, wird das Skript abgebrochen, und Sie erhalten die Fehlernummer -128, die sich in einem try abfangen lässt.
Beispiel set myFile to choose file with prompt "Bitte Bild auswählen:" ¬ of type {"public.jpeg", "public.tiff"} ¬ default location alias "Macintosh HD:Users:Hans:Pictures:" ¬ with multiple selections allowed and ¬ showing package contents without invisibles
536
Die Standarderweiterungen
Kapitel 5
choose file name Mit choose file name erzeugen Sie eine neue Referenz auf eine Datei, ohne die Datei selbst auf der Festplatte zu erzeugen. Dieser Dialog stellt einen normalen Sichern-Dialog zur Verfügung, in welchem Sie Namen und Ort für die später zu erzeugende Datei angeben können. Trotz des Sichern-Dialogs wird die Datei nicht gleich erzeugt. Wenn Sie im Finder nachsehen, werden Sie dort also keine Datei vorfinden. Dieser Befehl kann zum Beispiel gut in Verbindung mit den Befehlen aus der Suite File Read/Write verwendet werden.
Abb. 5-4 Auswahl eines Dateinamens und eines Ablageorts
Parameter Der Befehl choose file name hat drei Parameter, die bei Bedarf verwendet werden können: << with prompt text << default name text << default location alias Der Parameter with prompt stellt die Aufforderungszeile unter dem Fenstertitel zur Verfügung: set myFile to choose file name with prompt "Geben Sie einen Namen und einen Ort für die Protokolldatei an:" Wenn Sie diesen Parameter weglassen, erhalten Sie die Standardaufforderung »Name und Ort der neuen Datei angeben«.
537
SmartBooks
AppleScript
Der Parameter default name gibt an, welcher Namensvorschlag für die zu erzeugende Datei in dem Feld Sichern unter des Dialogs stehen soll: set myFile to choose file name default name "Protokoll vom dd.mm.yyyy.txt" Wenn Sie diesen Parameter nicht angeben, bleibt das Namensfeld im Dialog leer. Mit dem Parameter default location können Sie den Ort angeben, der im Sichern-Dialog gleich zu Anfang angezeigt wird. Der angegebene Ort stellt nur einen Vorschlag dar und ist nützlich, um unnötige Navigation zu vermeiden, wenn die Dateien immer an einem ganz bestimmten Ort abgesichert werden sollen. Der Parameter muss als alias vorliegen: set myFile to choose file name default location alias "Macintosh HD:Users:Hans:Documents:"
Rückgabewert Der Rückgabewert ist immer vom Typ file, da ein alias ja bereits existieren muss: file "Macintosh HD:Users:Hans:Desktop:Test.txt" Wenn Sie in dem Dialog auf Abbrechen klicken, wird das Skript abgebrochen und Sie erhalten die Fehlernummer -128, die sich in einem try abfangen lässt.
Beispiel set myFile to choose file name with prompt¬ "Geben Sie einen Namen und einen Ort für die Protokolldatei an:"¬ default name "Protokoll vom dd.mm.yyyy.txt"¬ default location alias "Macintosh HD:Users:Hans:Documents:" Beachten Sie auch das Beispiel beim Parameter saving to des Befehls say am Ende dieser Suite.
choose folder Dieser Befehl ist das Gegenstück zum Befehl choose file. Statt einer Datei können Sie hier nur einen Ordner auswählen, Dateien sind im Dialog ausgegraut.
Parameter Der Befehl choose folder kennt insgesamt fünf optionale Parameter: << with prompt text << default location alias 538
Die Standarderweiterungen
Kapitel 5
<< invisibles boolean << multiple selections allowed boolean << showing package contents boolean Der Text, der für den Parameter with prompt angegeben wird, erscheint direkt unter der Fensterleiste. Wenn Sie diesen Parameter weglassen, erscheint dort kein Text. set myFolder to choose folder with prompt¬ "Bitte Ordner für das Protokoll auswählen:" Der Titel Wählen Sie einen Ordner in der Fensterleiste kann bei choose folder nicht verändert werden. Der Parameter default location kann dafür verwendet werden, den Auswahldialog bereits auf einen bestimmten Ordner einzustellen. Wenn der Dialog öfter verwendet wird, kann das dem Anwender das Navigieren dorthin ersparen. Der Parameter muss als alias vorliegen: set myFolder to choose folder default location¬ alias "Macintosh HD:Users:Hans:Documents:Briefe:" Ohne Angabe wird der zuletzt verwendete Ordner angezeigt. Der Parameter invisibles gibt an, ob unsichtbare Dateien und Ordner im Auswahldialog angezeigt werden. Standardmäßig werden diese nicht angezeigt, im Gegensatz zu choose file. Wenn auch unsichtbare Ordner auswählbar sein sollen, so müssen Sie invisibles auf true setzen: set myFolder to choose folder invisibles true Nach dem Übersetzen wird diese Form in die Schreibweise mit with/without umgewandelt: set myFolder to choose folder without invisibles Wenn für den Parameter multiple selections allowed der boolesche Wert true angegeben wird, dann ist die Auswahl mehrerer Ordner erlaubt (mit gedrückter Befehls- oder Umschalttaste auswählen). Wenn Sie diesen Parameter weglassen oder auf false setzen, kann nur ein einziger Ordner ausgewählt werden. set myFolder to choose folder with multiple selections allowed Der Parameter showing package contents erwartet einen booleschen Wert: set myFolder to choose folder showing package contents true
539
SmartBooks
AppleScript
Wenn der Wert auf true steht, ist es möglich, in Bundles hineinzuschauen. So können Sie zum Beispiel den Resources-Ordner in einem Bundle auswählen. Hier das Ergebnis von einem Skript-Bundle: set myFolder to choose folder with showing package contents -- alias "Macintosh HD:Users:Hans:Desktop:Test.app:Contents:Resources:" Wenn Sie diesen Parameter weglassen oder auf false setzen, können Sie nicht in Bundles hineinsehen.
Rückgabewert Der Rückgabewert von choose folder ist ein alias auf den ausgewählten Ordner: set myFolder to choose folder -- alias "Macintosh HD:Users:Hans:Desktop:" Wenn Sie multiple selections allowed auf true setzen, erhalten Sie eine Liste mit allen ausgewählten Ordnern als alias, auch wenn nur ein einzelner Ordner ausgewählt wurde: set myFolder to choose folder with multiple selections allowed --{alias "Macintosh HD:Users:Hans:Desktop:"} Wenn Sie auf Abbrechen klicken, wird das Skript abgebrochen, und Sie erhalten die Fehlernummer -128 die sich in einem try abfangen lässt.
Beispiel set myFolder to choose folder with prompt¬ "Bitte Ordner für das Protokoll auswählen:"¬ default location¬ alias "HD:Users:Hans:Desktop:Skript.app:Contents:Resources:"¬ with multiple selections allowed and¬ showing package contents without invisibles
choose from list Dieser Befehl ruft einen Dialog auf, in dem Sie ein Element aus einer Liste auswählen können.
Abb. 5-5 Der Dialog zur Auswahl aus einer Liste 540
Die Standarderweiterungen
Kapitel 5
Parameter Der Befehl choose from list hat acht Parameter, wovon der erste ein direkter Parameter ist und dem Befehl unmittelbar folgen muss. Seine Angabe ist daher unbedingt erforderlich: << list << with title text << with prompt text << default items list << OK button name text << cancel button name text << multiple selections allowed boolean << empty selection allowed boolean Der direkte Parameter muss eine Liste sein. Die Elemente der Liste müssen sich implizit in Text umwandeln lassen, falls sie nicht bereits Text sind, wie in folgendem Fall: set listItem to choose from list {"Merkur", "Venus", "Erde", "Mars", "Jupiter", "Saturn", "Uranus", "Neptun"} Eine Liste mit Objektreferenzen lässt sich also nicht anzeigen. Diese muss vorher zum Beispiel in eine Liste mit den Namen der Objekte oder in eine Liste mit einer Eigenschaft oder einem Unterelement des Objekts umgewandelt werden: tell application "Mail" set listItem to choose from list¬ (get subject of every message in inbox) end tell Hier wird zum Beispiel die Property subject einer E-Mail-Nachricht verwendet. Eine message selbst ist ein Programmobjekt von Mail, welches sich nicht direkt in Text umwandeln lässt. Die explizite Verwendung von get ist hier oft erforderlich. Der direkte Parameter folgt dem Befehl unmittelbar und muss immer vorhanden sein. Die Angabe einer leeren Liste ist nicht erlaubt. Der Parameter with title setzt den Titel in der Fensterzeile des Dialogs. Ist dieser Parameter nicht vorhanden, enthält die Titelleiste des Fensters keinen Text. set listItem to choose from list {"Merkur", "Venus", "Erde", "Mars", "Jupiter", "Saturn", "Uranus", "Neptun"} with title "Planeten auswählen"
541
SmartBooks
AppleScript
Der Parameter with prompt stellt den Aufforderungstext unter der Titelzeile dar. Wenn Sie diesen Parameter nicht angeben, wird der Standard Treffen Sie Ihre Auswahl verwendet. set listItem to choose from list {"Merkur", "Venus", "Erde", "Mars", "Jupiter", "Saturn", "Uranus", "Neptun"} with prompt "Wählen Sie einen Planeten:" Mit dem Parameter default items werden beim Öffnen des Dialogs bereits die angegebenen Werte zur Auswahl markiert. Dieser Parameter ist daher vor allem dort zu empfehlen, wo ein bestimmter Wert besonders häufig verwendet wird. Der Parameter benötigt eine Liste mit Werten, die auch in der Liste des direkten Parameters vorkommen. set listItem to choose from list {"Merkur", "Venus", "Erde", "Mars", "Jupiter", "Saturn", "Uranus", "Neptun"} default items {"Jupiter"} Kommt ein Wert nicht vor, kann er auch nicht in der Liste ausgewählt werden. Es gibt dabei keine Fehlermeldung. Die Liste kann auch mehrere Werte enthalten, die dann alle in der Liste bereits ausgewählt sind, jedoch muss dann auch der Parameter multiple selections allowed auf true stehen, ansonsten erhalten Sie eine Fehlermeldung: set listItem to choose from list {"Merkur", "Venus", "Erde", "Mars", "Jupiter", "Saturn", "Uranus", "Neptun"} default items {"Erde", "Jupiter"} with multiple selections allowed Mit dem Parameter OK button name können Sie den Namen des OK-Knopfes verändern. Es wird Text erwartet: set listItem to choose from list {"Merkur", "Venus", "Erde", "Mars", "Jupiter", "Saturn", "Uranus", "Neptun"} OK button name "Start" Mit dem Parameter cancel button name können Sie den Namen des Knopfes Abbrechen verändern. Es wird Text benötigt: set listItem to choose from list {"Merkur", "Venus", "Erde", "Mars", "Jupiter", "Saturn", "Uranus", "Neptun"} cancel button name "Startabbruch" Wenn für den Parameter multiple selections allowed der boolesche Wert true angegeben wird, dann ist die Auswahl mehrerer Listenelemente erlaubt (mit gedrückter Befehlsoder Umschalttaste auswählen). Wenn Sie diesen Parameter weglassen oder auf false setzen, kann nur ein einziger Wert ausgewählt werden. set listItem to choose from list {"Merkur", "Venus", "Erde", "Mars", "Jupiter", "Saturn", "Uranus", "Neptun"} with multiple selections allowed Mit dem Parameter empty selection allowed können Sie es zulassen, dass gar nichts aus der Liste ausgewählt wird. Standardmäßig ist der OK-Knopf nicht aktiv, solange kein
542
Die Standarderweiterungen
Kapitel 5
Element in der Liste ausgewählt ist. Wenn Sie diese Option jedoch auf true setzen, ist der Knopf auch aktiv, wenn kein Wert in der Liste ausgewählt wurde. Sie erhalten dann eine leere Liste. set listItem to choose from list {"Merkur", "Venus", "Erde", "Mars", "Jupiter", "Saturn", "Uranus", "Neptun"} with empty selection allowed
Rückgabewert Der Rückgabewert von choose from list ist eine Liste mit einem einzigen Element – dem ausgewählten Element aus der Liste des direkten Parameters: set listItem to choose from list {"Merkur", "Venus", "Erde", "Mars", "Jupiter", "Saturn", "Uranus", "Neptun"} -- {"Uranus"} Wenn Sie in dem Dialog auf Abbrechen klicken, wird der Wert false zurückgeliefert. Das Skript wird dabei nicht beendet, sondern fährt mit den folgenden Anweisungen fort. Aus diesem Grund sollte ein Skript, welches unbedingt eine Auswahl aus der Liste benötigt, den Rückgabewert auf false überprüfen. Steht multiple selections allowed auf true, kann die Liste auch mehrere Elemente enthalten, wenn denn mehrere Werte in der Liste ausgewählt wurden: set listItem to choose from list {"Merkur", "Venus", "Erde", "Mars", "Jupiter", "Saturn", "Uranus", "Neptun"} with multiple selections allowed -- {"Merkur", "Erde", "Jupiter"} Steht empty selection allowed auf true, kann der OK-Knopf auch gedrückt werden, wenn keine Auswahl getroffen wurde. Der Rückgabewert ist dann eine leere Liste: set listItem to choose from list {"Merkur", "Venus", "Erde", "Mars", "Jupiter", "Saturn", "Uranus", "Neptun"} with empty selection allowed -- {}
Beispiel set listItem to choose from list¬ {"Merkur", "Venus", "Erde", "Mars", "Jupiter", "Saturn", "Uranus"}¬ with title "Planeten auswählen"¬ with prompt "Wählen Sie einen Planeten:"¬ default items {"Erde"}¬ OK button name "Start"¬ cancel button name "Startabbruch"¬ without multiple selections allowed and empty selection allowed
543
SmartBooks
AppleScript
choose remote application Dieser Befehl wurde schon im Rahmen des Kapitels Steuerung von Anwendungen auf entfernten Rechnern am Ende von Kapitel 4 behandelt. Beachten Sie daher auch die ausführlicheren Erläuterungen dort. Mit choose remote application können Sie eine Anwendung auf einem entfernten Rechner im Netzwerk auswählen. Falls mehrere Anwender auf dem Rechner angemeldet sind, können diese anhand der Spalte Benutzer-ID im Dialog unterschieden werden. Sie steuern also nicht den Rechner direkt, sondern immer nur eine Anwendung. Der Rechner kann über seinen Bonjour-Namen oder über seine IP-Adresse ausgewählt werden. Es sind nur bereits laufende Programme auswählbar und es können keine Programme gestartet werden.
Abb. 5-6 Auswahl einer Anwendung auf einem anderen Rechner
Parameter Dieser Dialog besitzt nur zwei Parameter: << with title text << with prompt text Der Parameter with title setzt den Titel in der Fensterzeile des Dialogs. Ist dieser Parameter nicht vorhanden, enthält die Titelleiste des Fensters den Text Entferntes Programm auswählen set remApp to choose remote application with title "Verbindung zu entferntem Programm herstellen"
544
Die Standarderweiterungen
Kapitel 5
Der Text, der für den Parameter with prompt angegeben wird, erscheint rechts unter der Fensterleiste. Wenn Sie diesen Parameter weglassen, erscheint dort der Text Programm auswählen. set remApp to choose remote application with prompt "Bitte wählen Sie eine Textverarbeitung aus:"
Rückgabewert Der Rückgabewert ist eine Referenz auf die ausgewählte Anwendung in Form einer EPPCURL. Im folgenden Beispiel wurde das Programm Finder des angemeldeten Anwenders mit der Benutzer-ID 501 (uid) ausgewählt. Der Finder hat hier die Prozess-ID (pid) 168. Der Rechner hat die IP-Adresse 192.168.1.4. set remApp to choose remote application -- application "Finder" of machine "eppc://192.168.1.4/?uid=501&pid=168" Wenn Sie in dem Dialog auf Abbrechen klicken, wird das Skript abgebrochen, und Sie erhalten die Fehlernummer -128, die sich in einem try abfangen lässt.
Beispiel set remApp to choose remote application¬ with prompt "Welches Programm soll ein neues Dokument anlegen?"¬ with title "Neues Dokument"
choose URL Dieser Befehl stellt einen Dialog zur Auswahl einer Netzwerkverbindung zur Verfügung. Die Verbindung selbst wird jedoch nicht von dem Dialog vorgenommen, das müssen Sie noch selber mit einem Programm Ihrer Wahl skripten. Wenn eine FTP-Adresse angegeben wurde, müssen Sie zum Beispiel mit einem FTP-Programm eine Verbindung zu der Quelle herstellen. Netzwerkquellen, die ihre Dienste über Bonjour offerieren, werden automatisch gefunden und im unteren Bereich zur Auswahl angeboten. Ansonsten ist die manuelle Eingabe einer Serveradresse möglich. Welche Dienste angeboten werden sollen und welche nicht, lässt sich über einen der Parameter definieren.
545
SmartBooks
AppleScript
Abb.5-7 Der Dialog zur Auswahl eines Bonjour-Dienstes oder zur Eingabe einer URL Bietet ein Rechner mehrere Bonjour-Dienste an, so erscheint dessen Gerätename mehrmals in der Liste. Klicken Sie einen Namen an, um dann an der darüber eingeblendeten Serveradresse die Art dieses Dienstes zu erkennen.
Parameter Der Befehl choose URL hat nur zwei Parameter: << showing list << editable URL boolean Der Parameter showing gibt an, welche Dienste mit dem Dialog ausgewählt werden können. Als Argument wird eine Liste erwartet. Die Elemente dieser Liste müssen dabei aus einer beliebigen Kombination folgender Konstanten bestehen oder aus Textelementen, die sich als Bonjour Service Type interpretieren lassen: Service (als Konstante)
Dienste
Directory services
LDAP
File servers
AFP, NFS und SMB
FTP servers
FTP
Media servers
RTSP
News servers
NNTP
Remote applications
EPPC
Telnet hosts
TELNET
Web servers
HTTP und HTTPS
546
Die Standarderweiterungen
Kapitel 5
Bonjour Service Type
Protokoll
_afpovertcp._tcp
Apple Filing Protocol (AFP)
_nfs._tcp
Network File System (NFS)
_webdav._tcp
WebDAV File System (WEBDAV)
_ftp._tcp
File Transfer Protocol (FTP)
_ssh._tcp
Secure Shell (SSH)
_eppc._tcp
Remote Apple Events (EPPC)
_http._tcp
Hypertext Transfer Protocol (HTTP)
_telnet._tcp
Remote Login (TELNET)
_printer._tcp
Line Printer Daemon (LPD/LPR)
_ipp._tcp
Internet Printing Protocol (IPP)
_pdl-datastream._tcp
PDL Data Stream (Port 9100)
_riousbprint._tcp
Remote I/O USB Printer Protocol, AirPort Extreme USB Printer Sharing
_daap._tcp
Digital Audio Access Protocol (DAAP), iTunes Sharing
_dpap._tcp
Digital Photo Access Protocol (DPAP), iPhoto Sharing
_ichat._tcp
iChat Instant Messaging Protocol (veraltet, von iChat 1.0)
_presence._tcp
iChat Instant Messaging Protocol
_ica-networking._tcp
Image Capture Sharing
_airport._tcp
AirPort Base Station
_xserveraid._tcp
Xserve RAID
_distcc._tcp
Distributed compiler, Xcode
_apple-sasl._tcp
Apple Password Server, Open Directory
_workstation._tcp
Workgroup Manager
_servermgr._tcp
Server Admin
_raop._tcp
Remote Audio Output Protocol (RAOP), AirTunes
Für weitere Erläuterungen zu diesen Bonjour-Services beachten Sie bitte folgenden Link: http://developer.apple.com/qa/qa2001/qa1312.html Packen Sie nur die Dienste in die Liste, die auch ausgewählt werden dürfen. Wenn Sie zum Beispiel eine URL zu einem File-Server suchen, dann brauchen Sie nur File servers in die Liste zu schreiben.
547
SmartBooks
AppleScript
Bei den Diensten aus der ersten Liste handelt sich um Schlüsselwörter der Standarderweiterung, das heißt, diese werden nicht in Anführungszeichen geschrieben! Im Folgenden werden Ihnen nur die Dienste von Verzeichnisdiensten (Directory Services) und DateiServern (File servers) zur Auswahl angeboten: set myURL to choose URL showing {Directory services, File servers} Bonjour Service Types müssen Sie hingegen in Anführungszeichen schreiben: set myURL to choose URL showing {"_afpovertcp._tcp","_nfs._tcp"} Beide Typen können auch gemischt werden. Der Parameter editable URL gibt an, ob das Eingabefeld Serveradresse änderbar ist. Wenn nicht, kann nur aus der Liste mit gefundenen Bonjour-Diensten ausgewählt werden. Standardmäßig ist das Feld änderbar. Wenn Sie nicht möchten, dass man eigene Adressen eingibt, müssen Sie editable URL auf false setzen. set myURL to choose URL showing {"_afpovertcp._tcp"} without editable URL Eine vom Anwender manuell eingegebene URL wird nicht auf ihre Gültigkeit hin überprüft!
Rückgabewert Der Rückgabewert ist die URL als reiner Text: set myURL to choose URL showing {File servers} -- "afp://192.168.1.22:548" Wenn Sie in dem Dialog auf Abbrechen klicken, wird das Skript abgebrochen, und Sie erhalten die Fehlernummer -128, die sich in einem try abfangen lässt.
Beispiel set myURL to choose URL¬ showing {"_ssh._tcp", File servers}¬ with editable URL
delay Der Befehl delay dient dazu, das Skript eine definierte Zeit lang pausieren zu lassen. Das kann sinnvoll sein, um zum Beispiel einem Programm die Zeit zu geben, einen Befehl zu Ende zu führen. Der Befehl kennt nur einen optionalen Parameter. Dieser Parameter bestimmt die Anzahl der Sekunden, die gewartet werden soll, bis mit den nächsten Anweisungen im Skript
548
Die Standarderweiterungen
Kapitel 5
fortgefahren wird. Der Parameter muss dem Befehl unmittelbar folgen und als integer oder real vorliegen: delay 3 beep Hier wird 3 Sekunden lang gewartet, bevor das Skript fortfährt und das beep ausgeführt wird. Der Standardwert beträgt 0 Sekunden. Wenn Sie den Parameter also ohne Angabe einer Zahl verwenden, wird nicht gewartet. Der Befehl hat keinen Rückgabewert.
display alert Mit diesem Befehl kann ein Warndialog angezeigt werden. Diese Warnung kann eine Überschrift und einen zusätzlichen erklärenden Text besitzen, sowie bis zu drei Knöpfe. Für das Icon auf der linken Seite existieren drei verschiedene Optionen, wobei sich zurzeit nur zwei wirklich voneinander unterscheiden.
Abb. 5-8 Ein einfacher Standard-Warndialog mit dem Icon »informational«
Abb. 5-9 Ein Warndialog mit dem »warning«-Icon, zusätzlichem »message«-Text und drei Knöpfen
Parameter Dieser Befehl hat 7 Parameter, wovon der erste ein direkter Parameter ist und dem Befehl unmittelbar folgen muss. Der direkte Parameter ist nicht optional, alle anderen Parameter können auch weggelassen werden. Die Parameter default button und cancel button können nur zusammen mit dem Parameter buttons verwendet werden.
549
SmartBooks
AppleScript
<< text << message text << as critical|informational|warning << buttons { text, …} << default button text|integer << cancel button text|integer << giving up after integer Der direkte Parameter benötigt die Angabe eines Textes. Dieser Text wird als Warnhinweis im Dialog verwendet. In den obigen Abbildungen ist dies der Text »Wollen Sie wirklich fortfahren?« set alertReply to display alert "Wollen Sie wirklich fortfahren?" Der Parameter message erwartet ebenfalls Text und dient als weitergehende Beschreibung. Er wird in kleinerer Schrift dargestellt, wie in der zweiten Abbildung ersichtlich. Dieser Parameter ist optional. Wenn Sie message weglassen, wird an dieser Stelle kein Text angezeigt. set alertReply to display alert "Wollen Sie wirklich fortfahren?" message "Alle Einstellungen werden gelöscht!" Über den Parameter as kann eines von drei zur Auswahl stehenden Icons ausgewählt werden. Als Wert sind nur die Konstanten critical, informational oder warning erlaubt. Nur einer der Werte kann genommen werden. Wenn der Parameter weggelassen wird, wird das Icon informational verwendet. Wenn Sie etwas dringlicher auf die drohende Gefahr hinweisen wollen, verwenden Sie explizit as warning. set alertReply to display alert "Wollen Sie wirklich fortfahren?" as warning Sie erhalten dann ein gelbes Warndreieck mit Ausrufezeichen, das schon etwas mehr nach Gefahr aussieht. Die dritte Stufe der Warnung ist as critical. Hier würde ich eine warnende Hand, oder ein anderes Symbol in vornehmlich roter Farbe erwarten, wie zum Beispiel das Icon stop von display dialog. Leider wird zurzeit aber noch das Standard-Icon informational angezeigt. Sie können die Icons, die hier verwendet werden, aber leider auch nicht ändern. Wenn Sie ein eigenes Icon in einem Warndialog einbauen wollen, so müssen Sie dafür den Befehl display dialog verwenden.
550
Die Standarderweiterungen
Kapitel 5
Der Parameter buttons benötigt eine Liste mit Text. Der Text dient der Beschriftung der Knöpfe. Da nur maximal drei Knöpfe angezeigt werden können, darf die Liste auch nur maximal drei Namen enthalten, oder Sie erhalten eine entsprechende Fehlermeldung. Die Reihenfolge der Namen entscheidet über die Positionierung im Dialog. Wenn Sie diesen Parameter weglassen, erscheint nur ein einziger Knopf mit dem Namen OK. Wenn Sie beim Parameter default button keinen anderen Knopf angegeben haben, ist außerdem immer der Knopf ganz rechts in der Liste der pulsierende Standardknopf, welcher sich mit der Taste [Return] auslösen lässt. Dieser Knopf muss dabei nicht unbedingt immer »OK« heißen, wie in folgendem Beispiel: set alertReply to display alert "Wollen Sie wirklich fortfahren?" buttons {"Nein", "Ja"} Der Parameter default button bestimmt, welcher der maximal drei Knöpfe der Standardknopf sein soll. Die Angabe dieses Parameters ist daher wirklich nur sinnvoll, wenn auch mehrere Knöpfe existieren und damit nur, wenn auch der Parameter buttons vorhanden ist. Existiert der Parameter buttons nicht, erhalten Sie bei Verwendung dieses Parameters eine Fehlermeldung. Ohne Angabe von default button ist immer der Knopf ganz rechts im Dialog der Standardknopf. Dieser wird umrandet und pulsierend dargestellt. Wenn Sie dieses Verhalten ändern wollen, dann können Sie mit diesem Parameter einen anderen Knopf zum Standard erheben. Als Angabe ist dabei der Knopfname erlaubt - wobei dieser genauso geschrieben werden muss wie im Parameter buttons - oder sein Index. Im Folgenden wird der Knopf Zurück über seinen Namen bestimmt: set alertReply to display alert "Wollen Sie wirklich fortfahren?" buttons {"Zurück", "Abbrechen", "OK"} default button "Zurück" Wenn Sie einen Index verwenden, müssen Sie beachten, dass die Knöpfe von links nach rechts durchgezählt werden. Die Indexnummer 1 entspricht also dem ersten Knopf in der Liste des Parameters buttons, der Index 2 dem mittleren Knopf und der Index 3 dem Knopf rechts, wenn 3 Knöpfe vorhanden sind. Sind nur zwei Knöpfe vorhanden, ist der Knopf ganz rechts natürlich die Nummer 2 und ist er alleine, ist er immer die Nummer 1. Negative Indexzahlen, um von rechts zu zählen, sind nicht erlaubt. Im folgenden Beispiel wird der Zurück-Knopf mit dem Index 1 ausgewählt: set alertReply to display alert "Wollen Sie wirklich fortfahren?" buttons {"Zurück", "Abbrechen", "OK"} default button 1
551
SmartBooks
AppleScript
Der Parameter cancel button bestimmt, welcher der Knöpfe auf das Drücken der [Esc]Taste reagieren soll. Ein solchermaßen definierter Knopf führt dann zum Abbruch des Skripts. Auch dieser Parameter kann nur verwendet werden, wenn der Parameter buttons vorhanden ist, da er sich auf die dort angegebenen Namen beziehungsweise deren Index in der Liste bezieht. Wenn Sie in einem beliebigen Mac OS X-Dialog die [Esc]-Taste drücken, dann wird dadurch immer der Knopf Abbrechen ausgelöst. In einem display alert hat standardmäßig keiner der Knöpfe diese Eigenschaft. Wenn Sie also möchten, dass einer der Knöpfe auf die [Esc]-Taste reagiert, müssen Sie diesem Parameter den entsprechenden Knopf zuweisen. Die Zuweisung geschieht per Name oder Index. In den folgenden Beispielen lässt sich der Abbrechen-Knopf durch die [Esc]-Taste auslösen: set alertReply to display alert "Wollen Sie wirklich fortfahren?" buttons {"Zurück", "Abbrechen", "OK"} cancel button "Abbrechen" Sie können auch einen Index verwenden: set alertReply to display alert "Wollen Sie wirklich fortfahren?" buttons {"Zurück", "Abbrechen", "OK"} cancel button 2 Der Parameter giving up after benötigt eine Ganzzahl. Diese Zahl wird als die Sekunden interpretiert, die der Dialog auf Antwort wartet. Ist die Zeit abgelaufen, wird der Dialog wieder geschlossen. Der folgende Dialog schließt sich zum Beispiel nach 5 Sekunden automatisch. Das Skript fährt dann mit den folgenden Anweisungen, wenn vorhanden, fort und wird dadurch nicht abgebrochen. set alertReply to display alert "Wollen Sie wirklich fortfahren?" giving up after 5
Rückgabewert Der Rückgabewert ist ein Record mit einer einzigen Property: set alertReply to display alert "Wollen Sie wirklich fortfahren?" -- {button returned:"OK"} Sie können dann den Rückgabewert nach seiner Eigenschaft button returned fragen und dementsprechend im Code fortfahren: if button returned of alertReply = "OK" then beep
552
Die Standarderweiterungen
Kapitel 5
Ist in dem Warndialog einer der Knöpfe als cancel button definiert worden, so führt dieser Knopf zum Abbruch des Skripts. Sie erhalten dann die Fehlernummer -128, die sich in einem try abfangen lässt. Haben Sie den Parameter giving up after verwendet, so enthält der zurückgelieferte Record auch eine Property namens gave up, die entweder true oder false enthält, je nachdem, ob die Zeit abgelaufen ist und sich der Dialog selbst beendet hat oder nicht. Steht gave up in dem Record auf true, enthält dementsprechend button returned einen leeren Text, da kein Knopf gedrückt wurde: set alertReply to display alert "Fortfahren?" giving up after 3 -- {button returned:"", gave up:true} Fragen Sie also nach dem Inhalt von button returned, um dann entsprechend darauf zu reagieren: set alertReply to display alert "Fortfahren?" giving up after 3 if button returned of alertReply = "" then return -- Skript beenden else say "You pressed " & button returned of alertReply end if beep Das beep wird hier nur ausgeführt, wenn ein Knopf gedrückt wird. Wird kein Knopf gedrückt, wird der implizite run-Handler (und damit das Skript) mit einem return beendet.
Beispiel set alertReply to display alert "Wollen Sie wirklich fortfahren?"¬ message "Alle Einstellungen werden gelöscht!"¬ as warning buttons {"Zurück", "Abbrechen", "OK"}¬ default button 1 cancel button 2 giving up after 10
display dialog Dieser Dialog ist außerordentlich flexibel und der einzige, der auch freie Informationen vom Anwender annehmen kann und damit seinen Namen dialog wirklich verdient. In den folgenden Abbildungen sehen Sie einige Möglichkeiten für ein display dialog.
553
SmartBooks
AppleScript
Abb. 5-10 Die 3 Standard-Icons stop, note und caution
Abb. 5-11 Einfache Abfragen, auch mit Bullets und Icon
Abb. 5-12 Auch eigene Icons sind möglich, hier ein »entliehenes« aus dem Finder-Bundle.
Parameter Ein display dialog kennt 9 Parameter: Der erste ist Pflicht. Es ist ein direkter Parameter, der unmittelbar dem Befehl folgt. Alle anderen sind optional. Im Gegensatz zu display alert können die Parameter default button und cancel button auch ohne den Parameter buttons verwendet werden. << text << with title text << buttons { text, …} << default button text|integer << cancel button text|integer << giving up after integer << with icon [stop|note|caution]|[ text|integer]|[alias|file]
554
Die Standarderweiterungen
Kapitel 5
<< default answer text << hidden answer boolean Der direkte Parameter benötigt die Angabe eines Textes und ist unbedingt erforderlich. Dieser Text wird als Hinweis im Dialog verwendet. In den obigen Abbildungen ist dies zum Beispiel der Text »Time for a break!« oder »Geben Sie Ihr Passwort ein:« set myDlg to display dialog "Time for a break!" Der Parameter with title gibt den Text an, der in der Fensterzeile angezeigt wird. set myDlg to display dialog "Wollen Sie wirklich alle Daten löschen?" ¬ with title "Löschen" Wird dieser Parameter nicht angegeben, erscheint kein Fenstertitel. Der Parameter buttons benötigt eine Liste, die Text enthält. Der Text dient der Beschriftung der Knöpfe in dem Dialog. Es können nur maximal drei Knöpfe angezeigt werden. Aus diesem Grund darf die Liste auch nur maximal drei Namen enthalten oder Sie erhalten eine Fehlermeldung. Die Reihenfolge der Namen entscheidet über die Positionierung im Dialog. Wenn Sie den Parameter default button nicht verwenden, ist keiner der Knöpfe als Standardknopf mit der Taste Return auswählbar: set myDlg to display dialog "Wollen Sie wirklich alle Daten löschen?" ¬ with title "Löschen" buttons {"Nein", "Ja", "Vielleicht"} Wenn Sie den Parameter cancel button nicht verwenden, ist auch keiner der angegebenen Knöpfe mit der Taste [Esc] bedienbar. Wenn Sie diesen Parameter nicht verwenden, hat jeder Dialog immer zwei Knöpfe, Abbrechen und OK. Beide sind durch die Tasten [Esc] beziehungsweise [Return] bedienbar. Der Parameter default button bestimmt, welcher der maximal drei Knöpfe der Standardknopf ist. Die Angabe dieses Parameters ist immer dann sinnvoll, wenn der Parameter buttons vorhanden ist. Existiert der Parameter buttons nicht, können Sie das Standardverhalten der Knöpfe Abbrechen und OK verändern: set myDlg to display dialog "Fortfahren?" default button "Abbrechen" Alternativ können Sie auch den Index verwenden. Die Knöpfe werden dabei von links nach rechts gezählt: set myDlg to display dialog "Fortfahren?" default button 1 In diesem Beispiel wird damit bei einem Return der Knopf Abbrechen angeklickt.
555
SmartBooks
AppleScript
Ohne Angabe von default button, aber mit Angabe von buttons ist kein Standardknopf definiert. Mit Angabe des Parameters buttons können Sie bestimmen, welcher der selbst definierten Knöpfe der Standardknopf sein soll. Auch hier können Sie den Knopf über seinen Namen oder seinen Index ansprechen: set myDlg to display dialog "Fortfahren?" buttons {"Nein", "Ja", "Vielleicht"} default button 3 set myDlg to display dialog "Fortfahren?" buttons {"Nein", "Ja", "Vielleicht"} default button "Vielleicht" Aufgepasst Negative Indexzahlen, um die Knöpfe von rechts nach links durchzuzählen, sind in einem display dialog nicht erlaubt. Der Parameter cancel button bestimmt, welcher der Knöpfe auf das Drücken der [Esc]Taste reagiert. Ein solchermaßen definierter Knopf führt dann zum sofortigen Abbruch des Skripts. Dieser Parameter ist vor allem sinnvoll, wenn der Parameter buttons vorhanden ist, da bei diesem kein standardmäßiger Abbrechen-Knopf vorhanden ist. set myDlg to display dialog "Fortfahren?" buttons ¬ {"Nein", "Ja", "Vielleicht"} cancel button 1 Die Angabe des Knopfes kann wie bei default button über den Index oder den Namen des Knopfes erfolgen. Wird der Parameter buttons nicht verwendet, können Sie mit diesem Parameter bewirken, dass der OK-Knopf durch Drücken der [Esc]-Taste ausgelöst wird: set myDlg to display dialog "Aufhören?" cancel button 2 Das stellt aber natürlich die übliche Verhaltensweise von Knöpfen in Dialogen auf den Kopf und wird sicher jeden Anwender verwirren. Der Parameter giving up after benötigt eine Ganzzahl. Diese Zahl wird als Sekunden interpretiert, die der Dialog auf Antwort wartet. Ist die Zeit abgelaufen, wird der Dialog wieder geschlossen. Der folgende Dialog schließt sich zum Beispiel nach 5 Sekunden automatisch. set myDlg to display dialog "Fortfahren?" giving up after 5 Wird der Parameter with icon verwendet, können Sie dem Dialog ein Icon mitgeben. Wenn Sie den Parameter with icon weglassen, wird kein Icon angezeigt.
556
Die Standarderweiterungen
Kapitel 5
Es stehen dabei grundsätzlich drei verschiedene zur Auswahl: die Icons stop, note und caution. Bei diesen drei Werten für den Parameter handelt es sich um Konstanten, die nicht in Anführungszeichen geschrieben werden. Sie können nur einen Wert davon verwenden: set myDlg to display dialog "Unerwarteter Fehler!" with icon stop Alternativ können Sie auf die drei Icons auch per Index zugreifen, wobei der Index in diesem Fall bei 0 beginnt: set myDlg to display dialog "Unerwarteter Fehler!" with icon 0 Die 0 steht für das Icon stop, die 1 für note und die 2 für caution. Das Beste, was der Parameter with icon zu bieten hat, ist die Fähigkeit, eigene Icons zu verwenden. Wenn Sie sich ein eigenes Icon mit dem Icon Composer der Developer Tools von Apple gebastelt oder wenn Sie ein passendes Icon in einem anderen Bundle gefunden haben (Copyright beachten!), so können Sie dieses auch in einem display dialog verwenden. Damit dieses Icon immer mit dem Skript zusammenbleibt, empfiehlt es sich natürlich, dieses Icon im Bundle des Skripts abzulegen. Speichern Sie daher folgende Zeile als Skript-Bundle ab und kopieren Sie dann ein beliebiges Icon, welches Sie dann mit path to resource und Namen ansprechen, im Format icns in den Ordner Resources: set myDlg to display dialog "Time for a break!" with icon ¬ (path to resource "ClockSearch.icns") Statt den Namen der Ressource im Bundle zu verwenden, können Sie aber auch eine beliebige Datei auf der Festplatte als alias- oder file-Objekt verwenden. Die Datei muss nur im icns-Format vorliegen. Das Icon ist natürlich nicht immer beim Skript, was zu beachten ist, wenn Sie es einmal weitergeben möchten. Im folgenden Beispiel wird ein Icon info.icns (ebenfalls vom Finder) auf dem Schreibtisch erwartet und von dort geladen: set myDlg to display dialog ("Uhrzeit: " & time string of (current date)) with icon alias ((path to desktop as text) & "info.icns") buttons {"OK"} default button 1 Der Parameter default answer ist dafür zuständig, eine Eingabezeile anzuzeigen. Ohne diese Angabe, erhalten Sie nur einen Dialog der oben beschriebenen Dialog-Varianten. Die Antwort besteht dort nur aus dem Drücken eines Knopfes. Mit default answer können Sie aber freie Antworten vom Benutzer erhalten. Als Parameter wird hier Text erwartet. Der Text erscheint in der Eingabezeile als Eingabevorschlag, kann also überschrieben werden: set myDlg to display dialog "Geben Sie eine Stadt ein:" default answer "Bonn" Wenn Sie keinen Eingabevorschlag machen wollen, so geben Sie dem Parameter einen leeren Text mit: set myDlg to display dialog "Geben Sie eine Stadt ein:" default answer "" 557
SmartBooks
AppleScript
Der Parameter hidden answer sorgt dafür, dass der Text, den der Anwender in die Eingabezeile schreibt, nur mit Bullets angezeigt wird. Nützlich ist dies vor allem, wenn es darum geht, mit sensiblen Daten wie Passwörtern umzugehen. Der Parameter ist nur sinnvoll, wenn auch default answer vorhanden ist. Ohne den Parameter default answer gibt es keine Eingabezeile. Als Parameter wird true oder false erwartet: set myDlg to display dialog "Geben Sie eine Stadt ein:" default answer "" ¬ hidden answer true Nach dem Kompilieren wird wieder in die Form mit with oder without übersetzt. Sie können es daher auch gleich so schreiben: set myDlg to display dialog "Geben Sie eine Stadt ein:" default answer "" ¬ with hidden answer
Rückgabewert Der Rückgabewert ist ein Record mit einer oder mehreren Propertys, abhängig davon, welche Parameter verwendet wurden. Im Maximalfall enthält der Record drei Werte: -- {text returned:"Berlin", button returned:"OK", gave up:false} Die Property text returned enthält den Text, den der Anwender eingegeben hat. Dieser Teil ist nur vorhanden, wenn der Dialog auch den Parameter default answer enthält. Der Text liegt immer im Klartext vor, auch wenn hidden answer eingeschaltet ist! Der Knopf, der gedrückt wurde, landet in der Property button returned und kann dort abgefragt werden: set myDlg to display dialog "Geben Sie was ein:" default answer "" -- {text returned:"Berlin", button returned:"OK"} if button returned of myDlg = "OK" then beep Aufgepasst Ist in dem Warndialog einer der Knöpfe als cancel button definiert worden, so führt dieser Knopf zum Abbruch des Skripts. Sie erhalten dann die Fehlernummer -128, die sich in einem try abfangen lässt. Haben Sie den Parameter giving up after verwendet, so enthält der zurückgelieferte Record auch eine Property namens gave up, die entweder true oder false enthält, je nachdem, ob die Zeit abgelaufen ist und sich der Dialog selbst beendet hat oder nicht. Steht gave up in dem Record auf true, enthält dementsprechend button returned einen leeren Text, da kein Knopf gedrückt wurde: set myDlg to display dialog "Time for a break!" giving up after 3 -- {button returned:"", gave up:true} 558
Die Standarderweiterungen
Kapitel 5
Beispiel set myDlg to display dialog "Bitte Passwort eingeben:"¬ with title "Login"¬ buttons {"Zurücksetzen", "Abbrechen", "OK"}¬ default button "OK" cancel button 1¬ giving up after 30 with icon note¬ default answer "" with hidden answer
say Dieser Befehl liest einen Text mit einer der im Betriebssystem eingebauten Stimmen vor. Die Stimmen, die standardmäßig zur Verfügung stehen, können allerdings nur englischsprachige Texte sauber vorlesen. Lässt man sich deutschen Text vorlesen, so ist das, je nach Stimme, kaum zu verstehen. Wenn man eine deutsche Stimme benötigt, muss man daher auf Drittanbieter zurückgreifen. Bekannt sind mir bisher zwei deutsche Stimmen, Katrin und Matthias, von cepstral.com. Sie lesen sehr sauber und ordentlich vor, beide sind nicht kostenlos, können aber vor Erwerb getestet werden. Aus diesem Grund enthalten die folgenden Beispiele alle englischen Text.
Parameter Der Befehl say kennt insgesamt 5 Parameter. Der erste Parameter ist ein direkter Parameter, dessen Angabe unbedingt erforderlich ist. << text << using text << displaying text << waiting until completion boolean << saving to any Der direkte Parameter ist nicht optional und muss auf jeden Fall angegeben werden. Hier wird ein Text erwartet, der vorgelesen wird: say "It's time for a break!" Der Parameter using erwartet ebenfalls einen Text. Dieser Text muss der Name einer installierten Stimme sein. say "It's time for a break!" using "Boing"
559
SmartBooks
AppleScript
Um einen Überblick zu bekommen, welche Stimmen verwendet werden können, schauen Sie einmal in den Systemeinstellungen unter Sprache nach. Dort finden Sie im Reiter Sprachausgabe im Einblendmenü Systemstimmen alle installierten Stimmen. Wählen Sie sich dort eine aus und klicken Sie auf Abspielen, um sich den Klang der Stimme anzuhören.
Abb. 5-13 Alle Systemstimmen stehen für say zur Verfügung. Der Parameter displaying ist für den Text zuständig, der im Feedback-Fenster der Spracherkennung angezeigt wird, wie in folgender Abbildung zu erkennen. say "Time for a break!" displaying "It's tea time" Natürlich muss dafür die Spracherkennung in den Systemeinstellungen unter Sprache eingeschaltet sein, ansonsten wird dieser Parameter ignoriert.
560
Die Standarderweiterungen
Kapitel 5
Abb. 5-14 Der Text des Parameters »displaying« wird am Feedback-Fenster der Spracherkennung angezeigt. Der Parameter waiting until completion sorgt dafür, dass das Skript auf das Ende des Vorlesens wartet - oder nicht. Standardmäßig, also ohne Angabe dieses Parameters, wird immer gewartet, bis der Text zu Ende vorgelesen wurde. Wenn Sie das nicht möchten, müssen Sie waiting until completion auf false setzen. Bemerkbar macht sich das erst, wenn es sehr viel Text vorzulesen gibt, zum Beispiel wenn der Text aus einem Dokument stammt. Das Skript fährt dann mit der Ausführung fort, während das System noch am Vorlesen ist. say "Time for a Break" without waiting until completion Mit dem Parameter saving to können Sie den Text gesprochen als Datei auf die Festplatte speichern. Die Datei wird dabei im Format aiff gespeichert. Der Text wird bei dieser Option nicht laut vorgelesen, aus diesem Grund ist der Befehl auch recht schnell fertig. say "It's time for a break!" using "Boing" saving to ((path to desktop) ¬ as string) & "Break.aiff" oder say "It's time for a break!" using "Boing" saving to (choose file name with prompt "Bitte einen Dateinamen mit der Endung .aiff und einen Speicherort auswählen")
Abb. 5-15 Der vorgelesene Text lässt sich als Datei abspeichern und damit auch in iTunes einfügen und in das mp3-Format umwandeln.
561
SmartBooks
AppleScript
Existiert die Datei schon, wird sie ohne Rückfrage überschrieben! Statt einen einfachen Pfad als Text anzugeben oder choose file name zu verwenden, können Sie auch ein alias-Objekt für diesen Parameter verwenden. Die Datei muss dann aber bereits existieren. Wenn Sie längere Texte auf diese Weise abspeichern, sollten Sie waiting until completion nicht auf false setzen, sondern besser ein display dialog dahinter setzen, ansonsten merken Sie nicht, wann die Aufnahme beendet ist. Ohne diesen Parameter wird der Text laut vorgelesen und in keiner Datei abgespeichert.
Rückgabewert Keiner Beispiel say "It's time for a break!" using "Boing"¬ displaying "It's tea time"¬ saving to ((path to desktop) as string) & "Break.aiff"¬ without waiting until completion
File Commands In der Suite File Commands der Standarderweiterung finden sich einige Befehle, die deprecated, also veraltet sind. Von ihrer Verwendung ist abzuraten. Es handelt sich um die Befehle info for, list disks und list folder. Auf diese Befehle gehe ich daher nur kurz ein, damit Sie damit umgehen können, wenn Sie ihnen in einem Skript begegnen. Dazu zeige ich Ihnen den alternativen Befehl mit den System-Events auf. Im Einzelnen stecken in dieser Suite folgende Befehle: << info for
Ermittlung von Dateiinformationen
<< list disks
Ermittlung der Namen aller eingebundenen Laufwerke
<< list folder
Auflisten der Namen aller Elemente in einem Ordner
<< mount volume
Einbinden eines Netzwerklaufwerks
<< path to
Ermittlung eines Pfades zu bestimmten Standardorten
<< path to resource Ermittlung des Pfades zu einer Ressource in einem Bundle
562
Die Standarderweiterungen
Kapitel 5
info for Dieser Befehl dient dazu, Informationen zu einem Ordner oder einer Datei abzufragen. Der Befehl hat zwei Parameter; Der erste ist ein direkter Parameter und erwartet ein alias oder eine file-Referenz. Er ist unbedingt erforderlich. Der zweite heißt size und erwartet einen booleschen Wert. Wenn size auf false steht, wird die Dateigrößeninformation eines Ordners oder einer Datei nicht ermittelt, was den Befehl schneller macht. Standardmäßig steht dieser Wert auf true. set fileInfo to info for alias "HD:Users:Hans:Desktop:Notizen.rtf" with size Der Rückgabewert ist ein Record. Dessen Inhalt entnehmen Sie bitte der linken Spalte der folgenden Tabelle. Aufgepasst Dieser Befehl ist veraltet. Apple empfiehlt stattdessen, die System-Events zu fragen: tell application "System Events" set fileInfo to properties of alias¬ "HD:Users:Hans:Desktop:Notizen.rtf" end tell Als Ergebnis erhalten Sie ebenfalls einen Record, jedoch mit den Informationen, die Sie in der rechten Spalte der Tabelle finden. Die Tabelle bezieht sich auf die Propertys, die eine einzelne Datei vom Typ RTF besitzt. Ordner und Programme und auch Bundle-Dokumente können noch zusätzliche oder andere Eigenschaften besitzen. Standarderweiterung – info for
System Events – properties of
name:"Notizen.rtf " creation date:date "Mittwoch, 30. Juli 2008 7:14:54 Uhr" modification date:date "Mittwoch, 30. Juli 2008 7:14:54 Uhr"
name:"Notizen.rtf " creation date:date "Mittwoch, 30. Juli 2008 7:14:54 Uhr" modification date:date "Mittwoch, 30. Juli 2008 7:14:54 Uhr" physical size:4096 size:340 class:alias
size:340 folder:false alias:false
563
SmartBooks
AppleScript
Standarderweiterung – info for
System Events – properties of
package folder:false
package folder:false stationery:false visible:true
visible:true extension hidden:false name extension:"rtf " displayed name:"Notizen.rtf " default application:alias "HD:Applications:TextEdit.app:" kind:"Formatierter Text (RTF)" file type:"" file creator:"" type identifier:"public.rtf " locked:false busy status:false short version:"" long version:""
name extension:"rtf " displayed name:"Notizen.rtf "
kind:"Formatierter Text (RTF)" file type:missing value creator type:missing value type identifier:"public.rtf " busy status:false short version:"" version:"" product version:"" volume:"HD" container:folder "HD:Users:Hans:Desktop:" of application "System Events" POSIX path:"/Users/Hans/Desktop/ Notizen.rtf " path:"HD:Users:Hans:Desktop:Notizen.rtf " URL:"file://localhost/Users/Hans/Desktop/ Notizen.rtf " id:"Notizen.rtf,-100,7425730"
list disks Dieser Befehl dient dazu, alle aktuell eingebundenen Laufwerke aufzulisten. Dieser Befehl kennt keinen Parameter. set myDisks to list disks Das Ergebnis ist eine Liste mit den Namen aller Laufwerke an diesem Rechner: {"Macintosh HD", "USB DISK", "Iomega750"} 564
Die Standarderweiterungen
Kapitel 5
Aufgepasst Dieser Befehl ist veraltet. Apple empfiehlt stattdessen, die System-Events zu fragen: tell application "System Events" set myDisks to get name of every disk end tell Das Ergebnis ist exakt dasselbe: {"Macintosh HD", "USB DISK", "Iomega750"}
list folder Mit diesem Befehl können Sie sich den Inhalt eines Ordners auflisten lassen. Der Befehl braucht als direkten Parameter eine alias- oder file-Referenz auf einen Ordner. Mit dem optionalen Parameter invisibles, welcher einen booleschen Wert benötigt, kann angegeben werden, ob auch unsichtbare Dateien gezeigt werden sollen. Standardmäßig steht invisibles auf true. set myItems to list folder alias "HD:Users:Hans:Test" with invisibles Als Ergebnis erhalten Sie eine Liste mit den Namen aller in dem Ordner enthaltenen Elemente: {".DS_Store", "Break.aiff", "callme.app", "Notizen.rtf"} Aufgepasst Dieser Befehl ist veraltet. Apple empfiehlt stattdessen, die System-Events zu fragen: tell application "System Events" set myItems to get name of every disk item of folder¬ "HD:Users:Hans:Test" end tell Das Ergebnis ist das gleiche: {".DS_Store", "Break.aiff", "callme.app", "Notizen.rtf"} Wenn keine unsichtbaren Dateien enthalten sein sollen, fragen Sie mit whose nach der Eigenschaft visible:
565
SmartBooks
AppleScript
tell application "System Events" set myItems to get name of every disk item of folder¬ "HD:Users:Hans:Test" whose visible is true end tell -- {"Break.aiff", "callme.app", "Notizen.rtf"}
mount volume Mit diesem Befehl können Sie ein freigegebenes Laufwerk im Netzwerk auf Ihrem Rechner einbinden. Dieser Befehl lässt sich gut in Kombination mit dem Befehl choose URL aus der Suite User Interaction verwenden, da dieser einen URL-Pfad für den direkten Parameter von mount volume liefert. Dieser Befehl stellt die AppleScript-Implementation des Finder-Menübefehls Gehe zu | Mit Server verbinden dar.
Parameter Dieser Befehl hat 5 Parameter. Der erste Parameter muss immer vorhanden sein. << text << on server text << in AppleTalk zone text << as user name text << with password text Der direkte Parameter muss aus einem Text bestehen, der sich als Name oder Pfad des externen Laufwerks interpretieren lässt. Das kann der Bonjour-Name sein: mount volume "afp://macminimi.local" Oder die IP-Adresse: mount volume "afp://192.168.1.8" Sie können auch Benutzer und Passwort gleich mit angeben: mount volume "afp://Hans:[email protected]" Das freigegebene Volume kann als Pfad angehängt werden: mount volume "afp://Hans:[email protected]/Hans" 566
Die Standarderweiterungen
Kapitel 5
Auch andere Protokolle sind natürlich möglich, zum Beispiel das SMB-Protokoll für den Zugriff auf einen freigegebenen Ordner eines Windows-Rechners: mount volume "smb://MSHEIMNETZ;Hans:[email protected]/ Hans/Eigene Dateien" Der Parameter on server muss nur angegeben werden, wenn der direkte Parameter nur den Namen des freigegebenen Ordners oder Laufwerks enthält, ohne Serveradresse. Für diesen Parameter wird ebenfalls ein Text erwartet. Theoretisch sollte es so funktionieren: mount volume "FreeForAll" on server "afp://macminimi.local" Das funktioniert bei mir jedoch weder unter Leopard noch unter Tiger, weder mit AFP noch mit SMB, noch mit relativer oder absoluter Angabe des Pfades. Vermeiden Sie besser diesen Parameter und geben Sie den Servernamen samt Ordner lieber gleich komplett im direkten Parameter an. Der Parameter in AppleTalk zone erwartet die Angabe eines Zonennamens. Da AppleTalk kaum noch für das Einbinden von Laufwerken verwendet wird, ist dieser Parameter mehr ein Relikt aus alten Zeiten. Wenn Sie den Namen bereits im URL-Pfad angeben, kann dieser Parameter wegfallen. Der Parameter as user name erlaubt Ihnen anzugeben, als welcher Benutzer Sie sich am anderen Rechner oder Server anmelden wollen. Durch diesen Parameter können Sie den Benutzer also aus dem direkten Parameter herausnehmen und stattdessen in diesen Parameter stecken: mount volume "afp://macminimi.local/Hans" as user name "Hans" Ohne Angabe eines Benutzernamens haben Sie nur Gastzugriff. Der Parameter with password erlaubt Ihnen, das Passwort mit in den Befehl zu packen. Dieser Parameter stellt nur eine Alternative zur Passwortangabe im direkten Parameter dar und muss bei Verwendung immer zusammen mit dem Parameter as user name verwendet werden: mount volume "afp://macminimi.local/Hans" as user name "Hans" ¬ with password "bizzelwizzel" Ohne Angabe eines Passwortes haben Sie nur Gastzugriff. Wenn es trotz Angabe von as user name und with password zur Anzeige eines Dialogs kommt, müssen Sie Benutzername und Passwort direkt in der URL des Parameters unterbringen. Der Befehl mount volume hat keinen Rückgabewert.
567
SmartBooks
AppleScript
path to Mit dem Befehl path to können Sie den Pfad zu einem der Standardorte in einem Mac OS X-Betriebssystem herausbekommen, egal, auf welchem Rechner Sie sich befinden. Jeder Mac hat eine bestimmte Grundstruktur an Ordnern, die auf jedem Rechner vorhanden sind. Der Pfad zu diesen Ordnern lässt sich mit path to ermitteln. Der erste Parameter ist ein direkter und unbedingt erforderlich, die anderen sind optional.
Parameter Der Befehl path to hat 2 oder 4 Parameter, abhängig davon, ob der direkte Parameter einen Wert aus application oder folder constant verwendet. << application|folder constant << as type class << folder creation boolean << from domain constant Der direkte Parameter mit application kann die folgenden Begriffe für ein Programm verwenden: << current application << frontmost application << application "AppName" << me << it Als Ergebnis erhalten Sie ein alias mit dem Pfad zu diesem Programm: path to application "TextEdit" -- alias "HD:Applications:TextEdit.app:" Wenn Sie für den direkten Parameter einen dieser Begriffe verwenden, können die Parameter folder creation und from nicht verwendet werden! Der direkte Parameter mit einer folder constant ist noch wesentlich vielseitiger. Folgende Konstanten weisen bei einem angemeldetem Benutzer auf folgende Ordner im Betriebssystem hin (bei einem frisch installierten Mac OS X ist nicht unbedingt jeder Ordner vorhanden):
568
Die Standarderweiterungen
Kapitel 5
folder constant
Standardpfad
apple menu
nur Mac OS 9 oder Classic domain
application support
"HD:Library:Application Support:"
applications folder
"HD:Applications:"
control panels
nur Mac OS 9 oder Classic domain
control strip modules
nur Mac OS 9 oder Classic domain
desktop
"HD:Users:UserName:Desktop:"
desktop pictures folder "HD:Library:Desktop Pictures:" "HD:Users:UserName:Documents:" documents folder downloads folder
"HD:Users:UserName:Downloads:"
extensions
nur Mac OS 9 oder Classic domain
favorites folder
"HD:Users:UserName:Library:Favorites:"
Folder Action scripts
"HD:Users:UserName:Library:Scripts:Folder Action Scripts:"
fonts
"HD:System:Library:Fonts:"
help
"HD:Library:Documentation:Help:"
home folder
"HD:Users:UserName:"
internet plugins
"HD:System:Library:Internet Plug-Ins:"
keychain folder
"HD:Users:UserName:Library:Keychains:"
launcher items folder
nur Mac OS 9 oder Classic domain
library folder
"HD:Library:"
modem scripts
"HD:System:Library:Modem Scripts:"
movies folder
"HD:Users:UserName:Movies:"
music folder
"HD:Users:UserName:Music:"
pictures folder
"HD:Users:UserName:Pictures:"
preferences
"HD:Users:UserName:Library:Preferences:"
printer descriptions
"HD:System:Library:Printers:PPDs:"
printer drivers
nur Mac OS 9 oder Classic domain
printmonitor
nur Mac OS 9 oder Classic domain
public folder
"HD:Users:UserName:Public:"
scripting additions
"HD:System:Library:ScriptingAdditions:"
scripts folder
"HD:Users:UserName:Library:Scripts:"
shared documents
"HD:Users:Shared:" 569
SmartBooks
AppleScript
folder constant
Standardpfad
shared libraries
"HD:System:Library:CFMSupport:"
shutdown folder
nur Mac OS 9 oder classic domain
sites folder
"HD:Users:UserName:Sites:"
speakable items
nur Mac OS 9 oder classic domain
startup disk
"HD:System:Library:Printers:PrintMonitor Documents:"
startup items
"HD:Library:StartupItems:"
stationery
nur Mac OS 9 oder classic domain
system folder
"HD:System:"
system preferences
"HD:System:Library:PreferencePanes:"
temporary items
"HD:private:var:folders:xy:xy............:TemporaryItems:"
trash
"HD:Users:UserName:.Trash:"
users folder
"HD:Users:"
utilities folder
"HD:Applications:Utilities:"
voices
nur Mac OS 9 oder classic domain
workflows folder
"HD:Users:UserName:Library:Workflows:"
Hier ein Beispiel für die Verwendung der obigen Konstanten: set movPath to path to movies folder -- alias "HD:Users:Hans:Movies:" Wie auch immer der Benutzer heißen mag, mit path to finden Sie den richtigen Weg zu »seinem« Filmordner. Der Parameter from: Wenn Sie die Liste oben genau betrachten, werden Sie feststellen, dass überall dort, wo der Ordner Library vorkommt, meist der Pfad zum Library-Ordner des Systems verwendet wird. path to fonts -- alias "HD:System:Library:Fonts:" Um auf die entsprechenden Ordner in einem anderen Bereich zuzugreifen, müssen Sie daher explizit die domain mit angeben. Das ist mit dem Parameter from möglich. Hier ein Beispiel, um den Pfad zum Zeichensatz-Ordner des Anwenders zu ermitteln: path to fonts from user domain -- alias "HD:Users:Hans:Library:Fonts:" 570
Die Standarderweiterungen
Kapitel 5
Folgende domains gibt es: domain constant
entspricht Library unter
system domain
HD:System:… (/System)
local domain
HD:… (/)
Network domain
NetzHD:… (/Network)
user domain
HD:Users:UserName:… (~/)
Classic domain
HD:Systemordner:…
Wenn es für einen Ordner mehrere Pfade gibt, empfiehlt es sich, immer explizit die Domain mit from anzugeben. Verlassen Sie sich nicht darauf, dass die in der Tabelle abgebildeten Pfade auf ewig so bestehen bleiben, und verwenden Sie nach Möglichkeit immer path to. Änderungen in zukünftigen Versionen des Betriebssystems können und werden Änderungen an diesen Orten zur Folge haben. Wenn Sie in Ihrem Skript path to verwendet haben, wird das Skript sehr wahrscheinlich auch in Zukunft problemlos funktionieren. Mit dem Parameter folder creation können Sie bestimmen, ob der Ordner, falls er noch nicht existiert, automatisch angelegt werden soll. Wenn Sie diesen Parameter nicht verwenden, wird immer versucht, diesen Ordner zu erschaffen, soweit die Rechte dafür bestehen. Wenn Sie das nicht wollen, müssen Sie folder creation auf false setzen: path to scripts folder from user domain without folder creation -- alias "HD:Users:Hans:Library:Scripts:" Falls der Ordner Scripts nicht existiert, wird er nun nicht erzeugt. Das Skript erzeugt dann einen Fehler. Mit dem Parameter as bestimmen Sie den Rückgabewert von path to. Der Parameter akzeptiert zwei Angaben, alias oder text. Ohne diesen Parameter wird immer ein alias zurückgeliefert. Wenn Sie den Pfad als Text brauchen, so verwenden Sie as text: path to downloads folder as text -- "HD:Users:Hans:Downloads:"
Rückgabewert Der Rückgabewert ist standardmäßig ein alias: path to fonts -- alias "HD:System:Library:Fonts:" Mit dem Parameter as können Sie sich den Pfad aber auch als Text zurückgeben lassen: path to fonts as text -- "HD:System:Library:Fonts:" 571
SmartBooks
AppleScript
path to resource Mit diesem Befehl können Sie auf Ressourcen in einem Bundle zugreifen. Das kann das eigene Bundle sein oder das Bundle eines anderen Programms. Der Befehl liefert den kompletten Pfad zu der angegebenen Datei als alias zurück. Beachten Sie hier auch die Beispiele unter Laden von Bibliotheken aus dem Bundle des Skripts in Kapitel 4.
Parameter Dieser Befehl hat drei Parameter: Der erste ist ein direkter Parameter, der unbedingt erforderlich ist. Die anderen beiden sind optional. << text << in bundle file << in directory text Der direkte Parameter muss immer angegeben werden. Hier wird der Name der angeforderten Ressource erwartet. Wenn Sie im Bundle des Skripts eine Datei in den Ordner Resources abgelegt haben und nun im Skript darauf zugreifen wollen, dann brauchen Sie nur den Namen dieser Datei zu wissen: set resPath to path to resource "tables.txt" -- alias "HD:Users:Hans:Desktop:Test.scptd:Contents:Resources:tables.txt" Anschließend können Sie über das zurückgelieferte alias darauf zugreifen. Verwenden Sie load script, wenn es sich dabei um ein Skript handelt, welches im aktuellen Skript benötigt wird. Verwenden Sie einen der Befehle aus der Suite File Read/Write, wenn es sich um einen anderen Dateityp handelt, wie zum Beispiel Text. In einem display dialog können Sie diesen Befehl verwenden, um ein eigenes Icon aus dem Bundle des Skripts für den Dialog zu verwenden. Wenn die Datei nicht im eigenen Bundle liegt, sondern im Bundle eines anderen Programms oder Skripts, so verwenden Sie zusätzlich den Parameter in bundle. Als Argument erwartet der Parameter eine alias- oder file-Referenz auf das entsprechende Bundle. Im folgenden Beispiel wird der Pfad zum Kompass-Icon von Safari ermittelt. set resPath to path to resource "compass.icns" in bundle alias ¬ ((path to applications folder as text) & "Safari.app") -- alias "HD:Applications:Safari.app:Contents:Resources:compass.icns"
572
Die Standarderweiterungen
Kapitel 5
Wenn Sie Safari mit tell ansprechen, können Sie sich die Pfadangabe zum Programm aber auch sparen: tell application "Safari" set resPath to path to resource "compass.icns" end tell -- alias "HD:Applications:Safari.app:Contents:Resources:compass.icns" Wenn Sie diesen Parameter nicht verwenden, wird also das Bundle des aktuellen Ziels verwendet. Wenn Sie sich in einem tell an ein Programm befinden und auf das Bundle des eigenen Skripts zugreifen wollen, müssen Sie daher mit tell me klarstellen, dass Sie sich auf das Bundle des eigenen Skripts beziehen wollen: tell application "Safari" tell me to set resPath to path to resource "info.icns" end tell -- alias "HD:Users:Hans:Desktop:Test.scptd:Contents:Resources:info.icns" Ist das aktuelle Skript kein Bundle, wird das Bundle der current application verwendet. Bei einem im Skripteditor geöffneten Skript ist es das Bundle des Skripteditors. Aufgepasst Unter Mac OS X 10.4 Tiger liefert path to resource bei einem im Skripteditor geöffneten Skript-Bundle und ohne Angabe des Parameters in bundle immer den Pfad zum Skripteditor. Zum Testen dieses Befehls müssen Sie unter Tiger daher immer explizit in bundle verwenden und auf das eigene Skript-Bundle verweisen oder das Skript vor dem Test immer als Programm-Bundle abspeichern. Der Parameter in directory erwartet den Namen eines Ordners im Ordner Resources des Bundles. Wenn Sie dort zum Beispiel einen Ordner für die Lokalisierung Ihres Skripts in eine andere Sprache angelegt haben oder auf ein Skript im Ordner Scripts zugreifen wollen, dann können Sie das mit dem Parameter in directory: set resPath to path to resource "lib.scpt" in directory "Scripts" -- alias "HD:Users:Hans:Desktop:Test.scptd:Contents:Resources:Scripts:lib.scpt" Wenn Sie mit in directory auf einen Ordner in einem anderen Skript zugreifen, dann muss dieses als Programm-Bundle vorliegen! Der Zugriff auf ein anderes Skript-Bundle geht nicht.
Rückgabewert Der Befehl path to resource liefert immer ein alias auf die Datei zurück. set resPath to path to resource "info.icns" -- alias "HD:Users:Hans:Desktop:Test.scptd:Contents:Resources:info.icns"
573
SmartBooks
AppleScript
Beispiel set resPath to path to resource "tables.txt"¬ in bundle alias ((path to desktop as text) & "Test.app")¬ in directory "data" -- alias "HD:Users:Hans:Desktop:Test.app:Contents:Resources:data:tables.txt"
String Commands In dieser Rubrik stecken 5 Befehle, von denen zwei seit der Umstellung von AppleScript auf Unicode veraltet sind. Es handelt sich um die beiden Befehle ASCII character und ASCII number. << ASCII character Ermittlung des Zeichens eines ASCII-Wertes << ASCII number
Ermittlung des ASCII-Wertes eines Zeichens
<< localized string der Schlüssel zur Lokalisierung eines Skripts << offset
Positionsermittlung eines Suchtextes
<< summarize
Der Dienst Zusammenfassung in AppleScript-Implementierung
ASCII character Dieser Befehl hat nur einen direkten Parameter und erwartet eine Ganzzahl: set myChar to ASCII character 75 -- Ergebnis: "K" Als Ergebnis erhalten Sie den Buchstaben K, welcher dem ASCII-Wert 75 entspricht. Der Rückgabewert ist immer ein Text. Liegt die Integerzahl außerhalb des Bereichs von 0 bis 255, erhalten Sie die Fehlermeldung Ungültiger Bereich mit der Fehlernummer -1720. Sie können dabei nur auf die Zeichen 0 bis 255 der Standardschriftcodierung des Betriebssystems zugreifen. Bei Integerwerten außerhalb dieses Bereichs erhalten Sie daher eine Fehlermeldung. Auf einem deutschen System ist die Mac OS Roman Codierung maßgeblich, wie im Anhang abgebildet.
574
Die Standarderweiterungen
Kapitel 5
Von den 256 möglichen Zeichen sind dabei nur die Zeichen 0 bis 127 über alle Mac-Codierungen hinweg identisch. Der Bereich darüber weicht in unterschiedlichen Codierungen mehr oder weniger voneinander ab. Aufgepasst Dieser Befehl ist veraltet. Bevorzugen Sie ab AppleScript 2.0 character id: set myChar to character id 2384 -- Ergebnis: "ॐ" Im Gegensatz zu ASCII character kann character id auch eine Liste von mehreren Unicodenummern (als Dezimalwert) enthalten und liefert diese dann als zusammenhängenden Text zurück: set myChar to character id {72, 97, 108, 108, 111} -- Ergebnis: "Hallo" Damit haben Sie Zugriff auf den gesamten Unicode-Zeichensatz. Beachten Sie hierzu das Kapitel Unicode unter Arbeiten mit Text im Kapitel 4.
ASCII number Dieser Befehl liefert Ihnen die Nummer eines ASCII-Zeichens zurück. Auch dieser Befehl hat nur einen direkten Parameter, welcher aber Text erwartet: set myChar to ASCII number "a" -- Ergebnis: 97 Mit diesem Befehl können Sie die Nummer eines ASCII-Zeichens ermitteln. Stehen in dem Argument mehrere Zeichen, wird nur die Nummer des ersten Zeichens zurückgeliefert. Auch hier ist mit ASCII wieder die Standardschriftcodierung des Betriebssystems gemeint. Auf einem deutschen System also die Mac OS Roman Codierung. Der Rückgabewert ist immer eine Ganzzahl. Liegt das Zeichen außerhalb des Bereichs von 0 bis 255, zum Beispiel weil Sie ein Unicode-Zeichen angegeben haben, erhalten Sie keine Fehlermeldung!
575
SmartBooks
AppleScript
Aufgepasst Dieser Befehl ist veraltet. Bevorzugen Sie ab AppleScript 2.0 die Eigenschaft id eines Textes: id of "H" -- Ergebnis: 72 Im Gegensatz zu ASCII number liefert id eine Liste mit den Unicodenummern (Dezimalwert) zurück, wenn Sie einen Text mit mehreren Zeichen angeben: id of "Hallo" -- Ergebnis: {72, 97, 108, 108, 111} Und natürlich können Sie mit id auf den gesamten Unicode-Zeichenvorrat zugreifen: id of "ॐ" -- Ergebnis: 2384 Beachten Sie hierzu das Kapitel Unicode unter Arbeiten mit Text im Kapitel 4.
localized string Dieser Befehl dient dazu, die Übersetzung zu einem bestimmten Schlüsselwort in einer Datei zu suchen und zurückzuliefern. Damit können Sie Ihr Skript mehrsprachig gestalten. Die Dateien mit den Schlüsseln und Texten liegen normalerweise im Bundle des Skripts selbst. Das Skript muss dann als Programm-Bundle gespeichert sein. Im Abschnitt Beispiel gebe ich eine ausführliche Anleitung, wie Sie Ihr Skript mit localized string für mehrere Sprachen lokalisieren können. Sie müssen dafür nämlich erst die entsprechenden Dateien mit den Schlüsseln im Bundle erzeugen. Zuerst einmal aber die Erklärung der Parameter.
Parameter Der Befehl hat drei Parameter. Der erste ist unbedingt erforderlich. << text << from table text << in bundle file Der direkte Parameter erwartet die Angabe des Schlüssels, unter dem der gesuchte Text zu finden ist. Von der Annahme ausgehend, dass der Schlüssel zum Beispiel "MyNotFound" heißt, können Sie dann auf diese Weise nach dem Text dazu fragen: set locString to localized string "MyNotFound" 576
Die Standarderweiterungen
Kapitel 5
Als Ergebnis erhalten Sie den Text, der sich hinter diesem Schlüssel verbirgt: "Dokument nicht gefunden" Haben Sie dabei mehrere Lokalisierungen in Ihrem Bundle angelegt, wird entsprechend der Text aus der Sprache verwendet, die gerade auf Ihrem Betriebssystem eingestellt ist oder bevorzugt wird. Haben Sie in Ihrem Skript also zum Beispiel eine englische und deutsche Lokalisierung angelegt, so erscheint der Text auf einem englischen Betriebssystem in englischer Sprache und auf einem deutschen in deutscher. Der Parameter from table bestimmt den Namen der Datei, in welcher die Übersetzungstexte liegen. Die Dateiendung strings wird dabei weggelassen. Wenn Sie diesen Parameter nicht verwenden, wird immer die Datei Localizable.strings verwendet. Sie können diese Datei aber trotzdem auch explizit angeben: set locString to localized string "MyNotFound" from "Localizable" Der Parameter in bundle erwartet eine file- oder alias-Referenz auf das Bundle, in dem die Textdateien enthalten sind. Wenn dieser Parameter fehlt, wird das eigene Bundle oder die current application verwendet. Damit können Sie also auch auf Schlüssel in anderen Bundles zugreifen: set locString to localized string "MyNotFound" in bundle alias ¬ "HD:Users:Hans:Desktop:LocTest.app"
Rückgabewert Der Rückgabewert ist immer ein Text. Beispiel Um die Verwendung dieses Befehls zu verdeutlichen, ist ein wenig Vorbereitung nötig. Aus diesem Grunde hier eine ausführliche Anleitung, wie Sie ein Skript komplett für mehrere Sprachen (hier zwei) lokalisieren können: 1. Erstellen Sie im Skripteditor ein neues Skript und speichern Sie es so leer, wie es ist, im Format Programm-Bundle mit dem Namen LocTest.app auf dem Schreibtisch ab. 2. Schließen Sie das Skript im Skripteditor. 3. Klicken Sie das Skriptprogramm auf dem Schreibtisch mit der rechten Maustaste an und wählen Sie Paketinhalt zeigen. 4. Öffnen Sie den Ordner Contents und dann den Ordner Resources. 5. Legen Sie im Ordner Resources zwei neue Ordner an und nennen Sie diese German. lproj und Englisch.lproj. In diese beiden Ordner kommen später die lokalisierten Textdateien hinein.
577
SmartBooks
AppleScript
6. Öffnen Sie ein neues Dokument in TextEdit und schreiben Sie die folgenden Zeilen hinein. Vergessen Sie dabei nicht das Semikolon am Ende jeder Zeile. Die erste Zeile bildet einen Kommentar, der mit zwei Schrägstrichen beginnt und bis zum Ende der Zeile gilt. Solche Zeilen werden später ignoriert, können Ihnen aber dabei helfen, Ordnung in dieser Datei zu halten: // Fehlerdialoge "MyNotFound" = "Dokument nicht gefunden"; "MyIsUsed" = "Dokument ist noch in Verwendung"; 7. Wählen Sie in TextEdit Format | In reinen Text umwandeln. 8. Speichern Sie das Dokument unter dem Namen Localizable.strings im Format Unicode (UTF-16) auf dem Schreibtisch. Achten Sie darauf, dass nicht die Dateiendung txt angehängt wird. 9. Schieben Sie die Datei Localizable.strings in das Bundle des Skripts in den Ordner Contents/Resources/German.lproj/. 10. Erstellen Sie ein zweites Dokument in TextEdit und schreiben Sie die folgenden Zeilen hinein. Vergessen Sie nicht die Semikolons am Ende jeder Zeile: // Error-Dialogs "MyNotFound" = "Document not found"; "MyIsUsed" = "Document still in use"; 11. Wandeln Sie die Datei wieder über Format | In reinen Text umwandeln in reinen Text um. 12. Speichern Sie das Dokument unter dem Namen Localizable.strings im Format Unicode (UTF-16) auf dem Schreibtisch. Achten Sie darauf, dass nicht die Dateiendung txt angehängt wird. 13. Schieben Sie die Datei Localizable.strings in das Bundle des Skripts in den Ordner Contents/Resources/English.lproj/. Damit haben Sie nun zwei Lokalisierungen im Skriptprogramm angelegt. Das Bundle des Applets muss nun so aussehen wie in folgender Abbildung.
578
Die Standarderweiterungen
Kapitel 5
Abb. 5-16 Der Inhalt eines lokalisierten Applets mit zwei lproj-Ordnern 14. Öffnen Sie nun das Programm LocTest.app mit dem Skripteditor, indem Sie es auf sein Icon ziehen. 15. Schreiben Sie folgenden Codezeilen in das Skript: set locString to localized string "MyNotFound" display dialog locString set locString to localized string "MyIsUsed" display dialog locString 16. Sichern Sie das Applet und schließen Sie es dann. 17. Doppelklicken Sie es im Finder. Als Ergebnis wird in zwei aufeinander folgenden Dialogen der deutsche Text aus der Datei Localizable.strings im Ordner German.lproj angezeigt. 18. Klicken Sie das Applet im Finder mit der rechten Maustaste an und wählen Sie Informationen. 19. Schauen Sie dort in der Rubrik Sprachen nach und klappen Sie diesen Bereich eventuell auf. Dort sind jetzt zwei Sprachen aufgelistet. Nehmen Sie zum Testen einmal den Haken bei Deutsch weg.
579
SmartBooks
AppleScript
Abb. 5-17 Das Applet enthält nun zwei Sprachpakete. 20. Wenn der Haken bei Deutsch entfernt ist, doppelklicken Sie das Applet erneut, um es zu starten. Als Ergebnis erhalten Sie nun die Dialoge mit den englischen Texten. Alternativ können Sie auch die Sprache in den Landeseinstellungen der Systemeinstellungen auf Englisch umstellen und sich dann abmelden und neu anmelden oder den Finder neu starten. Danach werden auch ohne Deaktivierung eines Sprachpakets die englischen Dialogtexte verwendet. Ihr Skript verwendet jetzt immer die Sprache, die gerade auf dem Mac eingestellt ist oder bevorzugt wird.
Abb. 5-18 Ob der Dialog auf Englisch oder Deutsch erscheint, hängt nun ganz von den Einstellungen des Betriebssystems und den Wünschen des Anwenders ab. Auf diese Weise wird ein Skript mit Hilfe des Befehls localized string lokalisiert. Aufgepasst Der Befehl localized string funktioniert nur zuverlässig, wenn das Skript als Programm gestartet wird. Aus dem Skripteditor heraus oder als Skript-Bundle können Sie es nicht testen!
580
Die Standarderweiterungen
Kapitel 5
offset Dieser Befehl liefert Ihnen die Position eines Textes in einem anderen wieder. Dieser Befehl hat zwei Parameter, die beide immer vorhanden sein müssen. Beide Parameter benötigen Text. << of text << in text Der Parameter of ist der Text, dessen Position ermittelt werden soll. Der Parameter in stellt den Text dar, in welchem der Text aus dem Parameter of gesucht werden soll. offset of "bin" in "Ich bin ein Berliner" -- Ergebnis: 5 Hier wird die Position des Textes "bin" im Text "Ich bin ein Berliner" gesucht. Als Ergebnis erhalten Sie die 5, da das b von bin an fünfter Stelle steht, der Suchtext dort also beginnt. Damit können Sie die Position eines Suchtextes in einem anderen, größeren Text ermitteln, was mit den text item delimiters nicht möglich ist. Der Rückgabewert ist immer eine Integerzahl und gibt die Position des Suchtexts im Haupttext wieder. Maßgebend für diesen Index ist dabei die Anzahl der Zeichen. Kommt der Suchtext nicht vor, wird 0 (null) zurückgeliefert. Existiert der Suchtext mehrmals, findet offset nur das erste Vorkommen des Suchtextes!
summarize Dieser Befehl fasst einen längeren Text auf wenige Sätze zusammen. Seine Wirkung entspricht dabei exakt dem Dienst Zusammenfassen im Dienste-Menü unter dem jeweiligen Programmnamen. Rufen Sie diesen Dienst erst auf, wenn Sie vorher einen längeren Text markiert haben.
Parameter Dieser Befehl hat zwei Parameter, einen direkten, der unbedingt erforderlich ist, und einen zweiten, optionalen, mit dem Sie die Anzahl der Sätze in der Zusammenfassung bestimmen können. << text|alias << in integer
581
SmartBooks
AppleScript
Bei dem direkten Parameter muss es sich um Text handeln oder um ein alias auf eine Textdatei. Der Text oder der Inhalt der Datei werden dann zusammengefasst. Hier ein Beispiel, welches den Text in einem offenen TextEdit-Dokument verwendet: tell application "TextEdit" summarize (get text of document 1) end tell Das Ergebnis wird ein einzelner Satz sein, egal, wie lang der Text in dem Dokument ist. Auch die Angabe eines alias auf eine Textdatei ist möglich: summarize alias "HD:Users:Hans:Desktop:Nachrichten.txt" Mit dem Parameter in bestimmen Sie, wie viele Sätze die Zusammenfassung haben soll. Der Wert kann also nicht kleiner sein als 1 und ist nach oben hin offen. Wenn Sie diesen Parameter weglassen, wird der Text immer auf einen einzigen Satz zusammengefasst. set sumTxt to summarize alias "HD:Users:Hans:Desktop:News.txt" in 5 Ob dem solchermaßen zusammengefassten Text noch sinnvolle Informationen und Zusammenhänge zu entnehmen sind, ist eine andere Frage – deren Beantwortung ich mich hier enthalte. Der Rückgabewert ist immer Text.
Clipboard Commands Die in dieser Suite versammelten Befehle drehen sich alle um die systemweite Zwischenablage von Mac OS X. Die Zwischenablage kann manchmal die einzige Möglichkeit sein, etwas aus einer Anwendung herauszuholen, was sich sonst per AppleScript nicht direkt ansprechen lässt. Im Einzelnen handelt es sich um folgende Befehle: << set the clipboard to etwas in die Zwischenablage kopieren << the clipboard
etwas aus der Zwischenablage herausholen
<< clipboard info
die Zwischenablage um Infos zu ihrem Inhalt bitten
582
Die Standarderweiterungen
Kapitel 5
set the clipboard to Mit diesem Befehl können Sie etwas in einem Skript in die Zwischenablage kopieren. Der einzige Parameter ist der direkte Parameter und dieser erwartet keine bestimmte Klasse als Wert. Sie können die Zwischenablage zum Beispiel direkt mit AppleScript-Werten füllen: set the clipboard to "ABC" Sobald diese Zeile ausgeführt wurde, können Sie zum Beispiel zu TextEdit wechseln und dort Bearbeiten | Einfügen wählen, und dieser Text wird eingefügt. Sie können aber auch eine Anwendung ansprechen und dort etwas in die Zwischenablage packen. tell application "TextEdit" activate set the clipboard to (get text of document 1) end tell Generell funktioniert das mit allen Objekten, die Sie auch von Hand über Bearbeiten | Kopieren in die Zwischenablage einfügen können. Eine Vorraussetzung ist nur, dass das entsprechende Programm den Zugang auf das clipboard über AppleScript auch ermöglicht. tell application "Finder" activate set the clipboard to alias "HD:Users:Hans:Desktop:test.txt" end tell Hier wird eine Datei in die Zwischenablage kopiert, möglich ist das, weil der Finder das unterstützt. Wenn Sie mit einer Anwendung sprechen, müssen Sie nur darauf achten, activate nicht zu vergessen, damit die Anwendung nach vorne kommt. Vorher hat die Anwendung keine Kontrolle über die Zwischenablage. Normalerweise ist es nicht nötig, die Zwischenablage zum Austausch von Daten zwischen Anwendungen zu verwenden, da Sie diese mit AppleScript meist auch direkt abfragen können. Ein Rückgabewert ist nicht vorhanden.
583
SmartBooks
AppleScript
the clipboard Mit diesem Befehl können Sie auf die Zwischenablage zugreifen und ihren Inhalt verwenden. Dieser Befehl hat die Zwischenablage als Rückgabewert. Aus diesem Grund ist auch immer darauf zu achten, von wem der Wert in der Zwischenablage stammt. Nicht jedes Programm kann mit Werten oder Objekten jedes anderen Programms umgehen. Aus diesem Grund hat dieser Befehl auch einen as-Parameter. << as type class Eine einfache Abfrage der Zwischenablage sieht so aus: set the clipboard to "ABC" set clipData to the clipboard -- "ABC" In der ersten Zeile wird der Text in die Zwischenablage gepackt und in der zweiten deren Inhalt über die Abfrage mit the clipboard der Variablen clipData zugewiesen. Im Folgenden wird die Zwischenablage in TextEdit gefüllt und dann im Finder im Spotlight-Kommentar einer Datei eingefügt: tell application "TextEdit" activate set the clipboard to (get text of document 1) end tell tell application "Finder" set comment of alias "HD:Users:Hans:Desktop:test.txt" to the clipboard end tell Mit dem Parameter as können Sie die Zwischenablage, soweit möglich, beim Abfragen auch gleich in einen Wertetyp von AppleScript umwandeln. Von besonderem Interesse ist dabei die Abfrage der Zwischenablage als Record. Kopieren Sie einmal im Finder mit Bearbeiten | Kopieren eine sehr kleine TextEdit-Datei. Gehen Sie dann in den Skripteditor und tippen Sie folgende Zeile: set clipData to the clipboard as record Sie erhalten die rohen Daten zu dieser Datei als Record. Bei einer einfachen TextEdit-Datei sieht das zum Beispiel so aus: {«class furl»:file "HD:Users:Hans:Desktop:test.txt", «class icns»:«data icns69636E730000…», picture:«data PICT08A000000…», «class ut16»:"test.txt", «class utf8»:"test.txt", «class hfs »:«data hfs 3F3F3…», string:"test.txt"}
584
Die Standarderweiterungen
Kapitel 5
Alle Elemente, die mit data beginnen, habe ich oben stark gekürzt, da sie selbst bei einer sehr kleinen Datei über Dutzende Seiten reichen. Nachdem die Zwischenablage so in ihre Klassen aufgeteilt wurde, können Sie nun ganz gezielt einzelne Bestandteile dieses Records abfragen: set dataIcon to «class icns» of clipData Wenn die Arbeit in solchen »Rohdaten« für Sie kein Problem ist, hilft das vielleicht in dem einen oder anderen Fall weiter, ansonsten gibt es auch noch die Befehle aus der Suite File Read/Write, die einem auch das Lesen und Schreiben von Binärdaten (as data) ermöglichen. Der Rückgabewert von the clipboard kann von jeder beliebigen Art sein und hängt nur davon ab, wer was hinein gepackt hat. Ob Sie oder irgendeine Anwendung damit etwas anfangen können, ist aber nicht immer sicher. Im Zweifel muss man es einfach testen.
clipboard info Dieser Befehl liefert Ihnen Informationen zu den in der Zwischenablage vorhandenen Klassen, ähnlich wie die Abfrage des clipboards als Record, nur dass hier der Datenteil nicht angezeigt wird. Dieser Befehl hat einen einzelnen, optionalen Parameter, den Sie verwenden können, um die Abfrage auf eine bestimmte Klasse zu reduzieren. << for type class Wenn Sie im Finder eine Datei in die Zwischenablage kopiert haben und dann nach der clipboard info fragen, erhalten Sie zum Beispiel folgenden Inhalt: set clipInfo to clipboard info -- {{«class furl», 46}, {«class icns», 42258}, {picture, 2208}, {«class ut16», 18}, {«class utf8», 8}, {«class hfs », 80}, {string, 8}} Das Ergebnis ist eine Liste mit Unterlisten. In jeder Unterliste steht dabei eine Klasse und dahinter deren Größe in Byte. Mit dem Parameter for können Sie die Auswahl auf einen einzigen Typ beschränken: set clipInfo to clipboard info for «class ut16» -- {{«class ut16», 18}} Wenn Sie den Parameter for weglassen, werden immer alle Klassen angezeigt.
585
SmartBooks
AppleScript
Der Rückgabewert ist immer eine Liste mit Listen als Elemente, die wiederum zwei Werte enthalten: einen Klassenbezeichner und die Größe des Datenteils der Klasse in Byte als Integerzahl.
File Read/Write In dieser Suite dreht sich alles darum, wie man direkt in AppleScript Dateien lesen und schreiben kann, ohne dafür ein anderes Programm zu steuern. Es enthält die folgenden Befehle: << open for access
öffnet eine Datei zum Lesen oder Beschreiben
<< close access
schließt eine Datei wieder
<< read
Auslesen einer Datei
<< write
Schreiben in die Datei
<< get eof
Abfragen des Dateiendes
<< set eof
Setzen des Dateiendes
open for access Dieser Befehl öffnet eine Datei zum Lesen oder Schreiben. Existiert die Datei noch nicht, wird sie erschaffen. Der Befehl liefert dabei eine Dateireferenznummer (file descriptor) zurück, über die in folgenden Befehlen auf die Datei zugegriffen werden kann. Beim Öffnen mit open for access wird über den file descriptor auch eine Art virtuelles »Lesezeichen« (file pointer) an den Anfang der Datei gestellt. Bei jedem nachfolgenden Befehl mit read oder write wird dieses Lesezeichen entsprechend weitergerückt, so dass nachfolgende Befehle an der Stelle weitermachen können, wo der vorige aufgehört hat. Eine einzelne Datei kann auch mehrmals mit open for access geöffnet werden. Jedes open for access hat dann seine eigene Dateireferenznummer und sein eigenes Lesezeichen und muss später auch, jedes für sich, einzeln wieder geschlossen werden. Tatsächlich ist es eigentlich nicht notwendig, eine Datei vor Anwendung der Befehle read oder write explizit mit open for access zu öffnen, da read und write auch mit alias oder file direkt auf die Datei zugreifen können. Die Datei wird dabei geöffnet und danach gleich wieder geschlossen. Wenn Sie jedoch mehrere Operationen hintereinander auf der Datei ausführen wollen, ist das vorherige Öffnen mit open for access und das
586
Die Standarderweiterungen
Kapitel 5
anschließende Schließen der Datei mit close access effektiver und schneller. Außerdem erleichtert der file pointer, das »Lesezeichen«, welches durch open for access zur Verfügung gestellt wird, die sequentielle Abarbeitung einer Datei erheblich. Ohne open for access müssen Sie die aktuelle Lese- oder Schreibposition jedes Mal selbst errechnen. Open for access bildet das Einstiegstor in alle folgenden Befehle in dieser Suite.
Parameter Dieser Befehl hat zwei Parameter, wovon nur der erste, ein direkter Parameter, obligatorisch ist: << file << write permission boolean Für den direkten Parameter wird eine Datei erwartet, und zwar im Format file oder alias: set newFile to open for access file "HD:Users:Hans:Desktop:text.txt" Wenn die Datei an dem angegebenen Ort bereits existiert, wird sie für das Skript mit Leseberechtigung geöffnet. Jedoch nicht etwa in einem Fenster, nein, sondern nur virtuell für den Code! Wenn die Datei an diesem Ort noch nicht existiert, wird dort eine Datei angelegt und für den Zugriff im Code mit Leseberechtigung geöffnet. Wenn Sie ein alias verwenden, muss die Datei natürlich bereits existieren, ansonsten verwenden Sie besser ein file. Das Ergebnis von open for access sollte dabei immer einer Variablen zugewiesen werden, da Sie später im Code über diese Variable auf die Datei zugreifen können. Wenn die Datei noch nicht existiert, bietet sich auch die Verwendung des Befehls choose file name zur Auswahl eines Dateinamens und Speicherorts an, da dieser Befehl ein file zurückliefert. set newFile to open for access (choose file name) Den optionalen zweiten Parameter write permission benötigen Sie, wenn Sie nicht nur lesend auf die Datei zugreifen möchten. Wenn Sie in die Datei hineinschreiben wollen, müssen Sie diesen Parameter immer explizit auf true setzen. Ohne diesen Parameter oder wenn er explizit auf false steht, haben Sie nur Lesezugriff. set newFile to open for access file ((path to desktop as text) & "test.txt") ¬ with write permission
587
SmartBooks
AppleScript
Rückgabewert Bei dem Rückgabewert handelt es sich um einen Integerwert, der eine Dateireferenznummer darstellt. Die Nummer ist einzigartig und bleibt bis zum Schließen der Datei unverändert. Diese Nummer können Sie mit den Befehlen in dieser Suite verwenden, um aus der Datei Daten auszulesen, um etwas hineinzuschreiben oder um die Datei nach getaner Arbeit wieder zu schließen. set newFile to open for access file "HD:Users:Hans:Desktop:text.txt" -- Ergebnis zum Beispiel: 277
close access Wenn Sie eine Datei mit open for access geöffnet haben, sollten Sie daran denken, die Datei nach Beendigung der Arbeit auch gleich wieder zu schließen. Wenn Sie das vergessen, bekommen Sie später Probleme, wenn Sie erneut auf die Datei zugreifen wollen und diese als noch in Verwendung gemeldet wird. Das Schließen einer Datei geschieht mit close access, welches nur einen direkten Parameter besitzt, welcher die Dateireferenznummer von open for access benötigt oder eine alias- oder file- Referenz auf die Datei. Wenn Sie das Ergebnis von open for access einer Variablen zugewiesen haben, geht das also so: set newFile to open for access file ((path to desktop as text) & "test.txt") -- weitere Befehle close access newFile In der ersten Zeile wird die Datei geöffnet und in der letzten wieder geschlossen. Dazwischen steht dann normalerweise der Code zum Lesen oder Schreiben in der Datei. Der Befehl close access hat keinen Rückgabewert.
read Nachdem Sie eine Datei mit open for access geöffnet haben, können Sie mit dem Befehl read in die Datei hineinsehen. Dieser Befehl sollte immer erst nach einem open for access ausgeführt werden. Sie können zwar auch direkt durch Angabe eines alias oder fileObjekts eine Datei lesen, verlieren dann jedoch den Vorteil des file pointers, wie bei open for access beschrieben. Wenn Sie mit dem Lesen fertig sind, dürfen Sie nicht vergessen, die Datei wieder mit close access zu schließen.
588
Die Standarderweiterungen
Kapitel 5
Parameter Dieser Befehl besitzt insgesamt 8 Parameter, wovon der erste ein direkter Parameter ist, dessen Angabe unbedingt erforderlich ist. Apple zählt zwar 9 Parameter, vom praktischen Standpunkt aus betrachtet handelt es sich bei den beiden Parametern using delimiters aber um ein und denselben Parameter, der zwei verschiedene Argumente akzeptieren kann, einmal Text und einmal eine Liste mit Text. Von den Parametern from, for, before und until darf maximal nur einer verwendet werden. Das Verwenden von before, until oder using delimiter führt dazu, dass der Dateiinhalt zuerst als Text interpretiert wird und erst danach als der im as-Parameter angegebene Wert. Wichtig ist dies aber nur für das Lesen binärer Daten oder für Daten, die zum Beispiel als Liste oder Record mit dem Befehl write in die Datei geschrieben wurden. << file descriptor|alias|file << as class << using delimiter(s) text|list of text << from integer << to integer|eof << for integer << before text << until text Vorbereitung: 1. Erstellen Sie für die folgenden Beispiele ein neues Dokument in TextEdit. 2. Wählen Sie Format | In reinen Text umwandeln. 3. Schreiben Sie einen einzelnen Satz wie zum Beispiel »Dies ist ein Test!« 4. Speichern Sie das Dokument dann über Ablage | Sichern unter im Format Westeuropäisch (Mac OS Lateinisch) (zu finden im Einblendmenü Codierung für reinen Text) mit dem Namen lat.txt auf dem Schreibtisch ab. 5. Speichern Sie das Dokument erneut über Sichern unter, diesmal aber im Format Unicode (UTF-16) mit dem Namen utf16.txt auf dem Schreibtisch ab. 6. Speichern Sie das Dokument ein letztes Mal über Sichern unter, diesmal aber im Format Unicode (UTF-8) mit dem Namen utf8.txt auf dem Schreibtisch ab.
589
SmartBooks
AppleScript
Der direkte Parameter erwartet die Angabe der Datei. Die Angabe kann als Dateireferenznummer, als alias oder file erfolgen. Am bequemsten und kürzesten ist auf jeden Fall die Verwendung der Dateireferenznummer (file descriptor): set newFile to open for access file ((path to desktop as text) & "lat.txt") set filesText to read newFile -- oder -- set filesText to read file ((path to desktop as text) & "lat.txt") -- oder -- set filesText to read alias ((path to desktop as text) & "lat.txt") close access newFile display dialog filesText Als Ergebnis erhalten Sie am Ende einen Dialog mit dem Satz aus der Datei. Hilfe Falls Sie einmal einen Fehler bekommen, kann das unter Umständen daran liegen, dass die Datei nicht korrekt geschlossen werden konnte. Kopieren Sie dann den Code, beenden Sie den Skripteditor und starten Sie ihn neu. Dadurch werden alle noch offenen Dateien automatisch geschlossen. Egal, ob der Text in der Datei nur aus einem Satz besteht oder hunderte Seiten umfasst, ohne einen weiteren beschränkenden Parameter wird der Text mit read immer komplett in die zur Verfügung gestellte Variable gepackt. Der Dateiinhalt wird also vom ersten bis zum letzten Buchstaben gelesen. Dabei gilt es zu beachten, dass sich AppleScript merkt, an welcher Stelle mit dem Lesen aufgehört wurde. Hier ist es am Ende der Datei. An dieser Stelle setzt sich AppleScript sein Lesezeichen (den file pointer), um dort dann mit eventuell folgenden read- oder writeBefehlen fortzufahren. Wenn, wie hier, die ganze Datei eingelesen wird und damit das unsichtbare Lesezeichen am Ende der Datei steht, wird jeder weitere read-Befehl fehlschlagen, da er versucht, am Ende der Datei mit dem Lesen anzufangen: set newFile to open for access file ((path to desktop as text) & "lat.txt") set filesText to read newFile set filesText to read newFile -- Das geht nicht! close access newFile display dialog filesText Hier erhalten Sie die Fehlermeldung, dass das Ende der Datei erreicht wurde. Der zweite read-Befehl fängt am Ende der Datei an und hat folglich keinen Text mehr »vor sich«. Der file pointer wird erst beim Schließen der Datei mit close access wieder zurückgesetzt oder wenn Sie mit einem der anderen Parameter eine neue Position bestimmen.
590
Die Standarderweiterungen
Kapitel 5
Beim Lesen gilt es noch die Codierung des Textes zu beachten. Wenn Sie ein Textdokument im Format Mac OS Lateinisch lesen, dann funktioniert das fehlerfrei. Im Format UTF-8 klappt das nur, wenn Sie keine Zeichen über einem ASCII-Wert von 127 verwenden. Und im UTF-16-Format erhalten Sie eventuell zwei seltsame Zeichen am Anfang des Textes (die BOM, byte order mark, dient als Hinweis auf die Byte-Sortierung) und falls Sie auch hier spezielle Zeichen verwenden, werden diese ebenfalls nicht richtig dargestellt. Schreiben Sie dafür einfach einmal ein paar Sonderzeichen wie zum Beispiel character id {8656, 8658, 8657, 8659} in die beiden Dokumente utf8.txt und utf16.txt. Standardmäßig geht der Befehl read davon aus, dass der Text in der Datei im nativen Format des Betriebssystems vorliegt. Welches das ist, hängt von den Ländereinstellungen ab. Bei einem deutschen System ist das Mac OS Roman, bei einem japanischen wäre es aber Mac OS Japanese. Um Text in einem anderen Format als Mac OS Roman korrekt einlesen zu können, müssen Sie daher noch den as-Parameter verwenden. Der as-Parameter ist dafür gedacht, den Typ des Dateiinhalts anzugeben. Liegt der Text in einer Datei im Format UTF-16 vor, dann verwenden Sie beim Lesen as Unicode text: set newFile to open for access file ((path to desktop as text) & "utf16.txt") set filesText to read newFile as Unicode text close access newFile display dialog filesText Jetzt wird der Text (und auch eventuell eingefügte Unicode-Zeichen) korrekt angezeigt. Liegt der Text im Format UTF-8 vor, dann verwenden Sie beim Lesen as «class utf8». Dieses Klasse hat in AppleScript keine Übersetzung und muss daher in diesem Rohformat verwendet werden: set newFile to open for access file ((path to desktop as text) & "utf8.txt") set filesText to read newFile as «class utf8» close access newFile display dialog filesText Auch hier wird der Text nun mit allen Sonderzeichen korrekt angezeigt.
591
SmartBooks
AppleScript
Sie können einen Text auch explizit mit as text auf einem deutschen System im Format Mac OS Roman lesen, obwohl dies schon das Standardverhalten und damit eigentlich unnötig ist: set newFile to open for access file ((path to desktop as text) & "lat.txt") set filesText to read newFile as text close access newFile display dialog filesText Aufgepasst Beachten Sie, dass bei dem Befehl read (und write) mit text nicht Unicode gemeint ist. Die Klasse text ist zwar in AppleScript generell auf Unicode umgestellt worden, hier ist aus Kompatibilitätsgründen jedoch mit text weiterhin das Standardformat auf dem Betriebssystem, bei uns Mac OS Roman, gemeint. Bei read muss also explizit die alte Klasse Unicode text verwendet werden, wenn Unicode in UTF-16-Kodierung gelesen werden soll. Damit ist die Nützlichkeit des Parameters as aber noch nicht erschöpft. Sie können sich damit auch den Dateiinhalt binär anzeigen lassen. Nützlich vor allem, wenn man mit einem Dateiformat bestens vertraut ist, ansonsten überlässt man das lieber einem Programm, welches sich damit auskennt, und steuert dieses per AppleScript. set newFile to open for access file ((path to desktop as text) & "lat.txt") set filesText to read newFile as data close access newFile get filesText -- «data rdat44696573206973742065696E205465737421» Power User Für die Programmierer: Bei binären Daten verwendet read immer Big-Endian byte order. Eine weitere nützliche Eigenschaft von read ist es, sich Daten als Datum, Liste oder Record anzeigen zu lassen. Das funktioniert aber nur, wenn vorher mit dem Befehl write diese Klassen auch aus dem Skript in die Datei geschrieben wurden. Aus diesem Grunde erkläre ich diese sehr nützliche Eigenschaft beim Befehl write. Der Parameter using delimiter benötigt einen Text oder eine Liste mit Text als Argument. Dieser Text wird als Trennzeichen verwendet, anhand dessen der gelesene Text in eine Liste aufgespalten wird. Für diesen Parameter wird der Dateiinhalt damit immer zuerst als Text behandelt und danach erst in den mit as angegebenen Typ umgewandelt, was zwar bei Textformaten keinen Unterschied ausmacht, wohl aber bei anderen Klassen wie data.
592
Die Standarderweiterungen
Kapitel 5
set newFile to open for access file ((path to desktop as text) & "lat.txt") set filesText to read newFile as text using delimiter " " close access newFile get filesText -- {"Dies", "ist", "ein", "Test!"} In diesem Beispiel wurde der Text am Leerzeichen getrennt. Das Ergebnis ist dann eine Liste mit den Textelementen zwischen den Leerzeichen. Das Leerzeichen als Trennzeichen ist darin nicht mehr enthalten. Damit eignet sich diese Technik auch wunderbar, wie bei den text item delimiters, um in Kombination mit write ein schnelles Suchen und Ersetzen im Text durchzuführen. Doch leider funktioniert das immer nur mit einem einzelnen Zeichen und nicht etwa mit einem Wort. Auch wenn Sie ein Wort als Argument von using delimiter angeben, nur das erste Zeichen wird gesucht. Hier ein Beispiel, um einen komma-separierten Text in einem Rutsch als Liste einzulesen. Wenn in einer Datei folgender Text steht: Meier,Hans,Am Schlierweg 7,80808,München Schulz,Gertrud,Hofgarten 1,20000,Hamburg Dann können Sie mit den folgenden Zeilen den Text beim Lesen in seine Einzelfelder aufteilen: set newFile to open for access file ((path to desktop as text) & "lat.txt") set filesText to read newFile as text using delimiter "," close access newFile get filesText --{"Meier", "Hans", "Am Schlierweg 7", "80808", "München Schulz", "Gertrud", "Hofgarten 1", "20000", "Hamburg"} Fehlt nur noch die Trennung am Zeilenumbruch. Das funktioniert auch mit den üblichen Textkonstanten wie tab oder return. Hier müssen Sie nur beachten, welches Absatzende-Zeichen in dem Text verwendet wird. Das kann das Zeichen linefeed oder das Zeichen return sein. Unter Mac OS X wird heutzutage mehr und mehr linefeed (character id 10) statt return (character id 13) verwendet. Hier müssen Sie also gegebenenfalls ausprobieren, welches Trennzeichen für das Absatzende wirklich in dem Text verwendet wird. Daher kann es geraten sein, im Zweifelsfall einfach beide Zeichen als Trennzeichen anzugeben, indem Sie using delimiters nicht ein einzelnes Zeichen als Text mitgeben, sondern eine Liste von Zeichen wie im folgenden Beispiel:
593
SmartBooks
AppleScript
set newFile to open for access file ((path to desktop as text) & "lat.txt") set filesText to read newFile as text using delimiter¬ {",", linefeed, character id 13} close access newFile get filesText -- {"Meier", "Hans", "Am Schlierweg 7", "80808", "München", "Schulz", "Gertrud", "Hofgarten 1", "20000", "Hamburg"} Nun ist der Text am Komma und an den möglichen Zeilenumbrüchen getrennt. Sie können als Trennzeichen auch Unicode-Zeichen als Literal verwenden, wenn Sie den Text mit dem as-Parameter auch als Unicode text einlesen. Wenn in der Textdatei utf16.txt folgende Textzeile steht: Dies⇒ist⇒ein⇒Test! Dann können Sie mit folgenden Zeilen den Text in eine Liste umwandeln: set newFile to open for access file ((path to desktop as text) & "utf16.txt") set filesText to read newFile as Unicode text using delimiter "⇒" close access newFile get filesText -- {"Dies", "ist", "ein", "Test!"} Der Parameter from bestimmt, an welcher Stelle mit dem Lesen begonnen wird. Die Angabe erfolgt in Ganzzahlen und bestimmt die Anzahl der Byte vom Anfang des Dokuments an gezählt. Wenn Sie ganze Minuszahlen angeben, wird vom Ende des Textes nach vorne gezählt. set newFile to open for access file ((path to desktop as text) & "lat.txt") set filesText to read newFile as text from 5 close access newFile get filesText -- " ist ein Test!" Die Zählweise ist 1-basiert. Um am Anfang der Datei anzufangen, muss also from 1 geschrieben werden. Bei Minusschreibweise wird von hinten nach vorne gelesen und damit der Text vom Ende aus extrahiert: set newFile to open for access file ((path to desktop as text) & "lat.txt") set filesText to read newFile as text from -5 close access newFile get filesText -- "Test!" 594
Die Standarderweiterungen
Kapitel 5
Gezählt wird in Bytes! Das bedeutet bei Mac OS Roman-Codierung: 1 Byte = 1 Zeichen. Bei einer Codierung in UTF-8 gilt: Die Zeichen von 0 bis 127 sind 1 Byte groß, alle Zeichen darüber nehmen 2 Byte ein. Bei einer Unicode-Codierung in UTF-16 gilt: 2 Byte = 1 Zeichen. set newFile to open for access file ((path to desktop as text) & "utf16.txt") set filesText to read newFile as Unicode text from 11 close access newFile get filesText -- " ist ein Test!⇐⇒⇑⇓" Bei UTF-16 müssen Sie daher wie oben darauf achten, immer eine ungerade Ganzzahl zu verwenden, ansonsten erhalten Sie eine Verschiebung der Bytehälften und damit falsche, unsinnige Unicode-Zeichen! Da die ersten beiden Zeichen oft (aber nicht immer) von der byte order mark (BOM) eingenommen werden, kann man auch oft erst mit dem dritten Byte beginnen. Wenn ein BOM vorhanden ist, interpretiert AppleScript Byte 1 und 3 gleichermaßen als Textbeginn. Eine eventuell vorhandene BOM wird also bei der Angabe from 1 immer übersprungen, wenn man den Text mit as Unicode text einliest. set newFile to open for access file ((path to desktop as text) & "utf16.txt") set filesText to read newFile as Unicode text from 3 close access newFile get filesText -- "Dies ist ein Test!⇐⇒⇑⇓" Hilfe Wenn Sie eine Unicode-Datei mit as text einlesen, wird die byte order mark (BOM), wenn vorhanden, am Anfang mit angezeigt. Außerdem erhalten Sie zwischen den lateinischen Buchstaben immer ein unsichtbares Zeichen, das meist keinen Platz einnimmt, also zuerst einmal gar nicht auffällt. Man bemerkt es aber, wenn man mit der Cursortaste darüber navigiert. Man braucht immer zwei Schritte, um zum nächsten Buchstaben zu gelangen. Dieses unsichtbare Zeichen ist das ASCII-Zeichen 0, im Folgenden mit kleinen Quadraten gekennzeichnet. Außerdem werden alle Zeichen über einem Unicode-Dezimalwert von 127 mit Ausrufe- oder Fragezeichen dargestellt, manchmal auch mit bestimmten Symbolen. Das ist abhängig von der Anwendung:
595
SmartBooks
AppleScript
set newFile to open for access file ((path to desktop as text) & "utf16.txt") set filesText to read newFile as text from 1 close access newFile get filesText -- Ergebnis: "˛ˇ□D□i□e□s□ □i□s□t□ □e□i□n□ □T□e□s□t□!!–! !“—!”" Wenn man einen Unicode-Text mit as text einliest, wird die BOM am Anfang der Datei sichtbar. Sie sieht als ASCII-Zeichen auf einem PowerPC so aus: ˛ˇ Es handelt sich dabei um die ASCII-Zeichen 254 und 255. Auf einem Intel Mac stehen diese Zeichen umgekehrt: ˇ˛ Hier kommt also zuerst das ASCII-Zeichen 255 und dann 254. Die BOM dient dazu, die Byte-Sortierung auf dem Rechner anzuzeigen. Auf dem PowerPC-Mac wird dabei die Byte-Reihenfolge »Big Endian« verwendet und auf dem IntelMac die Byte-Reihenfolge »Little Endian«. Für weitergehende Informationen einfach mal die Schlagwörter BOM, Big Endian und Little Endian bei Wikipedia eingeben. Normalerweise brauchen Sie sich über die BOM keine Gedanken zu machen. Es kann jedoch einmal sein, dass Sie diese explizit setzen müssen oder wollen. Beachten Sie dann den Tipp beim Befehl write. Wenn Sie diese Zeichen beim Lesen am Anfang der Datei bemerken, dann wissen Sie, dass Sie den Text mit as Unicode text einlesen müssen, um ein lesbares Ergebnis zu erhalten. Die BOM ist allerdings keine Pflicht beim Speichern im UTF-16-Format, es kann also auch sein, dass diese fehlt. Dann hilft es nur, alle Formate nacheinander auszuprobieren, bis ein sinnvolles Ergebnis vorliegt. Das Format «class utf8» erkennen Sie daran, dass beim Einlesen as text keine unsichtbaren Zeichen zwischen den einfachen lateinischen Buchstaben stecken. Die Zeichen über Dezimal 127 werden aber alle ebenfalls nicht angezeigt, stattdessen erscheinen meist seltsame Zeichenpaare: "Dies ist ein Test!‚áê‚áí‚áë‚áì" Auch UTF-8 kann eine BOM haben, muss es aber nicht. Lesen Sie diese Datei dann explizit mit as «class utf8» ein. Mit dem Parameter from wird auch der file pointer, das »Lesezeichen«, auf die angegebene Position verschoben. Der folgende Code würde ohne from zum Beispiel fehlschlagen, da nach dem ersten read das Dateiende bereits erreicht wäre. Durch das from wird aber wieder auf einen beliebigen Punkt davor zurückgesprungen:
596
Die Standarderweiterungen
Kapitel 5
set newFile to open for access file ((path to desktop as text) & "utf16.txt") set filesText to read newFile as Unicode text display dialog filesText -- "Dies ist ein Test!⇐⇒⇑⇓" set filesText to read newFile as Unicode text from 13 close access newFile display dialog filesText -- "ist ein Test!⇐⇒⇑⇓" Liegt die Integerzahl von from außerhalb der Dateigröße, erhalten Sie den Fehler »Ende der Datei erreicht« mit der Nummer -39. Standardmäßig wird immer von der mit from angegebenen Position bis zum Ende der Datei gelesen. Wenn Sie das nicht möchten, müssen Sie auch den Parameter to verwenden. Der Parameter to bestimmt, bis zu welchem Byte gelesen werden soll. Auch hier wird wieder mit 1 beginnend gezählt. Wenn Sie mit from keinen anderen Beginn festlegen, wird immer von der Position des letzten read- oder write-Befehls, also vom file pointer, aus gelesen. Bei to müssen Sie bei der Verwendung von UTF-16 darauf achten, immer gerade Zahlen zu verwenden, damit es keine »halben« Zeichen (1-Byte-Zeichen) am Ende gibt: set newFile to open for access file ((path to desktop as text) & "utf16.txt") set filesText to read newFile as Unicode text from 1 to 12 display dialog filesText -- "Dies " set filesText to read newFile as Unicode text to 26 display dialog filesText -- "ist ein" set filesText to read newFile as Unicode text to eof display dialog filesText -- " Test!⇐⇒⇑⇓" close access newFile Um das Ende der Datei zu kennzeichnen, müssen Sie dabei nicht die Anzahl Bytes in der Datei zählen. Sie können einfach eof schreiben, welches für das Signal steht, das bei Dateiende gesendet wird. Eof ist also ein Synonym für das letzte Byte in der Datei. Ohne eof müssen Sie zuerst mit dem Befehl get eof das Dateiende ermitteln und diesen Wert dann hier einsetzen. Liegt die Integerzahl des Parameters to außerhalb der Dateigröße, erhalten Sie den Fehler »Ende der Datei erreicht« mit der Nummer -39. Aufgepasst Der Parameter to kann nicht zusammen mit den Parametern for, before oder until verwendet werden.
597
SmartBooks
AppleScript
Mit dem Parameter for können Sie die Anzahl der Bytes festlegen, die gelesen werden sollen. Sie geben hier also nicht explizit den Anfang mit from und das Ende mit to an, sondern nur die Anzahl der Bytes. Das darauf folgende read macht aufgrund des internen file pointers automatisch an der letzten Position weiter. Wenn Sie mit Unicode text arbeiten, müssen Sie darauf achten, für den ersten Start wieder eine ungerade Zahl zu verwenden und dann immer nur eine gerade Anzahl an Bytes zu lesen: set newFile to open for access file ((path to desktop as text) & "utf16.txt") set filesText to read newFile as Unicode text from 1 for 14 display dialog filesText -- "Dies i" set filesText to read newFile as Unicode text for 14 display dialog filesText -- "st ein " set filesText to read newFile as Unicode text for 18 display dialog filesText -- "Test!⇐⇒⇑⇓" close access newFile . Aufgepasst Der Parameter for bietet sich geradezu an, in einer Schleife verwendet zu werden. Dabei müssen Sie nur beachten, dass Sie die augenblickliche Position des file pointers nicht ermitteln können. Das heißt, Sie müssen die aktuelle Position, also die Anzahl der gelesenen Bytes, in der Schleife mitzählen oder die Schleife in ein try packen und den Fehler beim Erreichen des Dateiendes damit abfangen. Im Folgenden zeige ich beide Varianten. Die Anzahl der Bytes in der Datei wird mit get eof vor Beginn der Schleife ermittelt, andere Varianten sind denkbar: set newFile to open for access file ((path to desktop as text) & "utf16.txt") set itsEOF to get eof newFile set currPOS to 1 -- nur ungerade Zahlen bei Unicode set stepWidth to 10 -- nur gerade Zahlen bei Unicode! repeat set filesText to read newFile as Unicode text for stepWidth display dialog filesText set currPOS to currPOS + stepWidth if currPOS ≥ itsEOF then exit repeat end repeat close access newFile Hier die Variante mit einem try-Block: set newFile to open for access file ((path to desktop as text) & "utf16.txt") try repeat set filesText to read newFile as Unicode text for 10 598
Die Standarderweiterungen
Kapitel 5
display dialog filesText end repeat on error close access newFile end try Alternativ können Sie auch explizit auf den Fehler -39 testen. Das ist die Fehlernummer, die beim Erreichen des Dateiendes geworfen wird. Aufgepasst Der Parameter for kann nicht zusammen mit den Parametern to, before oder until verwendet werden. Der Parameter before liest den Dateiinhalt als Text bis zu dem angegebenen Zeichen. Für before wird dabei ein einzelnes Zeichen erwartet. Das Zeichen selber wird mitgelesen, ist aber nicht Teil des Ergebnisses. Im Folgenden wurde das Leerzeichen verwendet: set newFile to open for access file ((path to desktop as text) & "utf16.txt") set filesText to read newFile as Unicode text before space display dialog filesText -- "Dies" set filesText to read newFile as Unicode text before space display dialog filesText -- "ist" set filesText to read newFile as Unicode text before space display dialog filesText -- "ein" set filesText to read newFile as Unicode text before space display dialog filesText -- "Test!⇐⇒⇑⇓" close access newFile Auch hier bietet sich eine Schleife an. Da Sie jedoch keinen Anhaltspunkt für die aktuelle Byte-Position haben, können Sie das Dateiende nur in einem try abfangen: set newFile to open for access file ((path to desktop as text) & "utf16.txt") try repeat set filesText to read newFile as Unicode text before space display dialog filesText end repeat on error close access newFile end try Aufgepasst Der Parameter before kann nicht zusammen mit den Parametern to, for oder until verwendet werden. . 599
SmartBooks
AppleScript
Der Parameter until verhält sich wie der Parameter before, nur dass in diesem Fall das angegebene Zeichen im Rückgabewert enthalten ist. Hier das Beispiel gleich in einer Schleife: set newFile to open for access file ((path to desktop as text) & "utf16.txt") try repeat set filesText to read newFile as Unicode text until space display dialog quote & filesText & quote end repeat on error close access newFile end try Aufgepasst Der Parameter until kann nicht zusammen mit den Parametern to, for oder before verwendet werden. Für before und until können Sie auch Unicodezeichen verwenden, wenn Sie den Text entsprechend mit dem as-Parameter als Unicode text einlesen. Verwenden Sie dafür das Unicode-Zeichen als Literal oder über Angabe der character id: set filesText to read newFile as Unicode text until "⇐" oder set filesText to read newFile as Unicode text until character id 8656
Rückgabewert Der Rückgabewert von read ist vom as-Parameter abhängig. Ohne dessen Angabe wird die primäre Schriftkodierung Mac OS Lateinisch auf einem deutschsprachigen Betriebssystem verwendet. Der Inhalt wird dann als Text eingelesen.
write Mit diesem Befehl können Sie etwas in eine Datei hineinschreiben. Wenn Sie für dessen Parameter to einen file descriptor verwenden, den Sie vorher durch ein open for access erhalten haben, dann wird der file pointer, das Lesezeichen, beim Schreiben entsprechend weitergeführt, so dass der nächste Schreibvorgang dort anfängt, wo der letzte aufgehört hat. Die Datei muss mit Schreibberechtigung geöffnet sein, ansonsten erhalten Sie eine Fehlermeldung mit der Fehlernummer -61.
600
Die Standarderweiterungen
Kapitel 5
Parameter Der Befehl write hat fünf Parameter, wovon der direkte Parameter und der Parameter to immer angegeben werden müssen. Die anderen Parameter sind optional. << any << to file descriptor|alias|file << as class << starting at integer|eof << for integer Der direkte Parameter bestimmt, was geschrieben werden soll, und der Parameter to bestimmt, in welche Datei. Für den direkten Parameter kann jede beliebige Klasse verwendet werden, für to muss eine Dateireferenznummer, die von open for access erhalten wurde, verwendet werden. Auch eine alias- oder file-Referenz ist möglich, jedoch erst nachdem die Datei mit open for access mit Schreibberechtigung geöffnet wurde. set newFile to open for access file ((path to desktop as text) &¬ "lat.txt") with write permission write "Hallo" to newFile close access newFile Hier wird der Text "Hallo" in die Datei newFile geschrieben. Wenn vorher in der Datei »Dies ist ein Test!« gestanden hat, so steht dort nun »Halloist ein Test!« Die Leerstelle nach »Dies« wird also überschrieben, da »Hallo« ein Zeichen mehr hat. Standardmäßig wird beim ersten Schreibvorgang immer am Anfang der Datei begonnen. Eventuell vorhandener Text wird überschrieben und nicht etwa nach hinten verdrängt wie in einer Textverarbeitung! Der Parameter as bestimmt, welche Klasse in die Datei geschrieben wird. Wenn Sie diesen Parameter nicht angeben, wird standardmäßig die Klasse verwendet, in der die Daten im direkten Parameter vorliegen. Handelt es sich dabei um text, wird Mac OS Roman auf einem deutschen Betriebssystem verwendet! Die Angabe der Klasse, in der Sie schreiben wollen, ist immer zu empfehlen. Für Text stehen Ihnen, wie beim Befehl read, drei Alternativen zur Auswahl; die Klasse Unicode text für das Format UTF-16, die Klasse «class utf8» sowie die Klasse text (oder string). Obwohl in AppleScript 2.0 der Text komplett auf Unicode umgestellt wurde, ist für den Befehl write (und read) die Klasse text weiterhin Mac OS Roman-kodiert!
601
SmartBooks
AppleScript
Geben Sie daher immer as Unicode text an, wenn Sie Unicode-Zeichen im Format UTF-16 schreiben wollen: set newFile to open for access file ((path to desktop as text) &¬ "utf16.txt") with write permission write character id 8658 to newFile as Unicode text close access newFile -- Text in der Datei: "⇒Dies ist ein Test!" Dabei ist zu beachten, dass an Position 1 mit dem Schreiben begonnen wird, nicht an Byteposition 3 wie beim Lesen einer UTF-16-Datei mit BOM. Wenn eine Datei bereits ein BOM hat, müssen Sie mit dem Schreiben über die Verwendung des Parameters starting at am dritten Byte beginnen, oder Sie überschreiben die byte order mark. Tipp Wenn die Datei noch nicht existiert, also durch open for access erst erstellt wurde, wird durch write kein BOM geschrieben: set newFile to open for access file ((path to desktop as text) &¬ "utf16_neu.txt") with write permission write character id 8658 to newFile as Unicode text close access newFile Wenn Sie nun die Datei mit TextEdit öffnen, werden Sie nur ein Ausrufezeichen mit einem Gänsefüßchen darin sehen. TextEdit kann wegen des fehlenden BOM nicht erkennen, dass es sich hier um einen Text in UTF-16-Kodierung handelt. Öffnen Sie daher die Datei in TextEdit über Ablage | Öffnen und wählen Sie dabei Unicode (UTF16) neben Codierung für reinen Text aus. Jetzt wird Ihnen der Pfeil ⇒ angezeigt, den Sie in die Datei geschrieben haben. Um dieses explizite Öffnen in TextEdit (und damit auch in anderen Programmen) zu vermeiden, empfiehlt es sich, das BOM zu Anfang mit write selbst anzulegen. Auf dem Intel Mac so: set newFile to open for access file ((path to desktop as text) &¬ "utf16_neu2.txt") with write permission write (ASCII character 255) & (ASCII character 254) to newFile write "⇒" to newFile as Unicode text close access newFile Auf dem PowerPC mit umgekehrter Reihenfolge der beiden ASCII-Zeichen: set newFile to open for access file ((path to desktop as text) &¬ "utf16_neu2.txt") with write permission 602
Die Standarderweiterungen
Kapitel 5
write (ASCII character 254) & (ASCII character 255) to newFile write "⇒" to newFile as Unicode text close access newFile Wenn Sie jetzt die Datei utf16_neu2.txt mit TextEdit öffnen, wird dessen Kodierung sofort erkannt, und der Pfeil darin wird korrekt angezeigt. Sie können mit dem Parameter as aber nicht nur Text schreiben, sondern auch jede beliebige andere Klasse. Sie müssen dann später beim Lesen nur darauf achten, ebenfalls wieder mit dem Parameter as die gewünschte Klasse anzugeben. Im Folgenden wird eine Liste mit den Zahlen 1 bis 9 in eine neue Datei geschrieben: set newFile to open for access file ((path to desktop as text) &¬ "classData.txt") with write permission set myList to {1, 2, 3, 4, 5, 6, 7, 8, 9} write myList to newFile as list close access newFile Nun können Sie die solchermaßen ins Dokument geschriebene Liste jederzeit wieder mit read und as list einlesen und zum Beispiel einer Variablen zuweisen: set newFile to open for access file ((path to desktop as text) &¬ "classData.txt") set myList to read newFile as list close access newFile get myList -- {1, 2, 3, 4, 5, 6, 7, 8, 9} Dieses Verfahren eignet sich damit hervorragend, um Skriptergebnisse auch für längere Zeit sicher abzuspeichern. Eine Liste ist dabei nur ein Beispiel, versuchen Sie das auch einmal mit der Klasse record oder date. Aufeinander folgende write-Befehle werden im Text hintereinander angefügt, da sich der file pointer, das Lesezeichen, mit jedem Schreibvorgang automatisch weiterschiebt. Das gilt aber nur, solange Sie die Dateireferenznummer für das Schreiben auf der Datei verwenden. Wenn Sie an einer anderen Position schreiben wollen, so müssen Sie das explizit mit dem Parameter starting at bestimmen. Dieser Parameter erwartet eine Ganzzahl. Diese Zahl steht für die Anzahl Bytes vom Anfang der Datei gezählt. Wenn Sie von hinten zählen wollen, so müssen Sie negative Ganzzahlen verwenden. Hier ist wieder zu beachten, dass Sie bei der Verwendung von as Unicode text immer zwei Byte pro Zeichen benötigen. Verwenden Sie daher immer nur ungerade Ganzzahlen für starting at, ansonsten überschreiben Sie die Hälfte eines anderen Zeichens, da ein Unicode-Zeichen ja aus 2 Byte besteht. Hat die Datei ein BOM, ist auch dieses zu berücksichtigen und damit der Byte-Wert für starting at noch einmal um zwei zu erhöhen.
603
SmartBooks
AppleScript
set newFile to open for access file ((path to desktop as text) &¬ "utf16.txt") with write permission write "⇒⇒⇒" to newFile as Unicode text starting at 3 close access newFile -- Text in der Datei: "⇒⇒⇒s ist ein Test!" Wenn Sie am Ende der Datei schreiben möchten, wenn also keine Daten überschrieben werden sollen, können Sie bei starting at statt einer Ganzzahl auch eof schreiben. eof steht für das Dateiende genau ein Byte hinter dem letzten Zeichen in der Datei. set newFile to open for access file ((path to desktop as text) &¬ "utf16.txt") with write permission write "⇒⇒⇒" to newFile as Unicode text starting at eof close access newFile -- Text in der Datei: "Dies ist ein Test!⇒⇒⇒" Mit dem Parameter for können Sie angeben, wie viele der im direkten Parameter angegebenen Daten geschrieben werden sollen. Die Angabe erfolgt in Bytes und erfordert daher eine Ganzzahl. Bei Unicode ist wieder darauf zu achten, nur eine gerade Anzahl von Bytes zu verwenden, da immer 2 Byte ein Unicodezeichen ausmachen. set newFile to open for access file ((path to desktop as text) &¬ "utf16.txt") with write permission write "⇒⇒⇒⇒⇒" to newFile as Unicode text for 4 close access newFile -- Text in der Datei: "⇒⇒ies ist ein Test!" Wenn Sie diesen Parameter nicht verwenden, werden immer alle Daten im direkten Parameter auf einmal geschrieben. Wenn Sie write in einer Schleife verwenden wollen, beachten Sie die bei read vorgestellten Beispiele.
Rückgabewert Der Befehl write hat keinen Rückgabewert.
get eof Mit get eof können Sie das Dateiende ermitteln. Der Wert stellt die Dateigröße in Byte dar und ist daher identisch zur Property size einer Datei, die man erhält, wenn man die System Events danach fragt. Der Befehl hat nur einen einzigen Parameter, einen direkten. Dieser benötigt als Argument einen file descriptor (von open for access) oder ein alias- oder file-Objekt. 604
Die Standarderweiterungen
Kapitel 5
Der Rückgabewert ist eine Ganzzahl und steht für die Größe der Datei in Byte. Dieser Wert kann gut in Schleifen verwendet werden, wenn man die aktuelle Position eines Schreiboder Lesevorgangs selber nachhalten möchte (siehe Beispiel bei read). set newFile to open for access file ((path to desktop as text) & "utf16.txt") set itsEOF to get eof newFile close access newFile get itsEOF -- Ergebnis: 38 Sie müssen die Datei aber nicht vorher öffnen um get eof anzuwenden. Im Gegensatz zu read und write ergeben sich hier keine Vorteile dadurch. Geben Sie die Datei also einfach als file oder alias an: set itsEOF to get eof file ((path to desktop as text) & "utf16.txt") -- Ergebnis: 38 Wenn die Datei sehr groß ist und die maximale Größe für Ganzzahlen in AppleScript übersteigt, wird der Rückgabewert in eine Dezimalzahl mit einer 0 hinter dem Komma umgewandelt.
set eof Mit diesem Befehl können Sie die Dateigröße bestimmen. Sie können damit eine bestehende Datei einfach an einer bestimmten Stelle abschneiden und sie damit kürzen oder auch nach hinten verlängern. Die Daten in dem verlängerten Teil sind in einem undefinierten Zustand. Bei einer Verkürzung sind die hinter dem Schnitt liegenden Daten sofort und unwiederbringlich verloren. Aufgepasst Vorsicht mit diesem Befehl! Wenn Sie, und sei es auch nur wegen eines Schreibfehlers, die falsche Datei erwischen und eine Kürzung der Datei vorgenommen haben, dann ist zumindest der abgeschnittene Teil für immer verloren. Der Befehl set eof ist scharf wie ein Skalpell und wird ohne jede Sicherheitsabfrage gehandhabt. Sie operieren sozusagen am offenen Dateiherzen. Erstellen Sie daher immer vor der Operation eine Sicherheitskopie der betroffenen Datei, damit Sie den Patienten notfalls wiederbeleben können. Der Befehl set eof hat zwei Parameter, die beide benötigt werden. Der direkte Parameter bestimmt die Datei. Diese kann als alias, file oder file descriptor angegeben werden. Der zweite Parameter heißt to und bestimmt die Dateigröße in Byte.
605
SmartBooks
AppleScript
In der folgenden Zeile wird die Dateigröße einer Datei auf 60 Bytes festgelegt und anschließend deren Länge mit get eof verifiziert: set eof file ((path to desktop as text) & "utf16.txt") to 60 get eof file ((path to desktop as text) & "utf16.txt") -- Ergebnis: 60 Schauen Sie danach einmal in die Finder-Information zu dieser Datei. Dort wird bei Größe ebenfalls der Wert 60 Byte in der Klammer stehen (der Wert vor der Klammer ist die Größe der belegten Blöcke auf der Platte). Wenn Sie einen file descriptor verwenden, müssen Sie darauf achten, die Datei mit Schreibberechtigung zu öffnen, sonst erhalten Sie einen Fehler, wenn Sie set eof darauf anwenden: set newFile to open for access file ((path to desktop as text) &¬ "utf16.txt") with write permission set eof newFile to 60 close access newFile Wenn Sie den Inhalt einer Datei komplett löschen wollen, so setzen Sie deren Dateigröße einfach auf 0: set newFile to open for access file ((path to desktop as text) &¬ "utf16.txt") with write permission set eof newFile to 0 close access newFile Der Befehl set eof hat keinen Rückgabewert.
Scripting Commands Die Befehle aus dieser Suite werden eingehend im Kapitel Handler (Laden von Bibliotheken mit load script) und im Kapitel Skriptobjekte (Skriptobjekte speichern und laden) behandelt. Die hier aufgelisteten Befehle drehen sich um Skriptobjekte und darum, wie man sie speichert, lädt und ausführt. << load script
Skript laden
<< store script
Skript speichern
<< run script
Skript ausführen
<< scripting components
Installierte OSA-Sprachen abfragen
606
Die Standarderweiterungen
Kapitel 5
load script Der Befehl load script kennt nur einen direkten Parameter, dessen Angabe Pflicht ist. Erwartet wird ein alias oder eine file-Referenz zu einem Skript. Das Skript muss als kompiliertes Skript im Format scpt (Skript) oder scptd (Skript-Bundle) vorliegen. set newScript to load script alias "Macintosh HD:Users:Hans:Desktop:lib.scpt" Der Rückgabewert ist ein Skriptobjekt. Wenn der Rückgabewert einer Variablen zugewiesen wurde, kann man dem Skriptobjekt darüber Befehle erteilen.
store script Der Befehl store script wird dazu verwendet, ein Skriptobjekt auf die Festplatte in einer Datei abzuspeichern. Der Befehl hat drei Parameter, wovon nur der direkte zwingend erforderlich ist. << script << in alias|file << replacing yes|no|ask Der direkte Parameter muss das Skriptobjekt enthalten, welches auf die Festplatte gespeichert werden soll: script henry say "Hello Henry" end script store script henry Der Parameter in ist optional. Hier können Sie angeben, an welchem Ort das Skript abgespeichert werden soll. Erwartet wird wieder ein alias oder file. Wenn Sie diesen Parameter weglassen, erhalten Sie einen Sichern-Dialog, in welchem Name und Ort der Datei angegeben werden können. Ein alias können Sie nur angeben, wenn die Datei bereits existiert. Verwenden Sie file, wenn die Datei noch nicht existiert: script henry say "Hello Henry" end script store script henry in file "HD:Users:Hans:Desktop:henry.scpt"
607
SmartBooks
AppleScript
Das Dateikürzel bestimmt das Format des Skripts. Der Parameter replacing bestimmt, ob eine eventuell vorhandene Datei einfach überschrieben werden soll. Wenn ja, dann wählen Sie den Wert yes. Die Datei wird dann ohne Rückfragen überschrieben: store script henry in file "HD:Users:Hans:Desktop:henry.scpt" replacing yes Wählen Sie no, wenn nichts überschrieben werden soll. Das Skript beendet sich dann mit einem Fehler. Wählen Sie ask, um dem Anwender einen Dialog anzubieten, in welchem er die Entscheidung zum Überschreiben, Abbrechen oder Sichern unter anderem Namen hat. Wird der Parameter replacing nicht angegeben, erhalten Sie immer diesen Dialog. Der Befehl hat keinen Rückgabewert.
run script Dieser Befehl dient dazu, ein Skript zu starten. Das Skript kann dabei als Datei oder als Text vorliegen, womit sich ein AppleScript auch während der Laufzeit aus Textbausteinen zusammenbauen lässt. Der Befehl run script hat drei Parameter. Nur der direkte Parameter ist erforderlich. << text|alias|file << with parameters list << in text Für den direkten Parameter können Sie Text angeben, welcher sich als AppleScript evaluieren lässt: run script "display dialog \"Hello\"" Der Text wird dabei zur Laufzeit kompiliert und ausgeführt. Sie können auch ein Skript auf der Festplatte über Angabe von alias oder file verwenden: run script alias "HD:Users:Hans:Desktop:henry.scpt" Dadurch wird der run-Handler in diesem Skript ausgeführt.
608
Die Standarderweiterungen
Kapitel 5
Enthält der run-Handler in dem angegebenen Skript einen Parameter, so können Sie diesem mit with parameters eine Liste übergeben. Der run-Handler in dem Skript auf der Festplatte braucht entsprechend auch eine Liste als Argument: on run {someone, someoneelse} say "Hello " & someone say "Hi " & someoneelse end run Dieses Skript kann für sich alleine nicht ausgeführt werden, da die Argumente des runHandlers erst gefüllt werden müssen. Speichern Sie das Skript als test.scpt auf dem Schreibtisch ab und rufen Sie es dann in einem zweiten Skript mit folgender Zeile auf. run script alias (((path to desktop) as string) & "test.scpt") ¬ with parameters {"John", "Susan"} Der Parameter in bestimmt, in welcher OSA-Sprache das Skript vorliegt. Wenn Sie diesen Parameter weglassen, wird automatisch AppleScript angenommen, ansonsten können Sie hier zum Beispiel auch ein JavaScript durch run script ausführen lassen. Beachten Sie das Beispiel unter run script mit anderen OSA-Sprachen im Kapitel 4 Skriptobjekte speichern und laden. Der Rückgabewert ist das Ergebnis des run-Handlers des ausgeführten Skripts.
scripting components Dieser Befehl ist rein informativer Natur und liefert Ihnen eine Liste mit den Namen der OSA-Sprachen, die auf Ihrem Rechner installiert sind. Wenn Sie zum Beispiel einmal den Script Debugger installiert hatten, dann sieht die Liste folgendermaßen aus: set OSALang to scripting components -- Ergebnis: {"JavaScript", "AppleScript Debugger X", "AppleScript"} Fragen Sie diese Liste ab, bevor Sie den Versuch unternehmen, eine andere Sprache zu verwenden. Der Rückgabewert ist immer eine Liste mit Text.
609
SmartBooks
AppleScript
Miscellaneous Commands In dieser Suite hat Apple alles versammelt, was nirgendwo anders hineinpasste. << current date
liefert das aktuelle Datum
<< do shell script
Ausführung eines Shell-Skripts
<< get volume settings
Lautstärke abfragen
<< random number
Zufallszahlen erzeugen
<< round
Runden von Zahlen
<< set volume
Lautstärke verändern
<< system attribute
Umgebungsvariablen ermitteln
<< system info
Systemeigenschaften ermitteln
<< time to GMT
Ermittlung von Zeitzonen
current date Der Befehl current date wird in Kapitel 4 unter Die Datumsklasse behandelt. Dieser Befehl hat keinen Parameter und liefert nur das aktuelle Datum zurück: current date -- date "Montag, 4. August 2008 20:55:03 Uhr"
do shell script Mit diesem Befehl können Sie einen Befehl oder ein Shellskript über die Bourne-Shell sh ausführen lassen. Dieser Befehl verwendet also nicht die Shell bash, die vom Programm Terminal verwendet wird. In einzelnen Fällen kann dies zu Unterschieden führen. Tipp Um einen Befehl, den man mit do shell script verwenden will, im Terminal zu testen, empfiehlt es sich, im Terminal die shell sh mit /bin/sh aufzurufen. Wenn Sie mit dem Testen fertig sind, können Sie jederzeit wieder zur bash-Shell zurückkehren, indem Sie exit eingeben und bestätigen.
610
Die Standarderweiterungen
Kapitel 5
Für weitergehende Informationen zur Shell selber, zu Shellskripts und zu den möglichen Befehlen empfiehlt sich die Lektüre der man-pages (»man Befehlsname« im Terminal eingeben, um die Dokumentation zu einem Befehl zu erhalten) und Unix-Literatur mit Schwerpunkt Mac OS X. Beachten Sie auch folgende ausführliche Technote von Apple zu diesem Befehl (in englischer Sprache): http://developer.apple.com/technotes/tn2002/tn2065.html Zusätzliche Tipps zu diesem Befehl und zur Arbeit mit der Unix-Shell gibt es auch noch am Ende des Buches im Kapitel Unix.
Parameter Der Befehl do shell script hat 6 Parameter, von denen nur der direkte Parameter immer zwingend erforderlich ist. << text << as class << administrator privileges boolean << user name text << password text << altering line endings boolean Der direkte Parameter benötigt Text, welcher von der Shell als Befehl oder Shellskript erkannt werden kann. Der folgende Befehl listet den Inhalt des angegebenen Benutzerordners auf. do shell script "ls -la /Users/Hans/" Da unter Mac OS X Ordner und Dateinamen durchaus auch Sonderzeichen und Leerzeichen enthalten können und diese von der Unix-Shell schnell falsch interpretiert werden, ist es oft hilfreich, die Eigenschaft quoted form of eines Textes für eine Pfadangabe zu verwenden (siehe Kapitel 4 Arbeiten mit Text und dort Eigenschaften eines Textes). do shell script "ls -la " & quoted form of "/Users/Hans/Neuer Ordner/" Ansonsten muss man in dem obigen Pfad das Leerzeichen mit einem Schrägstrich »escapen«, um damit anzuzeigen, dass der Pfad hier noch nicht beendet ist. Da in einem Text in AppleScript der Schrägstrich aber ebenfalls das Escape-Zeichen ist, muss er gleich doppelt verwendet werden:
611
SmartBooks
AppleScript
do shell script "ls -la /Users/Hans/Neuer\\ Ordner" Wenn in dem Skript Anführungszeichen oder Sonderzeichen vorkommen, die von der Shell als Befehle interpretiert werden könnten, müssen diese ebenfalls als Escape-Sequenz geschrieben werden, ansonsten vermutet AppleScript dort bereits das Ende des Textes, oder die Shell hält eines der Sonderzeichen für einen Befehl: do shell script "echo \"Hello User\"" Wenn viele Leerzeichen und Sonderzeichen vorhanden sind, ist es daher am besten, quoted form of zu verwenden – aber nur für die Bestandteile des Befehls, die nicht interpretiert werden sollen, also auf keinen Fall für den Befehl selber. Folgende Zeile führt daher zu einer Fehlermeldung: set listIt to "ls -la /Users/Hans/" do shell script quoted form of listIt Daher nur für die Bestandteile quoted form of verwenden, die keine Befehle an die Shell darstellen, sondern Textargumente: set listIt to quoted form of "/Users/Hans/" do shell script "ls -la " & listIt Für Zeilenumbrüche ist ebenfalls eine Escape-Sequenz notwendig. Verwenden Sie dabei unbedingt einen Unix-Zeilenumbruch \n oder die Konstante linefeed. Folgendes Shellskript würde zum Beispiel nicht funktionieren. Erstens fehlt die EscapeSequenz vor den inneren Anführungszeichen, und zweitens ist hier ein Zeilenumbruch mitten im Text. Der Skripteditor verwendet dafür das Zeichen return. Unix benötigt aber ein linefeed: set gruesse to "#!/bin/sh echo "Hello, my world!";" do shell script gruesse Sie müssen dieses Shellskript daher so schreiben (in fetter Schrift die Escape-Sequenzen): set gruesse to "#!/bin/sh\necho \"Hello, my world!\";" do shell script gruesse -- Ergebnis: "Hello, my world!" Alternativ können Sie den Text auch mit den Konstanten von AppleScript zusammenbauen: set shebang to "#!/bin/sh" set gruesse to quoted form of "Hello, my world!" do shell script shebang & linefeed & "echo " & gruesse -- Ergebnis: "Hello, my world!" 612
Die Standarderweiterungen
Kapitel 5
Mit dem Parameter as können Sie den gewünschten Typ des Rückgabewerts festlegen. Wenn Sie diesen Parameter nicht verwenden, wird standardmäßig UTF-8 verwendet, also die Klasse «class utf8». Wenn das Ergebnis von der Shell jedoch kein gültiges UTF-8 ist, dann wird Text in der primären Kodierung des Betriebssystems verwendet, also hierzulande Mac OS Roman. Wenn Sie den Rückgabewert explizit als Mac OS Roman haben möchten, müssen Sie as text angeben, bei UTF-16 as Unicode text. Im folgenden Beispiel wird der Inhalt einer Datei, die im UTF-16-Format vorliegt, mit dem Befehl cat ausgelesen, mit dem Ergebnis, dass die Zeichen nicht korrekt angezeigt werden: set getContent to "cat /Users/Hans/Desktop/utf16.txt" set filesText to do shell script getContent -- "˛ˇ□D□i□e□s□ □i□s□t□ □e□i□n□ □T□e□s□t□!!–! !“—!”" Deutlich sichtbar ist hier das BOM am Anfang der Datei, welches einen Hinweis darauf gibt, dass die Datei in UTF-16 kodiert ist. Die ASCII 0 Zeichen wurden hier mit kleinen Quadraten gekennzeichnet. Oft sind diese unsichtbar und nur beim Navigieren mit den Cursortasten erkennbar. Beachten Sie hier auch die Hinweise zu den Formaten bei den Befehlen read und write. Wenn Sie obiges do shell script jedoch mit as Unicode text verwenden, wird der Text korrekt angezeigt: set getContent to "cat /Users/Hans/Desktop/utf16.txt" set filesText to do shell script getContent as Unicode text -- "Dies ist ein Test!⇐⇒⇑⇓" Den Parameter administrator privileges brauchen Sie, wenn Sie für einen Befehl in der Shell Admin-Rechte benötigen. Bei Verwendung dieses Parameters wird dann ein Passwortdialog in einem Fenster angezeigt, in welchem Sie sich mit Administratornamen und Passwort ausweisen können. Wenn Sie in diesem Dialog auf Abbrechen klicken, wird das Skript mit Fehler beendet. Bei erfolgter Autorisierung wird der Befehl ausgeführt. Vor allem nützlich, wenn ein Befehl mit sudo ausgeführt werden muss, wie folgender manueller Aufruf der täglichen Unix-Wartungsarbeiten: set theCommand to "sudo periodic daily" do shell script theCommand with administrator privileges Hilfe Wenn Sie nicht genau wissen, ob Sie Admin-Rechte haben, schauen Sie in den Systemeinstellungen unter Benutzer nach, welche Benutzer auf Ihrem Rechner vorhanden sind und welche mit Admin oder Standard gekennzeichnet sind. Üblicherweise erhält der erste Benutzer bei der Einrichtung des Rechners Admin-Rechte.
613
SmartBooks
AppleScript
Wenn Sie einen Passwortdialog vermeiden wollen, können Sie den Benutzernamen und das Passwort auch direkt in das Skript schreiben. Empfehlenswert ist das aus Sicherheitsgründen natürlich nicht. Dafür benötigen Sie die Parameter user name und password. Wenn Sie user name verwenden, müssen Sie auch password verwenden. Wenn Sie nur password verwenden, wird angenommen, dass der User der aktuell angemeldete Benutzer ist. set theCommand to "sudo periodic daily" do shell script theCommand user name "Hans" password "bizzelwizzel" Mit dem Parameter altering line endings können Sie das Zeilenendezeichen im Rückgabewert bestimmen. Meist wird im Ergebnis eines Shell-Befehls ein linefeed-Zeichen (ASCII 10) verwendet. Immer weniger Anwendungen bereitet es heute noch ein Problem, das Zeilenende von Unix zu akzeptieren. Wenn Sie diesen Parameter weglassen oder explizit auf true setzen, wird dieses Zeichen immer ausgetauscht, also von Unix (ASCII 10, linefeed) zu Mac (ASCII 13, return). Wenn Sie das nicht wollen, müssen Sie diesen Parameter auf false setzen. set theFile to do shell script "ls -la ~" without altering line endings
Rückgabewert Die Standardausgabe der Shell ist der Rückgabewert von do shell script. Tritt bei der Ausführung ein Fehler auf, so wird der Fehlertext der Standard-Fehlerausgabe zum Skript durchgereicht und in einem Fehlerdialog angezeigt, zum Beispiel: AppleScript-Fehler: sh: line 1: ech: command not found Der Fehler kann auch in einem try-Block abgefangen werden.
get volume settings Dieser Befehl hat keinen Parameter und liefert einen Record mit den Lautstärkeeinstellungen aus den Systemeinstellungen Ton zurück: set volSets to get volume settings -- Ergebnis: {output volume:50, input volume:83, alert volume:100, output muted:false} Die Werte in dem Record stehen nicht in direkter Verbindung zu den Toneinstellungen. Sie können diese zwar verändern, was aber keine Auswirkung auf den Ton hat. Die Werte haben also einen rein informativen Wert. Benutzen Sie den Befehl set volume in dieser Suite, wenn Sie die Lautstärke verändern wollen.
614
Die Standarderweiterungen
Kapitel 5
Die Werte liegen zwischen 0 (stumm) und 100 (maximale Lautstärke) und stellen damit prozentuale Werte dar. output volume steht für die Lautstärke an den Lautsprechern bzw. am Tonausgang. input volume steht für den Eingangspegel am Mikrophon bzw. Toneingang. alert volume steht für die Lautstärke der Warntöne. 100 Prozent bedeutet hier, 100 Prozent von output volume! Wenn muted auf true steht, ist der Ton aktuell stumm geschaltet.
random number Dieser Befehl wurde bereits ausführlich unter Zahlen am Anfang von Kapitel 4 behandelt. Beachten Sie bitte die Beispiele dort. Dieser Befehl liefert eine Zufallszahl. Die Zufallszahlen gelten als Pseudo-Zufallszahlen, das heißt, sie sind nicht für Verschlüsselungszwecke geeignet. Der Befehl hat drei optionale Parameter: << from number << to number << with seed number Wenn Sie den Befehl ohne Parameter verwenden, wird eine Zufallszahl zwischen 1 und 0 zurückgeliefert. Die Zufallszahl ist dann eine Kommazahl: random number -- Ergebnis zum Beispiel: 0.574732299766 Mit dem Parameter from können Sie die niedrigste Zahl bestimmen, die per Zufall ausgewählt werden kann. Ohne Angabe dieses Parameters ist dies immer die 0.0. Dieser Parameter wird meist in Kombination mit dem Parameter to verwendet. Wenn Sie eine Ganzzahl angeben, ist auch das Ergebnis immer eine Ganzzahl, ansonsten eine Dezimalzahl. Diese Zahl darf auch negativ sein: random number from -1 -- Mögliche Werte: -1, 0, +1
615
SmartBooks
AppleScript
Mit dem Parameter to legen Sie die Obergrenze für die Zufallszahl fest. Ohne Angabe dieses Parameters liegt die Obergrenze bei 1.0. Dieser Parameter wird meist in Kombination mit dem Parameter from verwendet. Die Zahl darf auch negativ sein. Wenn Sie eine Ganzzahl angeben, ist auch das Ergebnis immer eine Ganzzahl, ansonsten eine Dezimalzahl. random number to 6 -- Mögliche Werte: 0, 1, 2, 3, 4, 5, 6 Der Parameter with seed dient dazu – zu Testzwecken – immer dieselbe Zufallszahl zu erzeugen. Dafür wird with seed eine beliebige Zahl mitgegeben. Beachten Sie hier auch die Erklärungen im Kapitel Der Befehl random number am Anfang von Kapitel 4. Folgender Befehl erzeugt nur ein Mal, ganz am Anfang, eine Zufallszahl und behält diese dann bei, egal, wie oft Sie das Skript erneut laufen lassen: random number from 1 to 6 with seed 3 -- Ergebnis zum Beispiel: 2 Erst wenn Sie den Bereich oder den Wert von seed ändern, wird eine neue Zufallszahl erzeugt.
round Dieser Befehl wurde bereits ausführlich unter Zahlen am Anfang von Kapitel 4 behandelt. Beachten Sie bitte die Beispiele dort. Er dient dazu, Zahlen zu runden. Der Befehl hat einen direkten Parameter, welcher die zu rundende Zahl aufnimmt, und einen optionalen Parameter. << real << rounding up|down|toward zero|to nearest|as taught in school Wenn Sie nur den direkten Parameter verwenden, wird der Wert immer mit dem Parameter rounding to nearest gerundet. Der Parameter rounding kann 5 verschiedene Konstanten annehmen: Wenn Sie up verwenden, wird auf die nächste Ganzzahl aufgerundet: rounding 2.3 rounding up -- Ergebnis: 3 Wenn Sie down verwenden, wird auf die nächste Ganzzahl heruntergerundet: round 2.7 rounding down -- Ergebnis: 2 616
Die Standarderweiterungen
Kapitel 5
Wenn Sie toward zero verwenden, werden alle Nachkommastellen entfernt: round 2.7 rounding toward zero -- Ergebnis: 2 Wenn Sie to nearest verwenden, wird eine unverzerrte mathematische Rundung vorgenommen. Dabei wird immer zur nächsten geraden Zahl gerundet. Vor allem für Statistiker interessant, da mit unserer kaufmännischen Rundung immer eine leichte Verfälschung nach oben stattfindet, da die 5 als Nachkommastelle immer nach oben gerundet wird: round 2.5 rounding to nearest ergibt eine 2, da 2 die nächste gerade Zahl ist. round 3.5 rounding to nearest ergibt jedoch 4, da die 4 die nächste gerade Zahl ist. Wenn Sie die Konstante as taught in school verwenden, wird die bekannte kaufmännische Rundung verwendet, wo eine Nachkommastelle ab 5 aufgerundet und darunter abgerundet wird: round 3.4 rounding as taught in school -- 3 round 3.5 rounding as taught in school -- 4
set volume Mit diesem Befehl können Sie die verschiedenen Lautstärkeregler des Betriebssystems verändern. Beachten Sie auch den Befehl get volume settings in dieser Suite, um die aktuellen Einstellungen zuerst einmal abzufragen. Für jede Property von get volume settings besitzt set volume einen Parameter. Wenigstens einer der Parameter muss vorhanden sein, ansonsten sind alle Parameter optional, auch der direkte. Wenn jedoch der direkte Parameter verwendet wird, darf kein anderer mehr zur Anwendung kommen. Die anderen Parameter können untereinander in beliebiger Kombination vorkommen. << number << output volume integer << input volume integer << alert volume integer << output muted boolean
617
SmartBooks
AppleScript
Der direkte Parameter ist als veraltet (deprecated) markiert und sollte nicht mehr verwendet werden! Erwartet wird ein Wert von 0 bis 7. Das kann eine Ganzzahl oder eine Dezimalzahl sein. Bei Dezimalzahlen findet keine Feinabstufung statt, Verwendung findet nur der Wert vor dem Komma. Die Abstufung ist damit recht grob. Verändert wird der Regler Gesamtlautstärke in den Ton-Systemeinstellungen. set volume 3 get volume settings -- {output volume:43, input volume:83, alert volume:100, output muted:false} Mit dem Parameter output volume können Sie die Lautstärke der internen Lautsprecher oder des Tonausgangs einstellen. Dies entspricht dem Regler Gesamtlautstärke in den Ton-Systemeinstellungen. Geben Sie einen Wert von 0 bis 100 Prozent an. set volume output volume 65 get volume settings -- {output volume:65, input volume:83, alert volume:100, output muted:false} Mit dem Parameter input volume verändern Sie den Regler Eingangslautstärke in den Ton-Systemeinstellungen. Geben Sie einen Wert von 0 bis 100 Prozent an: set volume input volume 50 get volume settings -- {output volume:65, input volume:50, alert volume:100, output muted:false} Mit dem Parameter alert volume verändern Sie den Regler Warnton-Lautstärke in den Systemeinstellungen Ton. Die Angabe ist relativ zur Gesamtlautstärke. 100 Prozent bedeutet hier also, einhundert Prozent der maximalen Gesamtlautstärke. Wenn diese auf 10 Prozent steht und die Warnton-Lautstärke ebenfalls auf 10 Prozent, dann besitzt der Warnton nur noch 1 Prozent Lautstärke. set volume alert volume 90 get volume settings -- {output volume:65, input volume:50, alert volume:90, output muted:false} Mit dem Parameter output muted können Sie den Ton stumm schalten. Geben Sie dafür einfach true an und false, wenn der Ton nicht stumm geschaltet werden soll: set volume with output muted get volume settings -- {output volume:65, input volume:50, alert volume:90, output muted:true} Der Befehl hat keinen Rückgabewert.
618
Die Standarderweiterungen
Kapitel 5
system attribute Mit diesem Befehl können Sie die Umgebungsvariablen des Rechners abfragen sowie auf einer sehr niedrigen Ebene der Hardware sogenannte Gestaltabfragen vornehmen. set isAttr to system attribute -- Ergebnis: {"PATH", "TMPDIR", "SHELL", "HOME", "USER", "LOGNAME", "DISPLAY", "SSH_AUTH_SOCK", "Apple_PubSub_Socket_Render", "__CF_ USER_TEXT_ENCODING", "SECURITYSESSIONID", "COMMAND_MODE", "XML_CATALOG_FILES"} Eine einfache Abfrage wie oben ergibt eine Liste mit den Namen aller Umgebungsvariablen. Der Befehl hat nur einen direkten optionalen Parameter. Wenn Sie dort den Namen einer der Umgebungsvariablen angeben, erfahren Sie deren Inhalt, zum Beispiel: system attribute "SHELL" -- "/bin/bash" system attribute "PATH" -- "/usr/bin:/bin:/usr/sbin:/sbin" Als Argument wird der Name der Umgebungsvariable oder ein Gestalt-Wert aus vier Buchstaben erwartet. Gestalt-Werte sind nicht einfach zu handhaben, da sie erstens nur aus vier kryptischen Buchstaben bestehen und zweitens sich die Information darin in einzelnen Bits oder Bitgruppen verbirgt. Je nachdem, welchen Zustand diese haben, sagt das etwas über das System aus. Sie sind ein Erbe des klassischen Mac OS, wohingegen die Umgebungsvariablen ein Erbe von Unix sind. Folgende Zeile liefert zum Beispiel die Versionsnummer über eine Gestalt zurück, anstatt AppleScript direkt zu fragen: system attribute "ascv" -- 17826305 Nun müssen Sie nur noch die Dokumentation zur Gestalt ascv lesen und werden feststellen, dass dort steht, die Versionsnummer von AppleScript verstecke sich in der unteren Hälfte eines 32bit Wertes. In der oberen Hälfte steckt eine Kompatibilitätsversion. Wenn Sie die Dezimalzahl 17826305 mit dem Taschenrechner (umschalten auf Darstellung | Programmierer) in einen Hexadezimalen Wert umwandeln, erhalten Sie: 0x1100201 Der untere Wert 0201 ist die installierte AppleScript-Version 2.0.1. Der obere Wert 110 besagt, dass ein Skript mindestens mit AppleScript 1.1.0 erstellt worden sein muss, um auf diesen Rechner funktionieren zu können.
619
SmartBooks
AppleScript
Ein genaues Studium der Dokumentation zu den einzelnen Gestalt-Werten ist also unumgänglich. Hinter jedem einzelnen Bit oder einer Bit-Gruppe kann sich eine andere Information verbergen. Bevor Sie eine Gestalt verwenden, sollten Sie aber trotzdem immer zuerst prüfen, ob die gesuchte Information nicht auch über den Befehl system info zurückgeliefert wird. Der Befehl system attribute hat noch einen weiteren Parameter, den Parameter has. Bei der Verwendung einer Umgebungsvariable wird dieser Parameter ignoriert. Er dient dazu, einzelne Bits der Gestalt zu testen. Da auf jedem einzelnen Bit eine Information sitzen kann, ist das unter Umständen sehr hilfreich. Ist ein Bit an dieser Stelle gesetzt, wird true zurückgeliefert, ansonsten false. Hier ein Beispiel zur Gestalt mit den Namen icon. Von ihr wird in der Dokumentation gesagt, dass die ersten 5 Bits belegt sind. Im Folgenden wird daher der Wert dieser fünf Bits einzeln abgefragt. Im Kommentar habe ich die Bedeutung dieser Bits aus der Gestalt Manager Reference vorangestellt, um Ihnen einen Eindruck zu geben, wofür jedes Bit steht, und um zu vermitteln, dass sich hinter einer einzelnen 1 oder 0 sehr wichtige Informationen verbergen können: -- Icon Utilities vorhanden? set x to system attribute "icon" has 1 -- true -- Werden 48x48 Pixel große Icons unterstützt? set x to system attribute "icon" has 2 -- true --Werden Icons mit 32 Bit Farbtiefe unterstützt? set x to system attribute "icon" has 4 -- true --Werden Masken mit 8 Bit Farbtiefe unterstützt? set x to system attribute "icon" has 8 -- true --Sind die IconServices vorhanden? set x to system attribute "icon" has 16 -- true Wenn Sie nach der Gestalt icon ohne den Parameter has fragen, erhalten Sie 31 als Wert, was der Summe der Dezimalwerte von has in den Einzelabfragen oben entspricht. Alle anderen Bits stehen also auf 0: set x to system attribute "icon" -- 31 Für weitere Informationen zur Gestalt bitte die Gestalt Manager Reference von Apple unter http://developer.apple.com/documentation/Carbon/Reference/Gestalt_Manager/ einsehen! Dort speziell den Bereich Constants.
620
Die Standarderweiterungen
Kapitel 5
system info Mit diesem Befehl werden Ihnen einige nützliche Information zum System angezeigt. Der Befehl hat keinen Parameter und liefert derzeit einen Record mit 16 Einträgen. Die einzelnen Elemente des Records habe ich der leichteren Lesbarkeit wegen auf mehrere Zeilen aufgeteilt und nach Namen sortiert: set sysInfo to system info -- Ergebnis: {AppleScript Studio version:"1.5", AppleScript version:"2.0.1", boot volume:"HD", computer name:"macmaximi", CPU speed:1800, CPU type:"PowerPC 970", home directory:alias "HD:Users:Detlef:", host name:"macmaximi.local", IPv4 address:"192.168.1.56", long user name:"Detlef Schulz", physical memory:2048, primary Ethernet address:"00:00:xx:xx:xx:xx", short user name:"Detlef", system version:"10.5.5", user ID:501, user locale:"de_DE"} Wenn Sie nur eine bestimmte Information daraus benötigen, so fragen Sie explizit nach dem entsprechenden Namen der Property: set itsLocale to user locale of (get system info) -- Ergebnis: "de_DE"
time to GMT Dieser Befehl wurde bereits in Kapitel 4 unter Die Datumsklasse behandelt. Der Befehl hat keinen Parameter und liefert den Zeitunterschied zwischen lokaler Zeit und Universal Time in Sekunden zurück. Der zurück gelieferte Wert ist damit abhängig von den Zeit- und Zeitzoneneinstellungen in den Systemeinstellungen unter Datum & Uhrzeit.
621
SmartBooks
AppleScript
Wenn dort als Zeitzone CEST eingestellt ist, zum Beispiel durch Auswahl der Stadt Berlin, dann ergibt time to GMT einen Zeitunterschied von 2 Stunden (7200 Sekunden), wenn keine Sommerzeit ist, sind es nur 3600 Sekunden: set timeDif to time to GMT -- 7200
Folder Actions Die Ordneraktionen werden gesondert unter Ordneraktionen im Kapitel Handler von Kapitel 4 behandelt. Bei den Folder Actions handelt es sich um Handler und nicht um Befehle. Diese Handler können in einem Appleskript in Aktion treten, wenn an oder in einem Ordner des Finders etwas geschieht, wie zum Beispiel das Ablegen einer Datei in den Ordner.
Internet Suite In dieser Suite finden sich nur zwei Befehle, die wohl nur noch aus Kompatibilitätsgründen mitgeschleppt werden. << open location << handle cgi request Um eine Webseite zu öffnen, steuert man beispielsweise lieber direkt einen Webbrowser wie Safari oder Firefox, anstatt open location zu verwenden. Siehe das Beispiel unter running im Kapitel Verzweigungen mit if von Kapitel 4. Und um AppleScript für ein cgi zu verwenden, fehlt unter Mac OS X sogar völlig die Voraussetzung. Der eingebaute Apache-Webserver kann mit einem AppleScript als CGI ohne Zuhilfenahme von Dritthersteller-Software gar nichts anfangen.
open location Mit diesem Befehl können Sie eine URL mit dem Standardprogramm für das entsprechende Protokoll öffnen. Der Befehl hat zwei Parameter, der erste ist erforderlich, der zweite optional: << text << error reporting boolean
622
Die Standarderweiterungen
Kapitel 5
Für den direkten Parameter wird die Angabe der URL als Text erwartet. Die folgende URL wird zum Beispiel mit ihrem Standardbrowser angesteuert und geöffnet, wahrscheinlich mit Safari: open location "http://www.skripteditor.de" Wenn der Webbrowser noch nicht läuft, wird er auch gleich gestartet. Das funktioniert natürlich auch mit anderen Protokollen als mit HTTP. Bei AFP wird zum Beispiel das entsprechende Volume vom Server im Finder eingebunden, nach Eingabe von Benutzernamen und Passwort natürlich: open location "afp://macminimi.local" Beim FTP-Protokoll wird bei mir zum Beispiel das Programm Cyberduck gestartet: open location "ftp://ftp.apple.com" Wenn Sie den Parameter error reporting auf true setzen, hat das keine Wirkung. Dieser Parameter wird nicht mehr unterstützt und ist nur noch vorhanden, um ältere Skripts, die davon Gebrauch machen, nicht außer Gefecht zu setzen. Dieser Befehl hat keinen Rückgabewert.
handle CGI request Hierbei handelt es sich um einen Handler und keinen Befehl. Dieser Handler wird von Apple offiziell nicht mehr unterstützt, eine Folge der Tatsache, dass seit Mac OS X auf jedem Mac ein Apache-Webserver installiert ist – und der kann kein Appleskript benachrichtigen. Um handle CGI request überhaupt nutzen zu können, muss daher auf Drittsoftware zugegriffen werden. Folgende zwei Möglichkeiten sind mir bekannt: << Verwendung des acgi dispatcher von James Sentman, zu erhalten unter http://www.sentman.com/acgi_dispatcher.html. Dieser baut eine Brücke zu Apache, nimmt die Anfragen von dort entgegen, wandelt sie in AppleEvents um und sendet diese an das Appleskript, welches die Events über die Verwendung des Handlers handle CGI request empfängt, um dann eine entsprechende HTML-Seite zurückzuliefern. << Verwendung des Smile Server, welcher in der Vollversion von Smile enthalten ist. http://www.satimage.fr/software/en/smileserver/index.html
623
SmartBooks
AppleScript
Dieser Handler besitzt eine ganze Reihe von Parametern. Alle Parameter sind optional. Im Folgenden habe ich sie alle aufgelistet. In der zweiten Spalte finden Sie eine kurze Erklärung, welcher Wert darin abgelegt wird: << text
der URL-Pfad
<< searching for text
die Daten für GET oder POST nach dem "?"
<< with posted data text
POST-Argumente
<< of content type text
MIME-Typ der POST-Argumente
<< using access method text
entweder "GET" oder "POST"
<< from address text
die IP-Adresse des Anfragenden
<< from user text
der mit der Anfrage verbundene Benutzername
<< using password text
das Passwort des Benutzers
<< with user info text
zusätzliche User-Infos, meist die E-Mail-Adresse
<< from server text
Name der Server-Anwendung des Anfragenden
<< via port text
die Portnummer des Servers
<< executing by text
der URL-Pfad zum CGI-Appleskript
<< referred by text
der URL-Link der Seite, die zum CGI führt
<< from browser text
der Name der Client-Software
<< using action text
der Pfad zur Datei oder dem CGI
<< of action type text
PREPROCESSOR, POSTPROCESSOR, CGI oder ACGI
< < from client IP address text
die Internet-Adresse des Clients
<< with full request text
die vollständige Anforderung, wie an den Server ge sendet
< < with connection ID integer die ID der Verbindung vom Client zum Server << from virtual host text
die URL des root-Verzeichnisses des virtuellen Hosts
Der Rückgabewert des Handlers muss eine HTML-Seite sein, das heißt ein HTML-Text für eine vollständige Seite. Beispielskripts zur Verwendung dieses Handlers sind im Download des acgi-Dispatchers enthalten, so dass man gleich loslegen kann. In der einfachsten Form sieht solch ein Handler in einem Skript so aus:
624
Die Standarderweiterungen
Kapitel 5
on handle CGI request urlPath¬ searching for getData ¬ with posted data postArgs ¬ of content type mimeType ¬ using access method getOrPost ¬ from address ipAddress ¬ from user theUser ¬ using password hisPassword ¬ with user info hisInfo ¬ from server theFromServer ¬ via port fromThePort ¬ executing by myURLtoCGI ¬ referred by theReferrer ¬ from browser hisBrowser ¬ using action myAction ¬ of action type myActionType ¬ from client IP clientIP ¬ with full request theFullRequest ¬ with connection ID theID ¬ from virtual host theVirtualHost return "Hallo Welt!
" end handle CGI request
625
Von der Kunst, ein AppleScript zu starten
6
Wenn Sie ein Appleskript bisher immer nur per Doppelklick oder aus dem Skripteditor heraus starten, dann entgehen Ihnen viele Möglichkeiten, die das Betriebssystem Mac OS X bietet. Dieses Kapitel widmet sich ausführlich der Frage, wie, wann und wo ein Appleskript gestartet werden kann. Ich erhebe dabei keinen Anspruch auf Vollständigkeit, hoffe jedoch, einen breiten Überblick und Einblick in die vielfältigen Mittel und Wege zu geben.
SmartBooks
AppleScript
Von der Kunst, ein AppleScript zu starten Neben den Lösungen von Apple stelle ich hier immer wieder Software anderer Hersteller vor. Diese dienen jeweils als Beispiel in der entsprechenden Kategorie und müssen nicht unbedingt auch eine Empfehlung des Autors darstellen. Beachten Sie daher auch die kritischen Untertöne, wenn Sie auf meine Meinung Wert legen. In vielen Fällen gibt es wahrscheinlich auch Alternativen in den Tiefen des Webs, denen ich noch nicht begegnet bin. Ein Wort zur Vorsicht möchte ich dabei gerne noch anbringen: Installieren Sie nicht alles, was hier vorgestellt wird oder Ihnen irgendwo unter die Finger kommt, sondern wählen Sie gezielt aus. Je mehr Programme und Hilfsmittel Sie installieren, je größer ist die Gefahr, dass nach einem Systemupdate von Apple oder einem Update eines anderen Herstellers etwas nicht mehr funktioniert. Seien Sie wählerisch. Ich selbst bin kein großer Freund davon, mein System mit allem möglichen Schnickschnack zu erweitern. Erst, wenn ich mit den bordeigenen Mitteln von Apple nicht mehr weiterkomme oder damit sehr unzufrieden bin, ziehe ich es überhaupt in Erwägung, ein Drittprogramm einzusetzen – und das ist verhältnismäßig selten der Fall. Wählen Sie daher gezielt aus, was Sie brauchen, machen Sie sich dann mit der gewählten Lösung bestens vertraut, und Sie behalten den Überblick und auch den Durchblick.
AppleScript im Finder Im Kapitel 3 wurde bereits das Skriptmenü als zentrale Anlaufstelle für die Aufbewahrung und den Start von Skripts aller Art behandelt. Der Finder von Mac OS X bietet aber noch weitere Möglichkeiten, die sich für den Start eines Appleskripts eignen oder in denen irgendwo AppleScript drin steckt.
Die Symbolleiste Allzu leicht vergisst man, dass sich die Symbolleiste eines Finderfensters nach eigenen Wünschen einrichten lässt. Wenn Sie mit der rechten Maustaste darauf klicken und Symbolleiste anpassen wählen, lassen sich die Schaltflächen nach Belieben auswählen und anordnen. Unabhängig von den dort angebotenen Möglichkeiten können Sie aber auch jede beliebige Datei auf der Festplatte in die Symbolleiste ziehen, auch ohne vorher Symbolleiste anpassen zu wählen. Wenn Sie die Datei auf die Symbolleiste ziehen, müssen Sie nur einen
628
Von der Kunst, ein AppleScript zu starten
Kapitel 6
kleinen Augenblick warten, bis das Plus-Zeichen erscheint, und dann die Datei loslassen. Um die Datei wieder aus der Symbolleiste zu entfernen, reicht es, die Befehlstaste beim Herausziehen gedrückt zu halten. Die Datei selbst wird dabei nicht gelöscht. Wenn Sie ein als Applet gespeichertes Skript in die Symbolleiste ziehen, wird es durch einen einfachen Klick gestartet. Handelt es sich um ein Skript im Skript-Format, wird es im Skripteditor geöffnet. Besonders sinnvoll ist es dabei natürlich, täglich verwendete Dokumente, Programme oder auch Skripts darin abzulegen. Da die Symbolleiste jedoch hauptsächlich dazu dient, die Darstellung oder Navigation im Fenster zu steuern, bietet es sich an, dort solche Skripts abzulegen, die sich ebenfalls um Darstellung oder Navigation kümmern. Ein schönes Beispiel findet sich auf der Webseite von Apple unter http://www.apple.com/applescript/examples.html. Laden Sie sich dort das Skript Browse Full Screen herunter, entpacken Sie die ZIP-Datei und ziehen Sie das Skript (ein Programm-Bundle) in die Symbolleiste eines beliebigen Finder-Fensters.
Abb. 6-1 Ein Skript kann auch in der Symbolleiste Platz nehmen. Wenn Sie nun in der Symbolleiste darauf klicken, wird das Fenster auf Bildschirmgröße vergrößert, das Dock ausgeblendet und die Ansicht auf Cover Flow umgestellt. Nun können Sie bequem durch die Vorschaubilder des Ordners blättern. Ein weiterer Klick auf das Icon in der Symbolleiste stellt den Ursprungszustand wieder her. Öffnen Sie das Skript auch ruhig einmal im Skripteditor. Es stellt eine gute Basis für eigene Skripts dieser Art dar. Besonders schön ist das natürlich, wenn Sie Ihrem Skript auch ein eigenes Icon spendieren, wie in Kapitel 3 unter Dateiformat »Programm-Bundle« beschrieben.
629
SmartBooks
AppleScript
Die Seitenleiste Auch die Seitenleiste bietet sich dafür an, Skripts darin abzulegen. Die Rubriken Geräte und Freigaben werden allerdings von Mac OS X verwaltet. Sie können darin nichts von Hand ablegen. Die Bereiche Orte und Intelligente Ordner können jedoch von Ihnen beeinflusst werden.
Orte In der Seitenleiste eines Finder-Fensters können Sie Skripts in den Bereich Orte ablegen, um sie von dort zu starten. Da der Bereich Orte heißt, sind hier vor allem Skripts sinnvoll, die Verbindung zu einem oder gleich mehreren Orten herstellen, FTP-Server und Webserver zum Beispiel. Beachten Sie hier die Hinweise in Kapitel 5 zum Befehl mount volume in den File commands.
Intelligente Ordner Unterhalb der Orte gibt es den Bereich, in dem Sie intelligente Ordner anlegen können. Sie können hier zwar nicht direkt Skripts ablegen, aber wie wäre es mit einem intelligenten Ordner, der ihnen einmal alle Appleskripts zeigt, die sich auf Ihrem Rechner tummeln? Das sind meist wesentlich mehr, als man denkt. Im Folgenden daher eine Anleitung für einen intelligenten Ordner, der alle OSA-Skripts Ihres Systems auflistet. Das kann auch sehr hilfreich sein bei der Suche nach verschollenen Skripts: 1. Wählen Sie im Finder Ablage | Neuer intelligenter Ordner. 2. Klicken Sie auf Diesen Mac und Dateiname in dem neu erschienenen Fenster. 3. Klicken Sie auf das Plus-Symbol. Der Eintrag Art ist Beliebig erscheint. 4. Klicken Sie mit gedrückter [Alt]-Taste auf das neue Plus-Symbol. Die Zeile mit dem Text Einer der folgenden Wert zutreffen erscheint und darf nicht verändert werden. 5. Klicken Sie auf das Minus-Zeichen bei der ersten Zeile Art ist Beliebig, um diese Zeile zu entfernen. Sie wird nicht benötigt. 6. Wählen Sie in der Zeile darunter im ersten Einblendmenü Name und im zweiten endet mit aus und geben Sie .scpt als Endung ein. 7. Klicken Sie auf das Plus-Symbol neben der letzten Zeile. 8. Wählen Sie für diese Zeile erneut Name endet mit aus und geben Sie .scptd als Endung ein. 9. Klicken Sie erneut auf das Plus-Symbol neben der letzten Zeile. 10. Wählen Sie für diese Zeile erneut Name endet mit aus und geben Sie .applescript als Endung ein. 630
Von der Kunst, ein AppleScript zu starten
Kapitel 6
Damit haben Sie alle Skripts erwischt, die nicht als Programm vorliegen. Die Skripts, die als Applet oder Droplet gespeichert wurden, können Sie nur an ihrem creator code unterscheiden. Da man nicht direkt nach dem creator code suchen kann, muss man mit den sogenannten kmdItem-Codes von Spotlight arbeiten: 11. Klicken Sie erneut auf das Plus-Symbol neben der letzten Zeile. 12. Wählen Sie im ersten Einblendmenü der neuen Zeile den Eintrag Andere… aus. Nach einer kurzen Zeit erscheint eine Liste mit Suchkriterien. 13. Scrollen Sie in der Liste nach unten bis zu dem Eintrag Reihenabfrage, klicken Sie diesen Eintrag ein Mal an und setzen Sie einen Haken rechts davon. Bestätigen Sie mit OK. 14. Im ersten Einblendmenü steht nun Reine Daten. Beachten Sie die Tatsache, dass Sie zuerst Reihenabfrage ausgewählt haben, der Eintrag jetzt aber Reine Daten heißt! Der Eintrag ist daher schwer zu finden, wenn man nicht genau weiß, wie er heißt. 15. Tippen Sie in das Feld dahinter den folgenden Text, um nach allen Applets zu suchen: kMDItemFSCreatorCode = "aplt" 16. Klicken Sie auf das Plus-Symbol neben der neuen letzten Zeile. 17. Wählen Sie im ersten Einblendmenü Reine Daten aus. 18. Tippen Sie in das Feld dahinter den folgenden Text für die Suche nach Droplets: kMDItemFSCreatorCode = "dplt" 19. Und zum Schluss, damit Sie auch noch ältere Skripts ohne Dateiendung erwischen, bitte noch einmal auf das Plus-Zeichen klicken, um nach dem type eines Skripts zu suchen. 20. Wählen Sie ein letztes Mal Reine Daten und geben Sie folgenden Text dahinter ein: kMDItemFSTypeCode = "osas" Die Suchkriterien müssen nun so aussehen wie in dieser Abbildung:
Abb. 6-2 Die Einstellungen für einen intelligenten Ordner, der alle Skripts auf dem Rechner findet 631
SmartBooks
AppleScript
21. Wenn alles richtig aussieht, klicken Sie bitte auf Sichern. 22. Geben Sie dem Intelligenten Ordner einen Namen wie zum Beispiel Appleskripts. 23. Wählen Sie Zur Seitenleiste hinzufügen. 24. Behalten Sie den vorgegebenen Ordner Gesicherte Suchabfragen bei und klicken Sie auf Sichern. Fertig ist der intelligente Ordner für alle OSA-Skripts auf Ihrem Rechner. Power User Wer sich für die direkte Suche über Reine Daten mit Spotlight interessiert, sollte sich die Terminal-Befehle mdls (Ermittlung der kmdItem in einer Datei) und mdfind (Spotlight-Suche mit dem Terminal) ansehen, die auch hervorragend mit einem do shell script aus einem Appleskript heraus verwendet werden können. Die Dokumentation von Apple ist unter http://developer.apple.com/documentation/Carbon/Reference/MetadataAttributesRef/ MetadataAttrRef.html und http://developer.apple.com/documentation/Carbon/Conceptual/SpotlightQuery/ Concepts/QueryFormat.html zu finden. Am besten ist es jedoch, sich mit mdls einfach die Attribute einer bestehenden Datei im Terminal anzusehen und daraus zu lernen, wer welche Attribute besitzt. Nun haben Sie alle Skripts in den Formaten Skript, Skript-Bundle, Text und Programm in diesem intelligenten Ordner versammelt. Das einzige, was jetzt noch fehlen kann, sind jene Skripts, die aus irgendeinem bedauerlichen Unfall heraus (vielleicht mal auf einem Windows-Rechner gelegen) weder Dateiendung noch einen file type haben und damit absolut nicht mehr als Skript erkennbar sind. Alternativ können Sie die obige Suche natürlich auch auf mehrere getrennte intelligente Ordner aufteilen, was vor allem sinnvoll ist, wenn Sie sehr, sehr viele Skripts auf Ihrem Rechner haben. Vor allem die Suche nach creator und type kann schon mal etwas dauern.
Das Dock Das Dock ist der übliche Weg, ein häufig benötigtes Programm zu starten. Das gilt auch für Skripts. Ziehen Sie diese einfach in das Dock hinein. Beachten Sie: Ein Skript muss dabei als Programm oder Programm-Bundle vorliegen, damit es direkt startet, ansonsten kann es nur als Dokument im rechten Teil des Docks abgelegt werden. Empfehlenswert ist hier auch die Anlage eines Ordners mit häufiger verwendeten Skripts und deren Ressourcen. Wenn man diesen Ordner dann rechts ins Dock hineinlegt und darauf klickt, erscheinen alle Dateien darin als Fächer oder Gitter (im Apple-Speak als sogenannter Stack) und lassen sich bequem auswählen.
632
Von der Kunst, ein AppleScript zu starten
Kapitel 6
Das Dienste-Menü Weitgehend unbeachtet von den meisten Anwendern, fristen die programmübergreifenden Dienste (englisch: Services) ihr Dasein im Programmmenü. Egal, welches Programm gerade aktiv ist, Sie finden im ersten Menüpunkt, also unter dem Programmnamen, immer einen Eintrag namens Dienste.
AppleScript-Dienste Wenn Sie das Menü öffnen, finden Sie dort einen Eintrag Skripteditor, unter dem drei Dienste versammelt sind, die mit AppleScript zu tun haben.
Abb. 6-3 Die AppleScript-Dienste im Dienste-Menü Im Folgenden wird zur Demonstration dieser Dienste TextEdit verwendet. Sie könnten dafür aber auch jedes andere Programm verwenden, welches Dienste unterstützt.
Dienst »Als AppleScript ausführen« Starten Sie TextEdit im Programme-Ordner und erzeugen Sie ein neues Textdokument über Ablage | Neu. Geben Sie folgende Zeile in das Fenster ein: say "Hello!" Markieren Sie diesen Text und rufen Sie TextEdit | Dienste | Skripteditor | Als AppleScript ausführen auf. Nach einem kleinen Augenblick, in welchem der Skripteditor gestartet wird (welcher den Text überprüft und kompiliert), werden Sie mit »Hello!« akustisch begrüßt. Diese Zeile ist bereits ein kleines Appleskript. Es verwendet den befehl say aus den Standarderweiterungen, um den Text zwischen den Anführungszeichen vorzulesen. So können Sie in jeder beliebigen Anwendung Text, der gültiges AppleScript darstellt, markieren und ausführen lassen. Befindet sich ein Fehler im Text, passiert übrigens gar nichts. Sie erhalten also keine Fehlermeldung. Diese Art, ein Skript zu schreiben, eignet sich also nur für kleine Skripts auf die Schnelle.
633
SmartBooks
AppleScript
Hier noch ein kleines Beispiel über mehrere Zeilen: tell app "Finder" make new folder at desktop end tell Schreiben Sie diese drei Zeilen in TextEdit, markieren Sie den Text über alle Zeilen hinweg und lassen Sie ihn über das Dienste-Menü als Appleskript ausführen. Der Finder wird damit angewiesen, auf Ihrem Schreibtisch einen neuen Ordner anzulegen. Wenn Sie sich vertippt haben, passiert gar nichts.
Dienst »Ergebnis aus AppleScript« Dieser kleine Dienst ist vielleicht noch praktischer als der vorige, spart er Ihnen vielleicht doch den einen oder anderen Weg zum Taschenrechner. Zudem hat dieser Dienst auch standardmäßig ein Tastaturkürzel und ist damit sehr schnell ausgeführt. Tippen Sie zum Beispiel 9*12 in TextEdit und markieren Sie den Text, am besten mit der Tastatur über [Befehl]+[Umschalt]+[Cursor links]. Betätigen Sie nun die Tasten [Befehl]+[Umschalt]+[+]. Das Ergebnis 108 wird statt der Rechnung eingefügt. (Auch hier wird wieder der Skripteditor im Hintergrund geöffnet, welcher die Anweisung überprüft, ausführt und das Ergebnis zurückliefert.) Sie können Berechnungen auch klammern, um bestimmte Reihenfolgen zu erzwingen. Sie müssen jedoch immer in einer Zeile bleiben. Berechnungen über mehrere Zeilen sind nicht möglich. Sie können alle arithmetischen Operatoren zum Rechnen mit Zahlen verwenden sowie Zahlkonstanten. Für das Dezimalkomma müssen Sie immer einen Punkt verwenden. Hier ein paar Beispiele: (8.5 + 12) * 2 12 / 5 13 div 5 13 mod 5 2 ^ 3 3 * pi 2 * minutes 5<6
(Ganzzahlige Division) (Modulo) (Exponent) (Die Zahl pi mal 3) (Anzahl Sekunden in 2 Minuten) (Ein Vergleich ergibt immer true oder false als Ergebnis)
634
Von der Kunst, ein AppleScript zu starten
Kapitel 6
Auch hier werden wieder keine Fehlermeldungen zurückgeliefert. Falls also nichts passiert, hat AppleScript etwas an dem Ausdruck nicht verstanden.
Dienst »Neues AppleScript erstellen« Wenn Sie bei der Lektüre in einem PDF oder im Internet auf ein Appleskript stoßen, welches Sie gleich ausprobieren möchten, so könnten Sie den Text manuell kopieren, den Skripteditor öffnen, ein neues Dokument im Skripteditor anlegen und dann den Text dort einfügen. Einfacher geht das mit dem Dienst Neues AppleScript erstellen. In einem Rutsch wird damit der markierte Text im Skripteditor in einem neuen Dokument eingefügt. Schreiben Sie in TextEdit folgendes kleine Skript: set x to display dialog "How’s the weather?" buttons {"Rainy", "Sunny"} if button returned of x is "Rainy" then say "Don’t forget your umbrella." using "Victoria" else say "Leave your coat at home." using "Alex" end if Markieren Sie dann den Text und wählen Sie Neues AppleScript erstellen im Dienste-Menü von TextEdit. Der Skripteditor öffnet sich, und der markierte Text wird darin eingefügt. Klicken Sie nun ein Mal auf den Knopf Ausführen in der Werkzeugleiste des Skripteditors, um das Skript zu kompilieren und zu starten. Wurden Fehler gefunden, werden nun auch entsprechende Fehlermeldungen im Skripteditor generiert. Wenn Sie keine Fehler beim Abschreiben gemacht haben, wird das Skript aber auf Anhieb funktionieren. Wo auch immer Sie im Internet oder in PDF-Dokumenten auf AppleScript-Beispiele stoßen, mit diesem Dienst haben Sie den Text schnell in ein neues Skript im Skripteditor eingefügt.
Eigene Dienste mit AppleScript erstellen Normalerweise benötigen Sie Kenntnisse in der Programmierung mit Objective-C und Cocoa, um dem Dienste-Menü eigene Dienste hinzuzufügen. Findige Entwickler haben jedoch auch die Möglichkeit geschaffen, eigene Dienste in AppleScript und anderen Skriptsprachen zu schreiben. Hier ist neben Bellhop von http://www.xendai.com vor allem das Programm ThisService von http://wafflesoftware.net zu nennen. Bellhop hat den Nachteil, dass es installiert sein muss, um damit erstellte Dienste auch nutzen zu können, bietet aber mehr Möglichkeiten zur Einflussnahme. Mit ThisService lassen sich Dienste leichter erstellen, man stößt aber schneller an dessen Grenzen. Dafür kann man diese Dienste problemlos auch auf Macs installieren, die das Programm nicht installiert haben.
635
SmartBooks
AppleScript
Abb. 6-4 Mit ThisService lassen sich auf einfache Weise eigene Dienste mit Hilfe von AppleScript erstellen.
ThisService Mit ThisService können Sie Dienste in AppleScript, Perl, Python oder Ruby schreiben. Folgende Beschreibung bezieht sich auf ThisService 2.0.1. ThisService ist »Donationware«. Das heißt, wenn Ihnen das Programm gefällt, würde sich der Autor über eine Spende zur Weiterentwicklung des Programms freuen. Das Appleskript selbst wird dabei nicht in ThisService erstellt, sondern ganz normal mit dem Skripteditor. Danach erst wird von ThisService ein Dienst daraus erstellt und in den Ordner ~/Library/Services/ abgelegt. Ein einfacher Dienst sieht in ThisService zum Beispiel wie folgender Fünfzeiler aus; on process(myText) set theWords to words of myText set numWords to length of theWords say "There are " & numWords & " words in your selection." end process Ein Skript, welches als Dienst verwendet wird, enthält in ThisService immer einen Handler namens process(). Dieser wird beim Start des Dienstes ausgeführt. Obiges Beispiel zählt die Anzahl der Wörter eines ausgewählten Textes und sagt das Ergebnis an. In welchem Programm der Text ausgewählt wurde, spielt dabei keine Rolle, solange es auf Cocoa basiert und Dienste unterstützt. Hier eine kurze Anleitung, die zeigt, wie einfach es ist, ein erstes brauchbares Ergebnis zu erzielen. 1. Tippen Sie das obige Skript im Skripteditor ein und sichern Sie es als Skript unter einem beliebigen Namen. 2. Starten Sie ThisService. 3. Klicken Sie auf den Knopf Choose und wählen Sie das Skript aus.
636
Von der Kunst, ein AppleScript zu starten
Kapitel 6
Abb. 6-5 Das einzige Fenster von ThisService 4. Geben Sie dann im obigen Feld den Namen Wörter zählen für den Dienst ein. Unter diesem Namen erscheint der Dienst dann im Menü. Bei Type wählen Sie bitte Acts on input. 5. Bei Menu shortcut können Sie dem Dienst auch ein Tastaturkürzel geben. Klicken Sie dafür auf das weiße Feld und drücken Sie dann die gewünschte Taste. Verwenden Sie nur die Befehls-Taste oder die Befehls-Taste in Verbindung mit der Umschalt-Taste. Andere Tasten funktionieren nicht mit Diensten. Die Anzeige der gedrückten Sondertasten ist dabei fehlerhaft in ThisService. ThisService zeigt bei mir immer beide Sondertasten an, egal, welche Taste ich gedrückt habe. Nicht daran stören, es funktioniert trotzdem mit den gedrückten Sondertasten. 6. Bei Include wählen Sie bitte Copy of script. Damit können Sie den so erzeugten Dienst später auch problemlos weitergeben und auf anderen Rechnern installieren. 7. Klicken Sie auf Create Service. 8. Sie erhalten eine Bestätigung, dass der Dienst erstellt und unter ~/Library/Services/ abgespeichert wurde. Schauen Sie dort einmal nach und Sie werden einen Dienst namens WörterZählen.service vorfinden. 9. Öffnen Sie nun eine beliebige Webseite in Safari. Markieren Sie mit der Maus einen beliebigen Text auf der Seite und wählen Sie dann Safari | Dienste | Wörter zählen. Eine Stimme wird Ihnen auf Englisch ansagen, wie viele Wörter in dem Text gezählt wurden. Hilfe Dienste sind kontextsensitiv! Wenn Ihr Dienst nicht im Dienste-Menü erscheint oder dort inaktiv dargestellt wird, liegt es sehr wahrscheinlich daran, dass Sie entweder keinen Text ausgewählt haben, oder dass das verwendete Programm Dienste nicht unterstützt. Ältere Carbon-Programme können mit Diensten ebenfalls Probleme haben, und natürlich kann ein Tastaturkürzel für einen Dienst bereits im Programm in Verwendung sein und damit den Aufruf des Dienstes über die Tastatur blockieren.
637
SmartBooks
AppleScript
Wenn Sie zu den Benutzern gehören, die das Dienste-Menü oft und gerne verwenden, mag ThisService oder auch Bellhop genau die Lösung sein, auf die Sie gewartet haben. Für meinen Geschmack ist das Dienste-Menü eine Ebene zu tief im System versteckt und nach einiger Zeit oft auch überladen mit Einträgen aus allen möglichen installierten Programmen. Dienste mit Tastaturkürzel sind da schon praktischer. Ja, manchmal ist man sich gar nicht mehr im Klaren darüber, dass ein bestimmtes Tastaturkürzel einen Dienst aufruft, wie zum Beispiel [Befehl]+[Umschalt]+[L], welches einen markierten Begriff über Google im Internet sucht.
Das Kontextmenü Das Kontextmenü bietet sich für Skripts an, die man immer möglichst nahe an der Maus haben möchte und die man oft verwendet. Die Einträge aus dem Kontextmenü sind in den diversen Library-Ordnern im Ordner Contextual Menu Items zu finden. Falls der Ordner in der Library Ihres Heimverzeichnisses nicht vorhanden ist, können Sie ihn dort auch manuell erzeugen. Sie können aber nicht einfach ein Appleskript in diesen Ordner legen, und fertig ist der neue Eintrag im Kontextmenü. Es wäre schön, wenn das so einfach wäre wie im Kontextmenü des Skripteditors (siehe Kapitel 3). Aus diesem Grund muss man hier zu Hilfsmitteln greifen.
Kontextmenübefehl für den Finder mit Automator erstellen Automator entwickelt sich immer mehr zu einer Entwicklungsumgebung für jeden Anwender. Für den Appleskripter interessant ist vor allem die Tatsache, dass Sie darin auch ein Appleskript erstellen können und dass sich dieses danach auch als Plug-In entweder für das Skriptmenü (es erscheint dann als Eintrag im Skriptmenü) oder für das Kontextmenü im Finder abspeichern lässt. Der Befehl ist damit also auf den Finder als Programm begrenzt, aber für viele Fälle ist das ja wahrscheinlich schon ausreichend. Hier eine kurze Anleitung, wie Sie ein Appleskript in Automator erstellen können und wie Sie dieses dann als Plug-in für das Kontextmenü abspeichern.
Abb. 6-6 Mit dem Programm Automator lassen sich nicht nur komplexe, automatisierte Arbeitsabläufe, sogenannte Workflows, erstellen, sondern auch Kontextmenübefehle für den Finder. 1. Starten Sie das Programm Automator im Ordner Programme.
638
Von der Kunst, ein AppleScript zu starten
Kapitel 6
2. Wählen Sie Eigene, wenn Sie von Automator aufgefordert werden, einen Ausgangspunkt zu wählen. 3. Klicken Sie links unter Bibliothek den Eintrag Dienstprogramme an und doppelklicken Sie dann rechts daneben in der Liste der Aktionen auf den Eintrag AppleScript ausführen. In der rechten Hälfte des Fensters wird nun ein Rahmen angezeigt mit einem Inhalt, der an den Skripteditor erinnert. Hier können Sie nun fast genau so wie im Skripteditor arbeiten und innerhalb des bereits angelegten run-Handlers ein beliebiges Appleskript schreiben. 4. Ersetzen Sie den Platzhalter (* Your script goes here *) gegen das folgende Appleskript. set pathList to {} tell application "Finder" to set myPath to selection repeat with i in myPath set end of pathList to (POSIX path of alias (i as text)) end repeat set text item delimiters to return set the clipboard to (pathList as text) Der Workflow in Automator wird nun so aussehen wie in der folgenden Abbildung. Das Protokoll kann durch Klick auf den kleinen Knopf mit den Aufzählungspunkten in der Fußzeile eingeblendet werden:
Abb. 6-7 Ein Automator-Workflow mit einem Appleskript
639
SmartBooks
AppleScript
5. Wählen Sie im Finder ein paar Dateien aus und klicken Sie dann in Automator auf Ausführen rechts oben. 6. Wechseln Sie in den Skripteditor oder eine Textverarbeitung und fügen Sie mit [Befehl]+[V] die Zwischenablage ein. Wenn Sie alles richtig gemacht haben, werden die POSIX-Pfade der im Finder ausgewählten Dateien eingefügt. 7. Wählen Sie im Ablage-Menü den Eintrag Als Plug-In sichern. 8. Geben Sie den Namen an, den der Befehl im Kontextmenü erhalten soll, zum Beispiel Kopiere POSIX-Pfad in Zwischenablage, und wählen Sie dann im Einblendmenü darunter den Eintrag Finder aus. 9. Bestätigen Sie mit einem Klick auf Sichern. Das Plug-In wird als Workflow in Ihrem Library-Ordner im Heimverzeichnis unter ~/Library/Workflows/Applications/Finder/ abgespeichert. Wenn Sie den Befehl wieder aus dem Kontextmenü entfernen möchten, müssen Sie den Workflow einfach nur aus diesem Ordner herausnehmen. Nun können Sie in den Finder wechseln und den Befehl im Kontextmenü ausprobieren. Einfach eine oder mehrere Dateien auswählen und dann mit der rechten Maustaste anklicken. Den Befehl finden Sie dann im Untermenü mit dem Namen Mehr. Darunter befindet sich das Untermenü Automator und darin steckt Ihr neuer Befehl. Nicht gerade unter den Fingerspitzen muss ich sagen. Es wäre schöner, wenn man sich bei Apple ein Untermenü gespart hätte.
Abb. 6-8 Die mit Automator erstellten Kontextmenübefehle sind leider etwas tief verschachtelt. Die gleichnamigen Skripts eine Ebene höher stammen übrigens vom Programm OMC, welches im nächsten Kapitel beschrieben wird.
640
Von der Kunst, ein AppleScript zu starten
Kapitel 6
Wenn Sie das Skript im Kontextmenü ausführen, achten Sie bitte auf die Menüzeile rechts oben. Dort wird während der Ausführung der Status eingeblendet. Ihnen wird auffallen, dass Automator-Kontextmenübefehle nicht gerade schnell sind. Sie eignen sich daher auch eher für langwierige Aktionen und nicht für Befehle, bei denen man ein schnelles Resultat erwartet. In dem oben verwendeten Skript ist Ihnen sicher aufgefallen, dass die Liste des run-Handlers gar nicht verwendet wurde und dass auch das return am Ende überflüssig war. Ich habe es aber drin gelassen, damit Sie sehen können, an welchen Stellen man den Arbeitsablauf vor und nach dem Skript erweitern kann. Statt die Auswahl mit selection im Skript vorzunehmen und das Ergebnis dann ebenfalls im Skript in die Zwischenablage zu kopieren, kann man für diese beiden Teile nämlich auch fertige Automator-Aktionen verwenden. Das Endergebnis wird dadurch zwar nicht gerade schneller, zeigt aber, wie man ein Skript mit anderen Aktionen kombinieren kann. Das Ergebnis sieht dann aus wie in folgender Abbildung. Es hat dieselbe Wirkung, es ermittelt also die POSIX-Pfade der ausgewählten Dateien und kopiert diese in die Zwischenablage.
Abb. 6-9 Die Übergabe von Daten an ein Appleskript erfolgt mit Hilfe des Listenparameters im run-Handler. Das Appleskript reicht die verarbeiteten Daten dann über die return-Anweisung am Ende an die nächste Aktion weiter.
641
SmartBooks
AppleScript
OnMyCommand OnMyCommand (OMC) ist sehr viel mehr als nur ein kleines Hilfsmittel. Es kann von http://free.abracode.com/cmworkshop/ kostenlos heruntergeladen werden. Primär ist OMC für das Erstellen von Kontextmenüeinträgen mit Appleskripts oder Shell-Skripts gedacht. Es stellt aber eine ganze Reihe weiterer Möglichkeiten zur Verfügung inklusive der Verwendung von Nib-Dateien aus dem Interface Builder. Falls Sie aus einem ShellSkript gerne ein Droplet machen möchten, ist das ebenfalls mit OMC möglich. (Andere Alternative sind hier DropScript von http://www.wsanchez.net/software/ oder Platypus von http://www.sveinbjorn.org/platypus). Beachten Sie die Hilfen, Tutorials und Beispiele auf der Webseite sowie die unzähligen fertigen Plug-Ins (über 500!), die von anderen Anwendern zur Verfügung gestellt werden, und die man bequem in OMC studieren, anpassen und verwenden kann. Auch die anderen Hilfsmittel auf der Seite, wie zum Beispiel das Programm Shortcuts, um Kontextmenü-Einträge per Tastaturkürzel aufzurufen, können äußerst hilfreich sein. Die folgende Anleitung setzt OMC in der Version 2.0 voraus. Das Programm liegt übrigens in deutscher Lokalisierung vor.
Abb. 6-10 Der Editor von OMC Hier ein kleines Beispiel, um Ihnen den Einstieg in den durchaus komplexen Editor von OMC zu erleichtern. Hier wird einfach nur dasselbe Skript wie für das Automator-Kapitel verwendet. Ein Pfad einer Datei oder eines Ordners wird ermittelt und in die Zwischenablage kopiert. Etwas, was ich als Skripter und Autor ständig benötige. Außerdem können Sie damit, wenn Sie erst einmal den Pfad ermittelt haben, das Skript auch schnell anpassen, um mit den Dateien noch wer-weiss-was anzustellen. Die Beispiele in OMC lassen an sich aber schon kaum Wünsche offen, so dass Sie vielleicht gar nichts Neues erstellen müssen. Wenn Sie OMC heruntergeladen und installiert haben, werden Sie aufgefordert, sich am Rechner erneut anzumelden. Das ist wichtig, da erst danach allen Anwendungen inklusive des Finders die Möglichkeiten von OMC zur Verfügung stehen. OMC ist ein Kontextmenü-Plug-In im Ordner /Library/Contextual Menu Items/. Des Weiteren wird ein Framework unter /Library/Frameworks/, ein Editor unter / Programme/OMC/, ein Plug-In unter /Library/Graphics/Quartz Composer Plug-Ins und ein Icon-Pack unter /Library/Application Support/OnMyCommand/ Icons installiert.
642
Von der Kunst, ein AppleScript zu starten
Kapitel 6
1. Nachdem Sie sich erneut angemeldet haben, starten Sie bitte das Programm OMCEdit im Ordner /Programme/OMC/. 2. Verbinden Sie sich mit dem Internet und klicken Sie in der Symbolleiste des erscheinenden Fensters auf Kommandos laden und dann noch mal auf den Knopf Laden. Es werden ca. 600 Beispiel-Kommandos heruntergeladen. Das geht ziemlich flott, da es sich nur um Text handelt. 3. Wenn Sie sich die heruntergeladenen Befehle ansehen möchten, klicken Sie auf Kommando-Bibliothek. In dem darauf erscheinenden Fenster können Sie sich Befehle aussuchen und mit einem Klick auf den Knopf Kommandos hinzufügen übernehmen. Klicken Sie aber jetzt erstmal nur auf den Knopf Fertig. Ich zeige Ihnen zuerst, wie Sie einen kleinen Kontextmenüeintrag von Grund auf selbst erstellen. 4. Klicken Sie links unten in der Ecke des Fensters auf das Plus-Zeichen, um ein neues Kommando anzulegen. Das Kommando erscheint links mit dem Namen Namenlos in der Spalte Bezeichnung. 5. Klicken auf den Eintrag namens Namenlos. 6. Wählen Sie in der mittleren Spalte Bearbeiten – Allgemein aus. 7. Geben Sie rechts im Feld Kommando-Bezeichnung den Text Kopiere POSIX-Pfad in Zwischenablage ein. Das wird der neue Name des Kontextmenü-Befehls. 8. Lassen Sie rechts das Feld für die Mehrzahl des Befehlsnamens leer. Dieser Name wird im Kontextmenü verwendet, wenn Sie mehr als nur eine Datei oder einen Ordner ausgewählt haben, hat aber den Nachteil, dass Sie, wenn Sie später mit dem Programm Shortcuts ein Tastaturkürzel zuweisen wollen, auch zwei Tastaturkürzel für denselben Kontextmenübefehl benötigen. 9. Wählen Sie im Feld Position den Eintrag Oberste Ebene aus und bei Escape für Sonderzeichen den Eintrag Escape für AppleScript. Oberste Ebene sorgt dafür, dass Ihr Skript nicht in einem weiteren Untermenü des Kontextmenüs verschachtelt wird. 10. Achten Sie darauf, dass der Haken bei Aktiv gesetzt ist. 11. Geben Sie in das Feld Kommando das folgende Appleskript ein: set pathList to {} tell application "Finder" to set myPath to selection repeat with i in myPath set end of pathList to (POSIX path of alias (i as text)) end repeat set text item delimiters to return set the clipboard to (pathList as text) 12. Klicken Sie auf Sichern. 643
SmartBooks
AppleScript
13. Wechseln Sie in der mittleren Spalte unter Bearbeiten zum Eintrag Aktivierung. 14. Wählen Sie im Einblendmenü Aktivierung den Eintrag Datei oder Ordner (außer Finder-Fenster) aus und klicken Sie erneut auf Sichern. Diese Wahl sorgt dafür, dass der Kontextmenübefehl nur erscheint, wenn im Finder auch Dateien oder Ordner ausgewählt sind. 15. Wechseln Sie in der mittleren Spalte in den Bereich Ausführung. 16. Wählen Sie rechts im Einblendmenü Ausführungsmodus den Eintrag AppleScript aus. Sie bekommen einen Hinweis, dass Sie bei Problemen mit dem Skript auch einen Haken bei An Hintergrundprozess übergeben auswählen sollten. Das ist bei diesem einfachen Skript aber nicht nötig. Entfernen Sie die Haken an allen vier Checkboxen. 17. Klicken Sie auf Sichern. 18. Wählen Sie im Menü Kommando den Eintrag Aktivieren. Damit steht der Befehl ab sofort im Kontextmenü zur Verfügung.
Abb. 6-11 Ein Appleskript wird als Kontextmenü angelegt. Wechseln Sie einfach einmal in den Finder und überprüfen Sie, ob es funktioniert. Wählen Sie eine oder mehrere Dateien aus, klicken Sie diese mit der rechten Maustaste an und wählen Sie dort das Untermenü Mehr und dann den Befehl Kopiere POSIX-Pfad in Zwischenablage. Wechseln Sie nun in den Skripteditor oder in ein Textprogramm und fügen Sie den Pfad über [Befehl]+[V] ein. Die POSIX-Pfade der markierten Dateien werden mit Zeilenumbruch getrennt eingefügt.
644
Von der Kunst, ein AppleScript zu starten
Kapitel 6
Wenn Sie möchten, können Sie jetzt noch ein weiteres Kommando erzeugen, mit exakt denselben Vorgaben wie oben, aber mit folgendem Skript, welches die HFS-Pfade (Pfadschreibweise mit Doppelpunkten) ermittelt und in die Zwischenablage kopiert. Damit haben Sie dann beide Pfad-Varianten im Kontextmenü stehen: tell application "Finder" set AppleScript's text item delimiters to return set the clipboard to selection as string end tell Das Skript ist wunderbar kurz, da die Umwandlung nicht in einer Schleife erfolgen muss. Wenn Sie in OMCEdit ein Kommando wieder aus dem Kontextmenü entfernen wollen, so klicken Sie den Befehl in der linken Spalte an und wählen Sie dann im Menü Kommando den Eintrag Deaktivieren. OMC ist ein Kontextmenü-Plug-In und muss vorhanden sein, damit die Kontextmenübefehle funktionieren. Wenn Sie einen Kontextmenübefehl weitergeben wollen, dann muss auf dem anderen Rechner also ebenfalls OMC installiert sein. Leider sind seit Leopard alle Fremdbefehle aus der obersten Ebene des Kontextmenüs verbannt worden, so dass sich nun alle eigenen Befehle immer im Unterordner Mehr befinden.
Abb. 6-12 Das Kontextmenü mit den neuen Einträgen Das einfache Beispiel hier macht von vielen weiteren Möglichkeiten von OMC noch gar keinen Gebrauch. So kann man alternativ auch die eingebauten Objektvariablen aus dem Menü Einfügen im Skript verwenden, zum Beispiel die Variable __Obj_Path__, statt den Finder nach der selection zu fragen. Das ist vor allem für die Arbeit mit der Shell von großer Bedeutung, da
645
SmartBooks
AppleScript
diese ja keine Mausauswahl kennt. Beachten Sie hier die vielen Beispiele und das EmptyFile-Tutorial auf der Webseite.
Big Cat Eine sehr einfache Möglichkeit, ein Skript aus dem Kontextmenü zu starten, ist das ebenfalls kostenlose Programm Big Cat von http://www.ranchero.com/bigcat/. Es kann sowohl mit AppleScript als auch mit Shell-Skripts verwendet werden und unterstützt die Textauswahl und die Auswahl von Dateien und Ordnern im Finder. Wenn Sie Big Cat heruntergeladen und ausgepackt haben, müssen Sie nur den Ordner Big Cat Scripts in ~/Library/Application Support/ ziehen, also den Library-Ordner Ihres Heimverzeichnisses, und das BigCat.plugin unter ~/Library/Contextual Menu Items/. Danach müssen Sie sich noch abmelden und am System neu anmelden, damit das Plug-In aktiv wird.
Abb. 6-13 Big Cat bietet den einfachsten und schnellsten Weg, um Skripts aus dem Kontextmenü zu starten. Nachdem Sie sich neu angemeldet haben, finden Sie im Kontextmenü im Untermenü Mehr einen neuen Eintrag namens Scripts. Darin finden Sie dann, abhängig vom Kontext, alle Scripts aus den Unterordnern Files oder Text aus dem Big Cat Scripts-Ordner. Wenn Sie eigene Skripts entwickelt haben, brauchen Sie diese also nur in einen dieser Ordner zu legen, abhängig davon, ob Ihr Skript auf einer Textauswahl oder auf Dateien und Ordner arbeitet. Das Skript muss einen Handler namens main() enthalten. An diesen wird die Text- oder Dateiauswahl geleitet: on main(fileList) set text item delimiters to return set the clipboard to fileList as string end main 646
Von der Kunst, ein AppleScript zu starten
Kapitel 6
Damit haben Sie zwar längst nicht so viele Möglichkeiten wie mit OMC, dafür empfiehlt sich Big Cat mit seiner Einfachheit. Das Programm ist damit für alle geeignet, die sich nicht stundenlang in neue Software einarbeiten wollen.
OpenMenu X Dieses kostenpflichtige Programm stammt von Satoshi Matsumoto, liegt in deutscher Lokalisierung vor, kostet nach einer gebührenfreien Testphase 10 US-Dollar und kann über http://www.artman21.com/en/openmenu_x/ bezogen werden. OpenMenu X verbindet ein Skriptmenü mit einem Kontextmenü und bringt gleich über 80 nützliche Skripts mit. Auf Wunsch kann man auch Programme, Dokumente, URLs, Dienste oder beliebige Ordner im Kontext/Skriptmenü anzeigen lassen und zudem allen Einträgen ein Tastaturkürzel zuweisen. OpenMenu X erinnert mich an das alte Apfel-Menü im klassischen Mac OS, das ebenfalls erlaubte, beliebige Ordner hineinzupacken, um somit das Menü zum Browsen durch die Festplatte zu verwenden. Das Kontextmenü hat natürlich wieder die systembedingte Beschränkung, dass sich alle eigenen Einträge im Untermenü Mehr befinden müssen, aber da kann wohl kein Entwickler etwas dran ändern. Das Programm ist nur eine Systemeinstellung. Wenn Sie diese nach dem Auspacken durch Doppelklick installiert haben, müssen Sie sich noch einmal abmelden und erneut anmelden.
Abb. 6-14 OpenMenu X installiert sich als Systemeinstellung. 647
SmartBooks
AppleScript
Nach dem erneuten Anmelden erhalten Sie rechts oben folgendes Skriptmenü:
Abb. 6-15 Das Skriptmenü von OpenMenu X, dessen Einträge sich auch im Kontextmenü wiederfinden In der Systemeinstellung können Sie dann jede Menge Einstellungen vornehmen, zum Beispiel Programme, Ordner, Dokumente und natürlich Skripts von überall auf der Festplatte hinzufügen und einzelnen Einträgen Tastaturkürzel zuweisen.
Abb. 6-16 Die Einstellungen zu den Menüs erlauben das Hinzufügen von ganzen Ordnern oder einzelnen Dateien beliebiger Art Im Bereich Allgemein sind weitere Einstellungen möglich. Außerdem, und das halte ich für sehr wichtig, kann man einzelne Programme als Ausnahmen definieren. Dann wird in diesen Anwendungen das Kontextmenü von OpenMenu X nicht erscheinen.
648
Von der Kunst, ein AppleScript zu starten
Kapitel 6
Abb. 6-17 Einzelne Anwendungen können von der Verwendung ausgeschlossen werden. Die Handhabung der Einstellungen ist dabei äußerst intuitiv und selbsterklärend. Dieses Programm ist mein Favorit, wenn es darum geht, Skripts aus einem Skriptmenü, einem Kontextmenü oder per Tastaturkürzel zu starten. OpenMenu X schränkt die Anwender nicht ein, sondern gibt ihnen die Wahl, einen der drei Wege zu nutzen.
Skripts über Tastaturkürzel starten Hier gibt es eine schlechte Nachricht zu vermelden: Es gibt keine Möglichkeit, mit systemeigenen Mitteln ein Skript auf der Festplatte mit einem Tastaturkürzel zu starten. Die Anlage von Tastaturkürzeln in den Systemeinstellungen bezieht sich leider immer nur auf vorhandene Menüeinträge von laufenden Programmen. Sollte ein Programm also kein Tastaturkürzel für einen bestimmten Menüeintrag besitzen, so können Sie dem Menübefehl dort ein Tastaturkürzel nachrüsten. Ein Programmstart selbst kann kein Tastaturkürzel erhalten. Mit anderen Worten: Hier muss man wieder auf Hilfsmittel kreativer Entwickler zurückgreifen.
649
SmartBooks
AppleScript
Programmeigene Skriptmenüs Eine Ausnahme bilden Programme, die ein eigenes Skriptmenü besitzen, wie zum Beispiel iTunes, GraphicConverter, BBEdit, RagTime und viele andere. Den Skripts in diesen Menüs können Sie wie gewohnt in den Systemeinstellungen Tastatur & Maus Tastaturkurzbefehle geben. Sie müssen nur nach dem Klick auf das Pluszeichen darauf achten, das richtige Programm auszuwählen und den Menüeintrag exakt so zu schreiben, wie das Skript im Skriptmenü des entsprechenden Programms heißt.
Abb. 6-18 Einem Skript im Skriptmenü eines Programms kann über die Systemeinstellungen Tastatur & Maus ein Tastaturkürzel zugewiesen werden.
ThisService und OpenMenu X Zwei weitere Möglichkeiten wurden bereits beschrieben: Erstens kann das Programm ThisService einen Menüeintrag im Dienste-Menü mit einem Tastaturkürzel versehen, und zweitens kann OpenMenu X allen seinen Einträgen im Skript- oder Kontextmenü ein Tastaturkürzel zuweisen.
Shortcuts Das Programm Shortcuts ist zusammen mit OnMyCommand auf derselben Webseite unter http://free.abracode.com/cmworkshop zu finden. Mit Shortcuts können Sie Befehlen aus dem Kontextmenü, und wirklich nur diesen, ein Tastaturkürzel geben. Fortan können Sie den Befehl wahlweise über das Kontextmenü
650
Von der Kunst, ein AppleScript zu starten
Kapitel 6
oder mit Tastenkürzel ausführen. Unterstützt werden alle Kontextmenü-Einträge, die mit Text oder Dateien/Ordnern arbeiten.
Abb. 6-19 Das Programm Shortcuts kann Kontextmenü-Einträgen ein Tastaturkürzel zuweisen. Bevor Sie einem Skript also ein Tastaturkürzel zuweisen können, müssen Sie dieses Skript erst einmal als Kontextmenübefehl angelegt haben. Das kann mit OnMyCommand (OMC) oder mit Big Cat erzeugt worden sein. Wenn das erfolgt ist, wird es recht einfach. Die folgende Beschreibung geht von Version 1.1.3 aus und davon, dass Sie das Beispiel von OMC ein paar Seiten zuvor bereits angelegt haben. Laden Sie das Programm Shortcuts von der Webseite herunter, entpacken Sie es und installieren Sie es, indem Sie den Ordner mit dem Programm zum Beispiel in den Ordner / Programme/AppleScripts ziehen. 1. Starten Sie Shortcuts. Das Fenster Shortcuts öffnet sich. 2. Wechseln Sie auf den Reiter Setup. 3. Damit die Tastaturkürzel erkannt werden, muss zuerst ein Hintergrundprozess, der ShortcutObserver, gestartet werden. Klicken Sie hier auf Start, um diesen Prozess zu starten. 4. Wenn Sie den Hintergrundprozess nicht jedes Mal manuell starten wollen, klicken Sie auch auf Add, um den Prozess nach jeder Anmeldung automatisch zu starten. Der Hintergrundwächter wird dann Ihren Startobjekten in den Benutzereinstellungen der Systemeinstellungen hinzugefügt und kann dort auch leicht wieder entfernt werden. 5. Wählen Sie unten bei Bezel window notification zum Beispiel cloud im Einblendmenü aus. Sie erhalten dann eine kurze Rückmeldung, wenn das Tastaturkürzel funktioniert oder nicht funktioniert hat. 6. Wechseln Sie auf die Ansicht Assign Hot Keys. 7. Wählen Sie im mittleren Einblendmenü, welches für die Auswahl von Dateien zuständig ist, den Kontextmenübefehl Kopiere POSIX-Pfad in Zwischenablage aus. Aus dem Fenster fährt ein Dialog heraus und Sie werden aufgefordert, ein Tastaturkürzel einzugeben.
651
SmartBooks
AppleScript
8. Denken Sie sich ein Tastaturkürzel aus, welches Sie sich gut merken können und welches höchstwahrscheinlich nicht in Verwendung ist, zum Beispiel [Befehl]+[alt]+[ctrl]+[P] oder einfach nur [ctrl]+[P], und führen Sie es aus. Bestätigen Sie das Kürzel mit Klick auf Assign. 9. Gehen Sie noch mal auf das mittlere Einblendmenü und wiederholen Sie Punkt 7 und 8 mit dem Kontextmenü-Befehl Kopiere HFS-Pfad in Zwischenablage, geben Sie aber das Tastaturkürzel [Befehl]+[alt]+[ctrl]+[H] oder [ctrl]+[H] ein und bestätigen Sie mit Assign. 10. Wechseln Sie in den Reiter Shortcut List. Dort müssen nun Ihre zwei Tastaturkürzel zu sehen sein.
Abb. 6-20 Tastaturkürzel anlegen in Shortcuts Nun können Sie das Programm Shortcuts beenden. Wechseln Sie in den Finder, markieren Sie ein paar Dateien oder Ordner und betätigen Sie eines der Tastaturkürzel. Eine kurz eingeblendete Wolke gibt Ihnen Rückmeldung, ob es funktioniert hat oder nicht. Wechseln Sie dann in ein Textprogramm oder den Skripteditor und fügen Sie die Zwischenablage ein. Das Tastaturkürzel wird übrigens nicht im Kontextmenü angezeigt, wie es sonst in Menüs üblich ist. Aufgepasst Bei Kontextmenüeinträgen, die – wie dieses Beispiel – aus dem Programm OnMyCommand stammen, müssen Sie darauf achten, dass Sie in OMC keinen zweiten Namen für die Mehrzahl des Befehlsnamens angeben, ansonsten muss man leider auch zwei Tastaturkürzel vergeben. Lassen Sie in OMC also unbedingt das Feld Kommando-Bezeichnung (Mehrzahl) leer, wenn Sie diesem Befehl ein Kürzel geben wollen. Siehe Abbildung 6-11.
652
Von der Kunst, ein AppleScript zu starten
Kapitel 6
FastScripts Eine der einfachsten Lösungen für ein Tastaturkürzel auf einem Skript ist sicher FastScripts von http://www.red-sweater.com. Es installiert ein eigenes Skriptmenü rechts oben in der Menüleiste wie das von Apple. Die entscheidenden Unterschiede: Hier kann man Einträgen ein Tastaturkürzel geben, und die Skripts starten schneller daraus als aus dem Skriptmenü von Apple.
Abb. 6-21 FastScripts von Red-Sweater bringt dem Skriptmenü Tastaturkürzel bei (und macht ihm Beine). Wenn Sie eifriger Benutzer des Skriptmenüs sind, ist FastScripts vielleicht eine Überlegung wert. Auf den ersten Blick unterscheidet es sich dabei nicht vom Skriptmenü Apples. Mit anderen Worten, Sie können das Skriptmenü von Apple danach ruhig ausschalten, ansonsten haben Sie nämlich zwei Skriptmenüs in der Menüleiste. FastScripts blendet dieselben Skripts von denselben Ordnern ein und verhält sich auch genauso wie das Skriptmenü inklusive des Verhaltens bei gedrückter [Alt]- oder [Umschalt]-Taste. Sie brauchen sich also weder umzugewöhnen noch Ihre Ablageordnung zu ändern (siehe Kapitel 3). Über den ersten Eintrag im Skriptmenü von FastScripts lassen sich die Einstellungen zu FastScripts aufrufen, wo jedem einzelnen Skript (oder Dokument, Programm oder was auch immer Sie an die Orte des Skriptmenüs gelegt haben) ein beliebiges Tastaturkürzel zugewiesen werden kann.
Abb. 6-22 In der Tafel »Script Shortcuts« der Einstellungen von FastScripts können Sie einem Skript ein Tastaturkürzel zuweisen.
653
SmartBooks
AppleScript
Zudem lässt sich auch das Menü selbst mit einem Tastaturkürzel öffnen, so dass man danach bequem mit den Cursortasten darin navigieren kann. So können Sie auch Skripts erreichen, die noch kein Tastaturkürzel besitzen, ohne die Maus in die Hand zu nehmen. Natürlich müssen Sie bei der Vergabe der Skripts darauf achten, dass dieses Tastaturkürzel möglichst von keinem Programm verwendet wird, ansonsten funktioniert das Kürzel dann aus diesen Programmen heraus nicht. Ach ja, außerdem können Sie in FastScripts Trennlinien im Menü einfügen und damit Ordnung halten. Tipp Der einzige Makel, den ich in FastScripts finden konnte, ist die Anzeige von Skripterweiterungen mit dem Dateikürzel osax. Im Skriptmenü von Apple werden diese als Datei angezeigt, und nach Auswahl wird deren Funktionsverzeichnis geöffnet. Bei FastScripts wird die Osax als Ordner angezeigt. Man sieht also im Skriptmenü in das Bundle hinein. Trotzdem lässt sich auch in FastScripts mit einem Trick die Funktionsbibliothek öffnen: Sie müssen nur die [Umschalt]-Taste drücken, während Sie den Namen der Scripting Addition auswählen. FastScripts ist Shareware und kann 30 Tage oder einhundert Skriptausführungen lang kostenlos getestet werden. Für die Vollversion sind dann 14,95 USD zu bezahlen.
Weitere Programme Weitere Möglichkeiten, ein Skript über Tastaturkürzel zu starten, sind neben den bereits behandelten Programmen ThisService und OpenMenu X, nicht direkt AppleScript-spezifisch und bringen daher meist noch Tonnen weiterer Möglichkeiten mit sich. Dazu zählen Programme wie zum Beispiel Quicksilver, iKey, QuicKeys oder DragThing. Mit Quicksilver von http://www.blacktree.com und iKey von http://scriptsoftware.com lassen sich das ganze Betriebssystem und alle Arbeitsabläufe per Tastatur steuern. Durch die Aneinanderreihung von Befehlen kann zudem ein gewisser Grad von Automatisierung erreicht werden. Quicksilver befindet sich schon seit längerem in der Betaphase und ist vielleicht (während Sie dies lesen) immer noch kostenlos. Das Programm ist aber trotzdem stabil und eine Empfehlung wert, alleine schon aufgrund seiner Eleganz und seiner strikten Philosophie. Viele Anwender schwören darauf. iKey ist ein kommerzielles Produkt, kostet 30 USD und verfolgt einen eher traditionellen Ansatz. QuicKeys von http://www.startly.com ist ein Urgestein auf dem Mac und kann fast alles.
654
Von der Kunst, ein AppleScript zu starten
Kapitel 6
DragThing von http://www.dragthing.com ist ein professioneller Dock-Manager, der unter anderem auch Tastaturkürzel auf die Elemente in seinem Dock legen kann. Nur zum Starten von Skripts per Tastaturkürzel sind diese Programme auf jeden Fall überdimensioniert und erfordern zudem einiges an Einarbeitungszeit. Wenn Sie aber ohnehin auf der Suche nach etwas Größerem sind, schauen Sie sich dort einmal um.
Skripts automatisch starten Ein Skript mit einem Tastaturkürzel zu starten, ist schon bequemer, als es mit der Maus im Betriebssystem zu suchen und dann erst auszuführen. Aber wie wäre es, wenn das Skript einfach automatisch startet, sobald es Zeit dafür ist? Entweder zu einem bestimmten Zeitpunkt, in bestimmten Zeitintervallen oder sogar auf bestimmte Ereignisse im Betriebssystem hin? Dieses Kapitel gibt Aufschluss über die vielfältigen Möglichkeiten, ein Skript automatisch zu starten, und darüber, welche Auslöser es dafür gibt.
Zu einer bestimmten Zeit Es gibt verschiedene Möglichkeiten, ein Skript zu einem bestimmten Zeitpunkt ausführen zu lassen. Die einfachste ist sicher die, iCal dafür zu verwenden, Sie können aber auch bis auf die Unix-Ebene hinuntergehen und die crontab editieren oder einen LaunchAgent erzeugen. Darüber hinaus gibt es viele weitere Programme auf dem Markt, die zu einem bestimmten Termin eine Datei öffnen oder starten können. Hier folgen daher nur die naheliegenden Möglichkeiten.
iCal iCal hat den Vorteil, dass es auf jedem Mac vorhanden ist. Es hat die wunderbare Fähigkeit, zu einem bestimmten Termin ein Skript auszuführen. Alles, was Sie dafür tun müssen, ist, ein Ereignis oder eine Aufgabe mit Termin anzulegen, wie aus der folgenden Abbildung ersichtlich.
655
SmartBooks
AppleScript
Abb. 6-23 Ein Termin oder eine Aufgabe kann in iCal ein Skript zu einem bestimmten Zeitpunkt ausführen. Bei Erinnerung müssen Sie Skript ausführen auswählen und in der Zeile darunter Eigene. Daraufhin erscheint ein Dateiauswahl-Dialog, in welchem Sie das Skript auswählen können. Das Skript muss im Format Skript (.scpt) oder Skript-Bundle (.scptd) vorliegen. Damit lassen sich bequem auch wiederkehrende Aufgaben anlegen, zum Beispiel solche, die täglich oder wöchentlich ausgeführt werden sollen. Beachten Sie nur, dass die Erinnerungen in den Einstellungen von iCal natürlich aktiv sein müssen. Das heißt, in der Tafel Erweitert darf dort kein Haken bei »Alle Erinnerungen deaktivieren« oder »Erinnerungen deaktivieren, wenn iCal nicht geöffnet ist« stehen. Nur dann funktionieren die Skripts, auch wenn iCal gar nicht gestartet ist. Außerdem ist es noch empfehlenswert, einen eigenen Kalender für Skripts einzurichten. So kann man diese »technischen Termine« dann leicht ausblenden. Wenn Sie diese Fähigkeit von iCal noch nicht kennen, machen Sie ruhig einmal einen Test mit einem kleinen Skript, das einfach nur einen Satz aufsagt, wie zum Beispiel: say "It’s time for lunch!" Setzen Sie dann einen Termin 5 Minuten in der Zukunft, welcher dieses Skript ausführt, und achten Sie darauf, die Erinnerung auf 0 Minute(n) davor zu setzen. Beenden Sie iCal dann. Wenn die 5 Minuten um sind, werden Sie darauf hingewiesen, dass es Zeit zum Mittagessen ist.
656
Von der Kunst, ein AppleScript zu starten
Kapitel 6
cron Mit cron, einem sogenannten Daemon im Unix-Kern von Mac OS X, geht es eine Ebene im Betriebssystem tiefer. Die Aufgabe von cron, welches unsichtbar im Hintergrund läuft, ist es, jede Minute ein Mal in einer Tabelle, der sogenannten crontab, nachzusehen, ob irgendwelche Aufgaben für diesen Zeitpunkt vorgesehen sind. Wenn ja, startet es die angegebenen Programme oder Befehle. Damit lassen sich auch als Programm gesicherte Appleskripts zu einem beliebigen Zeitpunkt oder in beliebigen Zeitintervallen starten. Alternativ können Sie das Skript auch mit Shebang-Zeile als Text absichern oder mit osascript in der crontab aufrufen. Die crontab ist eine einfache Textdatei und kann mit einem einfachen Texteditor oder mit dem Terminal erstellt und bearbeitet werden oder mit einem Hilfsmittel wie CronniX. Inzwischen wird von Apple aber klar die Verwendung von launchd favorisiert, und man sollte deshalb ebenfalls launchd den Vorzug geben.
CronniX CronniX ist ein kleines, kostenloses Programm (der Entwickler freut sich aber über Spenden) von http://www.abstracture.de. Damit können Sie eine crontab statt mit dem Texteditor oder dem Terminal mit einer grafischen Benutzeroberfläche bearbeiten. Mit CronniX gelingt das daher auch Anwendern mit Unix-Antipathie schnell und leicht.
Abb. 6-24 Mit CronniX ist eine crontab schnell und einfach bearbeitet. Ein Beispiel: Nehmen Sie das Skript aus dem iCal-Beispiel mit der Zeile: say "It’s time for lunch!" Sichern Sie es als Programm mit dem Namen TimeForLunch.app in Ihrem Heimordner. Wenn Sie CronniX von der Webseite auf Ihrem Rechner geladen und in Ihren Programme-Ordner kopiert haben, starten Sie es. Klicken Sie dann auf die Schaltfläche Neu links oben in der Symbolleiste und wechseln Sie auf den Reiter Einfach.
657
SmartBooks
AppleScript
Füllen Sie die Tafel wie in folgender Abbildung aus. Statt 30 bei Minute und 13 bei Stunde, was 13:30 Uhr bedeutet, sollten Sie aber eine Uhrzeit auswählen, die für Sie ca. 5 Minuten in der Zukunft liegt. Dann brauchen Sie nicht so lange auf die Ausführung zu warten.
Abb. 6-25 Das Skript TimeForLunch.app startet bei diesen Einstellungen um 13:30 Uhr jeden Tag, jeden Monat. In der unteren Zeile bei Kommando bitte einen Haken bei "/usr/bin/open"-Präfix setzen. Diesen Shell-Befehl benötigen Sie, wenn Sie ein Programm oder eine Datei aus Unix heraus starten/öffnen wollen. Klicken Sie dann auf Suchen und wählen Sie das Skript im Heimordner aus. Die Kommandozeile sollte dann wie in obiger Abbildung aussehen, wenn nicht, editieren Sie diese noch. Natürlich erscheint im Pfad Ihr eigener Benutzername und nicht meiner, wie in der Abbildung. Falls der Pfad Leerstellen oder Sonderzeichen enthalten sollte, setzen Sie ihn bitte in Anführungszeichen, falls diese nicht schon automatisch gesetzt wurden.
658
Von der Kunst, ein AppleScript zu starten
Kapitel 6
Mit Anführungszeichen sieht ein korrektes Startkommando zum Beispiel so aus: /usr/bin/open "/Users/Hänschen Klein/TimeForLunch.app" Eine genaue Anleitung für die zulässigen Werte und Zeichen in der crontab finden Sie in der CronniX-Hilfe im Hilfe-Menü unter Crontab Syntax. Ein Sternchen bedeutet immer alle Tage, Monate, Stunden oder Minuten, je nachdem wo Sie es gesetzt haben. Klicken Sie dann auf Anwenden und wählen Sie im Ablage-Menü Sichern, um den Eintrag in die crontab zu übernehmen. Wenn Sie keine Lust haben, auf die Ausführung zu warten, können Sie auch Jetzt ausführen im Menü Eintrag wählen. Startet das Skript nicht, stimmt noch etwas mit dem Kommando nicht. Überprüfen Sie, ob der Pfad stimmt und ob nach open im Kommando auch eine Leerstelle steht. Als Kommando können Sie alle Befehle verwenden, die Sie so auch im Terminal eingeben würden. Mit anderen Worten: Sie können auch osascript zum Ausführen eines Appleskripts verwenden (siehe Kapitel Unix).
launchd Einführung Der Daemon launchd ist die Mutter aller Prozesse in Mac OS X. Es ist der Prozess mit der Nummer 1 und er kommt damit direkt nach dem Kernel mit der Nummer 0. launchd kümmert sich um das Starten aller anderen Prozesse, Anwendungen und Server. Schön zu sehen ist das, wenn Sie in der Aktivitätsanzeige (unter /Programme/Dienstprogramme) die hierarchische Ansicht der Prozesse einschalten und dann launchd zuklappen. Alle Prozesse sind launchd untergeordnet. In anderen Unix-Systemen ist der Start von Prozessen auf die unterschiedlichsten Daemonen wie cron, at, rc, inetd oder xinetd verteilt. Apple hat das nach und nach mit der Einführung von launchd geändert, welcher inzwischen fast alle Aufgaben übernommen hat. Die Bedienung und Verwaltung von Prozessen ist damit wesentlich einfacher handhabbar geworden. Wenn Sie, wie im vorigen Abschnitt, CronniX verwenden, so wird cron letztlich ebenfalls von launchd gestartet und überwacht.
659
SmartBooks
AppleScript
Abb. 6-26 launchd ist die Mutter aller Prozesse und damit die Shakti (treibende Kraft) hinter allen Aktivitäten im Kosmos des Mac OS X Betriebssystems. (Wodurch der Kernel mit der Nummer 0 dann sozusagen dem ruhenden Shiva entspricht, wenn ich schon gerade dabei bin, zu personifizieren.) launchd ist damit die zentrale Anlaufstelle für alles, was den Start von irgendwelchen Diensten betrifft. Warum also nicht gleich launchd statt cron verwenden? Dass das gar nicht so schwer ist, wird dieses Kapitel aufzeigen. Das Schöne an launchd ist, dass man nicht mehr die Handhabung mehrerer Daemonen erlernen muss, es reicht, launchd zu kennen. Damit kann alles gestartet (und überwacht und verwaltet) werden. Des Weiteren steckt die Konfiguration eines sogenannten LaunchAgents oder LaunchDaemons in einer einzigen XML-Datei, die wunderbar mit dem Property List Editor von Apple bearbeitet werden kann. Ein LaunchAgent bestimmt in launchd die Einstellungen zum Starten eines Programms. Er besteht nur aus einer XML-Datei. Ein sogenannter LaunchDaemon ist ein Hintergrundprozess, der von launchd überwacht und kontrolliert wird und der sich zum Beispiel um das Starten von Serverdiensten kümmert. Wenn Sie ein Skript zu einem bestimmten Zeitpunkt starten möchten, brauchen Sie nur einen LaunchAgent.
660
Von der Kunst, ein AppleScript zu starten
Kapitel 6
Das folgende Beispiel dient als Einführung in das Thema. Wenn Sie tiefer einsteigen wollen, empfehle ich die Lektüre der man-Seiten zu launchd, launchd.plist und launchctl im Terminal. Alles, was Sie benötigen, um sich einen eigenen LaunchAgent zu erstellen, ist das Terminal und das Programm Property List Editor. Das Programm findet sich im Ordner /Developer/Applications/Utilities/, das heißt, Sie müssen Xcode, also die Developer Tools von Apple, installiert haben. Hinweise zur Installation finden Sie in Kapitel 3. Aufgepasst Die folgende Beschreibung beruht auf dem Property List Editor der Version 3.1, die mit Xcode 3.1 geliefert wird. Die Vorgängerversion 2.2 des Property List Editors weicht in der Darstellung und Handhabung teils deutlich ab! In dieser Einführung weise ich in Klammmern noch auf die Unterschiede hin. In späteren Abschnitten wird nur die aktuelle Version berücksichtigt. 1. Speichern Sie zuerst einmal folgendes Beispielskript als Programm mit dem Namen break.app auf dem Schreibtisch ab: say "Time for a break" display dialog "Mach mal Pause!" buttons "OK" default button 1 giving up after 60 2. Starten Sie das Programm Property List Editor unter /Developer/Applications/Utilities/, zum Beispiel, indem Sie einfach die ersten Buchstaben des Programmnamens rechts oben in Spotlight eingeben (mit [Befehl]+[Leertaste] öffnen). Gefundene Programme, die mit diesen Buchstaben beginnen, werden standardmäßig als Erstes als Top-Treffer angezeigt, und Sie brauchen meist nur noch Enter zu drücken, um das Programm zu starten. 3. Falls nicht automatisch ein neues, leeres Dokument erscheint, wählen Sie bitte im Menü File | New (oder [Befehl]+[N], Das Programm hat, wie viele Entwicklerwerkzeuge, keine deutsche Lokalisierung). 4. In dem Dokument steht bisher nur ein einzelner Eintrag mit dem Namen Root in der Spalte Key. Falls das nicht der Fall ist, wählen Sie bitte View | Property List Type | Default for File Type (in älteren Property List Editoren einfach nur auf den Knopf New Root klicken!). 5. Klicken Sie auf die Zeile Root und betätigen Sie dann die Return-Taste. Ein neuer Eintrag erscheint eingerückt unter Root (in älteren Versionen Root aufklappen und dann auf New Child klicken!). 6. Geben Sie diesem neuen Eintrag in der Spalte Key (in Version 2.2 die Spalte Property List) den Namen Label, in der Spalte Type (Class) wählen Sie bitte String und in der Spalte Value (zur Eingabe doppelklicken) geben Sie bitte den Wert de.skripteditor.samples.launchd1 ein (siehe Abbildung). 661
SmartBooks
AppleScript
7. Markieren Sie noch einmal die Root-Zeile und betätigen Sie erneut die Return-Taste, um eine neue Zeile unter Root hinzuzufügen (in 2.2 auf New Child klicken!). 8. Geben Sie Disabled als Namen ein, Boolean als Type und setzen Sie keinen Haken in das Ankreuzkästchen in der Spalte Value (in 2.2 den Wert No auswählen!). 9. Markieren Sie noch einmal die Zeile Root und betätigen Sie erneut die Return-Taste, um eine Zeile hinzuzufügen (in 2.2 auf New Child klicken!). 10. Geben Sie RunAtLoad als Key (Property List) ein, Boolean als Type (Class) und setzen Sie einen Haken in das Ankreuzkästchen in der Spalte Value (in 2.2 auf Yes setzen!). Beachten Sie die Groß- und Kleinschreibung im Namen. 11. Wieder Root anklicken und mit Return bestätigen (in 2.2 auf den Knopf New Child klicken!) und für die neue Zeile StartInterval als Key (Property List) eingeben, als Type (Class) Number und als Wert 30. 12. Noch einmal Root anklicken und mit Return betätigen (in 2.2 auf den Knopf New Child klicken!). In der neuen Zeile dann ProgramArguments als Key (Property List) eingeben und als Typ (Class) Array. Dann den Eintrag am Dreieck davor aufklappen und Return betätigen, um einen neuen Eintrag eingerückt unter ProgramArguments hinzuzufügen (in Version 2.2 auf den Knopf New Child klicken!). 13. Geben Sie dem neuen Eintrag Item 1 unter ProgramArguments (in Version 2.2 heißt der Eintrag nur 0) den Typ (Class) String und den Wert /usr/bin/open. Den Key (Property List) können Sie hier nicht verändern. 14. Wenn die Zeile ProgramArguments oder die Zeile Item 1 (0) ausgewählt ist, die Return-Taste betätigen (auf den Knopf New Sibling klicken) und für die neue Zeile mit dem Schlüssel Item 2 (1) bitte ebenfalls wieder String als Type (Class) wählen und als Value bitte den POSIX-Pfad zu Ihrem Skript angeben, bei mir ist das zum Beispiel: /Users/Detlef/Desktop/break.app. Alles in allem sollte Ihr LaunchAgent in Version 3.1 nun so aussehen wie in folgender Abbildung, wobei die Reihenfolge der Einträge unter Root keine Rolle spielt:
Abb. 6-27 Ein erster, einfacher LaunchAgent
662
Von der Kunst, ein AppleScript zu starten
Kapitel 6
15. Sichern Sie das Dokument über File | Save. Achten Sie darauf, dass im Sichern-Dialog als File Format der Eintrag XML Property List (in Version 2.2 der Eintrag XML Property List File) ausgewählt ist, geben Sie der Datei den Namen launchdSample1.xml und speichern Sie die Datei in den Ordner Library/LaunchAgents/ in Ihrem Heimverzeichnis. Legen Sie den Ordner dort an, falls er noch nicht existiert. Nun erst einmal eine Erklärung zu allen Schlüsseln (Keys oder Property Lists) in dieser Datei. Beachten Sie, dass die Groß- und Kleinschreibung generell in Unix wichtig und daher immer zu beachten ist. << Label: Hier kann theoretisch ein beliebiger Name stehen. Anhand dieses Namens wird der LaunchAgent identifiziert. Wichtig ist, dass Sie keine Leerstellen oder Sonderzeichen verwenden und dass der Name einmalig ist. Es dürfen also keine doppelten Namen vorkommen. Von Apple wird hier üblicherweise empfohlen, den Namen der Webseite des Herstellers in umgekehrter Schreibweise mit angehängtem Programmnamen zu verwenden. Ich nehme in diesem Beispiel daher die Buch-Webseite als Namen des LaunchAgents und füge eine Rubrik samples an und dann den Namen dieses Beispiels launchd1. Das ergibt als fertigen Namen: de.skripteditor.samples.launchd1. Das sollte eindeutig genug sein, so dass keine doppelten Namen zu erwarten sind. << Disabled: Wenn diese Eigenschaft angekreuzt ist (oder in älteren Versionen auf True steht), ist der LaunchAgent nicht aktiv. Diese Eigenschaft wird dabei üblicherweise über das Terminal mit dem Befehl launchctl gesetzt und nicht direkt von Ihnen. Sie können diese Eigenschaft auch weglassen. Sie wird, wie im Folgenden bei launchctl beschrieben, auch automatisch hinzugefügt, wenn sie benötigt wird. << RunAtLoad: Wenn Sie diese Eigenschaft aktivieren, dann wird der LaunchAgent sofort ausgeführt, wenn er gestartet wird. Normalerweise ist das der Fall, wenn Sie sich in Ihrem Benutzerkonto anmelden oder wenn Sie den LaunchAgent manuell aktivieren. Entfernen Sie den Haken oder gleich die ganze Eigenschaft, wenn Sie das nicht möchten. Für dieses Beispiel sollten Sie RunAtLoad aus Testgründen eingeschaltet lassen. Dann können Sie die Wirkung gleich überprüfen. << StartInterval: Hier müssen Sie eine Ganzzahl angeben. Diese Zahl bestimmt die Anzahl an Sekunden zwischen zwei Ausführungen des Skripts. Wenn, wie hier, eine 30 darin steht, so wird das Skript alle 30 Sekunden ausgeführt. Das ist natürlich nur zum Testen so eingestellt, nach erfolgreichem Test können Sie das auf einen vernünftigen Wert hochsetzen, zum Beispiel auf 7200, was dann einem Intervall von 2 Stunden entspricht. Alle zwei Stunden ein Pause zu machen, dürfte in Ordnung sein. << ProgramArguments: Hier steht, was denn nun eigentlich alle 30 Sekunden passieren soll. Und zwar soll hier ein Befehl ausgeführt werden. Dieser Befehl setzt sich aus mehreren Items zusammen. Diese Items werden in der angegebenen Reihenfolge mit
663
SmartBooks
AppleScript
einer Leerstelle zusammengebaut. Der Befehl, der hier ausgeführt wird, lautet also letztlich: /usr/bin/open /Users/Detlef/Desktop/break.app Hier wird der Unix-Befehl open im Pfad /usr/bin aufgerufen und ihm als Argument der Pfad zu Ihrem Skript übergeben. Sie können den Befehl auch genau so im Terminal eingeben, und Ihr Skript wird direkt ausgeführt. Der Unix-Befehl open macht nichts anderes, als eine beliebige Datei zu öffnen, bei einem Programm wird das Programm also gestartet. Sie könnten hier demnach genauso gut auch den Pfad zu einem Programm wie zum Beispiel Safari angeben, anstatt desjenigen zu Ihrem Skript. All diese Schlüssel und noch einige mehr sind übrigens in der man-page zu launchd.plist dokumentiert. Dieser LaunchAgent wurde unter Library/LaunchAgents/ in Ihrem Heimverzeichnis abgespeichert. Das ist der übliche Platz für benutzerbezogene LaunchAgents. Dieser Ordner wird von launchd überwacht, und darin aufgeführte LaunchAgents werden nach dem Anmelden automatisch ausgeführt. Da Sie sich noch nicht ab- und wieder angemeldet haben, ist dieser LaunchAgent also noch nicht aktiv. Ich zeige Ihnen gleich, wie Sie das auch manuell mit dem Befehl launchctl machen können. Diesen Befehl brauchen Sie auch, um den LaunchAgent wieder sauber abzumelden, bevor Sie ihn wieder aus dem Ordner entfernen. Dieser Ordner Library/LaunchAgents/ ist jedoch nicht der einzige Ordner, der von launchd überwacht wird. Insgesamt gibt es fünf Orte, die in der man-page zu launchd aufgelistet werden: << ~/Library/LaunchAgents
LaunchAgents des Anwenders
<< /Library/LaunchAgents
LaunchAgents des Administrators für An- wender
<< /Library/LaunchDaemons
Systemweite Daemons des Administrators
<< /System/Library/LaunchAgents
LaunchAgents von Mac OS X für Anwender
<< /System/Library/LaunchDaemons Systemweite Daemons von Mac OS X Verwenden Sie für Ihre eigenen Bedürfnisse nur den ersten, wenn ein LaunchAgent für mehrere Benutzer zur Verfügung stehen soll, dann eventuell auch den zweiten Ort.
launchctl Nachdem Sie den LaunchAgent mit dem Property List Editor erstellt haben und er in den richtigen Ordner abgespeichert wurde, müssen Sie den Agenten noch aktivieren. Dafür brauchen Sie den Befehl launchctl und das Terminal.
664
Von der Kunst, ein AppleScript zu starten
Kapitel 6
16. Öffnen Sie das Terminal im Ordner /Programme/Dienstprogramme. 17. Tippen Sie folgenden Befehl ein und passen Sie den Pfad entsprechend an: launchctl load /Users/Detlef/Library/LaunchAgents/launchdSample1.xml Damit wird der LaunchAgent geladen, und Sie werden direkt mit der Ansage und dem Dialog begrüßt und aufgefordert, eine Pause zu machen. Der Schlüssel RunAtLoad hat also funktioniert. Bestätigen Sie den Dialog und warten Sie 30 Sekunden. Sie werden erneut aufgefordert, eine Pause zu machen. Auch das StartInterval von 30 funktioniert also. Damit Sie nun nicht alle 30 Sekunden genervt werden, sollten Sie den LaunchAgent im Terminal erstmal wieder abschalten. Kümmern Sie sich derweil nicht um den Dialog, wenn er wieder erscheint. Der Befehl sieht genauso aus wie beim Laden, Sie müssen nur unload statt load schreiben. launchctl unload /Users/Detlef/Library/LaunchAgents/launchdSample1.xml So, damit ist der LaunchAgent erstmal wieder abgeschaltet, und Sie haben wieder Ruhe. Wichtig ist jedoch zu wissen, dass er nicht dauerhaft abgeschaltet ist! Sobald Sie sich abmelden und erneut anmelden, wird der LaunchAgent wieder automatisch geladen, da er im überwachten Ordner liegt! Damit man nun nicht ständig Dateien in den Ordner hineinlegen und wieder herausnehmen muss, gibt es den Schlüssel Disabled. Wenn Sie solch einen LaunchAgent dauerhaft deaktivieren wollen, sollten Sie daher die Option -w verwenden. Diese Option macht nichts anders, als bei dem Schlüssel Disabled einen Haken zu setzen, und falls dieser Schlüssel noch nicht existiert, wird er auch gleich angelegt. Erst wenn dieser Schlüssel auf Disabled steht, sollten Sie den LaunchAgent wieder aus dem Ordner entfernen, wenn Sie ihn denn dort loswerden wollen: Die Option -w kann sowohl beim load als auch beim unload erfolgen. Folgt die Option nach einem load, wird damit der Schlüssel Disabled einfach entfernt und der LaunchAgent damit dauerhaft aktiviert. Um das Skript zu aktivieren und den Schlüssel Disabled zu entfernen, schreiben Sie also: launchctl load -w /Users/Detlef/Library/LaunchAgents/launchdSample1.xml Um den LaunchAgent dauerhaft zu deaktivieren, so dass er nicht mehr automatisch bei einem Neustart oder einer Anmeldung wieder geladen wird, schreiben Sie: launchctl unload -w /Users/Detlef/Library/LaunchAgents/launchdSample1.xml Mit diesen beiden Befehlen können Sie die LaunchAgents in Ihrem LaunchAgents-Ordner nach Bedarf dauerhaft aktivieren oder deaktivieren, ohne sie deswegen gleich aus dem Ordner zu entfernen.
665
SmartBooks
AppleScript
Zu weiteren Optionen bitte die man-Seite zu launchctl beachten! Mit diesen beiden Befehlen kommen Sie aber in der Regel völlig aus. Aufgepasst Achten Sie immer darauf, den LaunchAgent vor seiner Bearbeitung zu deaktivieren. Sie operieren sonst im laufenden Prozess mit unvorhersehbarem Ergebnis.
Weitere Beispiele Statt den Befehl open aus /usr/bin zu verwenden, können Sie natürlich auch andere Befehle nehmen. Der Befehl osascript bietet sich zum Beispiel an (siehe Kapitel Unix). Damit können Sie mit der Option -e ein kleines Appleskript auch direkt auf der Kommandozeile eingeben. Ein LaunchAgent könnte dann zum Beispiel so aussehen wie in folgender Abbildung:
Abb. 6-28 Auch der Befehl osascript bietet sich für einen LaunchAgent an. Ansonsten können Sie natürlich jeden beliebigen Shell-Befehl verwenden oder sogar Skripts in anderen Programmiersprachen, ob es sich dabei um ein Shellskript oder ein Skript in der Sprache Python, Perl oder einer anderen Sprache handelt, spielt keine Rolle. Sie können einem LaunchAgent auch wie bei cron genaue Anweisungen geben, um welche Uhrzeit oder an welchen Tagen der Woche er aktiv werden soll. Der Schlüssel dazu heißt StartCalendarInterval und er hat den Typ dictionary mit numbers als Elementen oder ein array mit dictionaries von numbers. Als dictionary kann StartCalendarInterval folgende Schlüssel enthalten, die, analog zu cron, den Zeitpunkt der Ausführung bestimmen:
666
Von der Kunst, ein AppleScript zu starten
Kapitel 6
Minute
Integerwerte von 0 bis 59. Bestimmt die Minute.
Hour
Integerwerte von 0 bis 23. Bestimmt die Stunde.
Day
Integerwerte von 1 bis 31. Bestimmt den Monatstag.
Weekday
Integerwerte von 0 bis 7. Bestimmt den Wochentag (0 und 7 ist Sonntag).
Month
Integerwerte von 1 bis 12. Bestimmt den Monat.
Wenn einer dieser Werte fehlt, so ist jeder dieser Zeitpunkte gültig, also zum Beispiel an jedem Tag oder zu jeder Stunde oder zu jeder Minute. Das Beispiel aus der folgenden Abbildung etwa wird an jedem Freitag (Weekday 5) um 18:45 Uhr ausgeführt:
Abb. 6-29 Ausführung zu einem bestimmten Zeitpunkt Bei der kleinsten Einheit Minute ist zu beachten, dass diese bis zu 59 Sekunden Varianz nach hinten haben kann. Also stellen Sie nicht unbedingt Ihre Uhr danach. Ob die Aufgabe am Anfang, in der Mitte oder am Ende der Minute ausgeführt wird, entscheidet launchd. Auf jeden Fall wird sie pünktlich in dieser Minute ausgeführt, nicht eine Minute früher und nicht eine Minute später. Wenn Sie die obige Meldung an mehreren Tagen erhalten möchten, zum Beispiel an jedem Freitag, Samstag und Sonntag, müssen Sie für StartCalendarInterval ein array mit dictionaries
667
SmartBooks
AppleScript
anlegen, wie in der folgenden Abbildung, wo für jeden Zeitpunkt, an dem der LaunchAgent ausgeführt werden soll, ein dictionary angelegt wurde . Hier wird der Befehl an den Wochentagen 5, 6 und 7 (Freitag bis Sonntag) um die angegebene Uhrzeit angezeigt.
Abb. 6-30 Wenn der Job an mehreren Zeitpunkten ausgeführt werden soll, brauchen Sie ein array mit dictionaries für den Schlüssel StartCalendarInterval.
SystemStarter Nicht mehr zeitgemäß ist der Gebrauch des SystemStarter von Apple, welcher die Dienste in den StartupItems-Ordnern der verschiedenen Library-Ordner startet. Apple rät zum Umstieg auf das wesentlich flexiblere launchd. Wie man die StartupItems zur Ausführung von Skripts verwendet, wird in diesem Buch daher nicht behandelt. Wenn Sie auf Ihrem Rechner einmal in den verschiedenen Library-Ordnern nachsehen, werden Sie, zumindest unter Leopard, wahrscheinlich keinen oder nur leere StartupItem-Ordner finden, es sei denn, ein Drittprogramm, welches noch darauf baut, hat einen angelegt und sich darin verewigt. StartupItems bestehen in der Regel aus einem Shell-Skript und einer Datei StartupParameters.plist, welche die Ausführungsparameter bestimmt.
Weitere Programme mit Timerfunktion Auf die Ausführung von Skripts zu bestimmten Zeiten spezialisiert sind noch die Programme Skript Timer von http://www.appsandmore.com und iDo Script Scheduler von http://www.sophisticated.com. Der Script Timer startet dabei auch Automator-Workflows, ohne Automator starten zu müssen. Es gibt sicher noch viele weitere Programme, welche die Fähigkeit haben, eine Datei zu einem bestimmten Zeitpunkt zu öffnen. Wenn ein Programm dies kann, eignet es sich
668
Von der Kunst, ein AppleScript zu starten
Kapitel 6
auch als Skript-Starter. Wenn es dann noch die Fähigkeit besitzt, den Start zu einem bestimmten Punkt in der Zeit erfolgen zu lassen, wenn möglich auch in Intervallen, qualifiziert es sich auch als Skript-Timer.
Einen eigenen Skript-Timer in AppleScript erstellen Eine letzte in Betracht kommende Möglichkeit, ein Skript zu einem bestimmten Zeitpunkt oder in bestimmten Intervallen zu starten, ist die, sich selbst einen Skript-Timer in AppleScript zu schreiben. Und das ist gar nicht so schwer. In Kapitel 3 wurde erklärt, dass Sie ein Skript als Programm mit der Option Nicht automatisch beenden sichern können. Ein solches Skript bleibt so lange geöffnet, bis Sie es explizit beenden. In den Systemeinstellungen können Sie unter Benutzer dieses Skript als Startobjekt definieren, so dass es nach dem Anmelden am Rechner auch sofort Wache steht. Alles, was fehlt, ist die Kenntnis davon, wie man einem geöffneten Skript beibringt, ab und zu mal auf die Uhr zu sehen und dann, wenn die Zeit gekommen ist, etwas zu tun. Was man dafür braucht, ist der sogenannte idle-Handler (siehe den Abschnitt Der idleHandler unter Handler im Kapitel 4). Das folgende einfache Beispiel überprüft regelmäßig die Uhrzeit und lädt pünktlich zu einer festgelegten Zeit zur »teatime« ein. Schreiben Sie das Skript einfach ab und sichern Sie es als Programm mit der Option Nicht automatisch beenden. Nach dem Start bleibt es dann geöffnet. Wenn die Uhrzeit nicht passt, ändern Sie die beiden Propertys am Anfang. Sie bestimmen die volle Stunde und die Minute, zu der zur Teezeit gerufen wird. Stellen Sie die Zeit dort auf wenige Minuten in der Zukunft ein. Dann brauchen Sie nicht den ganzen Tag auf die Ausführung zu warten. property teatimeHour : "15" --die Stunde der Teezeit property teatimeMinute : "05" -- die Minute der Teezeit on idle set currentTime to time string of (current date) set currentHour to first word of currentTime set currentMinute to second word of currentTime if currentMinute is equal to teatimeMinute and ¬ currentHour is equal to teatimeHour then say "Time for a cup of tea!" end if return 60 end idle
669
SmartBooks
AppleScript
Die Anweisung return 60 besagt, dass die Uhrzeit erst in 60 Sekunden erneut geprüft werden soll. Das verhindert hier, dass die Ansage mehrmals in der entsprechenden Minute aufgesagt wird. Nachdem das Skript gestartet ist, wechseln Sie in irgendein Programm, arbeiten Sie darin, oder warten Sie einfach ab, bis der entsprechende Zeitpunkt eintritt. Da die Uhrzeit nur alle 60 Sekunden geprüft wird, kann es eine entsprechende Verzögerung von bis zu 59 Sekunden geben. Nachteil dieser Lösung ist natürlich, dass das Skript im Finder als Programm sichtbar ist und damit leicht aus Versehen beendet werden kann.
Skriptwächter als Hintergrundprozess Damit ein Skript mit Wächterfunktion nicht aus Versehen beendet werden kann, schickt man es am besten in den Hintergrund. Dafür muss man nur das Skript als Programm-Bundle sichern und einen Eintrag in der darin enthaltenen Datei info.plist vornehmen. Dafür brauchen Sie den Property List Editor, der automatisch zusammen mit Xcode installiert wird. 1. Sichern Sie obiges Skript als Programm-Bundle mit der Option Nicht automatisch beenden. 2. Öffnen Sie das Programm-Bundle im Finder. 3. Doppelklicken Sie die Datei info.plist, um sie mit dem Property List Editor zu öffnen. 4. Schauen Sie im Menü View nach. Dort sollte kein Haken bei Show Raw Keys/Values stehen. Wenn dort ein Haken steht, wählen Sie den Eintrag ein Mal aus, um ihn zu entfernen. 5. Klicken Sie den Eintrag Information Property List an. 6. Klicken Sie dann auf den Knopf Add Child. In der ersten Spalte öffnet sich ein Einblendmenü. 7. Wählen Sie darin den Eintrag Application is background only (in älteren Versionen des Property List Editors LSBackgroundOnly von Hand hinein schreiben!). 8. Rechts daneben bitte einen Haken setzen (in älteren Versionen den Type auf String setzen und eine 1 als Value eingeben!). 9. Die Datei sichern und schließen.
670
Von der Kunst, ein AppleScript zu starten
Kapitel 6
Abb. 6-31 Mit diesem Eintrag in der info.plist wird ein Appleskript zum Hintergrundprogramm. Wenn Sie das Skript nun starten, wird es im Hintergrund laufen, kann also über den Finder nicht mehr aufgerufen werden. Wenn Sie das Skript beenden wollen, müssen Sie daher das Programm Aktivitätsanzeige im Ordner /Programme/Dienstprogramme bemühen. Die Schlüssel für eine info.plist-Datei sind übrigens unter folgendem Link dokumentiert: http://developer.apple.com/documentation/MacOSX/Conceptual/BPRuntimeConfig/ Articles/PListKeys.html Schalten Sie im Property List Editor im View-Menü Show Raw Keys/Value ein, damit Sie die Einträge auch in der Dokumentation anhand der unübersetzten Originalbezeichnung (LSBackgroundOnly) wieder finden. Aufgepasst Ein Skript, welches auf diese Art und Weise in den Hintergrund geschickt wurde, kann keine Dialoge wie display dialog verwenden. Brauchen Sie unbedingt einen solchen Dialog, so schachteln Sie diesen in einen tell-block mit einem activate an den Finder oder an die System Events.
Bei einem Ereignis Außer ein Skript zu einer bestimmten Uhrzeit automatisch starten zu lassen, kann es sinnvoll sein, es bei Eintreten eines bestimmten Ereignisses zu aktivieren. Im Folgenden werden die unterschiedlichen Möglichkeiten dazu beschrieben.
Start und Anmeldung Um ein Skript nach dem Start des Rechners ausführen zu lassen, gibt es unter Mac OS X mehrere Möglichkeiten. Die einfachste ist es, die Startobjekte in den Benutzer-Systemeinstellungen zu verwenden.
671
SmartBooks
AppleScript
Startobjekte Sichern Sie ein Skript als Programm und fügen Sie es dann in den Benutzer-Systemeinstellungen unter Startobjekte hinzu. Genau genommen wird das Skript dann also nach jeder Anmeldung ausgeführt und nicht bei jedem Rechnerstart. Handelt es sich um ein Skript, das geöffnet bleibt und erst den richtigen Zeitpunkt abwartet, wie zum Beispiel der Tea-Timer aus dem letzten Beispiel, wird das Skript natürlich erst zu dem entsprechenden Zeitpunkt ausgelöst.
Abb. 6-32 Ein Skriptprogramm, ausgewählt als Startobjekt, wird direkt nach der Anmeldung ausgeführt. Eine einfacher Gruß als Programm abgesichert, zum Beispiel ein Morgengruß, sorgt dafür, dass Sie ab sofort nach dem Start persönlich begrüßt werden. beep 2 say "Good morning Dave." using "Zarvox" Aber sicher gibt es auch noch sinnvollere Sachen. Wie wäre es zum Beispiel, wenn man mit dem Öffnen des Mail-Programms zum Abholen der Post und dem anschließenden Öffnen der Morgenzeitung im Browser begrüßt wird?
672
Von der Kunst, ein AppleScript zu starten
Kapitel 6
Hier ein entsprechendes, schön kurzes Skript: launch application "Mail" open location "http://news.google.de" say "Good morning Dave. Here is your mail and your newspaper." using "Zarvox" Das Skript geht davon aus, dass Sie in den Einstellungen von Mail den Empfang von E‑Mails nicht auf Manuell stehen haben (Reiter Allgemein und dort bei Empfang von Emails auf einen anderen Wert als Manuell umstellen) und dass sich Ihr Rechner bei Bedarf automatisch mit dem Internet verbindet. Falls Ihr Rechner sich nicht automatisch mit dem Internet verbindet und Sie auch Ihre Mails manuell abrufen wollen, nehmen Sie folgendes erweiterte Skript als Vorlage. Sie müssen darin aber noch den Namen der Umgebung „Automatisch“ und des Services „Ethernet“ gegebenenfalls ändern, je nachdem, wie Ihre Umgebung in den Netzwerkeinstellungen heißt und mit welchem Dienst Sie ins Internet gehen. tell application "System Events" tell network preferences –-Netzwerk Systemeinstellungen tell location "Automatisch" --Name Ihrer Umgebung tell service "Ethernet" to connect --Name des Dienstes end tell end tell end tell delay 5 --Wartezeit in Sekunden bis die Verbindung steht, evtl. anpassen. launch application "Mail" tell application "Mail" set fetches automatically to true --Automatische Abholung ein set fetch interval to 30 --Zeit in Minuten bis zur nächsten Abholung end tell open location "http://news.google.de" --Nach Wunsch abändern say "Good morning Dave. Here is your mail and your newspaper." using "Zarvox" delay 15 --Wartezeit in Sekunden, Mail Zeit geben die Post abzuholen tell application "Mail" --Automatische Abholung ausschalten set fetches automatically to false end tell
673
SmartBooks
AppleScript
Damit ist Ihr selbsterstellter Morgenbutler fertig zum Einsatz – als Programm sichern und dann in Ihrem Benutzeraccount als Startobjekt eintragen, fertig. Ab sofort werden Sie jeden Morgen mit Ihren neuesten E-Mails und dem Nachrichtenüberblick begrüßt.
launchd beim Start Auch hier können Sie wieder einen LaunchAgent verwenden. Alles, was Sie brauchen, ist die Eigenschaft RunAtLoad, die bereits zuvor beschrieben wurde. Damit wird ein Skript direkt nach dem Laden des LaunchAgents bei der Anmeldung ausgeführt. Siehe launchd Einführung ein paar Seiten zuvor. loginwindow und LoginHook loginwindow ist ein Prozess, welcher dafür sorgt, dass beim Anmelden die eigenen Einstellungen und die Startobjekte geladen werden. Danach kümmert er sich darum, dass diese auch erhalten bleiben. Zum Beispiel wird von loginwindow der Finder oder das Dock bei einem Absturz automatisch neu gestartet. Mit einem Terminal-Befehl an com. apple.loginwindow kann man ein Shell-Skript an den LoginHook von loginwindow ankoppeln, welches dann von loginwindow bei jeder Anmeldung ausgeführt wird. Da Sie hier nur ein Shell-Skript anbinden können und nicht direkt ein Appleskript, müssen Sie ein Shell-Skript schreiben, welches osascript verwendet (Beispiel im Kapitel Unix) oder mit dem Befehl open ein Applet öffnet. Ein kleines Beispiel: 1. Erstellen Sie auf dem Schreibtisch ein Skript-Programm mit Namen break.app und folgendem AppleScript-Code: say "Good morning Dave" using "Trinoids" 2. Erstellen Sie auf dem Schreibtisch mit einem Textprogramm, welches Unix-Zeilenumbrüche beim Sichern verwenden kann (TextEdit funktioniert hier nicht!), zum Beispiel mit TextWrangler (http://www.barebones.com/products/) oder im Terminal mit einem Editor wie nano eine Textdatei mit folgendem Shell-Skript und speichern Sie diese als break.sh ab: #!/bin/bash open /Users/Detlef/Desktop/break.app
674
Von der Kunst, ein AppleScript zu starten
Kapitel 6
Hilfe Zur Handhabung von nano im Terminal: Im Terminal auf der Kommandozeile nano break.sh eingeben und bestätigen (oder gleich mit Pfadangabe: nano /Users/Detlef/Desktop/break.sh). Daraufhin öffnet sich der Editor im Terminal. Geben Sie die beiden Zeilen ganz normal wie in einer Textverarbeitung ein. Wenn Sie fertig sind, beenden Sie nano mit [ctrl]-[X]. Bestätigen Sie dann mit der Taste [Y], dass Sie sichern wollen, und den Dateinamen anschließend mit [Return]. Die Datei break.sh liegt anschließend im Arbeitsverzeichnis des Terminals, also dem Pfad, der vor dem $-Zeichen auf der Kommandozeile angegeben ist, normalerweise das Heimverzeichnis. Verschieben Sie die Datei dann noch auf den Schreibtisch. Natürlich müssen Sie hier Ihren eigenen Benutzernamen im Pfad verwenden. Wenn Sonderzeichen oder Leerzeichen im Pfad vorkommen, setzen Sie den Pfad in einfache Anführungszeichen. Beachten Sie hier auch das Kapitel Unix mit seinen Hinweisen zur Erstellung eines ausführbaren Shell-Skripts. 3. Nachdem das Skript erstellt ist, müssen Sie es noch im Terminal ausführbar machen. Schreiben Sie dafür ins Terminal: chmod +x /Users/Detlef/Desktop/break.sh 4. Testen Sie das Shell-Skript nun im Terminal: /Users/Detlef/Desktop/break.sh Wenn jetzt das »Good morning Dave« ertönt, hat es geklappt. 5. Nun können Sie das Shell-Skript an den LoginHook anbinden: sudo defaults write com.apple.loginwindow LoginHook /Users/Detlef/Desktop/break.sh Sie brauchen dafür Administratorrechte. Geben Sie daher Ihr Passwort ein, wenn Sie im Terminal danach gefragt werden. Aktiv wird das jetzt aber erst, wenn Sie sich neu anmelden. Wenn Sie den LoginHook wieder loswerden wollen, können Sie ihn mit folgender Zeile im Terminal wieder entfernen: sudo defaults delete com.apple.loginwindow LoginHook Die Verwendung der Startobjekte in den Benutzereinstellungen oder der Gebrauch von launchd erscheint mir einfacher und komfortabler. Der Grund, warum ich trotzdem die Arbeit mit loginwindow aufzeige, liegt im nächsten Abschnitt begründet.
675
SmartBooks
AppleScript
Ausschalten und Abmelden Leider gibt es für die Ausführung eines Skripts beim Ausschalten oder Abmelden, analog zu den Startobjekten, keine Ausschaltobjekte in den Benutzereinstellungen. Von daher bleiben nur folgende Möglichkeiten übrig:
loginwindow und LogoutHook Der Prozess loginwindow kann im Gegensatz zu launchd ein Skript auch kurz vor dem Abmelden vom System ausführen. Alles, was dafür nötig ist, ist das Shellskript, welches das Appleskript auffordert, an den LogoutHook von loginwindow anzukoppeln. Das verhält sich exakt so wie die Beschreibung bei loginwindow und LoginHook. Beachten Sie daher die Ausführung auf den vorigen Seiten. Die einzige Änderung besteht darin, dass Sie das Skript auf folgende Art an den LogoutHook anbinden müssen: sudo defaults write com.apple.loginwindow LogoutHook /Users/Detlef/Desktop/break.sh
Eigenen Skriptwächter erstellen Neben dem LogoutHook können Sie auch wieder einen eigenen Skriptwächter mit einem quit-Handler (Kapitel 4: Der quit-Handler) verwenden und dieses Skript mit Rechnerstart gleich mitstarten. Das Skript muss natürlich als Programm mit der Option Nicht automatisch beenden gespeichert werden. Es wird dann beim Herunterfahren des Rechners oder beim Ausloggen des Benutzers ausgeführt. Kurz bevor ein Rechner heruntergefahren wird oder Sie sich abmelden, wird allen Prozessen und Programmen ein quit-Befehl erteilt. Sobald dieser quit-Befehl das laufende Skript erreicht, wird in diesem der quit-Handler ausgeführt, bevor das Skript sich dann tatsächlich beendet. Ein einfaches Skript sieht so aus: on run say "Shutdown-Script is active!" end run on quit say "Quit-Handler is triggered, now!" continue quit end quit Der run-Handler kann auch weggelassen werden, er steht hier nur, um eine akustische Rückmeldung zu geben, dass das Skript auch wirklich läuft. Alles, was im run-Handler steht, wird nur ein Mal beim Start des Skripts ausgeführt. Was im quit-Handler steht, wird nur ein Mal vor dem Beenden des Skripts ausgeführt. Da vor dem Abmelden alle Programme beendet werden, wird das Skript also noch die Befehle, die im quit-Handler
676
Von der Kunst, ein AppleScript zu starten
Kapitel 6
stehen, ausführen können, bevor es dann mit continue quit den Befehl an sich selbst weitergibt und sich beendet. Danach erst werden Sie abgemeldet oder der Rechner wird heruntergefahren. Aufgepasst Der quit-Befehl muss immer unbedingt mit continue quit weitergereicht werden. Sonst beendet sich das Programm nicht und der Rechner fährt nicht herunter. Wenn Sie das Skript im Skripteditor als Programm mit der Option Nicht automatisch beenden gespeichert haben, doppelklicken Sie es, um es zu starten. Sie werden mit der Ansage »Shutdown-Script is active!« begrüßt. Beenden Sie nun das Skript. Sie erhalten die Meldung: »Quit-Handler is triggered, now!“ Alternativ können Sie sich bei laufendem Skript auch abmelden oder den Rechner neu starten, was dieselbe Wirkung wie das Beenden des Skripts hat. Tipp Wenn Sie das Skript als Programm-Bundle abspeichern und dann in der info.plist das Skript als Hintergrundprozess aktivieren (Application is background only), ist es auch nicht mehr für den normalen Anwender sichtbar und kann folglich nicht mehr aus Versehen beendet werden (siehe einige Seiten zuvor unter Skriptwächter als Hintergrundprozess).
Ruhezustand Um ein Appleskript auszuführen, bevor der Rechner oder der Monitor in den Ruhezustand übergeht oder direkt nachdem er daraus wieder aufwacht, sind mir bisher zwei Möglichkeiten bekannt:
SnoozeRun SnoozeRun stammt von http://www.jadechord.com/ und ist klein, handlich, kostenlos und schnell in der Anwendung. Wenn Sie das Programm heruntergeladen und an einer beliebigen Stelle auf die Festplatte gezogen haben, können Sie es doppelklicken und dort mit einem Klick auf den Kopf Add Task ein beliebiges Skript (nur Skript-Formate, keine Programme!) an eine der beiden verfügbaren Aktionen anknüpfen. Das ist einmal vor dem Einschlafen und einmal nach dem Aufwachen nötig.
677
SmartBooks
AppleScript
Die folgende Abbildung zeigt, wie einfach das Programm gehalten ist:
Abb. 6-33 SnoozeRun ist einfach, muss aber laufen. Nachdem Sie den Pfad zu Ihrem Skript angegeben haben, brauchen Sie nur noch angeben, ob das Skript vor dem Einschlafen (Sleeping) oder nach dem Aufwachen (Waking up) ausgeführt werden soll. Der einzige Nachteil: Das Programm muss laufen, damit es funktioniert, da es auch gleichzeitig der Wächter ist. Beenden Sie es also nicht aus Versehen.
SleepWatcher Eine weitere Möglichkeit ist das Programm SleepWatcher von http://www.bernhard-baehr.de. Das Programm steht unter der GNU General Public License und ist damit kostenlos. Der Sourcecode ist beigefügt. SleepWatcher besteht aus einem Kommandozeilenprogramm und einem StartupItem. Wenn Sie den SleepWatcher in der leopardkompatiblen Version 2.0.5 von der Webseite des Entwicklers herunterladen, finden Sie darin zwei Installationspakete. Doppelklicken Sie zuerst das Paket sleepwatcher.pkg. Damit wird das Programm sleepwatcher selbst installiert. Der Terminalbefehl sleepwatcher wird unter /usr/local/sbin/ und die dazugehörige Manual-Seite unter /usr/local/share/man/man8/ abgelegt. Wenn Sie das Programm wieder deinstallieren wollen, so entfernen Sie dort die beiden Dateien. Wenn Sie nun das Terminal öffnen und dort man sleepwatcher als Befehl eingeben und mit der Return-Taste bestätigen, erscheint die Hilfe für sleepwatcher. Hilfe Mit den Cursor-Tasten können Sie sich zeilenweise in der Seite bewegen und mit der Leertaste eine ganze Seite nach unten steuern. Mit der Taste q können Sie die ManualSeite wieder verlassen.
678
Von der Kunst, ein AppleScript zu starten
Kapitel 6
Installieren Sie danach das Paket SleepWatcher StartupItem.pkg. Dadurch wird ein StartupItem in den Ordner /Library/StartupItems/ abgelegt, welches das Programm sleepwatcher schon beim Start des Rechners lädt. Wichtig: sleepwatcher wird also nicht über die Startobjekte in den Benutzer-Systemeinstellungen aktiviert! Sie müssen es, wenn Sie es wieder deaktivieren wollen, manuell aus dem Ordner /Library/StartupItems/ entfernen. Zusätzlich installiert dieses Paket zwei Beispiel-Shell-Skripts (rc.sleep und rc.wakeup) im Verzeichnis /etc/. Nun müssten Sie eigentlich einen Neustart machen, damit das StartupItem sleepwatcher mit den richtigen Einstellungen startet. Ich kürze das hier aber folgendermaßen ab: Wechseln Sie in das Verzeichnis /Library/StartupItems/ und öffnen Sie den Ordner SleepWatcher. Doppelklicken Sie die Unix-Datei SleepWatcher. Ein Terminalfenster mit Statusmeldungen öffnet sich, welches Sie gleich wieder schließen können. Als Nächstes testen Sie einmal, ob sleepwatcher auch aktiv ist, indem Sie den Rechner mittels sleepwatcher in den Ruhezustand versetzen. Also bitte nicht erschrecken, wenn gleich der Bildschirm dunkel wird. Drücken Sie dann eine beliebige Taste, um ihn aus dem Ruhezustand wieder aufzuwecken. Geben Sie folgenden Befehl im Terminal ein und bestätigen Sie ihn mit der Taste Enter: /usr/local/sbin/sleepwatcher –n Der Rechner geht in den Ruhzustand über. Wie Sie sehen, müssen Sie den vollständigen Pfad zu dem Befehl angeben, da er standardmäßig nicht in der Umgebungsvariable path steht. Wenn soweit alles geklappt hat, kann es nun daran gehen, ein Appleskript anzuhängen. Da sleepwatcher ein Terminalbefehl ist, müssen Sie das Appleskript als Shell-Skript verpacken. Das geht unter Leopard recht einfach (siehe auch Kapitel Unix). 1. Öffnen Sie in TextEdit eine neue Datei. 2. Da ein Shell-Script nicht als formatierter Text gespeichert werden darf, wählen Sie Format / In reinen Text umwandeln.
679
SmartBooks
AppleScript
3. Schreiben Sie folgende zwei Zeilen in die Datei: #!/usr/bin/osascript say "Goodbye!" Das Appleskript gibt nur eine akustische Rückmeldung, um zu erkennen, ob das Skript auch ausgeführt wurde. Die erste Zeile ist die sogenannte Shebang-Zeile, die angibt, mit welchem Interpreter die folgende Anweisung ausgeführt werden soll. Für AppleScript muss osascript verwendet werden. Sie schreiben hier also ein Appleskript in einer Textdatei, welches später vom Terminal ausgeführt wird und nicht vom Skripteditor. 4. Wählen Sie Sichern im Ablage-Menü. 5. Geben Sie dem Skript den Namen goodbye und wählen Sie die oberste Ebene Ihres Heimatordners als Speicherort aus. 6. Entfernen Sie den Haken bei .txt verwenden, falls kein Suffix angegeben ist. 7. Wählen Sie als Codierung Unicode (UTF-8) und klicken Sie auf Sichern. 8. Schließen Sie die Datei in TextEdit. 9. Öffnen Sie das Terminal (im Ordner /Programme/Dienstprogramme/). 10. Schreiben Sie in das Terminal: chmod +x 11. Fügen Sie eine Leerstelle hinter dem x an und ziehen Sie die Datei goodbye vom Heimordner hinter die Leerstelle nach dem x. Lassen Sie die Datei dann los. Der Pfad zu der Datei wird eingefügt. Der Befehl wird nun so aussehen wie in der folgenden Zeile, nur dass bei Ihnen natürlich an zweiter Stelle Ihr eigener Benutzername steht. chmod +x /Users/Detlef/goodbye 12. Bestätigen Sie den Befehl mit der Enter- oder Return-Taste. 13. Die Datei goodbye in Ihrem Heimordner erhält nun ein neues Icon. Das Symbol eines grauen Bildschirms, auf dem in grüner Schrift exec steht. Dies ist das Symbol für ausführbare Unix-Dateien. 14. Doppelklicken Sie die Datei goodbye. Ein Terminalfenster mit Statusmeldungen öffnet sich, und eine Stimme sagt Ihnen auf Englisch »Auf Wiedersehen«. Damit haben Sie das Skript erfolgreich getestet. Das Terminalfenster können Sie dann wieder schließen. Nun müssen Sie sleepwatcher noch sagen, dass diese Datei vor dem Ruhezustand des Rechners ausgeführt werden soll.
680
Von der Kunst, ein AppleScript zu starten
Kapitel 6
15. Wechseln Sie in das Verzeichnis /etc/. Da dieses Verzeichnis im Finder nicht sichtbar ist, müssen Sie über das Menü Gehe zu | Gehe zum Ordner dorthin navigieren. Geben Sie dort als Pfad /etc ein und bestätigen Sie. In diesem Verzeichnis finden Sie das Shellskript rc.sleep. Dieses Skript gibt an, welche Datei vor Eintreten des Ruhezustands ausgeführt werden soll. 16. Sichern Sie zuerst eine Kopie von rc.sleep in Ihrem Heimverzeichnis als Sicherungskopie. Damit können Sie dann die nachfolgenden Änderungen leicht wieder rückgängig machen. 17. Ziehen Sie nun mit gedrückter [alt]-Taste eine Kopie von rc.sleep auf den Schreibtisch. 18. Ziehen Sie die Datei rc.sleep auf dem Schreibtisch mit der Maus auf das Symbol von TextEdit im Dock oder auf dessen Icon im Programmordner, um es zu öffnen. In dieser Datei finden Sie in der Mitte folgende drei Zeilen: if [ -x "$home/.sleep" ]; then logger -t $0 "executing .sleep of user $user" su - $user -c "$home/.sleep" Diese Zeilen geben an, welche Datei vor dem Ruhezustand ausgeführt wird. Hier ist es eine Datei mit dem Namen .sleep. Wegen des vorangehenden Punktes ist diese Datei unsichtbar. In der ersten Zeile wird zuerst geprüft, ob die Datei in Ihrem Heimverzeichnis existiert. Wenn sie nicht existiert, wird also auch nichts gemacht. Da ich in diesem Beispiel die Arbeit mit unsichtbaren Dateien vermeiden möchte, müssen Sie hier noch den Namen des Skripts ändern. 19. Ersetzen Sie in allen drei Zeilen .sleep durch goodbye. Die Zeilen sollten danach so aussehen: if [ -x "$home/goodbye" ]; then logger -t $0 "executing goodbye of user $user" su - $user -c "$home/goodbye" 20. Speichern Sie. 21. Ziehen Sie die Datei vom Schreibtisch in den Ordner /etc und bestätigen Sie, dass Sie die vorhandene Datei überschreiben wollen. Falls Sie keine Administratorrechte haben, geben Sie bitte ein Administrator-Passwort ein. Damit ist alles eingerichtet und fertig für einen Test. 22. Wählen Sie im Apfel-Menü Ruhezustand aus. Sie hören den Abschiedsgruss, und der Mac geht schlafen. Ein Druck auf eine Taste, und er wacht wieder auf. Analog zu dieser Beschreibung können Sie auch ein Skript nach dem Aufwachen ausführen lassen, indem Sie das Skript rc.wake anpassen.
681
SmartBooks
AppleScript
Bildschirmschoner Um ein Skript beim Start oder Ende des Bildschirmschoners auszuführen, brauchen Sie ein externes Hilfsmittel. Bisher ist mir nur der ScriptSaver des findigen Entwicklers Matt Swann bekannt.
ScriptSaver Der ScriptSaver ist selbst ein Bildschirmschoner und unter http://swannman.wordpress.com/projects/scriptsaver/ zu beziehen. Der ScriptSaver ist frei und der Source-Code ist im Download enthalten. Wenn Sie das Zip-Archiv geladen und entpackt haben, finden Sie darin zum einen die Bedienungsanleitung in der Read-Me-Datei, und zum anderen ein Beispiel-Appleskript namens Log Out.scpt und den Bildschirmschoner selbst mit dem Namen ScriptSaver.saver. 1. Kopieren Sie diesen Bildschirmschoner in den Ordner Screen Savers eines LibraryOrdners. Entweder in Ihrem Heimverzeichnis, oder, wenn er für alle Benutzer verwendet werden soll, in den Library-Ordner auf der Root-Ebene des Startvolumes. 2. Danach können Sie in die Systemeinstellungen gehen und dort die Tafel Schreibtisch & Bildschirmschoner aufrufen und auf Bildschirmschoner klicken. 3. Auf der linken Seite finden Sie ganz am Ende der Liste unter dem Eintrag Andere den Bildschirmschoner ScriptSaver. Wählen Sie ihn aus und klicken Sie auf Optionen. Die Einstellungen für den ScriptSaver öffnen sich.
Abb. 6-34 Die Einstellungen für den ScriptSaver
682
Von der Kunst, ein AppleScript zu starten
Kapitel 6
Jetzt brauchen Sie noch ein sinnvolles Skript. Hier ein kleines Mini-Skript für iChat. Es setzt Ihren Status auf Abwesend, bevor sich der Bildschirmschoner aktiviert. Das ist flexibler als die 15-Minuten-Einstellung in iChat. Dadurch können Sie mit der Anzeige des Bildschirmschoners einstellen, ab wann Sie als abwesend gelten möchten und, wenn Sie eine aktive Ecke für den Bildschirmschoner festgelegt haben, diesen auch jederzeit manuell aufrufen. tell application "iChat" set status to away say "I'm gone" end tell 4. Schreiben Sie es in den Skripteditor und sichern Sie es ganz normal als Skript mit der Endung scpt, zum Beispiel mit dem Namen iChat_away.scpt. 5. Schreiben Sie das folgende zweite Skript mit dem Namen iChat_available.scpt. Dieses Skript wird verwendet, um nach dem Aufwachen aus dem Bildschirmschoner den Status wieder auf Anwesend zu setzen. tell application "iChat" set status to available say "Back again" end tell Da man bei aktiviertem Bildschirmschoner nicht sehen kann, ob der Status von iChat auch wirklich abgeschaltet wird, sollten Sie beide Skripts auch aus dem Skripteditor heraus testen und dabei den Status in iChat beobachten. Wählen Sie nun in der Optionen-Tafel von ScriptSaver diese beiden Skripts aus: Oben, unter Activation Script, das Skript, welches den Status auf Abwesend setzt, und unten, unter Deactivation Script, das Skript, welches Ihren Status wieder auf Anwesend setzt. Zum Testen habe ich in beiden Skripts noch eine Ansage mit say dazugepackt, damit Sie auch hören können, dass das Skript tatsächlich ausgelöst wurde. Bestätigen Sie die Einstellungen von ScriptSaver und klicken Sie anschließend auf Testen. Der Bildschirmschoner wird aktiviert, und eine Stimme sagt »I’m gone«. Bewegen Sie die Maus oder drücken Sie eine Taste, der Bildschirmschoner wird deaktiviert, und die Ansage »Back again« erfolgt.
683
SmartBooks
AppleScript
Mailregeln Das Programm Mail ist wie iCal eines der Programme, welches ein Appleskript starten kann, und zwar beim Eintreffen einer E-Mail. Alles, was Sie dafür in Mail machen müssen, ist, eine Regel einzurichten und natürlich ein Appleskript zu schreiben. Das folgende Beispiel macht nichts anderes, als jede ankommende E-Mail darauf hin zu überprüfen, ob deren Absender in Ihrem Adressbuch vorkommt. Wenn ja, werden Sie mit say auf deren Eingang hingewiesen. So werden Sie schnell über private E-Mails von Personen aus Ihrem Adressbuch informiert – und nur über Mails von diesen. Alle WerbeE-Mails, Listen oder Newsletter bleiben damit unberücksichtigt, und Sie können ruhig weiterarbeiten. Falls Sie bei einem wichtigen Absender auf eingehende E-Mails hingewiesen werden wollen, brauchen Sie nur dessen E-Mail-Adresse im Adressbuch einzutragen – oder umgekehrt. Das Skript sieht so aus: using terms from application "Mail" on perform mail action with messages theMessages for rule theRule tell application "Mail" repeat with eachMessage in theMessages set theSender to sender of eachMessage say "Message received from " & theSender end repeat end tell end perform mail action with messages end using terms from Der Trick ist hier der sogenannte Handler perform mail action. Mit diesem können Sie auf das Ergebnis einer Regel zugreifen. Wenn Sie sich mehr dafür interessieren, schauen Sie sich die Beispielskripts bei den Computerskripts im Skriptmenü an (Mail Scripts | Rule Actions). Die Zeile using terms ist nötig, damit der Handler in der nachfolgenden Zeile nicht als ein selbst definierter Handler missverstanden wird, sondern als einer, der zum Funktionsverzeichnis von Mail gehört. In der Mitte des tell-Bereichs finden Sie das eigentliche Skript. Hier wird in einer repeatSchleife der Absender jeder angekommenen E-Mail aus der Nachricht extrahiert und dann mit "Message received from " & theSender vorgelesen. 1. Sichern Sie das Skript im Format Skript an einem beliebigen Ort und richten Sie dann in Mail eine Regel wie in folgender Abbildung ein. Die Mailregeln finden Sie unter Mail | Einstellungen und dann im Reiter Regeln.
684
Von der Kunst, ein AppleScript zu starten
Kapitel 6
Abb. 6-35 Eine E-Mail-Regel, die ein Appleskript ausführt 2. Wählen Sie als Regel Absender ist im Adressbuch. 3. Bei Folgende Aktionen durchführen müssen Sie AppleScript ausführen auswählen und dann rechts davon über den Knopf Auswählen das eben angelegte Skript anhängen. 4. Mit einem Klick auf OK ist die Regel ab sofort aktiv. 5. Schicken Sie sich dann zum Testen einfach selbst einmal eine E-Mail. 6. Warten Sie etwas und holen Sie dann Ihre E-Mails ab. Wenn Ihre E-Mail eintrifft, wird eine Stimme sagen »Message received from…« und dann Ihren Namen und Ihre E-Mail-Adresse nennen. (Unter der Annahme, dass Sie selbst und die verwendete E-Mail-Adresse natürlich in Ihrem eigenen Adressbuch stehen.)
Ordneraktionen Ordneraktionen sind bereits ein altes Thema in AppleScript. Es gab sie schon seit klassischen Zeiten. Aufgrund ihrer Komplexität und Vielseitigkeit finden Sie zu diesem Thema einen eigenen Abschnitt in Kapitel 4. Bei einer Ordneraktion wird einem Ordner im Finder einfach ein Skript angehängt. Dieses Skript wird dann bei bestimmten Aktionen in oder an diesem Ordner ausgelöst, wie bei einer Mausefalle. Mit Ordneraktionen lässt sich ein Appleskript bei folgenden Ereignissen auslösen: << Eine Datei wird dem Ordner hinzugefügt. << Eine Datei wird aus dem Ordner entfernt. << Der Ordner wird geöffnet. << Der Ordner wird geschlossen. << Das Ordnerfenster des geöffneten Ordners wird bewegt oder in seiner Größe verändert.
685
SmartBooks
AppleScript
Ordneraktionen waren früher nicht besonders zuverlässig, da sich der Finder darum kümmerte, und der war etwas schläfrig und bekam nicht immer alles mit. Inzwischen kümmert sich launchd um die Ausführung, was die Zuverlässigkeit deutlich verbessern sollte.
launchd und WatchPaths Statt die Ordneraktionen des Finders zu verwenden, können Sie auch direkt launchd verwenden. launchd kennt die Schlüssel WatchPaths und QueueDirectories, die dafür sorgen, dass ein Job gestartet wird, wenn sich an den angegebenen Pfaden etwas ändern sollte. WatchPaths ist vor allem für Dateien gedacht, QueueDirectories versteht sich nur auf Ordner. WatchPaths benötigt als Wert einen array mit strings. Bei den strings muss es sich um die zu überwachenden Pfade handeln. Beachten Sie auch die grundlegende Beschreibung der Funktionsweise von launchd einige Seiten zuvor unter launchd Einführung. Das folgende Beispiel führt mit dem Befehl osascript einen kleinen say-Befehl aus. 1. Erstellen Sie mit TextEdit auf dem Schreibtisch eine leere Textdatei mit dem Namen test.rtf. 2. Erstellen Sie dann mit dem Property List Editor einen LaunchAgent entsprechend der folgenden Abbildung.
Abb. 6-36 Ein LaunchAgent für eine zu überwachende Datei 3. Speichern Sie den LaunchAgent als launchdSample5.xml unter ~/Library/LaunchAgents/ ab. 4. Aktivieren Sie den LaunchAgent im Terminal: launchctl load -w /Users/Detlef/Library/LaunchAgents/launchdSample5.xml Natürlich müssen Sie dabei Ihr eigenes Heimverzeichnis angeben.
686
Von der Kunst, ein AppleScript zu starten
Kapitel 6
So, jetzt können Sie ausprobieren, ob es funktioniert. Öffnen Sie die Textdatei, schreiben Sie etwas hinein, Sichern Sie die Datei und schließen Sie sie wieder. Nach kurzer Zeit ertönt das »Hey! What are you doing?«, da sich das Änderungsdatum der Datei geändert hat. Das funktioniert auch, wenn Sie die Datei in einen anderen Ordner verschieben. Wenn Sie die Datei dann aber von diesem Ordner in wiederum einen anderen Ordner verschieben, funktioniert es nicht mehr, da der Pfad nicht nachgehalten wird. Wenn Sie die Datei aber wieder auf ihren ursprünglichen Platz schieben, wird der Befehl erneut ausgeführt. Um den Agenten nach dem Test wieder zu deaktivieren, geben Sie bitte folgenden Befehl mit Ihrem eigenen Pfad ins Terminal ein: launchctl unload -w /Users/Detlef/Library/LaunchAgents/launchdSample5.xml Da es sich bei WatchPaths um ein array handelt, können Sie natürlich auch gleich eine ganze Reihe von Dateien oder Ordnern angeben.
launchd und QueueDirectories Mit dem Key QueueDirectories von launchd können Sie ebenfalls einen Pfad auf Veränderungen überwachen. Im Gegensatz zu WatchPaths wird QueueDirectories aber nur ausgelöst, wenn es sich bei dem Pfad um einen nicht-leeren Ordner handelt. Bei der Verwendung im Finder gibt es allerdings ein Problem: Der Finder legt in jeden Ordner, in dem Sie etwas hineinlegen oder den Sie öffnen, auch immer eine unsichtbare Datei mit dem Namen .DSStore ab, die jedes Mal den LaunchAgent startet. Auch Spotlight legt gerne unsichtbare Dateien an. Diese unsichtbaren Dateien müssen also beseitigt werden. Hieran erkennen Sie, dass QueueDirectories eher für den Unix-Unterbau von Mac OS X gedacht ist und nicht für die Arbeit im Finder mit AppleScript. Trotzdem kann man sich damit arrangieren und die unsichtbaren Dateien einfach hartnäckig immer wieder entfernen. Wenn man den Ordner dann noch an einen ausgeblendeten Ort im Unix-Bereich von Mac OS X legt, zum Beispiel unter /private/, vermeidet man von vornherein einen regen Finder-Zugriff. Hier ein kleines Beispiel, um die Funktionsweise zu verdeutlichen: 1. Erstellen Sie einen Ordner mit dem Namen Drehscheibe auf dem Schreibtisch. 2. Erstellen Sie mit dem Property List Editor einen LaunchAgent gemäß folgender Abbildung:
687
SmartBooks
AppleScript
Abb. 6-37 Ein LaunchAgent für ein QueueDirectory 3. Speichern Sie den LaunchAgent als launchdSample6.xml unter ~/Library/LaunchAgents/ ab. 4. Erstellen Sie mit dem Skripteditor folgendes Skript und speichern Sie es als Programm mit dem Namen drehscheibe.app. Legen Sie es neben dem Order Drehscheibe auf den Schreibtisch. tell application "System Events" set theOrigin to alias "/Users/Detlef/Desktop/Drehscheibe/" set theDestination to alias "/Users/Detlef/Documents/Projekte/Archiv/" delete (every file of theOrigin whose visible is false) move every file of theOrigin to theDestination delete (every file of theOrigin whose visible is false) say "Moving" end tell Dieses Skript macht nichts anderes, als alle Dateien in den Ordner Archiv im Ordner Projekte weiter zu schieben, stellt also so etwas wie eine Drehtür dar. Natürlich könnte der Ordner genauso gut auch auf einer anderen Festplatte oder auf einem Laufwerk im Netz liegen. Geben Sie hier für die Variable theDestination einen beliebigen existierenden Ort an. Damit die unsichtbaren Dateien den LaunchAgent nicht ständig aktivieren, werden in dem Skript am Anfang und am Ende alle unsichtbaren Dateien gelöscht. Das Skript enthält natürlich noch keine Fehlerbehandlung, für den Fall, dass am Zielort bereits eine Datei mit demselben Namen existiert. Der dabei entstehende Fehler sollte natürlich noch abgefangen werden, um dann zum Beispiel dem Namen der Datei noch eine Zufallszahl anzuhängen. In jedem Fall muss der Ordner am Ende wieder leer sein! Nun können Sie den LaunchAgent mit launchctl starten: launchctl load -w /Users/Detlef/Library/LaunchAgents/launchdSample6.xml Eventuell startet das Skript direkt, falls der Finder schon seine .DSStore darin abgelegt hat. Da die Datei aber unsichtbar ist, wird sie vom Skript sofort gelöscht.
688
Von der Kunst, ein AppleScript zu starten
Kapitel 6
Schieben Sie nun ein paar Dateien in den Ordner. Die Ansage »Moving« ertönt, und wenn Sie nachschauen, ist der Ordner nun leer und alle Dateien sind im Zielordner verschoben worden. Durch das Nachschauen wird der Agent eventuell gleich noch mal aufgerufen und entfernt die unsichtbare Datei gleich wieder. Deaktivieren Sie den LaunchAgent wieder mit: launchctl unload -w /Users/Detlef/Library/LaunchAgents/launchdSample6.xml Da der Finder ab und zu unsichtbare Dateien in den überwachten Ordner ablegt, kommt es schon mal zu »Fehlauslösungen«, die aber gewollt sind und nicht weiter stören (wenn man das say nach dem Test wieder aus dem Skript herausnimmt), da diese schnell wieder gelöscht werden. Wenn Sie jetzt noch das Skript als Programm-Bundle speichern und den Schlüssel LSBackgroundOnly in seiner info.plist setzen, dann läuft das Skript auch noch unsichtbar im Hintergrund. Siehe Skriptwächter als Hintergrundprozess.
Einlegen einer CD oder DVD und das Digital Hub Scripting In den Systemeinstellungen können Sie bekanntlich unter CDs & DVDs ein Programm angeben, welches beim Öffnen einer bestimmten Art von CDs oder DVDs gestartet wird. Genau hier haben Sie auch die Möglichkeit, statt eines Programms den Eintrag Skript ausführen auszuwählen. Das Skript muss dabei nicht als Programm abgespeichert werden, es reicht, wenn es im Format Skript vorliegt.
Abb. 6-38 Die Systemeinstellung CDs & DVDs kann ein Skript starten, wenn eine bestimmte Art von CD eingelegt wird. Diese Systemeinstellung lässt sich auch über die Suite CD and DVD Preferences Suite im Funktionsverzeichnis der System Events skripten.
689
SmartBooks
AppleScript
Damit ein von Ihnen erstelltes Skript auch erfährt, welche Disk denn nun gerade eingelegt wurde, gibt es die Skripterweiterung Digital Hub Scripting. Im Funktionsverzeichnis dieser Erweiterung sind fünf Handler definiert. Die Handler lauten: << music CD appeared file << picture CD appeared file << video DVD appeared file << blank CD appeared text << blank DVD appeared text Dort wo file steht, wird der Name der disk zurückgeliefert. Dort wo text steht, wird der unix device identifier für diese disk abgeliefert. So kann ein Skript zum Beispiel folgenden Handler enthalten: on music CD appeared theDisk display dialog "CD " & theDisk as text & " ist da!" tell application "Finder" set theFiles to every file of disk theDisk -- Weitere Befehle eject disk theDisk -- CD wieder auswerfen end tell end music CD appeared Wenn Sie dieses Skript in den Systemeinstellungen CDs & DVDs als Aktion für das Einlegen einer Musik-CD auswählen, dann wird der Name der eingelegten CD im Skript im Parameter theDisk abgelegt, und Sie können darüber dann direkt auf den Inhalt der CD zugreifen. Im Beispiel werden mit every file of disk theDisk alle Dateien der obersten Ebene der CD in eine Variable gepackt und lassen sich dann leicht in einer Schleife abarbeiten. Mit dem eject-Befehl kann man anschließend die disk auch gleich wieder auswerfen.
Einbinden eines Laufwerks und launchd Wenn es um das Einbinden eines Laufwerks geht, also nicht nur um CDs oder DVDs, bietet sich wieder launchd als Helfer an. launchd kennt den Schlüssel StartOnMount. Dieser Schlüssel braucht nur einen booleschen Wert. Wenn dieser auf true steht, also im Property List Editor einen Haken hat, dann wird die Aktion ausgeführt, sobald ein neues Laufwerk eingebunden wird. Der Vorteil dabei ist, dass es nicht nur mit CDs oder DVDs funktioniert, sondern für alle Laufwerke, selbst virtuelle wie zum Beispiel DMG-Dateien.
690
Von der Kunst, ein AppleScript zu starten
Kapitel 6
Auch hier braucht man zuerst einmal wieder ein LaunchAgent. Erstellen Sie diesen mit dem Property List Editor anhand der folgenden Abbildung. Beachten Sie dazu die ausführliche Einweisung in launchd unter launchd Einführung weiter vorne. Speichern Sie den Agenten dann als launchdSample7.xml unter ~/Library/LaunchAgents/ ab.
Abb. 6-39 Ein LaunchAgent, der beim Einbinden eines Laufwerks aktiv wird Jetzt muss man im Skript nur noch herausfinden, welche disk denn gerade eingebunden wurde. Der Finder packt das zuletzt eingebundene Laufwerk in der Liste von every disk zum Glück immer an den Schluss der Liste, und auch der Index der disk wird hochgezählt. Ich verwende daher den letzten Eintrag in der Liste der disks des Finders. Bei meinen Tests hat das zuverlässig funktioniert, ansonsten sollten die einzelnen disks, die mit get every disk ermittelt werden, noch genauer untersucht werden (Propertys der Disk). Erstellen Sie dann folgendes Skript und legen Sie es als Programm mit dem Namen listfiles. app auf dem Schreibtisch ab. tell application "Finder" set theDisk to last item of (get every disk) set theFiles to every file of theDisk say "Disk " & name of theDisk & " is mounted" repeat with i in theFiles --mach was end repeat --eject theDisk -- zum Auswerfen, wenn gewünscht end tell Dann können Sie jetzt den LaunchAgent im Terminal aktivieren: launchctl load -w /Users/Detlef/Library/LaunchAgents/launchdSample7.xml Legen Sie jetzt eine CD ein, schließen Sie einen USB-Stick an oder doppelklicken Sie eine DMG-Datei. Der LaunchAgent meldet sich mit seiner Stimme und sagt Ihnen, welches Laufwerk eingebunden wurde.
691
SmartBooks
AppleScript
Um den LaunchAgent wieder zu deaktivieren, bitte Folgendes im Terminal eingeben: launchctl unload -w /Users/Detlef/Library/LaunchAgents/launchdSample7.xml Tipp Eine Alternative zu launchd stellt noch das Programm Do Something When (DSW) von http://www.azarhi.com/Projects/DSW/ dar. Es handelt sich um eine Systemeinstellung, die alle Laufwerke überwacht und sowohl beim Einbinden als auch beim Auswerfen aktiv werden kann, um zum Beispiel ein Programm oder Applet zu starten
Eigenen Skriptwächter Ereignisse beobachten lassen Falls Sie ein Appleskript automatisch bei einem Ereignis ausführen möchten, welches hier bisher nicht behandelt wurde, haben Sie immer noch die Möglichkeit, sich einen »Wächter« in AppleScript selbst zu schreiben. Das ist nichts anderes als ein Appleskript, welches zum Beispiel beim Anmelden automatisch gestartet wird und im Hintergrund geöffnet bleibt, um dann kontinuierlich zu überprüfen, ob ein bestimmtes Ereignis eingetreten ist. Das geht natürlich nur, wenn das Ereignis irgendwie mit Apple-Events zu tun hat. Einen Unix-Daemon, der keine Apple-Events sendet, werden Sie damit also nicht überwachen können. Dafür müssten Sie dann ebenfalls auf die Unix-Ebene hinuntersteigen. Im Folgenden zeige ich ein Beispiel für einen einfachen AppleScript-Wächter. Er ist im Prinzip genauso aufgebaut wie der bereits vorgestellte Tea-Timer. Diesmal wird jedoch nicht die Zeit abgefragt, sondern welcher Song gerade in iTunes gespielt wird. Fügen Sie im Code noch an die Stelle zwischen den Anführungszeichen bei "UnerwuenschterInterpret" den Namen eines Interpreten ein, den Sie jetzt nicht hören wollen. Wird dieser Interpret dann in iTunes gespielt, so wird ein Ausruf der Ablehnung hervorgestoßen ("Oh no, no, no!"), die Lautstärke auf 20 Prozent heruntergesetzt und der Titel übersprungen. An der Stelle zwischen den Anführungszeichen bei "ErwuenschterInterpret" müssen Sie dann noch den Namen eines Interpreten einfügen, den Sie gerne mit voller Lautstärke hören möchten. Läuft ein Stück von diesem Interpreten, wird ein Ausruf der Zustimmung hörbar ("Yeah! More of it!"), und die Lautstärke auf 100 Prozent gesetzt. Hervorragend funktionieren tut das natürlich im zufälligen Abspielmodus.
692
Von der Kunst, ein AppleScript zu starten
Kapitel 6
Hier das Skript: property sameTrack : true property lastTrack : {} on idle tell application "iTunes" if player state is playing and sameTrack is true then set thisTrack to current track set lastTrack to current track set sameTrack to false --Ablehnen, Lautstärke runtersetzen und überspringen if artist of thisTrack is "UnerwuenschterInterpret" then set sound volume to 20 say "Oh no, no, no!" next track end if --Zustimmen und Lautstärke auf Maximum if artist of thisTrack is "ErwuenschterInterpret" then say "Yeah! More of it!" set sound volume to 100 end if end if -- Prüfen ob sich der Titel inzwischen geändert hat if player state is playing and sameTrack is false then set thisTrack to current track if thisTrack is not lastTrack then set sameTrack to true end if end if end tell return 5 -- Wartezeit in Sekunden bis zur nächsten Prüfung end idle on quit set sameTrack to true set lastTrack to {} continue quit end quit Sichern Sie das obige Skript im Skripteditor als Programm mit der Option Nicht automatisch beenden.
693
SmartBooks
AppleScript
Starten Sie iTunes und dann das Skriptprogramm. Nun spielen Sie einfach mal ein paar Lieder von den beiden Interpreten. Sie werden sehen, je nachdem, welcher der beiden Interpreten gespielt wird, wird entweder die Lautstärke herunter gesetzt und gleich zum nächsten Song gesprungen oder die Lautstärke wird hoch gesetzt und der Song spielt bis zum Ende durch. Basis ist auch hier wieder der idle-Handler, der kontinuierlich, hier alle 5 Sekunden, überprüft, ob sich der Song geändert hat. Wenn ja, wird die Prüfung auf den Interpretennamen erneut gestartet. Mit den Hinweisen im Kapitel Skriptwächter als Hintergrundprozess können Sie das Skript natürlich auch noch als Hintergrundprozess laufen lassen, so dass es nicht aus Versehen beendet werden kann.
Aktionen im Benutzerinterface Eine ganz ausgefuchste Art, ein Appleskript zu starten, bietet Prefab (http://prefabsoftware.com), der Hersteller des für das GUI-Scripting unverzichtbaren UI Element Inspectors (siehe Kapitel GUI-Scripting) mit den Prefab UI Actions an. So wie Sie mit dem UI Element Inspector herausfinden können, wie Sie mit GUI-Scripting das Benutzerinterface von OS X skripten können, so können Sie mit den UI Actions an jedes der Benutzerelemente auch ein Appleskript anhängen. So können Sie zum Beispiel, immer wenn ein Menübefehl in einem Programm ausgewählt wird, stattdessen Ihr eigenes Skript ausführen lassen. Da Sie damit ein Programm auch leicht in seiner Funktionalität beeinträchtigen oder sogar unbrauchbar machen können, ist diese Software mit Vorsicht zu handhaben, und kostenlos ist sie natürlich auch nicht. Falls Sie genau nach so etwas suchen, schauen Sie mal beim Hersteller vorbei und laden Sie die Software mit den zahlreichen Beispielskripts und der englischen Dokumentation herunter. Sie können das Programm 30 Tage lang testen.
AppleScript URLs Vielleicht sind Sie diesen Links schon mal auf einer Webseite begegnet. Apple verwendet diese etwa für seine Beispiele unter http://www.apple.com/applescript/sbrt/index.html. Wenn Sie dort bei einem der Skripts auf das AppleScript-Symbol klicken, öffnet sich das Skript im Skripteditor, und zwar in unkompilierter Form. Der Trick liegt darin, dass der Appleskript-Code im Link URL-kodiert vorliegt.
694
Von der Kunst, ein AppleScript zu starten
Kapitel 6
Die Syntax für das nötige -Attribut in HTML sieht wie folgt aus: Hier klicken Der Beginn lautet applescript://com.apple.scripteditor?. Damit wird der Skripteditor anhand seines Bundle Identifiers als Ziel zum Öffnen dieses Links bestimmt. Auch wenn es so aussieht, Sie können hier aus Sicherheitsgründen keinen Bundle Identifier eines anderen Programms angeben. Als Nächstes kommt die action. Diese bestimmt, wie das folgende Skript im Skripteditor eingefügt wird. Zur Verfügung stehen folgende Möglichkeiten: << action=new&
Fügt das Skript in einem neuen Fenster ein.
<< action=insert&
Fügt das Skript an der Einfügemarke ein.
<< action=append&
Fügt das Skript am Ende des aktuellen Skripts an.
Wenn kein Skript geöffnet ist, verhalten sich alle gleich. Es wird ein neues Fenster im Skripteditor geöffnet und das Skript als Text eingefügt. Der letzte Teil bestimmt das Skript selbst: script=say%20%22Hello%22 Hier ist zu beachten, dass der gesamte Text des Skripts URL-kodiert werden muss, das heißt, dass zum Beispiel alle Leerstellen mit %20 und alle Anführungszeichen mit %22 kodiert werden müssen. Um sicher zu gehen, sollten Sie generell alle Zeichen über ASCII 128 für den Link kodieren. Das Skript im obigen Link steht also für den AppleScript-Code: say "Hello" Da es ziemlich aufwendig sein kann, ein ganzes Skript von Hand zu kodieren, empfiehlt sich der Einsatz einer Routine, wie sie zum Beispiel auf der Webseite von Apple unter http://www.apple.com/applescript/sbrt/sbrt-08.html zu finden ist. Angenommen, Sie haben folgendes Skript im Skripteditor geschrieben und geöffnet: tell application "Finder" set myWindow to make new Finder window tell myWindow set current view to list view set collapsed to true end tell end tell 695
SmartBooks
AppleScript
Nun möchten Sie dieses Skript für einen Link kodieren. Lassen Sie es dann in seinem Fenster geöffnet, erstellen Sie ein neues Skript, kopieren Sie die zwei Handler von Apple hinein und erweitern Sie diese beiden Handler so, dass am Ende folgendes Skript dabei herauskommt: property scriptWindow : "test.scpt" tell application "Skripteditor" set encText to contents of document scriptWindow end tell set encText to encode_text(encText, true, true) set the clipboard to encText on encode_char(this_char) -- Handler ist ein Beispiel von Apple set the ASCII_num to (the ASCII number this_char) set the hex_list to {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"} set x to item ((ASCII_num div 16) + 1) of the hex_list set y to item ((ASCII_num mod 16) + 1) of the hex_list return ("%" & x & y) as string end encode_char on encode_text(this_text, encode_URL_A, encode_URL_B) -- Beispiel von Apple set the standard_characters to "abcdefghijklmnopqrstuvwxyz0123456789" set the URL_A_chars to "$+!'/?;&@=#%><{}[]\"~`^\\|*" set the URL_B_chars to ".-_:" set the acceptable_characters to the standard_characters if encode_URL_A is false then set the acceptable_characters to the acceptable_characters & the URL_A_chars if encode_URL_B is false then set the acceptable_characters to the acceptable_characters & the URL_B_chars set the encoded_text to "" repeat with this_char in this_text if this_char is in the acceptable_characters then set the encoded_text to (the encoded_text & this_char) else set the encoded_text to (the encoded_text & encode_char(this_char)) as string end if end repeat return the encoded_text end encode_text
696
Von der Kunst, ein AppleScript zu starten
Kapitel 6
Der einzige von mir hinzugefügte Code sind die sechs Zeilen am Anfang vor den beiden Handlern von Apple. Hier wird einfach nur der Code im Skripteditor mit dem Fensternamen test.scpt in die Variable encText gepackt, welche dann kodiert und in die Zwischenablage eingefügt wird. Sie brauchen bei diesem Code also nur den Fensternamen in der Property zu ändern, wenn ein anderes Skript kodiert werden soll. Wenn Sie nun die Zwischenablage in einem Textprogramm einfügen, erhalten Sie folgenden kodierten Text den Sie als Argument für script in den Link einfügen können: tell%20application%20%22Finder%22%0D%09set%20myWindow%20to%20make%20 new%20Finder%20window%0D%09tell%20myWindow%0D%09%09set%20current%20 view%20to%20list%20view%0D%09%09set%20collapsed%20to%20true%0D%09end%20 tell%0Dend%20tell Schreiben Sie dann in TextEdit in einem reinen Textdokument (Format | In reinen Text umwandeln) den Link auf folgende Art, mit stark vereinfachter HTML-Struktur und speichern Sie das Dokument als test.html auf dem Schreibtisch. Hier klicken Markieren Sie die drei x mit der Maus und fügen Sie über [Befehl]+[V] die Zwischenablage mit dem kodierten Skript ein. Das Endergebnis sieht dann so aus: Hier klicken Öffnen Sie dieses Dokument nun mit Safari und klicken Sie auf den Link. Der Code wird im Skripteditor in einem neuen Fenster eingefügt. Natürlich lässt sich das noch erweitern und anpassen, um zum Beispiel ein Droplet daraus zu machen. Bezüglich der Handler in obigem Skript beachten Sie bitte die Hinweise auf der Webseite von Apple mit der Beschreibung der Parameter.
697
SmartBooks
AppleScript
Aufgepasst Wenn unbekannte Webseiten solche Links anbieten, sollten Sie sehr vorsichtig sein und nicht gleich jedes Skript, das Sie so in den Skripteditor eingefügt haben, auf gut Glück ausprobieren. Das gilt natürlich generell für alle Skripts, die Sie aus dem Internet beziehen. Nicht jeder muss es gut meinen mit Ihnen. Studieren Sie das Skript aufmerksam und führen Sie es nicht aus, wenn Sie den Verdacht haben, dass es Schaden anrichten könnte oder sogar genau dafür erstellt wurde. Wenn in dem Skript auch noch ein do shell script vorkommt, ist erhöhte Vorsicht geraten. Nehmen Sie das Skript dann besser auseinander, studieren Sie die Elemente und Befehle darin einzeln und schlagen Sie sie in diesem Buch, dem Funktionsverzeichnis der Anwendung, dem Internet oder den man-Seiten im Terminal nach, bis Sie verstanden haben, was das Skript macht und wie es funktioniert. Vorher sollten Sie im Skripteditor niemals auf den Ausführen-Knopf drücken.
698
GUI-Scripting
7
In diesem Kapitel wird darauf eingegangen, wie man mit AppleScript auf die Elemente der grafischen Benutzerschnittstelle (graphical user interface – GUI) zugreifen kann. Nützlich ist dies vor allem dann, wenn ein Programm nicht skriptbar ist oder wenn ein Programm für eine ganz bestimmte Aktion keine direkte Zugriffsmöglichkeit in seinem Funktionsverzeichnis vorgesehen hat.
SmartBooks
AppleScript
Grundlagen Als Mac OS X das Licht der Welt erblickte, war das vorerst auch das Ende für einige der überaus nützlichen Makroprogramme (darunter den »Dinosaurier« QuicKeys von http://www.cesoft.com), mit denen seit Jahren im klassischen Mac OS zuverlässig Aktionen im Benutzerinterface als Makro aufgezeichnet und jederzeit wieder abgespielt werden konnten. Die ersten Versionen von Mac OS X boten einfach keine Schnittstelle, um einen Knopf oder einen Menüpunkt mit etwas anderem als mit der Maus oder der Tastatur auszuwählen. Da diese Fähigkeit aber unbedingt erforderlich ist, um zum Beispiel Menschen mit Schwierigkeiten beim Sehen, Hören oder Greifen den Zugang zur Betriebssystemoberfläche zu erleichtern, führte Apple mit Mac OS X 10.2 das Accessibility-Framework als Schnittstelle ein. Alle Programme, die auf Cocoa zugreifen, erben dieses Framework dabei automatisch, so dass der Zugriff auch möglich ist, wenn man beim Programmieren nicht explizit darauf Rücksicht genommen hat. Beachten Sie hier auch die Einführung von Apple in englischer Sprache unter: http://developer.apple.com/documentation/Accessibility/Conceptual/AccessibilityMacOSX/. Für den Appleskripter ist vor allem die Tatsache bedeutend, dass man bei der Erschaffung dieser Schnittstelle daran gedacht hat, diese auch gleich skriptbar zu machen. Der Zugriff auf die Accessibility-Schnittstelle erfolgt dabei über das Programm System Events, darin insbesondere über die Processes Suite. In ihr sind alle Befehle und Interface-Elemente für die Arbeit damit aufgelistet. Auf der Webseite von Apple finden sich, versteckt unter folgendem Link, auch noch ein paar Beispiele: http://www.apple.com/applescript/uiscripting/index.html. Auch im Skriptmenü finden sich unter UI Element Scripts ein paar Beispiele.
Zugriff für Hilfsgeräte Damit man per AppleScript zum Beispiel auf einen Knopf drücken kann, muss der Zugriff auf die Accessibility-Schnittstelle erst einmal freigeschaltet werden. Standardmäßig ist der Zugriff nämlich ausgeschaltet. Das geschieht, indem Sie in den Systemeinstellungen auf Bedienungshilfen klicken. Ganz unten finden Sie die Option Zugriff für Hilfsgeräte aktivieren. Setzen Sie dort einen Haken. Ab sofort können Sie Ihren Mac wie von Geisterhand Knöpfe drücken und Menüpunkte auswählen lassen.
700
GUI-Scripting
Kapitel 7
Abb. 7-1 Um per AppleScript auf Knöpfe, Menüs und andere Elemente zugreifen zu können, muss der Zugriff für Hilfsgeräte aktiviert werden. Dieses Einschalten lässt sich natürlich auch per AppleScript erledigen: tell application "System Events" set UI elements enabled to true end tell Eventuell werden Sie dabei nach einem Administrator-Passwort gefragt. Nach dessen Eingabe wird der Zugriff für Hilfsgeräte eingeschaltet. UI elements enabled ist ein Property von application in der System Events Suite des Funktionsverzeichnisses beim Programm System Events.
Tastatur & Maus Eine weitere nützliche Einstellung für die Bedienung und das Navigieren durch InterfaceElemente in einem Fenster oder Dialog findet sich in den Systemeinstellungen Tastatur & Maus. Wählen Sie dort unter Tastaturkurzbefehle bei Steuerung durch die Tastatur die Option Alle Steuerungen. Sie können die Wirkung dann sofort in diesem Fenster ausprobieren. Drücken Sie die Tabulatortaste und beobachten Sie, wie nach jedem Drücken ein anderes Element im Fenster durch eine leichte Umrandung hervorgehoben und ausgewählt wird. Dieses hervorgehobene Element lässt sich mit der Leertaste auslösen. Auf diese Weise kann man in einem Fenster oder Dialog komplett mit der Tastatur navigieren.
701
SmartBooks
AppleScript
Mit [ctrl]+[F7] können Sie, ohne die Systemeinstellungen zu öffnen, auch wieder zu der Auswahl Nur Textfelder und Listen zurückkehren. Wenn Sie dann die Tabulatortaste drücken, wird nur noch zwischen dem Suchfeld und der Liste mit den Tastaturkürzeln navigiert. Für das GUI-Scripting ist die Einstellung Alle Steuerungen besonders nützlich, weil Sie damit die einzelnen Elemente eines Fensters hervorheben können. Diese Steuerung betrifft allerdings nur Elemente, die auch eine Aktion erlauben. Im GUI-Scripting können Sie zusätzlich noch auf Elemente zugreifen, die keine Interaktion erlauben, wie hier zum Beispiel auf den Fenstertitel Tastatur & Maus.
Abb. 7-2 Die Option »Steuerung durch die Tastatur« ermöglicht die Auswahl der Steuerelemente eines Fensters durch die Tabulator-Taste. Auch dies lässt sich natürlich per AppleScript erledigen. Da die Systemeinstellungen jedoch nur schlecht skriptbar sind, muss man hier bereits auf das erste GUI-Scripting zugreifen. Daher präsentiere ich den folgenden Code erst einmal ohne weitere Erläuterung. Nach dem Studium des restlichen Kapitels wird der Code verständlich sein: tell application "System Preferences" activate reveal anchor "shortcutsTab" of pane id "com.apple.preference.keyboard"
702
GUI-Scripting
Kapitel 7
end tell tell application "System Events" tell process "Systemeinstellungen" click radio button "Alle Steuerungen" of radio group 1 of ¬ tab group 1 of window "Tastatur & Maus" end tell end tell Alternativ kann man auch das globale Tastaturkürzel [ctrl]+[F7] mit GUI-Scripting auslösen (mit dem Befehl key code). Jedoch kann man dann nicht genau sagen, auf welcher von beiden Positionen der Radio-Knopf dann steht.
Grenzen Die folgenden Einschränkungen sind beim GUI-Scripting zu beachten: << Da das GUI-Scripting auf der Accessibility-API beruht, funktioniert dies nur in den Programmen, die auch die entsprechenden Cocoa-Bibliotheken verwenden. Ein Java-Programm zum Beispiel, das nicht die spezielle Java-Schnittstelle zu Cocoa nutzt, oder ein Programm in der X11-Umgebung werden sich damit nicht steuern lassen. << Wenn der Hersteller eigene Interface-Elemente erschaffen hat, ist der Zugriff auf diese wahrscheinlich erschwert oder sogar unmöglich. << Drag und Drop-Aktionen lassen sich generell nicht mit GUI-Scripting ausführen. Sollte ein Programm eine Funktion nur über Drag und Drop zugänglich gemacht haben, kommen Sie mit GUI-Scripting nicht an diese Aktion heran. Bitten Sie den Hersteller darum, diese Funktionalität auch als Menüpunkt aufzuführen. << Der Zugriff über das GUI ist langsam. Beim GUI-Scripting wird eine sichtbare Aktion durchgeführt, so als klicke eine unsichtbare Hand an die entsprechenden Stellen oder betätige die Tastatur. Teilweise ist es sogar nötig, im Code delay-Befehle einzufügen, da ein Skript oft schneller ist als das grafische Benutzerinterface der Software. Falls Sie also einmal unerklärliche Probleme mit einem GUI-Skript haben, versuchen Sie, das Skript mit einem delay zwischen den einzelnen Aktionen zu verlangsamen. Manchmal dauert es einfach ein bisschen, bis ein Fenster oder Dialog erscheint. Tipp Statt mit eine delay kann man auch mit einem repeat auf die Existenz eines GUI-Elements prüfen, bevor man fortfährt. Das kann zum Beispiel so aussehen: repeat until exists window "Save as…" end repeat Der Code bleibt hier so lange in der völlig leeren Warteschleife hängen, bis das SichernFenster endlich geöffnet ist und damit die Prüfung auf dessen Existenz geklappt hat. 703
SmartBooks
AppleScript
<< GUI-Scripting funktioniert nur bei Programmen, die sich im Vordergrund befinden. Jedes Programm, das Sie per GUI-Scripting steuern möchten, muss also mit einem activate im Skript nach vorne geholt werden. Die Steuerung eines Programms im Hintergrund ist nicht möglich. << Der Zugriff auf ein Programm über das Benutzerinterface stellt eine Hilfslösung dar und sollte wirklich nur dann verwendet werden, wenn ein Programm an dieser Stelle nicht skriptbar ist. Das kann durchaus auch bei ansonsten sehr gut skriptbaren Programmen passieren. Kein Programm ist wirklich bis in den letzten Winkel perfekt über AppleScript steuerbar. Wenn möglich, sollte jedoch immer der direkte Zugriff über die im Funktionsverzeichnis des Programms definierten Klassen und Befehle bevorzugt werden. Der Zugriff auf Daten des Programms über die GUI-Schnittstelle ist meist schwer zu realisieren und äußerst mühsam. GUI-Scripting stellt keine ernsthafte Alternative dar, um an die Daten eines Programms heranzukommen. Verwenden Sie GUI-Scripting daher niemals, um auf die Daten eines Programms zuzugreifen, wenn das Programm dafür auch eine reguläre Möglichkeit in seinem Funktionsverzeichnis anbietet. << Da ein Element der grafischen Benutzerschnittstelle auch unterschiedliche Rollen (AXRole) einnehmen kann und damit unterschiedliche Attribute erhält, kann es auch immer wieder zu einem ungewöhnlichen Verhalten eines GUI-Elements kommen. Ein GUI-Element muss daher manchmal anders angesprochen werden, als es sein Aussehen vermuten lässt. Schon bei den hauseigenen Programmen von Apple begegnet man immer wieder der ungebremsten Kreativität der Designer und damit ungewohnten Bedienelementen in ungewöhnlichen Rollen, die den Skripter viel Zeit kosten können.
Hilfreiche Software Wie jedes Objekt, will auch ein Element der grafischen Benutzeroberfläche, wie zum Beispiel ein Knopf in einem Fenster, entsprechend seines Standes in der Objekthierarchie korrekt angesprochen werden. Doch wie findet man die Objekthierarchie bei GUI-Elementen heraus? Da jedes Fenster und jedes Menü anders ist, ist auch die Hierarchie eines Objekts in jedem Fenster oder jedem Menü anders. Einmal ist der Knopf direkt ein Element des Fensters, ein anderes Mal ist er ein Element einer Tabelle oder Teil einer Gruppe. Die gesamte Hierarchie muss bei der Anrede immer mit angegeben werden. Eine Möglichkeit wäre, sich in einem AppleScript schrittweise in die Tiefen der Hierarchie durchzufragen. Wie das geht, wird weiter unten in diesem Kapitel unter Die Propertys eines UI elements aufgezeigt.
704
GUI-Scripting
Kapitel 7
Da diese Ermittlung per Skript äußerst mühsam ist, empfiehlt es sich, ein Hilfsprogramm zu verwenden, welches einem die Hierarchie anzeigt. Solch ein Hilfsprogramm ist für einen entspannten Gemütszustand des GUI-Skripters dringend zu empfehlen – es ist unglaublich, wie tief Benutzerelemente verschachtelt sein können. Es gibt derzeit zwei Hilfsprogramme für das GUI-Scripting: den UI Element Inspector von Apple und den UI Browser von Prefab.
Der UI Element Inspector Dieses Programm stammt von Apple und ist als Code-Beispiel für die Programmierer gedacht. Es kann daher mitsamt Quellcode von Apples Entwicklerseite geladen werden: http://developer.apple.com/samplecode/UIElementInspector/ Ich empfehle Ihnen, den Ordner, den Sie nach dem Auspacken erhalten, in den Ordner AppleScript im Ordner Programme zu legen. Dann haben Sie die Programme, die mit AppleScript zu tun haben, alle an einem Ort. Tipp Wenn Sie die Xcode Developer Tools von Apple installiert haben, finden Sie dieses Programm auch unter dem Namen Accessibility Inspector im Ordner /Developer/Applications/Utilities/Accessibility Tools/. Es handelt sich dabei jedoch um eine ältere Version als derjenigen aus dem Code-Beispiel. Ebenfalls in diesem Ordner befindet sich noch ein weiteres kleines Programm namens Accessibility Verifier, mit dem sich testen lässt, ob das Benutzerinterface eines Programms zugänglich ist, und welche Elemente das genau sind und welche nicht. Das Programm selbst heißt UIElementInspector.app.
Abb. 7-3 Das Programm UIElementInspector lässt Sie die Objekthierarchie, die Eigenschaften und die Aktionen von Bedienelementen einsehen. Wenn Sie das Programm starten, öffnet sich ein kleines Fenster, das immer über allen anderen schwebt. Je nachdem, über welches GUI-Element Sie die Maus halten, werden entsprechende Informationen als Text dazu eingeblendet. Holen Sie das Programm, über das Sie Informationen einholen wollen, nach vorne und halten Sie dann die Maus ruhig über
705
SmartBooks
AppleScript
irgendeinen Knopf oder ein anderes Element des Programms. Drücken Sie dann die Tastenkombination [Befehl]+[F7]. Die Anzeige wird nun eingefroren, und der Text in der Palette wird in roter Schrift angezeigt. Ein kleines Fenster mit dem Titel Locked on <ein GUIElement> erscheint.
Abb. 7-4 Der UI Element Inspector zeigt die Informationen zu einem Zoom-Knopf an.
Das Fenster »Accessibility Inspector« Ignorieren Sie für den Moment das Locked on-Fenster und schauen Sie sich den Text in dem Fenster Accessibility Inspector in Ruhe an. Ganz oben sehen Sie die Objekthierarchie des ausgewählten Bedienelements – in der Abbildung oben ist es die Objekthierarchie des grünen Zoom-Knopfs: Dieser Zoom-Knopf ist ein Element des Fensters mit dem Namen UIElementInsepctor. Dieses Fenster ist wiederum ein Element der Anwendung "Finder". Hier kommt nun das erste Hindernis bei der Verwendung des UI Element Inspectors. Er zeigt die Schaltflächen und Bedienelemente mit der AXRole an, das ist der Name der Rolle des GUI-Elements im Accessibility-Framework. Als Skripter müssen Sie jedoch auf diese Elemente über den Klassennamen aus dem Funktionsverzeichnis der System-Events zugreifen. Dort sind alle GUI-Elemente in der Processes-Suite definiert, und den dort angegebenen Klassennamen müssen Sie verwenden. Sie können den Knopf also nicht adressieren, indem Sie schreiben: tell AXbutton 706
GUI-Scripting
Kapitel 7
Stattdessen müssen Sie schreiben: tell button Wobei hier natürlich noch die Angabe fehlt, um welchen Knopf es sich handelt – die Indexnummer oder der Name des Knopfes fehlen also ebenfalls. Das zieht sich durch alle Namen hindurch, so ist ein AXWindow einfach ein window. Meistens reicht es, das AX wegzulassen, um die benötigte Klasse aus den System-Events zu erhalten. Bei AXApplication müssen Sie aber process verwenden und nicht etwa application. Hinzu kommt noch, dass, wenn ein Element einen Namen hat, dieser zwar mit angegeben wird, wenn das Element aber keinen Namen hat, so wird gar nichts angezeigt. Hilfreich wäre hier die Indexnummer. Dieser Mangel des UI Element Inspectors führt dazu, dass man als Skripter zwar schon einen Anhaltspunkt zur Hierarchie hat, aber trotzdem immer noch viel ausprobieren und nachfragen muss. In der zweiten Gruppe stehen im Fenster Accessibility Inspector die sogenannten Attribute des ausgewählten Elements. Sie stellen die Eigenschaften eines GUI-Elements dar: Attributes: AXRole: “AXButton” AXRoleDescription: “Taste zum Zoomen” AXSubrole: “AXZoomButton” AXParent: “” AXWindow: “(null)” AXTopLevelUIElement: “” AXPosition: “x=817 y=273” AXSize: “w=14 h=16” AXEnabled: “1” Die Attribute sind meist auch über eine entsprechende Property der GUI-Klasse ermittelbar, können aber auch direkt über value of attribute "NameDesAXAttributs" abgefragt werden. Als Letztes sind im Fenster Accessibility Inspector die Aktionen aufgelistet, die dieses Element ausführen kann. Im Falle eines Knopfes ist dies nur die Aktion AXPress, welche für das Drücken eines Knopfes steht. Actions:
AXPress - drücken
707
SmartBooks
AppleScript
Eine solche Aktion kann im Skript mit dem Befehl perform action "NameDerAXAktion" ausgeführt werden. In dem Einblendmenü unten rechts können Sie noch die Schriftgröße der Anzeige einstellen.
Das Fenster »Locked on« Sobald mit [Befehl]+[F7] die Sicht auf ein Element fixiert wurde, erscheint das Fenster Locked on. In diesem Fenster können Sie über das Einblendmenü Attribute einzelne Attribute des Elements auswählen. Im Textfeld darunter wird dann der Wert des Attributs eingeblendet. Dieses Einblendmenü stellt also nur eine Einzelsicht, eines der im Fenster Accessibility Inspector aufgelisteten Attribute dar. Wenn sich der Wert dieses Elements verändern lässt, zum Beispiel bei einem Suchfeld, kann in dem Feld darunter der Wert auch eingegeben oder verändert werden, um dann mit einem Klick auf den Knopf Set Value auf das GUIElement übertragen zu werden. Wenn das Attribut in dem Textfeld unter dem Einblendmenü Attribute jedoch inaktiv ist, heißt das, dass dieses Attribut nicht von Ihnen verändert werden kann. Attribute, die sich verändern lassen, können natürlich auch in einem AppleScript mit set gesetzt oder verändert werden. In dem Einblendmenü goto können Sie in der Objekthierarchie nach oben oder nach unten wechseln (AXParent und AXChildren), ganz zur obersten Ebene (AXTopLevelUIElement) oder zu einem Nachbarelement auf der gleichen Hierarchieebene. Besonders wichtig sind hier AXParent und AXChildren, da Sie damit herausfinden können, in welchem GUI-Element das ausgewählte Element steckt und welche GUI-Elemente in dem Objekt selber enthalten sind. Darin spiegelt sich also die Objekthierarchie wieder. Trotz der Wortwahl parent und children ist damit nicht etwa eine Vererbung im objektorientierten Sinn gemeint! Ein Klick auf den Knopf refresh kann hilfreich sein, wenn sich an dem GUI-Element inzwischen etwas geändert hat. Wenn Sie einen Haken bei Highlight setzen, wird das gerade ausgewählte Element mit einer halbtransparenten Farbe abgedeckt und hervorgehoben. Damit erhalten Sie eine visuelle Rückmeldung, welches Element ausgewählt wurde – vor allem nützlich bei der Verwendung des Einblendmenüs goto, da man dort nicht unbedingt erkennen kann, wo sich das ausgewählte Element nun befindet. Ganz unten im Lock on-Fenster befindet sich das Einblendmenü Action. Wenn das ausgewählte Element eine Aktion hat, wie zum Beispiel das Drücken eines Knopfes, dann kann
708
GUI-Scripting
Kapitel 7
diese Aktion hier ausgewählt werden. Je nach GUI-Element kann es mehrere Aktionen geben. Mit einem anschließenden Klick auf den Knopf Perform wird die Aktion ausgeführt, also zum Beispiel der Knopf gedrückt – mit allen Konsequenzen, die das Drücken eines Knopfes in einem Programm so haben kann.
Der UI Browser von Prefab Diese kommerzielle Alternative wird von http://prefabsoftware.com angeboten. Wenn Sie öfter mit GUI-Scripting zu tun haben, ist der UI Browser von Prefab jeden seiner derzeit 55 Dollar wert. Der UI Browser zeigt einem nicht nur mehr Informationen an, wie zum Beispiel den so überaus wichtigen Index eines Elements, er liefert Ihnen auf Wunsch auch gleich die nötige AppleScript-Syntax zur Adressierung eines Objekts zurück. Diese Eigenschaft alleine macht den UI Browser unverzichtbar. So brauchen Sie den Code einfach nur noch zu kopieren und im Skripteditor einzusetzen – wenn Sie den UI Browser in seinen Preferences nicht gleich so einstellen, dass er den Code automatisch in die Zwischenablage kopiert. Mit der Lösung von Apple, die ja auch eigentlich nur ein Code-Beispiel für Programmierer ist, werden Sie – je tiefer die Verschachtelung eines Elements, desto höher der Zeitaufwand – wesentlich mehr Zeit beim Ermitteln der Adressierung für ein tell verwenden. Sie können sich den UI Browser von Prefab kostenlos herunterladen und für 30 Tage uneingeschränkt testen. Ich zeige hier nur einige der wichtigsten Vorzüge des UI Browsers auf, da hier nicht der Platz ist, um ein eigenes Handbuch dafür zu schreiben.
Abb. 7-5 Der Prefab UI-Browser ist für das GUI-Scripting unverzichtbar.
Das Fenster »UI Browser Screen Reader« Wenn Sie den UI Browser starten und dann im Fenster UI Browser auf den Knopf Switch to Screen Reader klicken, erhalten Sie ein ähnliches Fenster wie beim UI Element Inspector. Holen Sie ein Fenster einer Anwendung nach vorne und gehen Sie mit der Maus über die einzelnen Elemente, und der Screen Reader zeigt Ihnen die Eigenschaften der GUIElemente an.
709
SmartBooks
AppleScript
Abb. 7-6 Der Screen Reader zeigt mehr Informationen an als der Accessibility Inspector. Das Besondere an ihm; Er zeigt nicht die AX-Namen der Attribute an, sondern eine ausgeschriebene Bezeichnung, die teilweise auch genau so in AppleScript verwendet werden kann, wenn man dieses Attribut als Property abfragen möchte. Wenn man jedoch die technischen AX-Namen bevorzugt, kann man die Anzeige aber auch in den Voreinstellungen umschalten. Darüber hinaus zeigt er auch einige Zusatzinfos an, darunter den so überaus wichtigen Index von Elementen ohne Namen, wie zum Beispiel denjenigen vieler Knöpfe. In obiger Abbildung sehen Sie, dass die Objekthierarchie unter Path to Element steht und dass der Knopf mit button 2 bezeichnet wird. Hier erfahren Sie also sofort, dass dieser Knopf über den Index 2 angesprochen werden kann, also mit einem tell button 2. Wenn Sie in diesem Fenster auf Switch to Browser klicken, kommen Sie zurück in das Fenster UI Browser – und das hat es wirklich in sich.
Das Fenster »UI Browser« Hier gibt es zwei unterschiedliche Möglichkeiten, ein GUI-Element auszuwählen. Zum einen können Sie in dem Einblendmenü Target eines der gerade laufenden Programme auswählen. Daraufhin erscheinen in der Spaltenansicht darunter alle GUI-Elemente dieses Programms. Hier können Sie sich dann über die Spalten bis zu dem gewünschten Element vorarbeiten. Um herauszufinden, welches Element sich hinter einem Namen wie
710
GUI-Scripting
Kapitel 7
zum Beispiel Gruppe (group 3) verbirgt, empfiehlt es sich, die Option Highlight zu markieren. Das GUI-Element wird dann in dem entsprechenden Programm mit einer halbtransparenten rosa Ebene abgedeckt und damit kenntlich gemacht. Auf diese Weise lassen sich spielerisch die GUI-Elemente eines Programms erforschen. Zum anderen können Sie auch die Maus über das gewünschte GUI-Element halten und sich dann mit der Tastenkombination [Befehl]+[ctrl]+[S] gezielt den Pfad zu diesem Element anzeigen lassen. Der Pfad kann in der Spaltenansicht oder in dem aufklappbaren Textbereich Path to Element abgelesen werden, wie in der folgenden Abbildung zu sehen.
Abb. 7-7 Der UI Browser zeigt einem auf Wunsch auch gleich den für den Zugriff nötigen AppleScript-Code an – so leicht kann GUI-Scripting sein. Für den Appleskripter ganz besonders hilfreich ist aber das kleine Einblendmenü AppleScript. Hier können Sie sich unterschiedlichen AppleScript-Code, zum Beispiel für die korrekte Anrede des ausgewählten Elements, als Code in einem kleinen Extra-Fenster namens Edit AppleScript anzeigen lassen. Auf Wunsch (eine Einstellung in den Voreinstellungen des Programms) landet der Text auch gleich in der Zwischenablage oder einem beliebigen Skripteditor.
711
SmartBooks
AppleScript
In einer Schublade am unteren Fensterrand, zu erreichen über das Einblendmenü Drawer rechts unten, können noch die Attribute des GUI-Elements eingeblendet werden. Attribute, die sich setzen lassen, können hier auch gleich verändert werden. Aber nicht nur die Attribute können hier angezeigt und verändert werden, auch Actions, Keystrokes und notifications sind hier einseh-, auslös- oder registrierbar.
Die Processes Suite der System Events Die Klassen und Befehle, die Sie für das GUI-Scripting benötigen, werden in der Processes Suite der System-Events definiert.
Abb. 7-8 Das Funktionsverzeichnis der System-Events enthält in der Processes Suite alle Befehle und Klassen, die für das GUI-Scripting benötigt werden. Das bedeutet dann auch, das alle Befehle an ein GUI-Element, ob Knopf, Textfeld oder Menü, immer in einem tell an die System-Events stehen müssen und nicht in einem tell an die Anwendung. Damit die System-Events dann identifizieren können, zu welchem Programm das GUIElement gehört, definiert es auch eine Klasse namens process. Ein Befehl an das GUIElement einer Anwendung muss daher immer in einem tell an den entsprechenden Prozess stehen. Der Prozess wird dabei üblicherweise über den Namen der Anwendung angesprochen.
712
GUI-Scripting
Kapitel 7
Weiter ist es erforderlich, dass die Anwendung, deren GUI-Elemente gesteuert werden sollen, aktiv ist. Von daher muss das Programm immer mit activate nach vorne geholt werden. Das Grundschema für Befehle an GUI-Elemente einer Anwendung sieht damit immer so aus wie der folgende Code am Beispiel des nicht skriptbaren Programms Vorschau: tell application "Vorschau" to activate tell application "System Events" tell process "Vorschau" -- Befehle end tell end tell Der Prozess trägt dabei üblicherweise den gleichen Namen wie die Anwendung. Es kann sein, dass beim Kompilieren des Skripts die englische Programmbezeichnung verwendet wird. Man kann die Processes Suite in insgesamt fünf Gruppen einteilen: << Die Prozess-Klassen process und application process: Die Klasse application process stammt von process ab und wird für Prozesse verwendet, die von einer Programmdatei gestartet werden, also einer Datei mit der Endung app. Die Suite definiert auch noch einen desk accessory process, der aber nur für die Klassik-Umgebung relevant ist. << Klassen für die Elemente der grafischen Benutzeroberfläche: Knöpfe, Menüs, Rollbalken und so weiter. Alle diese Klassen sind Kinder der Super-Klasse UI element und erben die darin definierten Propertys. << Fünf Befehle, um Aktionen im User-Interface auszulösen: Klicken mit der Maus, eine Auswahl oder Eingaben über die Tastatur vornehmen und so weiter. << Die Klasse attribute: Die AppleScript-Implementation der AX-Attribute aus dem Accessibility-Framework. Welche Attribute vorkommen, hängt von dem Attribut AXRole ab, welches die Aufgabe des GUI-Elements bestimmt. Jedes Objekt, das von der Klasse UI element abstammt, enthält für jedes AX-Attribut ein Objekt der Klasse attribute als Element. Es kann durch seinen AX-Attributsnamen angesprochen werden, zum Beispiel: attribute "AXParent" of window 1. << Die Klasse action: Diese Klasse beschreibt die Handlungen, die an einem GUI-Element möglich sind. Jedes Objekt der Klasse UI element enthält für jede mögliche Aktion ein Objekt der Klasse action. Es kann durch seinen AX-Namen angesprochen werden, zum Beispiel: action "AXRaise" of window 1.
713
SmartBooks
AppleScript
Die folgende Abbildung verdeutlicht die Beziehungen:
Abb. 7-9 Ein Prozess kann ein oder mehrere Fenster und Menüleisten besitzen, die wiederum eine Vielzahl an User-Interface-Elementen mit beliebig tiefer Verschachtelung enthalten können. Jeder Prozess kann null, ein oder mehrere Fenster und Menüleisten enthalten. Jedes dieser Objekte kann wiederum null, ein oder mehrere unterschiedliche GUI-Elemente enthalten. Der Begriff GUI-Elemente steht hier als Platzhalter für Knöpfe, Textfelder oder andere Elemente der grafischen Benutzeroberfläche. Die Verschachtelungstiefe ist beliebig, aber nicht jedes GUI-Element kann beliebige andere GUI-Elemente enthalten. Unterhalb von process stammt jede Klasse von der Klasse UI element ab und enthält immer attributes und actions als Elemente. Da aber auch process von der Klasse UI element erbt, hat auch ein Prozess Attribute, nur actions fehlen ihm.
714
GUI-Scripting
Kapitel 7
Prozesse Ein Prozess besitzt eine ganze Reihe Eigenschaften, die in dem einen oder anderen Fall für den Skripter eine Hilfe sein können. Sie können die Eigenschaften eines Prozesses ermitteln, indem Sie nach dessen Propertys fragen: tell application "Preview" to activate tell application "System Events" tell process "Vorschau" get properties end tell end tell Als Ergebnis erhalten Sie jede Menge Eigenschaften, von denen einige von der Klasse UI element geerbt werden, die bei einem Prozess meist missing value enthalten. Diese nicht relevanten Eigenschaften habe ich in der folgenden Liste der Eigenschaften eines Prozesses ausgelassen: Property
Beschreibung
Kann der Prozess auf die Befehle open application, open document, print document und quit reagieren? (High-Level-Awareness) Akzeptiert der Prozess entfernte Apple-Events? accepts remote events:false (Kapitel 4) Programmpfad und Name, von dem der Prozess application file:alias "HD:Applications:Preview.app:" gestartet wurde Die Prozessor-Architektur des Rechners ("ppc" architecture:"i386" für PowerPC oder "i386" für Intel) Läuft der Prozess nur im Hintergrund? background only:false accepts high level events:true
bundle identifier:"com.apple. Preview"
Der Bundle-Identifier des Programms
class:application process
Die Klasse (Von UI element geerbt) Läuft der Prozess in der Klassik-Umgebung?
Classic:false creator type:"prvw" description:"Programm"
displayed name:"Vorschau"
Der vierstellige creator type des Programms Eine Beschreibung des UI-Elements und seiner Funktion, liegt teilweise in lokalisierter Form vor (von UI element geerbt) Der Name der Datei, von welcher der Prozess gestartet wurde, wie im Betriebssystem angezeigt
715
SmartBooks
AppleScript
Property
Beschreibung
entire contents:{}
Liefert eine Liste aller Objekte der Klasse UI element über alle Verschachtelungstiefen hinweg. Die Liste wird nur bei expliziter Nachfrage nach dieser Property zurückgeliefert, da die Abfrage lange dauern kann, je nachdem, wie tief man sich bereits befindet und wie viele GUI-Elemente sich darunter noch befinden. Bei einem Prozess werden alle UI elements der geöffneten Fenster und Menüleisten des Programms aufgelistet (von UI element geerbt). Der vierstellige Dateityp der Datei des Prozesses
file type:"APPL"
Die Datei, von welcher der Prozess gestartet file:alias "HD:Applications:Preview.app:" wurde Ist der Prozess im Vordergrund? frontmost:true has scripting terminology:false
Hat der Prozess ein Funktionsverzeichnis und kann es daher geskripted werden?
id:282693
Einzigartige ID des Prozesses (Von item geerbt)
name:"Preview"
Der Name des Prozesses (nicht lokalisiert)
partition space used:0
Die Bytes, die der Prozess gegenwärtig in der Speicherpartition des Prozesses verwendet Liefert einen Record mit allen Propertys des Prozesses. Wird bei der Abfrage der Propertys wegen endloser Rekursion natürlich nicht noch einmal angezeigt. (Von item geerbt)
properties:{}
role:"AXApplication"
short name:"Vorschau"
Die Rolle des GUI-Elements (AXRole). Bestimmt die möglichen AXAttribute. (Von UI element geerbt) Der Kurzname der Datei (ohne Dateikürzel) des Prozesses
total partition size:0
Der Titel des UI elements, wie auf dem Bildschirm angezeigt (Von UI element geerbt) Die Größe der Speicherpartition des Prozesses
unix id:549
Die Unix-Prozess-ID
visible:true
Ist der Prozess sichtbar?
title:"Vorschau"
716
GUI-Scripting
Kapitel 7
Eine einzelne Eigenschaft können Sie durch direkte Abfrage der Property erreichen, wie bei einem record üblich. Im Folgenden wird abgefragt, ob das Programm skriptbar ist, also ein Funktionsverzeichnis besitzt. Die Antwort ist false. Das Programm Vorschau ist also nicht skriptbar. tell application "Preview" to activate tell application "System Events" tell process "Vorschau" get has scripting terminology end tell end tell -- Ergebnis: false Von besonderem Interesse ist die Eigenschaft entire contents. Damit können Sie sämtliche GUI-Elemente in dem Prozess auf einen Schlag abfragen, bis in die letzte Verschachtelungstiefe hinab. Wenn Sie das direkt mit dem Prozess machen, kann es etwas dauern, bis die Abfrage fertig ist. So eine Anwendung kann, je nachdem, wie viele ihrer Fenster gerade geöffnet sind, unglaublich viele GUI-Elemente besitzen. Ein Prozess hat auch Attribute. Wie sich Attribute ermitteln lassen, steht im entsprechenden Abschnitt einige Seiten weiter in diesem Kapitel.
Die UI elements Die folgende Tabelle listet alle Klassen auf, die von UI elements abstammen. Die Abbildungen sind nur ein Beispiel. Bei vielen Elementen sind unterschiedliche grafische Darstellungsformen möglich. Außerdem sind die Fähigkeiten eines grafischen Elements durch die Definition seiner AXRole definiert und nicht durch sein Aussehen. Welche Propertys eines GUI-Elements mit Werten gefüllt sind und welche Attribute ein GUI-Element hat, hängt ebenfalls von seiner Rolle (AXRole) ab. Beachten Sie für eine detaillierte Übersicht der Rollen bitte Appendix B:Roles and Associated Attributes in der Dokumentation von Apple unter http://developer.apple.com/documentation/Accessibility/Conceptual/ AccessibilityMacOSX/. Darin sind alle möglichen AXAttributes einer AXRole aufgelistet. In der folgenden Tabelle sind alle Klassen der Processes Suite der System-Events aufgelistet, die ein GUI-Element darstellen und von der Klasse UI element abstammen. Nicht aufgelistet sind nur die Prozessklassen sowie die Klassen attribute und action, die gesondert behandelt werden. Die angegebenen Befehle und Aktionen sind Beispiele für den Fall, dass dieses GUI-Element auch die Standardrolle des Klassennamens innehat (browser = AXBrowser, busy indicator = AXBusyIndicator …).
717
SmartBooks
AppleScript
class
Beschreibung
browser
Spaltenansicht von Daten, wie die Spaltenansicht eines Fensters im Finder. Keine Aktionen oder Befehle. Die Elemente, die in dem browser enthalten sind, können aber entsprechend ihrer Klasse angesprochen werden. Anzeige, dass das Programm gerade beschäftigt ist. Keine Aktionen oder Befehle möglich.
busy indicator button
checkbox color well
Ein Knopf löst eine Aktion aus, wenn man ihn anklickt. Lässt sich mit click oder perform action "AXPress" anklicken. Ein Knopf zum Auswählen einer Option. Reagiert auf die Befehle click und die Aktion "AXPress". Ein Knopf zur Auswahl einer Farbe. Ruft in der Regel die Farbauswahl des Betriebssystems auf. Reagiert auf die Befehle click und die Aktion "AXPress". Die Farbe kann leider nicht über die Property value gesetzt werden, obwohl das laut Funktionsverzeichnis möglich sein sollte. Man muss daher den color well anklicken und dann in der erscheinenden Farbpalette die Farbe zum Beispiel über das Setzen des values der Schieberegler einer RGBoder CMYK-Farbe steuern.
–
Eine Spalte in table, outline oder browser. Kann unter Umständen mit dem Befehl select ausgewählt werden. combo box Auswahl eines Elements aus einer Liste. Kennt die Aktionen "AXShowMenu" und "AXConfirm". Der Knopf rechts ist ein Element der combo box. Er kann mit click angeklickt werden, um das Menü zu öffnen. Am einfachsten einzustellen, indem man seine Property value verändert (set value of combo box 1 of … to "Wert"). Ansonsten schwierig zu steuern. Ein Fenster, das wie eine Schublade aus dem Rand eines drawer Fensters herausfährt. Verwenden Sie perform action "AXRaise", um die Schublade mit dem Fenster nach vorne zu holen.
–
group
column
718
Eine beliebige Gruppe von UI elements. Keine direkte grafische Repräsentation. Eine Gruppe wird aber meist durch das Layout optisch klar von anderen Gruppen oder GUI-Elementen abgegrenzt. Reagiert auf keine Befehle oder Aktionen und dient als reine Containerklasse.
GUI-Scripting
Kapitel 7
class
Beschreibung
grow area
Die Ecke rechts unten in einem Fenster, an der sich die Größe dieses Fensters verändern lässt. Reagiert auf keine Befehle oder Aktionen. Um die Größe eines Fensters zu verändern, müssen Sie dessen Property size ändern.
image
Bereich mit einem Bild. Ohne Aktionen oder Befehle.
incrementor
Knopf zum Erhöhen oder Verringern von Werten. Der Befehl click hat hier keine Wirkung. Verwenden Sie perform mit einer der Aktionen "AXIncrement" oder "AXDecrement" zum Erhöhen oder Verringern des Wertes. Der Wert des entsprechenden Feldes kann aber auch direkt über dessen Property value gesetzt werden. Die Propertys minimum value und maximum value bestimmen den Wertebereich.
–
list
Eine Liste von UI elements, oft static text. Befehle oder Aktionen müssen zu der Klasse des UI elements in der Liste passen. Mit dem Befehl select kann, wenn von der Klasse her möglich, ein Element in der Liste ausgewählt werden. Siehe Beispiel beim Befehl select.
–
menu
Element von menu bar item. Hat keine eigene grafische Repräsentation. Besitzt die Aktionen "AXPress" und "AXCancel" und reagiert damit auch auf click, worauf sich die menu bar item öffnet. Jedes Untermenü in einem menu bar item ist wiederum ein menu des entsprechenden menu items.
menu bar
Die Menüzeile eines Programms. Neben window das einzige Element eines process. Kann nicht angeklickt werden. Klicken Sie stattdessen ein menu bar item an, wenn Sie ein Menü sichtbar öffnen wollen. Besitzt nur die Aktion "AXCancel", um ein offenes Menü wieder zu schließen.
menu bar item
Einzelnes Menü in einer Menüzeile, Element von menu bar. Hat die Aktionen "AXPress" und "AXCancel". Kann mit dem Befehl click oder Aktion "AXPress" angeklickt werden, worauf sich das Menü öffnet. Normalerweise aber nicht nötig, da sich ein einzelner Menüpunkt (menu item) direkt anklicken lässt, ohne das Menü sichtbar öffnen zu müssen.
719
SmartBooks
AppleScript
class
Beschreibung
menu button
Ein Knopf, der ein Menü anzeigt. Wie der Aktionsknopf in der Symbolleiste eines Finder-Fensters. Kann mit click oder perform action "AXpress" oder der Aktion "AXShowMenu" dazu gebracht werden, das Menü anzuzeigen. Erst nachdem das Menü angezeigt wird, kann mit einem click ein menu item darin ausgewählt werden (siehe Beispiel beim Befehl click).
menu item
Ein einzelner Eintrag in einem Menü. Element von menu bar item. Kann direkt mit dem Befehl click ausgewählt werden, ohne vorher die menu bar und das menu bar item anzuklicken. Besitzt die Aktionen "AXPress" und "AXCancel". Ansicht von hierarchischen Daten entsprechend der aufklappbaren Listenansicht im Finder. Keine Aktionen oder Befehle. Die Elemente in der outline können aber entsprechend ihrer Klasse angesprochen werden. Ein Knopf zur Auswahl eines einzelnen Elements. Erst mit click oder perform action "AXPress" anklicken und dann mit click auf das Menü zugreifen. Aktion "AXShowMenu" funktioniert zwar, der Zugriff auf das Menü funktioniert danach aber nicht. Die Property value kann nur gelesen werden. Siehe Beispiel beim Befehl click. Fortschrittsanzeige. Keine Befehle oder Aktionen möglich.
outline
pop up button
progress indicator radio button
Ein Radioknopf. Wird meist in einer radio group verwendet. Kann mit click oder der Aktion "AXPress" ausgewählt werden.
radio group
Eine Gruppe von radio buttons. In der Gruppe kann immer nur einer ausgewählt sein. Keine Aktion oder Befehle möglich. Relevanzanzeige, wird zum Beispiel in der Anzeige von Suchergebnissen verwendet, um anzuzeigen, wie hoch die Übereinstimmung zum Suchbegriff ist. Keine Befehle oder Aktionen möglich.
relevance indicator
–
Eine Zeile in einer table, outline oder browser. Kann eventuell mit dem Befehl select ausgewählt werden. Siehe Beispiel zum Befehl select.
row
720
GUI-Scripting
Kapitel 7
class
Beschreibung
scroll area
Der Rollbalken in einem Fenster inklusive des zu bewegenden Fensterbereichs. Aktionen und Befehle können nur auf die darin enthaltenen Elemente erfolgen. Ein Rollbalken, dient zur Navigation in Datenmengen, die größer als der zur Verfügung stehende Darstellungsbereich sind. Eine scroll bar hat keine Aktionen oder Befehle. Der Knopf in der scroll bar ist ein slider oder value indicator. Die anderen Flächen sind ebenfalls Knöpfe. Es gelten daher die Befehle und Aktionen für diese Elemente. Ein Fenster, welches aus der Titelzeile eines Fensters herausfährt. Wird zum Beispiel im Sichern-Dialog des Skripteditors verwendet. Besitzt nur die Aktion "AXRaise", welche das sheet mit dem Fenster nach vorne holt.
scroll bar
sheet
slider
splitter
Ein Schieberegler, meist als value indicator verwendet, um einen Wert einzustellen. Verwenden Sie perform mit einer der Aktionen "AXIncrement" oder "AXDecrement" zum Erhöhen oder Verringern des Wertes. Der Wert kann aber meist auch direkt über die Property value gesetzt werden. Die Propertys minimum value und maximum value bestimmen den Wertebereich. Trenngriff um einen Bereich in einem Fenster in zwei Ansichten zu teilen. Keine direkten Aktionen oder Befehle darauf möglich. Die Position des splitters kann aber über seine Property value eingestellt werden.
splitter group
Ein Bereich, der mit einem splitter geteilt wurde. Keine Aktionen oder Befehle.
static text
Nicht editierbarer Text, oft als Name oder Überschrift verwendet. Keine Interaktion möglich. Der Text kann in der Property value abgefragt werden. Ein Bereich, in dem sich über Knöpfe verschiedene Ansichten einblenden lassen. Es kann immer nur ein Bereich auf einmal angezeigt werden. Keine Interaktionen auf die Gruppe selber möglich, nur auf die darin enthaltenen Elemente. Tabellarische Ansicht von Daten. Containerklasse, die andere Elemente enthalten kann. Auf Zeilen und Spalten kann meist über die Klassen row und column zugegriffen werden. Keine eigenen Aktionen oder Befehle darauf möglich.
tab group
table
721
SmartBooks
AppleScript
class
Beschreibung
text area
Bereich zur freien Texteingabe. Der Text darin kann als Property value ausgelesen und auch gesetzt werden. Kennt eventuell die Aktion "AXShowMenu", um das Kontextmenü zum Editieren des Textes zu öffnen, und die Aktion "AXConfirm", um die Texteingabe zu bestätigen. Textfeld mit begrenzter Aufnahmekapazität. Der Text kann als Property value ausgelesen und auch gesetzt werden. Kennt eventuell die Aktion "AXShowMenu", um das Kontextmenü zum Editieren des Textes zu öffnen, und die Aktion "AXConfirm", um die Texteingabe zu bestätigen.
text field
tool bar
value indicator
window
Eine Palette mit Knöpfen. Eine tool bar ist eine Containerklasse ohne eigene Aktionen. Befehle müssen an die Elemente darin gerichtet werden. Die Position und Größe der tool bar kann, wenn frei beweglich, über die Propertys position und size verändert werden. Ein Schieberegler, meist zur Wahl eines Wertes aus einem Bereich. Viele Darstellungsformen möglich, auch kreisförmig wie hier. Meist ein Element eines sliders. Sein Wert muss daher über die Property value des sliders verändert werden. Siehe slider. Die Propertys minimum value und maximum value bestimmen den Wertebereich. Ein Fenster. Neben der menu bar ist window das einzige Element eines process. Mit der Aktion "AXRaise" kann das Fenster nach vorne geholt werden. Mit den Propertys position und size können die Position und die Größe verändert werden, wenn erlaubt.
Die Propertys eines UI elements Alle oben aufgelisteten Objekte besitzen Eigenschaften, die beim Steuern derselben sehr nützlich, ja teilweise sogar erforderlich sind. In der folgenden Tabelle sind alle Eigenschaften eines GUI-Elements aufgelistet. Nicht jede dieser Eigenschaften ist für jedes GUI-Element relevant, so kommt es oft vor, dass einzelne Eigenschaften missing value enthalten. In Klammern das der Property entsprechende AXAttribut.
722
GUI-Scripting
Kapitel 7
Property
Typ
Lesen/ Schreiben
Beschreibung
class
class
Nur Lesen
Die Klasse des UI elements, zum Beispiel button.
description
text
Nur Lesen
enabled
boolean
Nur Lesen
Eine Beschreibung des GUI-Elements und seiner Funktion. Liegt teilweise in lokalisierter Form vor. (AXRoleDescription) Ist das GUI-Element aktiv? Kann es angeklickt werden? (AXEnabled)
entire contents
list
Nur Lesen
focused
boolean
Lesen/ Schreiben
help
text
Nur Lesen
id
text
Nur Lesen
maximum value
integer
Nur Lesen
minimum value
integer
Nur Lesen
Liefert eine Liste aller GUI-Elemente, die in diesem GUI-Element enthalten sind, über alle Verschachtelungstiefen hinweg. Die Liste wird nur bei expliziter Nachfrage nach dieser einen Property zurückgeliefert, da die Abfrage länger dauern kann, je nachdem, wie tief man sich bereits befindet und wie viele GUI-Elemente sich darunter noch befinden. (entire contents geht damit weiter als das Attribut AXChildren, welches nur die unmittelbar enthaltenen Elemente auflistet.) Ist das UI Element gerade ausgewählt? (Wird es also mit einem Hervorhebungsrahmen dargestellt, wie bei der Navigation mit Tab durch GUI-Elemente?) (AXFocused) Eine Beschreibung des UI elements und seiner Möglichkeiten. Wird beim Verweilen mit der Maus als gelber Hilfetext über dem GUI-Element eingeblendet. (AXHelp) Die ID des GUI-Elements. Meist nicht vorhanden! Von item geerbt. Der maximale Wert, den das GUI-Element einnehmen kann. Wird zum Beispiel von Schiebereglern (slider) verwendet. (AXMaxValue) Der minimale Wert, den das GUI-Element einnehmen kann. Wird zum Beispiel von Schiebereglern (slider) verwendet. (AXMinValue)
723
SmartBooks
AppleScript
Property
Typ
Lesen/ Schreiben
Beschreibung
name
text
Nur Lesen
Der Name des GUI-Elements. Neben dem Index eine der beiden Möglichkeiten, ein Objekt direkt anzusprechen.
orientation
text
Nur Lesen
Die Orientierung des UI elements. Der Wert liegt als Text vor und heißt entweder "AXHorizontalOrientation" oder "AXVerticalOrientation". Zum Beispiel bei Schiebereglern von Bedeutung. (AXOrientation)
position
list
Lesen/ Schreiben
properties
record
Die Position des UI elements auf dem Bildschirm als globale Koordinaten in Pixel. Eine Liste mit zwei Integerwerten: {Abstand von links, Abstand von oben}. Lässt sich nur für verschiebbare Elemente wie zum Beispiel Fenster verändern, ansonsten nur Leseberechtigung. (AXPosition) Liefert einen Record mit allen Propertys des GUI-Elements. Wird bei der Abfrage der Propertys wegen endloser Rekursion natürlich nicht noch einmal angezeigt. Von item geerbt.
role
text
Nur Lesen
selected
boolean
Lesen/ Schreiben
size
list
Lesen/ Schreiben
724
–
Die Rolle des GUI-Elements (AXRole). Bestimmt die möglichen AXAttribute. Die möglichen Rollen sind in Appendix B des Accessibility Overviews von Apple aufgelistet (siehe Link zu Anfang des Abschnitts). Die AXRole wird im UIElementInspector zur Anzeige der Objekthierarchie verwendet. Ist das GUI-Element gerade ausgewählt? In der Menüleiste und den Menüs von pop up buttons von Bedeutung. (AXSelected) Die Größe des GUI-Elements in Pixel. Der Wert ist eine Liste mit zwei Integerzahlen: {Breite, Höhe}. Lässt sich nur für GUI-Elemente setzen, die ihre Größe ändern können, wie zum Beispiel Fenster, ansonsten nur Leseberechtigung. (AXSize)
GUI-Scripting
Kapitel 7
Property
Typ
Lesen/ Schreiben
Beschreibung
subrole
text
Nur Lesen
title
text
Nur Lesen
value
integer
Lesen/ Schreiben
Die Unterrolle des GUI-Elements (AXSubrole). Enthält eine näher gehende Beschreibung der Funktion eines buttons, rows, text fields oder windows. Der Titel des GUI-Elements wie auf dem Bildschirm angezeigt. (AXTitle) Der aktuelle Wert des GUI-Elements. Von Bedeutung bei color wells, combo boxes, progress indicators, radio buttons, radio groups, relevance indicators, scroll bars, sliders, splitters, static texts, tab groups und text fields. (AXValue)
Die meisten der oben aufgelisteten Eigenschaften sind von den AX-Attributen des Accessibility-Frameworks sozusagen in die Propertys des GUI-Elements durchgereicht worden. Aus diesem Grund habe ich der Beschreibung in Klammern die entsprechenden Namen des AX-Attributs hinzugefügt. Die Propertys eines GUI-Elements stellen dabei nur eine Auswahl der möglichen Attribute eines GUI-Elements dar. Es kann daher im Einzelfall hilfreich sein, ein entsprechendes AX-Attribut zu verwenden statt der Property des UI elements, zumal wenn dieses Attribut gar nicht als Property vorliegt. Die Verwendung von Attributen erweitert also die zur Verfügung stehenden Möglichkeiten. Falls Sie an einem Punkt nicht weiterkommen, kann ein Blick in die Attribute nützlich sein. Wie man auf Attribute zugreift, erläutere ich im Anschluss. Der Zugriff auf die Property eines GUI-Elements funktioniert auf die altbekannte Weise, davon ausgehend, dass im Programm Vorschau ein PDF geöffnet und die Symbolleiste sichtbar ist: tell application "Preview" to activate tell application "System Events" tell process "Preview" tell window 1 get description of tool bar 1 end tell end tell end tell -- Ergebnis: "Symbolleiste" Wenn sich eine Property auch verändern lässt, können Sie das mit set tun.
725
SmartBooks
AppleScript
Im folgenden Beispiel wird ein Text in eine offene Notiz des Programms Notizzettel eingefügt. Das Programm liegt im Ordner Programme und ist nicht skriptbar. Im Programm vorher bitte eine Notiz öffnen: activate application "Stickies" tell application "System Events" tell process "Notizzettel" set value of text area 1 of scroll area 1 of window 1 to ¬ "Geburtstagsgeschenk nicht vergessen!" end tell end tell
Abfragen mit whose Sie können Propertys auch verwenden, um ein GUI-Element anhand einer seiner Eigenschaften aus einer Gruppe herauszufinden, und zwar mit dem bekannten Filter whose. Der Rückgabewert ist bei whose natürlich eine Liste, so dass Sie danach mit item auf die Elemente darin zugreifen müssen. Im folgenden Beispiel wird nach der Gruppe gesucht, in der sich das Suchfeld der Symbolleiste von Vorschau verbirgt. Dafür wird der Wert der Property help verwendet. Dort steht bei dieser Gruppe nämlich »Im PDF nach Text suchen« (kurz die Maus über das Suchfeld von Vorschau halten, um den Hilfetext zu sehen). Danach wird als nächster Schritt das Textfeld in der Gruppe ermittelt, um dieses mit dem Suchwort zu füllen. Achten Sie darauf, dass das Suchfeld in der Symbolleiste sichtbar ist, sonst erhalten Sie eine Fehlermeldung: tell application "Preview" to activate tell application "System Events" tell process "Preview" tell window 1 tell tool bar 1 set theGroups to every group whose help contains "suchen" set suchFeld to every text field of item 1 of ¬ theGroups whose name is "Suchen nach" set value of item 1 of suchFeld to "Appendix B" end tell end tell end tell end tell Oben wird vereinfacht davon ausgegangen, dass nur ein Objekt gefunden wird. Aufgrund der Schachtelung der GUI-Elemente sind hier mehrere whose erforderlich. Wenn Sie sicher sind, dass nur ein Ergebnis gefunden wird, können Sie im whose auch gleich nach dem ersten Element fragen: 726
GUI-Scripting
Kapitel 7
tell application "Preview" to activate tell application "System Events" tell process "Preview" tell window 1 tell tool bar 1 set theGroup to first group whose help contains "suchen" set suchFeld to first text field of theGroup whose ¬ name is "Suchen nach" set value of item 1 of suchFeld to "Appendix B" end tell end tell end tell end tell Sie können whose natürlich auch gleich im tell verwenden, wenn Sie sich erst einmal sicher sind: tell application "Preview" to activate tell application "System Events" tell process "Preview" tell tool bar 1 of window 1 tell (first group whose help contains "suchen") -- (it = das Ziel des tells) tell (first text field of it whose name is "Suchen nach") set value of item 1 to "Mein Suchtext" end tell end tell end tell end tell end tell
Abfragen mit entire contents Nun könnte man auf die Idee kommen, die Property entire contents mit whose zu verwenden. Dadurch würde sich ein mehrfaches whose vermeiden lassen. Das funktioniert jedoch leider nicht. Diese Property verhält sich anders als andere Propertys, da sie nur bei expliziter Abfrage ermittelt wird. Aus diesem Grund funktioniert sie nicht im Zusammenhang mit whose. Sie können entire contents also nur abfragen und das Ergebnis in eine Variable packen. Da man aber über eine Liste nicht mit whose arbeiten kann, bleibt nur der Weg, eine Schleife darüber zu legen. Das hat natürlich den Nachteil der Langsamkeit, je nach Tiefe der Schachtelung. Es kann Ihnen aber helfen, ein einzelnes Element zu finden und damit seine Hierarchie kennenzulernen.
727
SmartBooks
AppleScript
Hier folgt als Beispiel, wie man das Suchfeld in der Symbolleiste von Vorschau mit einer Schleife über den entire contents der tool bar 1 herausfindet. Anschließend wird das Suchwort im Suchfeld eingesetzt. Da manche GUI-Elemente keinen Namen haben, muss die Abfrage in einem try stehen, da sonst die Schleife bei dem ersten Objekt ohne Namen abbricht. Des Weiteren muss, weil es noch einen static text mit demselben Namen gibt, auch noch die Klasse des Suchfelds (text field) abgeglichen werden. Bei der Ausführung bitte ein wenig geduldig sein, das kann zwei, drei Sekunden dauern. tell application "Preview" to activate tell application "System Events" tell process "Preview" set allContents to entire contents of tool bar 1 of window 1 repeat with i in allContents try if class of i is text field and name of i is "Suchen nach" then set suchFeld to contents of i exit repeat end if end try end repeat set value of suchFeld to "Mein Suchtext" end tell end tell
Tricks zum manuellen Ermitteln der Objekthierarchie Die oben beschriebenen Techniken eignen sich alle sehr gut, um die Objekthierarchie eines Elements zu ermitteln. Wenn Sie nur mit dem UIElementInspector von Apple arbeiten, werden Sie vor allem die Technik mit entire contents zu schätzen wissen. Alles, was Sie brauchen, ist die Objektart, um die es sich handelt – das verrät Ihnen der UIElementInspector –, und eines der dort angegebenen Attribute, welches auch als Property vorliegen muss. Bei dem Suchfeld von Vorschau sagt der UIElementInspector zum Beispiel Folgendes zur Hierarchie:
728
GUI-Scripting
Kapitel 7
Was Sie suchen, ist also ein AXTextField. Ein AXTextField scheint vom Namen her einem Objekt der Klasse text field in AppleScript zu entsprechen – was richtig ist. Generell können Sie den Namen hinter dem AX einfach in der Tabelle der UI elements oben nachschlagen und den Namen dort dann verwenden. Manchmal wird der Name nur in zwei oder drei Worten getrennt geschrieben, ansonsten liegen Sie aber bei den GUI-Elementen damit immer richtig. Nachdem Sie nun wissen, dass Sie nach einem text field suchen, schauen Sie einmal nach den Attributen dieses Elements im Fenster des UI Element Inspectors. Nach dem Namen werden Sie dort jedoch vergebens suchen. Der name ist eine reine Property der Klasse UI element und kein Attribut, Sie müssen daher etwas anderes verwenden. Hier bietet sich zum Beispiel das Attribut AXRoleDescription an, welches der Property description entspricht, wie Sie der Tabelle der Properties entnehmen können. AXRoleDescription: “Feld für Suchtext” Nun können Sie nach der Klasse text field und der description »Feld für Suchtext« suchen und sich das gefundene Textfeld als Referenz zurückgeben lassen: tell application "Preview" to activate tell application "System Events" tell process "Preview" set allContents to entire contents of tool bar 1 of window 1 repeat with i in allContents try if class of i is text field and ¬ description of i is "Feld für Suchtext" then set hereIsIt to contents of i exit repeat end if end try end repeat end tell end tell get hereIsIt -- Ergebnis: text field "Suchen nach" of group 5 of tool bar 1 of window "AccessibilityMacOSX.pdf (Seite 3 von 74)" of application process "Preview" of application "System Events"
729
SmartBooks
AppleScript
Nach wenigen Sekunden haben Sie Ihre Referenz auf das Objekt im Ergebnisbereich des Skripteditors vorliegen. Dieses Ergebnis können Sie einfach herauskopieren und in Ihrem Code verwenden, um genau dieses Suchfeld anzusprechen. (Wobei das Fenster besser verkürzt mit Index als window 1 angesprochen wird, da es seinen Titel durch die Anzeige der Seitenzahl ständig ändert.) Tipp Ein Index kann bekanntlich auch negativ sein und zählt damit von hinten. Das gilt auch für die Auswahl eines GUI-Elements. In einer tool bar zum Beispiel wird mit einem Index von -1 das letzte Objekt darin ausgewählt. Wenn sich das Suchfeld im Programm Vorschau ganz rechts befindet, so ist dieses mit folgender Abfrage am schnellsten zu füllen: tell application "Preview" to activate tell application "System Events" tell process "Preview" tell tool bar 1 of window 1 set value of text field "Suchen nach" of group -1 to ¬ "noch‘n Suchtext" end tell end tell end tell Ansonsten können Sie, wann immer Sie nicht weiterwissen, einfach nach dem Attribut AXParent oder dem Attribut AXChildren fragen. Dann erfahren Sie durch Ermittlung der Eltern oder der Kinder, wo Sie sich gerade in der Hierarchie befinden und welche Elemente sich eine Ebene tiefer oder höher befinden. tell application "Preview" to activate tell application "System Events" tell process "Preview" tell tool bar 1 of window 1 tell group 2 set eltern to value of attribute "AXParent" set kinder to value of attribute "AXChildren" end tell end tell end tell end tell get eltern -- tool bar 1 of window "AccessibilityMacOSX.pdf (Seite 11 von 74)" of
730
GUI-Scripting
Kapitel 7
application process "Preview" of application "System Events" get kinder -- {static text "Zoomen" of group 2 of tool bar 1 of window "AccessibilityMacOSX.pdf (Seite 11 von 74)" of application process "Preview" of application "System Events", group "Zoomen" of group 2 of tool bar 1 of window "AccessibilityMacOSX.pdf (Seite 11 von 74)" of application process "Preview" of application "System Events"} Durch die Abfrage der Kinder erfahre ich hier zum Beispiel, dass sich bei mir in der group 2 ein static text und eine weitere group befinden. Was es mit diesen Attributen auf sich hat, wird auf den folgenden Seiten erklärt.
Die AXAttribute Jedes GUI-Element besitzt sogenante AXAttribute. Jedes Attribut ist eine eigene Klasse. Eine Klasse hat dann natürlich auch wieder eigene Propertys. Falls die Propertys eines GUI-Elements Ihnen nicht weiterhelfen, kann es hilfreich sein, in diese Attribute hineinzuschauen. In den zuvor beschriebenen Hilfsprogrammen können die AXAttribute leicht eingesehen werden. Wenn Sie direkt in AppleScript ermitteln wollen, welche Attribute für ein GUI-Element zur Verfügung stehen, so können Sie das auf folgende Art machen: tell application "Preview" to activate tell application "System Events" tell process "Preview" tell window 1 attributes of tool bar 1 end tell end tell end tell Als Ergebnis erhalten Sie eine ziemlich lange Liste aller vorhandenen AXAttribute in Referenzform: {attribute "AXRole" of tool bar 1 of window "AccessibilityMacOSX.pdf (Seite 1 von 74)" of application process "Preview" of application "System Events", attribute "AXRoleDescription" of …
731
SmartBooks
AppleScript
Wenn Sie die Eigenschaften eines dieser Attribute ermitteln wollen, so fragen Sie einfach nach den Propertys dieses einen Attributs: tell application "Preview" to activate tell application "System Events" tell process "Preview" tell window 1 properties of attribute "AXRole" of tool bar 1 end tell end tell end tell Als Ergebnis erhalten Sie immer einen Record mit vier Eigenschaften: {class:attribute, name:"AXRole", value:"AXToolbar", settable:false} << class – Diese Eigenschaft gibt einfach nur an, dass Sie ein Objekt der Klasse attribute vor sich haben. Jede Klasse besitzt diese Property. << name – Das ist der Name des Attributs. << value – Der Wert des Attributs, sehr wichtig vor allem, wenn sich dieser auch verändern lässt. << settable – Wenn diese Eigenschaft auf true steht, kann der Wert des Attributs verändert werden, ansonsten nicht. Wenn Sie also wissen wollen, was für ein Wert in einem Attribut steckt, so müssen Sie immer explizit nach der Property value fragen. Das Attribut muss dabei über seinen Namen angesprochen werden: tell application "Preview" to activate tell application "System Events" tell process "Preview" tell window 1 value of attribute "AXSize" of tool bar 1 end tell end tell end tell -- Ergebnis: {1074, 48} Der Wert des Attributes "AXSize", welches die Größe der Toolbar in Pixeln darstellt, ist also {1074, 48}. Wenn ein Attribut settable ist, können Sie auch den Wert mit set verändern, wie hier bei dem Suchfeld in der Symbolleiste von Vorschau. Voraussetzung ist bei diesem Beispiel
732
GUI-Scripting
Kapitel 7
nur, dass das Suchfeld ganz rechts in der Symbolleiste steht. (Negativer Index zählt von rechts) tell application "Preview" to activate tell application "System Events" tell process "Preview" tell tool bar 1 of window 1 set value of attribute "AXValue" of text field ¬ "Suchen nach" of group -1 to "Suchtext" end tell end tell end tell Als Ergebnis wird das Suchfeld mit dem Wort Suchtext gefüllt. Sie sehen hier auch, dass die Property value des Attributs AXValue also tatsächlich dasselbe ist, wie die Property value des text fields. Verwenden Sie die AXAttribute daher vornehmlich dort, wo ein AXAttribut nicht als Property der Klasse UI element vorliegt. Wie man nach dem Füllen des Suchfelds die Suche starten kann, steht im folgenden Abschnitt. Die Klasse action, die ebenfalls ein Element eines UI elements ist, wird in der Beschreibung des Befehls perform auf den folgenden Seiten erklärt.
Die Befehle Es gibt insgesamt 5 Befehle zur Steuerung von GUI-Elementen in der Processes Suite. Diese Befehle dienen dazu, einen Mausklick oder Tastatureingaben zu generieren.
click Dieser Befehl wird entweder an ein Objekt der Klasse UI element gerichtet oder es wird eine Koordinate auf dem Bildschirm angegeben. Beide Parameter sind optional, und nur die Angabe eines von beiden ist sinnvoll. Wird kein Parameter angegeben, wird der click an das Ziel des innersten tell-Blocks gesendet.
click an ein UI element Es folgt ein Beispiel mit dem Dock. Das Dock lässt sich zwar in seinen Eigenschaften schon ganz gut skripten (System-Events nach den properties of dock preferences fragen), um jedoch ein Icon darin anzuklicken, bedarf es des GUI-Scriptings. Das Dock hat dabei seinen eigenen Prozess. Die Elemente im Dock sind eine Liste. Die Elemente darin lassen sich dann anklicken, entweder über ihren Namen oder den Index in der Liste:
733
SmartBooks
AppleScript
activate application "Dock" tell application "System Events" tell process "Dock" tell list 1 click UI element "Safari" end tell end tell end tell Für den Index schreiben Sie den Befehl so: click UI element 3 Der Rückgabewert von click ist der Bezug zu dem angeklickten UI element: -- UI element "Safari" of list 1 of application process "Dock" of application "System Events" Im folgenden Beispiel wird der Befehl click an den Knopf Dokument vergrößern im ersten Fenster des Programms Vorschau gerichtet. Als Ergebnis wird der Inhalt des Fensters vergrößert. Falls der Knopf bei Ihnen nicht in der Symbolleiste steht, bitte vorher mit rechter Maustaste in die Titelleiste klicken und über Symbolleiste anpassen die Plus/Minus-Knöpfe an zweiter Stelle von links nach den Zurück/Vorwärts-Knöpfen in die Leiste ziehen. Ansonsten bitte den Index für die zweite Gruppe im folgenden Code ändern: tell application "Preview" to activate tell application "System Events" tell process "Vorschau" tell window 1 click button 2 of group 1 of group 2 of tool bar 1 end tell end tell end tell Aber nicht nur Knöpfe lassen sich anklicken, auch Menüs. Mit einem click können Sie einen Menüpunkt auswählen, ohne das Menü überhaupt zu öffnen. Im folgenden Beispiel wird der Menüpunkt Drucken aufgerufen. Beachten Sie bei menu item "Drucken …" die drei Punkte, die Sie mit der Tastenkombination [alt]+[.] erzeugen müssen: tell application "System Events" tell application "Preview" to activate tell process "Vorschau" click menu item "Drucken …" of menu 1 of ¬ menu bar item "Ablage" of menu bar 1 734
GUI-Scripting
Kapitel 7
end tell end tell Sie sehen hier, dass das Menü vorher nicht geöffnet werden muss. Sie können ein menu item anklicken, ohne dass es sichtbar ist. Das gilt jedoch nicht für andere GUI-Elemente. Im folgenden Beispiel wird ein Menüpunkt aus einem pop up button angeklickt. Dieses Skript verwende ich in Mail, um in der Rechtschreibprüfung schnell die Sprache von Deutsch auf Englisch und wieder zurück umzustellen. Der hier aufgerufene Dialog kann in Mail manuell über Bearbeiten | Rechtschreibung und Grammatik | Rechtschreibung und Grammatik prüfen aufgerufen werden. Dieser Dialog ist leider nicht skriptbar und bietet sich daher als Beispiel für das GUI-Scripting an. Vor der Ausführung bitte eine neue E-Mail öffnen und die Einfügemarke in den Text der E-Mail setzen. tell application "Mail" to activate tell application "System Events" tell process "Mail" click menu item "Rechtschreibung und Grammatik einblenden" of ¬ menu 1 of menu item "Rechtschreibung und Grammatik" of ¬ menu 1 of menu bar item "Bearbeiten" of menu bar 1 tell window "Rechtschreibung und Grammatik" set currLang to value of pop up button 1 if currLang = "Deutsch" then click pop up button 1 click menu item "English" of menu 1 of pop up button 1 else click pop up button 1 click menu item "Deutsch" of menu 1 of pop up button 1 end if click button 1 end tell end tell end tell Hier wird zuerst der value des pop up button abgefragt, abhängig davon wird dann die Sprache ausgewählt. Der pop up button wird nun zweimal angeklickt. Wenn Sie den ersten click wegnehmen, funktioniert das Skript nicht. Zuerst muss das Menü des Knopfes durch einen Klick geöffnet werden, dann erst kann der entsprechende Menüpunkt angeklickt werden. Das Menü wird durch den ersten Klick tatsächlich erst erzeugt, ist vorher also noch gar nicht vorhanden. Manche Knöpfe machen Probleme, weil deren Menüeinträge sich schlecht ermitteln lassen. Zum Beispiel der Menüknopf Aktion mit dem Zahnrad als Symbol in der Symbolleiste des
735
SmartBooks
AppleScript
Finderfensters. Wenn dieser Knopf bei Ihnen nicht vorhanden ist, müssen Sie in einem Finderfenster mit der rechten Maustaste in die Symbolleiste klicken und über Symbolleiste anpassen den Knopf Aktion in die Symbolleiste ziehen. Davon ausgehend, dass der Knopf in Gruppe 2 der Symbolleiste eines Fensters steht, wird auf folgende Weise mit zwei clickBefehlen ein Menüeintrag darin ausgeführt: activate application "Finder" tell application "System Events" tell process "Finder" tell window 1 click menu button 1 of group 2 of tool bar 1 click menu item "Informationen" of UI element 2 of ¬ process "Finder" of application "System Events" end tell end tell end tell Wie Sie hier sehen, ist das Menü seltsamerweise ein Element eines UI elements 2, welches Element des Prozesses selbst ist und nicht des Knopfes! Das führt dazu, dass der zweite click zur Auswahl eines Menüeintrags wieder explizit an den Prozess gerichtet werden muss und nicht an das Fenster oder den menu button. Solche Überraschungen begegnen einem beim GUI-Scripting öfters.
click an Bildschirmkoordinate Sie können für click auch Koordinaten verwenden. Der click wird dann immer direkt an den Prozess gesendet. Die Koordinaten sind global, das heißt, es wird von der linken oberen Ecke des Bildschirms aus gemessen. Die Koordinaten bestehen aus einer Liste mit zwei Integerzahlen. So gibt {50, 100} einen Punkt an, der 50 Punkte vom linken Rand und 100 Punkte vom oberen Rand des Bildschirms entfernt ist. Um Koordinaten zu ermitteln, ist das kleine Programm Pixie aus den Developer Tools hilfreich. Wenn Sie diese installiert haben, finden Sie das Programm unter /Developer/ Applications/Graphics Tools/. Das Programm vergrößert in einem kleinen Fenster den Bildschirmausschnitt um den Mauszeiger herum und zeigt in der linken unteren Ecke die Koordinaten der Maus an.
736
GUI-Scripting
Kapitel 7
Abb. 7-10 Das Programm Pixie vergrößert einen Bildschirmausschnitt und zeigt die einzelnen Pixel mit Bildschirmkoordinate an. Der Parameter für die Angabe von Koordinaten ist benannt und wird mit dem Schlüsselwort at eingeleitet: tell application "Preview" to activate tell application "System Events" tell process "Vorschau" set thisButton to click at {50, 100} end tell end tell Befindet sich an der Koordinate {50, 100} ein GUI-Element des angegebenen Prozesses, so wird dieses angeklickt. Befindet sich an dieser Stelle kein Element des Prozesses, so passiert gar nichts. Eventuell dahinter liegende Fenster oder Objekte anderer Prozesse können also nicht aus Versehen angeklickt werden, da der Klick immer ausdrücklich nur für den angegebenen Prozess gilt. Als Rückgabewert erhalten Sie das UI element, welches unter dem Mauszeiger liegt. Befindet sich an dieser Stelle kein Fenster oder Menü der Anwendung, erhalten Sie missing value. Wenn Sie das angeklickte Objekt öfters ansprechen müssen, lohnt es sich, den Rückgabewert wie in obigem Beispiel in einer Variablen aufzufangen, die Sie dann für weitere tell verwenden können.
737
SmartBooks
AppleScript
Da sich ein Klick mit Koordinaten direkt an den Prozess wendet, ist er wirkungslos, wenn er in einem tell an ein UI element steht. Eventuell muss daher in einer tieferen tellSchachtelung für den click ein erneutes tell an den process verwendet werden: tell application "Preview" to activate tell application "System Events" tell process "Vorschau" tell window 1 -- Hier Befehle an das Fenster - tell process "Vorschau" of application "System Events" ¬ to click at {215, 60} -- Befehl an den Prozess - -- Hier wieder Befehle an das Fenster end tell end tell end tell Mit click kann kein Doppelklick simuliert werden, indem man zweimal direkt hintereinander einen click auf dieselbe Stelle ausführt. Stattdessen ist eine action des Objekts mit perform auszuführen.
select Dieser Befehl wählt ein GUI-Element der Anwendung aus, hat aber nur bei rows, columns und lists eine sichtbare Auswirkung. Verwenden Sie diesen Befehl daher dort, wo er auch Wirkung zeigt, und das ist nach meinem Kenntnisstand nur bei Reihen, Spalten und Listen der Fall. Ein click auf diese Elemente hat keine Auswirkung, so dass diese wirklich nur mit select zugänglich werden. Sollten Sie einmal auf ein GUI-Element stoßen, welches nicht auf einen click reagiert, versuchen Sie es daher unbedingt auch mit select. Im folgenden Beispiel werden die Systemeinstellungen geöffnet und der Warnton in Reihe 4 ausgewählt: tell application "System Preferences" reveal anchor "effects" of pane id "com.apple.preference.sound" end tell activate application "System Preferences" tell application "System Events" tell process "Systemeinstellungen" select row 4 of table 1 of scroll area 1 of tab group 1 of window "Ton" end tell end tell
738
GUI-Scripting
Kapitel 7
Im folgenden Beispiel wird in einem Finderfenster in der Seitenleiste der Ordner Bilder ausgewählt: activate application "Finder" tell application "System Events" tell process "Finder" select UI element "Bilder" of list 1 of scroll area 1 of ¬ splitter group 1 of window 1 end tell end tell Der Befehl hat nur einen direkten Parameter, dessen Angabe immer erforderlich ist. Erwartet wird ein Objekt aus der Familie der UI elements. Der Rückgabewert ist eine Referenz auf das ausgewählte UI element.
perform Dieser Befehl erwartet einen Wert der Klasse action. Es handelt sich um einen direkten Parameter. Die durch die Klasse action definierte Aktion wird dann ausgeführt. Das Ziel des Befehls wird ganz normal durch das tell oder ein of definiert. Eine Referenz auf die action bildet auch den Rückgabewert.
Die Klasse action Die Aktionen eines UI elements kann man mit dem UI Element Inspector von Apple oder dem UI Browser von Prefab ermitteln und zum Testen dort auch gleich ausführen. Alternativ können Sie ein GUI-Element auch im Skript nach seinen Aktionen fragen. Das Suchfeld von Vorschau hat zum Beispiel zwei Aktionen: tell application "Preview" to activate tell application "System Events" tell process "Preview" tell tool bar 1 of window 1 get every action of text field 1 of group -1 end tell end tell end tell -- {action "AXShowMenu" of text field "Suchen nach" of group 5 of tool bar 1 of window "AccessibilityMacOSX.pdf (Seite 1 von 74)" of application process "Preview" of application "System Events", action "AXConfirm" of text field "Suchen nach" of group 5 of tool bar 1 of window "AccessibilityMacOSX.pdf (Seite 1 von 74)" of application process "Preview" of application "System Events"}
739
SmartBooks
AppleScript
Das eine ist die Aktion AXShowMenu, die das Kontextmenü im Suchfeld aufruft, und das andere ist die Aktion AXConfirm, welche die Eingabe bestätigt. Welche Aktionen ein GUI-Element besitzen kann, hängt von seinem Attribut AXRole ab. Insgesamt gibt es bisher 7 verschiedene Aktionen: << AXPress – einen Knopf drücken << AXIncrement – den Wert eines Schiebereglers (slider, incrementor, value indicator) erhöhen << AXDecrement – den Wert eines Schiebereglers (slider, incrementor, value indicator) verringern << AXConfirm – eine Auswahl oder Eingabe bestätigen << AXCancel – Aktion oder Auswahl abbrechen << AXRaise – Fensterobjekt nach vorne holen << AXShowMenu – ein Menü oder Kontextmenü anzeigen << AXOpen – Elemente öffnen, zum Beispiel einen Ordner Wenn es um die Aktion AXPress geht, können Sie alternativ auch immer den Befehl click stattdessen verwenden. Für andere Aktionen muss perform und die entsprechende Aktion verwendet werden. Wenn Sie nach den Propertys einer action fragen, erhalten Sie übrigens einen Record mit nur drei Werten: tell application "Preview" to activate tell application "System Events" tell process "Preview" tell tool bar 1 of window 1 properties of action "AXConfirm" of text field ¬ "Suchen nach" of group -1 end tell end tell end tell -- Ergebnis: {name:"AXConfirm", class:action, description:"Bestätigen"} Von besonderem Interesse ist hier außer dem Namen, über den die action angesprochen wird, höchstens noch die Property description mit einer näheren Erläuterung zum Befehl. Ansonsten sind die Propertys einer action ziemlich uninteressant, zumal sie alle nur gelesen und nicht verändert werden können.
740
GUI-Scripting
Kapitel 7
Beispiele Im folgenden Beispiel wird die Eingabe in das Suchfeld von Vorschau mit der Aktion AXConfirm bestätigt. Dadurch wird die Suche angestoßen, und die Suchergebnisse werden angezeigt: tell application "Preview" to activate tell application "System Events" tell process "Preview" tell tool bar 1 of window 1 tell text field 1 of group -1 set value to "Mein Suchtext" perform action "AXConfirm" end tell end tell end tell end tell Das folgende Beispiel verwendet die Aktion AXDecrement, um die Anzeige Aktivieren nach des Bildschirmschoners in den Systemeinstellungen eine Stufe herunterzusetzen, so dass er früher angezeigt wird (funktioniert nur, wenn die Anzeige nicht am Anschlag auf Nie steht.): tell application "System Preferences" reveal anchor "ScreenSaverPref" of pane id ¬ "com.apple.preference.desktopscreeneffect" end tell activate application "System Preferences" tell application "System Events" tell process "Systemeinstellungen" perform action "AXDecrement" of slider 1 of group 1 of ¬ tab group 1 of window 1 end tell end tell Beachten Sie bei slidern auch die Propertys maximum value und minimum value. Wenn Sie die Position des sliders mit der Maus setzen und dann diese Propertys abfragen, können Sie erkennen, aus welchem Bereich die Werte stammen müssen. Beim Bildschirmschoner werden zum Beispiel Werte zwischen 1 und 360 erwartet. Sie können den Wert dann auch auf folgende Art direkt verändern: set value of slider 1 of group 1 of tab group 1 of window 1 to 60 -- entspricht 5 Minuten
741
SmartBooks
AppleScript
keystroke Mit diesem Befehl können Sie Text auf der Tastatur eingeben. Der Text wird dabei wie von Geisterhand in dem GUI-Element eingefügt. Das GUI-Element muss natürlich Texteingabe unterstützen. Der Befehl benötigt immer Text als direkten Parameter. Der optionale Parameter using kann eine oder mehrere Konstanten verwenden, die für die Tasten [Befehl], [Option], [ctrl] und [Umschalt] stehen. Die Konstanten heißen: << command down << control down << option down << shift down Im folgenden Beispiel wird das aktive Fenster des nicht skriptbaren Programms Notizzettel mit einem Text gefüllt. tell application "Stickies" to activate tell application "System Events" tell process "Notizzettel" tell window 1 tell text area 1 of scroll area 1 keystroke "Nicht vergessen: Abflug 13:15 Uhr Köln" end tell end tell end tell end tell Das Ergebnis in dem Notizzettel sieht dann leider so aus: Nicht vergessen: Abflug 13:15 Uhr Kˆln Der Text im Skripteditor ist zwar Unicode, das Senden mit keystroke funktioniert aber nur mit der unteren Hälfte der Mac OS Roman Kodierung, also mit den ersten 128 Zeichen!
742
GUI-Scripting
Kapitel 7
Tipp Die einzige Möglichkeit, ohne Probleme Unicode-Zeichen in ein GUI-Element einzufügen, ist über seine Property value gegeben: tell application "Stickies" to activate tell application "System Events" tell process "Notizzettel" tell text area 1 of scroll area 1 of window 1 set value to "Nicht vergessen: Abflug 13:15 Uhr Köln" end tell end tell end tell Verwenden Sie keystroke daher nicht, wenn Sie Zeichen aus dem oberen ASCII-Bereich benötigen oder sogar Unicode-Zeichen. Ansonsten kann man noch mit dem Befehl key code tricksen. Die Zeichen müssen dafür aber auf der Tastatur zugänglich sein, Unicode-Zeichen außerhalb des gewählten Tastaturlayouts sind nicht zugänglich, es sei denn, Sie stellen die Tastatur auf eine andere Sprache um. Das Skript wird damit abhängig von der Tastaturbelegung und wird in einem anderen Land, mit einer anderen Tastatur, nicht mehr unbedingt funktionieren. set myText to "Nicht vergessen: Abflug 13:15 Uhr K" tell application "Stickies" to activate tell application "System Events" tell process "Notizzettel" tell window 1 tell text area 1 of scroll area 1 keystroke myText key code 41 keystroke "ln" end tell end tell end tell end tell -- Ergebnis: Nicht vergessen: Abflug 13:15 Uhr Köln Wenn Sie den Parameter using verwenden, so können Sie damit ein oder auch mehrere Argumente angeben: keystroke myText using shift down Damit wird der Text aus der Variablen myText groß geschrieben.
743
SmartBooks
AppleScript
Wenn mehrere Modifikationstasten gleichzeitig gedrückt werden sollen, so verwenden Sie eine Liste: keystroke myText using {shift down, option down} Seien Sie vorsichtig bei der Verwendung der [Befehl]- und [ctrl]-Taste, da diese hauptsächlich für Tastaturkürzel verwendet werden. Folgendes Beispiel ruft mit [Befehl]+[N] den Menübefehl Neue Notiz im Programm Notizzettel auf, anstatt ihn mit click anzuklicken: tell application "Stickies" to activate tell application "System Events" tell process "Notizzettel" tell window 1 tell text area 1 of scroll area 1 keystroke "n" using {command down} end tell end tell end tell end tell Geben Sie dem Befehl keystroke nicht zu viele Zeichen auf einmal mit, irgendwo ist eine Grenze (definiert durch den Puffer der Tastatureingabe), an der Zeichen verschluckt werden können. Bei größeren Textmengen ist es daher besser, den value des UI elements zu setzen oder mehrere keystroke-Befehle mit einem delay zu schichten: keystroke "abcdefghijklmn..." delay 0.5 keystroke "opqrstuvwxyz..."
keystroke und tab Oft sieht man im Internet Beispiele, in denen keystroke für die einfachste Form des GUIScriptings, einer Art »GUI-Scripting für Anfänger«, verwendet wird. Einfach dadurch, dass man ein Tab sendet. Mit der Tabulatortaste kann man ja durch alle Schaltflächen in einem Fenster oder Dialog manövrieren und mit der Leertaste zum Beispiel auswählen, wenn in den Tastatureinstellungen die Steuerung auf Alle Steuerungen steht. Im folgenden Beispiel wird mal wieder in den nur schlecht skriptbaren Systemeinstellungen gearbeitet. Hier wird in der Systemeinstellung Softwareaktualisierung der Schalter Nach Updates suchen ein oder ausgeschaltet: tell application "System Preferences" reveal anchor "UpdateSoftware" of pane id ¬ "com.apple.preferences.softwareupdate" end tell activate application "System Preferences" tell application "System Events" 744
GUI-Scripting
Kapitel 7
tell process "Systemeinstellungen" tell window "Softwareaktualisierung" keystroke tab keystroke tab keystroke tab keystroke space end tell end tell end tell Vermeiden Sie diese Form des GUI-Scriptings. Erstens können Sie das Skript nur aufrufen, wenn das Fenster geschlossen ist, da Sie immer vom selben Ausgangszustand starten müssen. Wenn Sie das Skript ausführen, solange das Fenster noch geöffnet ist, landen Sie beim dritten tab dann nämlich auf dem Zurück-Knopf. Zweitens ist diese Form langsamer. Wo immer möglich, sollten Sie daher besser direkt auf die checkbox zugreifen. Verwenden Sie dabei den Index, da Ihr Skript dadurch auch mit anderen Sprachen funktionieren wird: tell application "System Preferences" reveal anchor "UpdateSoftware" of pane id ¬ "com.apple.preferences.softwareupdate" end tell activate application "System Preferences" tell application "System Events" tell process "System Preferences" tell window 1 click checkbox 1 of tab group 1 end tell end tell end tell Dieser Zugriff ist schneller, funktioniert auch im Mac OS anderer Sprachen und auch bei wiederholter Anwendung mit noch geöffnetem Fenster. Dieser Befehl hat keinen Rückgabewert.
key code Mit diesem Befehl wird kein Text des unteren ASCII-Bereichs gesendet, sondern das, was die Tastaturbelegung definiert. Das Tastaturmenü gibt Ihnen hier verlässliche Auskunft, was tatsächlich mit einer Taste gesendet wird. Das, was auf der Taste gedruckt ist, ist also nicht maßgebend. Stellen Sie das Tastaturmenü über Landeseinstellungen in den Systemeinstellungen und dort unter Tastaturmenü ein.
745
SmartBooks
AppleScript
Der Befehl erwartet eine einzelne Integerzahl oder eine Liste mit Integerzahlen. Die Integerzahlen stellen den dezimalen Tastencode der Taste dar. Das Problem ist nur: Wie erhält man diesen Tastencode für eine Taste? Mit dem UI Browser von Prefab ist es ganz einfach. Hier im Einblendmenü Drawer einfach Keystrokes auswählen und dann eine Taste drücken. Rechts neben dem Feld Key wird der dezimale Wert eingeblendet. Es gibt aber auch Alternativen wie zum Beispiel Key Codes von http://www.manytricks.com/keycodes/ oder die sehr schlanke Alternative Full Key Codes von http://softwares.bajram.com/utilities/. Wenn Sie zum Beispiel das Programm Full Key Codes starten, nach vorne holen und dann die gewünschte Taste drücken, können Sie in der rechten unteren Ecke des kleinen Fensters den dezimalen Wert der Taste ablesen.
Abb. 7-11 Das Fenster des Programms »Full Key Codes« Tipp Egal, welches Programm Sie verwenden, Probleme gibt es bei Tasten, die vom System abgefangen werden, wie zum Beispiel den Tasten für Spaces und Exposé. Hier helfen diese Programme auch nicht weiter – aber ein Blick in die Tabelle Key Codes im Anhang dieses Buches. Auch hier können Sie den Parameter using verwenden. Die Optionen bestehen aus denselben Konstanten wie bei keystroke. Die Konstanten heißen: << command down << control down << option down << shift down
746
GUI-Scripting
Kapitel 7
Wenn Sie mehrere davon angeben wollen, so setzen Sie diese, wie bei keystroke dargestellt, in eine Liste. Worin liegt der Vorteil von key code, wenn man hier immer zuerst den Tastaturcode herausfinden muss? Mit key code können Sie auch Tasten drücken, die keinen Text beinhalten. Für den Tabulator und den Absatzumbruch können Sie ja noch die AppleScript-Konstanten tab und return verwenden. Aber was ist, wenn Sie die Cursortasten verwenden wollen, um nach oben oder unten, nach rechts oder links zu navigieren? Oder wenn Sie eine der Funktionstasten drücken möchten? Das ist alles mit key code möglich. Hier zum Beispiel der Code für die Cursor-Tasten: Nach Nach Nach Nach
oben = 126 unten = 125 links = 123 rechts = 124
Damit können Sie zum Beispiel auch in einer Liste nach oben oder unten wandern oder sogar ein Spiel bedienen, welches sich mit den Cursortasten steuern lässt. Ein Beispiel: Rechts oben in der Menüleiste eines Macs finden sich neben der Uhrzeit viele kleine Symbole. Auch diese kann man anklicken. Verantwortlich für diese Menüsymbole ist dabei ein Prozess namens SystemUIServer. Diese Menüs lassen sich zwar anklicken, die Auswahl eines Menüpunktes darin ist jedoch nicht direkt möglich, so dass diese Stelle ein geeigneter Kandidat für das Nachhelfen mit key code ist. Das folgende Beispiel klickt das Menüsymbol Nummer 4 an, bei mir der PPPoE-Status zur Einwahl ins Internet, und wählt dann den ersten Eintrag darin aus. Als Folge werde ich mit dem Internet verbunden oder davon getrennt. activate application "SystemUIServer" tell application "System Events" tell process "SystemUIServer" click menu bar item 4 of menu bar 1 -- Menüsymbol anklicken key code 125 -- Eine Zeile nach unten keystroke return -- Auswahl bestätigen end tell end tell
747
SmartBooks
AppleScript
Beachten Sie, dass Fremdprogramme, die sich als Symbole rechts oben im Menü einnisten, oft nicht vom SystemUIServer verwaltet werden. Dieser Befehl hat keinen Rückgabewert.
748
Unix
8
Das Herz von Mac OS X besteht aus einem Unix-Kern. Das macht sich auch in AppleScript bemerkbar. In diesem Kapitel wird behandelt, wie AppleScript auf die Unix-Welt und umgekehrt, wie man aus der Unix-Welt auf AppleScript zugreifen kann.
SmartBooks
AppleScript
Das AppleScript-Shebang Aufgepasst Das AppleScript-Shebang ist neu in Leopard. Die folgende Beschreibung setzt daher Mac OS X 10.5 voraus! Als Shebang wird in Unix die Zeichenfolge #! am Anfang eines Skripts bezeichnet. Anhand dieser Zeichenfolge erkennt Unix, dass der folgende Text ein ausführbares Skript ist. Da es verschiedene Skriptsprachen gibt, folgt diesem Anfangszeichen noch der Pfad zum sogenannten Interpreter, an den der folgende Text weitergegeben werden muss, welcher ihn dann prüft und ausführt. Ein AppleScript-Shebang sieht folgendermaßen aus: #!/usr/bin/osascript An diesem Pfad befindet sich unter Mac OS X dann natürlich auch der Interpreter namens osascript, welches ein Shell-Befehl ist, der den Text aufbereitet und an die AppleScriptKomponente weiterreicht. Der Pfad /usr/bin/ ist normalerweise nicht sichtbar. Geben Sie den Pfad daher im Findermenü Gehe zu | Gehe zum Ordner ein oder benutzen Sie den Befehl ls /usr/bin/ im Terminal, um den Inhalt zu sehen. Hier eine kleine Anleitung, wie Sie ein eigenes Shell-Skript erstellen können, welches AppleScript als Sprache enthält. 1. Öffnen Sie in TextEdit eine neue Datei. 2. Da ein Shell-Skript nicht als formatierter Text gespeichert werden darf, wählen Sie Format / In reinen Text umwandeln. 3. Schreiben Sie folgende Zeilen in die Datei: #!/usr/bin/osascript say "Hello!" 4. Wählen Sie Sichern im Ablage-Menü. 5. Geben Sie dem Skript den Namen hello, ohne jedes Dateikürzel, und wählen Sie den Schreibtisch als Speicherort aus. 6. Entfernen Sie den Haken bei .txt verwenden, falls kein Suffix angegeben ist. 7. Wählen Sie als Codierung Unicode (UTF-8) und klicken Sie auf Sichern. 750
Unix
Kapitel 8
8. Schließen Sie die Datei in TextEdit. 9. Öffnen Sie das Terminal (zu finden im Ordner /Programme/Dienstprogramme/). 10. Schreiben Sie in das Terminal: chmod + x 11. Fügen Sie eine Leerstelle hinter dem x an und ziehen Sie die Datei hello vom Schreibtisch hinter die Leerstelle nach dem x. Lassen Sie die Datei dort los. Der Pfad zu der Datei wird eingefügt. Der Befehl wird nun so aussehen wie in der folgenden Zeile, nur dass bei Ihnen natürlich an zweiter Stelle Ihr eigener Benutzername steht. chmod +x /Users/Detlef/Desktop/hello 12. Bestätigen Sie den Befehl mit der Enter- oder Return-Taste. 13. Die Datei hello auf dem Schreibtisch erhält nun ein neues Icon. Das Symbol eines grauen Bildschirms, auf dem in grüner Schrift exec steht. Dies ist das Symbol für ausführbare Unix-Dateien. 14. Doppelklicken Sie die Datei oder ziehen Sie die Datei ins Terminal auf eine neue, leere Zeile nach dem Prompt und bestätigen Sie mit der Enter-Taste. Ein Terminalfenster öffnet sich mit einigen Hinweisen zur Ausführung des Programms, und eine Stimme begrüßt Sie mit »Hello!«.
Abb. 8-1 Aus einem einfachen Textdokument mit Shebang-Zeile wird über das Terminal durch Setzen des »Executable«-Flags eine ausführbare Unix-Datei, die AppleScript als Sprache verwendet.
751
SmartBooks
AppleScript
Die vier osa-Befehle Der Unix-Kern von Mac OS X kennt insgesamt vier Befehle, die mit der Open Scripting Architecture (OSA) zu tun haben. Es handelt sich um die Befehle osalang, osacompile, osadecompile und osascript. Diese vier Befehle gelten für alle OSA-Sprachen gleichermaßen, also nicht nur für AppleScript (siehe Kapitel 2 zur Architektur). Die Dokumentation zu diesen Befehlen kann im Terminal durch Eingabe von man und anschließendem Befehlsnamen aufgerufen werden, also zum Beispiel man osalang. Die Dokumentation liegt immer nur in englischer Sprache vor. In der man-Seite (man kommt von manual = Handbuch) kann man mit den Cursortasten navigieren oder mit der Taste [f] eine Bildschirmseite vorwärts und mit [b] eine Seite zurück blättern. Mit der Taste [h] können Sie eine Hilfe aufrufen, und mit der Taste [q] verlässt man die Seite wieder und kehrt zur Eingabeaufforderung zurück. Der Inhalt wird mit dem Programm less angezeigt. Zu den möglichen Tastenkürzeln daher bitte auch man less beachten.
Escape- und Anführungszeichen Für alle Befehle gilt: Bei Pfadangaben und Argumenten, die nicht von der Shell interpretiert werden dürfen, ist auf Sonderzeichen und Leerstellen zu achten. Diese müssen mit rückwärts gewandtem Schrägstrich (erreichbar über [Alt]+[Umschalt]+[7]) vor dem Zeichen versehen werden (»escaped« werden). Die Shell interpretiert ein Leerzeichen sonst als den Beginn eines neuen Arguments. In der folgenden Zeile ist das Leerzeichen im Pfad korrekt mit rückwärtsgewandtem Schrägstrich »escaped« worden. /Users/Detlef/Desktop/Neuer\ Ordner\ Auch Sonderzeichen, die von der Shell als Befehl interpretiert werden könnten, müssen »escaped« werden, wie im Folgenden das >-Zeichen: /Users/Detlef/Desktop/Briefe\ 1981\ \>\ 1982 Befinden sich sehr viele störende Sonderzeichen im Text oder Pfad, können Sie auch den gesamten Pfad in einfache Anführungszeichen setzen. Damit wird eine Evaluation des Textes komplett unterbunden: '/Users/Detlef/Desktop/Briefe 1981 > 1982'. Diese Form ist am sichersten.
752
Unix
Kapitel 8
Aufgepasst Vergessen Sie niemals das Escape-Zeichen oder die Anführungszeichen. Die Shell kennt kein Pardon, und ein Widerrufen eines Befehls ist nicht möglich. Speziell wenn es sich um potentiell gefährliche Befehle handelt die etwas löschen, ist immer allergrößte Vorsicht angeraten! Eine mildere Form bilden doppelte Anführungszeichen, hier werden die meisten Zeichen ebenfalls nicht interpretiert, die Zeichen $, `, \ und eventuell das Ausrufezeichen aber weiterhin. Für die genauen Regeln bitte die man-Seiten zur bash-Shell, im Abschnitt Quoting beachten! Tipp Für eine angenehmere Anzeige des wirklich sehr, sehr langen Bash-Manuals können Sie auf http://developer.apple.com oder in der Entwickler-Dokumentation in Xcode auch nach Bash suchen. Der erste gefundene Eintrag ist meist das bash-Manual, welches Sie dann auf einer einzigen HTML-Seite lesen können. Eine Alternative, die ich persönlich bevorzuge, ist das kleine Programm Bwana (http://www.bruji.com/bwana/). Nach Ziehen des Programms auf den Rechner können Sie die man-Seiten in Safari oder einem anderen Browser durch Eingabe von man:Befehlsname in der Adresszeile aufrufen, die Dokumentation zur bash also durch Eingabe von man:bash.
osalang Wenn Sie diesen Befehl im Terminal eingeben, erhalten Sie Informationen zu den installierten OSA-Sprachen. Der Befehl ist damit ähnlich wie der AppleScript-Befehl scripting components, bietet jedoch mehr Informationen zu den Komponenten. Wenn Sie zum Beispiel den Script Debugger installiert haben, wird im Terminal nach Eingabe von osalang und Bestätigung mit [Return] folgende Liste angezeigt: JavaScript AppleScript Debugger X AppleScript Generic Scripting System Es werden also alle installierten OSA-Sprachen aufgelistet. Wenn Sie osalang mit der Option -d aufrufen, wird nur die Standardsprache angezeigt: osalang -d
753
SmartBooks
AppleScript
Das Ergebnis ist dann: AppleScript Wenn Sie osalang mit der Option -l (kleines L) aufrufen, erhalten Sie eine detaillierte Liste: osalang -l Ergebnis: Jscr LNS cgxe-v-h JavaScript asDB lns cgxerv-h AppleScript Debugger X ascr appl cgxervdh AppleScript scpt appl cgxervdh Generic Scripting System Die ersten vier Buchstaben stehen für die Komponente, die zweiten vier Buchstaben für den Hersteller (LNS=Late Night Software, appl=Apple). Danach folgt eine Liste von Flags, die für den Komponenten-Entwickler von Interesse sein können. Eine Beschreibung dieser Flags findet sich in der man-page zu osalang. So steht das r zum Beispiel für die Fähigkeit des recordings, also die des Aufnehmens eines Skripts. Hier kann man zum Beispiel sehen, dass die OSA-Sprache JavaScript nicht in der Lage ist, Befehle aufzunehmen, da dieses Flag nicht gesetzt ist. Wenn Sie den Befehl mit der Option -L aufrufen, erhalten Sie dieselbe Liste wie mit -l, aber zusätzlich mit einer Beschreibung zu jeder Komponente: osalang -L Ergebnis: Jscr LNS cgxe-v-h JavaScript (JavaScript Scripting System) asDB lns cgxerv-h AppleScript Debugger X (AppleScript Debugger X Scripting System) ascr appl cgxervdh AppleScript (AppleScript.) scpt appl cgxervdh Generic Scripting System (Transparently supports all installed OSA scripting systems.)
osacompile Mit diesem Befehl können Sie eine Datei im Format Text oder Skript kompilieren beziehungsweise neu kompilieren. Dieser Befehl ist damit das Unix-Äquivalent zum Übersetzen-Knopf im Skripteditor. Wenn Sie zum Beispiel eine Textdatei mit Anweisungen in der Sprache AppleScript vorliegen haben, können Sie den Text mit diesem Befehl kompilieren.
754
Unix
Kapitel 8
Standardmäßig wird davon ausgegangen, dass die Quelle gültigen AppleScript-Code enthält. Das Skript wird kompiliert und im Format Skript mit dem Namen a.scpt im aktuellen Arbeitsverzeichnis abgelegt. Der file type ist standardmäßig 'osas', und der creator ist 'ToyS' für den Skripteditor. Ohne Angabe der Option -d wird das Skript immer in der ResourceFork der Datei gespeichert. Es wird also ein klassisches Skript erstellt! (Siehe Kapitel 3 Ein Wort zu Type- und Creator-Codes und Resource-Forks) Wenn Sie osacompile einfach ohne jede weitere Option eingeben und bestätigen, können Sie das Skript direkt im Terminal eingeben und am Ende mit [ctrl]+[D] abschließen. Der eingegebene Text wird dann in die Standardsprache AppleScript kompiliert und als Datei a.scpt im Arbeitsverzeichnis des Terminals (standardmäßig das Heimverzeichnis des Anwenders) abgespeichert. Die folgenden Zeilen bitte nacheinander eingeben und mit Return bestätigen: osacompile set someOne to "Hello Joe" say someOne ^D Das Zeichen ^D steht für die Tastenkombination [ctrl]+[D] und wird nicht mit eingetippt. Damit beenden Sie die Eingabe des Skripts. Sie können aber auch eine Datei als Input angeben: osacompile /Users/Detlef/Desktop/hello.txt Hier wird die Datei hello.txt vom Schreibtisch im Format Skript im Heimverzeichnis mit dem Namen a.scpt abgespeichert. Um Namen, Ort und das Format der Ausgabedatei zu ändern, ist zusätzlich die Option -o nötig. Mit der Option -l können Sie eine andere Sprache als AppleScript verwenden. Die Sprache muss genau so angegeben werden, wie sie in osalang geschrieben wird. Wenn Sie diese Option nicht angeben, wird immer die Standardsprache AppleScript verwendet: osacompile -l "JavaScript" /Users/Detlef/Desktop/hello.txt Wenn durch die Option -o nicht anders angegeben, landet die Datei standardmäßig als a.scpt im Arbeitsverzeichnis. Beachten Sie, dass der Skripteditor Dateien in anderen Sprachen nachträglich nicht mehr öffnen kann. Verwenden Sie daher den Script Debugger dafür und speichern Sie die Datei auch immer ein Mal zur Sicherung als Text ab.
755
SmartBooks
AppleScript
Mit der Option -e kann eine einzelne Zeile eines Skripts direkt auf der Terminalzeile angegeben werden. Wenn das Skript aus mehreren Zeilen besteht, darf für jede Zeile eine weitere -e Option verwendet werden: osacompile -e 'set someOne to "Hello Joe"' -e 'say someOne' Wenn der Text in einfachen Anführungszeichen steht und am Ende der Zeile noch nicht geschlossen wurde, können Sie mit [Return] auch auf die nächste Zeile springen und dort weiter schreiben. Dann brauchen Sie trotz mehrerer Zeilen nur eine einzelne -e Option. Das Zeichen > wird im folgenden Beispiel von der Shell eingefügt und wird nicht mitgeschrieben. Geben Sie die Zeilen bitte nacheinander ein, bestätigt mit einem Return: osacompile -e 'set someOne to "Hello Joe" > say someOne' Nachdem der Text am Schluss mit ' geschlossen wurde, wird nach anschließendem [Return] der Befehl ausgeführt. Wenn durch die Option -o nicht anders angegeben, landet die Datei standardmäßig als a.scpt im aktuellen Arbeitsverzeichnis. Beim AppleScript-Code ist darauf zu achten, dass Zeichen wie " entsprechend korrekt »escaped« werden oder der Code in einfache Anführungszeichen gesetzt wird. Mit der Option -o kann die Ausgabedatei und deren Format bestimmt werden: osacompile -o /Users/Detlef/Desktop/hello.scptd /Users/Detlef/Desktop/hello.txt Hier wird die Textdatei hello.txt kompiliert und in die Datei hello.scptd abgespeichert. Das verwendete Dateikürzel bestimmt das Format. Im obigen Fall ist es ein Skript-Bundle. Wenn das Dateikürzel app ist, wird ein Programm mit dem type 'appl' und dem creator 'aplt' erzeugt. Für ein Droplet wird der creator 'dplt' automatisch gesetzt, wenn ein openHandler vorhanden ist. Bei der Endung scpt wird ein normales Skript erzeugt und bei scptd ein Skript-Bundle. Wird diese Option nicht verwendet, wird die Datei immer mit dem Namen a.scpt im Arbeitsverzeichnis abgespeichert. Existiert die Datei an dieser Stelle bereits, wird sie ohne Rückfrage überschrieben. Da die Ausgabe immer kompiliert ist, ist die Angabe von applescript oder txt als Dateikürzel nicht sinnvoll. Sie erzeugen sonst eine Textdatei mit dem kompilierten Skript in der Resource-Fork oder dem Datenteil der Textdatei, was sehr ungewöhnlich ist. Die Option -d hat keine Argumente. Wird sie angegeben, wird das erzeugte Skript in der Data-Fork gespeichert. Ohne diese Angabe wird das Skript immer in der Resource-Fork der Datei abgespeichert. Da das Skript unter Mac OS X normalerweise immer in der
756
Unix
Kapitel 8
Data-Fork steckt und zumal der Skripteditor gar keine Skripts mehr in diesem Format speichern kann, sollte dieser Schalter immer verwendet werden. osacompile -d -e 'say "Hello Detlef"' -o /Users/Detlef/Desktop/hello.scpt Mit der Option -r kann angegeben werden, in welcher Resource-ID der Resource-Fork das Skript gespeichert werden soll. Als Angabe wird der Typ der Resource und deren ID erwartet, getrennt durch einen Doppelpunkt. Ohne diese Angabe wird standardmäßig scpt:128 verwendet, wie in folgender expliziter Angabe. Normalerweise sollten Sie daran nie etwas ändern, wenn Sie wirklich ein Skript mit Resource-Fork haben möchten. Wenn sich das Skript unter einem anderen Resource-Type oder -ID versteckt, wird es womöglich nicht mehr automatisch von einem Skripteditor oder einem anderen Programm gefunden. osacompile -r scpt:128 -e 'say "Hello Joe"' -o /Users/Detlef/Desktop/hello.scpt Wenn -r zusammen mit der Option -d angegeben wird, wird das Skript in die ResourceFork und die Data-Fork geschrieben. Mit der Option -t kann der file type der Ausgabedatei bestimmt werden. Standardmäßig ist dies ein kompiliertes Skript, also 'osas'. Ein file type besteht immer aus vier Zeichen. Im Folgenden wird dieser auf 'text' gesetzt, was zur Folge hat, dass sich das kompilierte Skript standardmäßig in einem Texteditor öffnet. Eine Veränderung des type ist selten sinnvoll. Beachten Sie auch die Ausführungen zum file type beim Befehl choose file in Kapitel 5. osacompile -d -e 'say "Hello Joe"' -o /Users/Detlef/Desktop/hello.txt -t "text" Mit der Option -c wird der creator der Ausgabedatei gesetzt. Ohne Angabe dieser Option wird der creator auf den des Skripteditors 'ToyS' gesetzt. Der creator bestimmt, mit welchem Programm die Datei standardmäßig geöffnet wird. Auch hier handelt es sich wieder um die klassischen vier Zeichen-Codes. Soll die Ausgabedatei zum Beispiel standardmäßig mit dem Script Debugger geöffnet werden, so setzen Sie hier den creator des Script Debuggers ein: osacompile -d -e 'say "Hello Joe"' -o /Users/Detlef/Desktop/hello.scpt -c "asDB" Mit der Option -x wird das Skript als Nur ausführbar gesichert. Diese Option hat kein Argument und dieselbe Wirkung, als würden Sie das Skript im Skripteditor mit der Option Nur ausführbar abspeichern. osacompile -x -e 'say "Hello Joe"' -o /Users/Detlef/Desktop/hello.app Mit der Option -s wird die Option Nicht automatisch beenden eingeschaltet. Diese Option hat kein Argument. Das Skript bleibt dann nach dem Start geöffnet, genau so, als wenn es mit dem Skripteditor mit dieser Option gesichert worden wäre. Diese Option zeigt daher erst beim Abspeichern als Programm Wirkung, und zwar nur, wenn die Ausgabedatei noch nicht existiert: osacompile -s -e 'say "Hello Joe"' -o /Users/Detlef/Desktop/hello.app 757
SmartBooks
AppleScript
Die Option -u steht für die Angabe des Startbildschirms und entspricht der Option Startdialog beim Sichern im Skripteditor. Sie steht entsprechend nur beim Abspeichern als Programm zur Verfügung. Diese Option hat kein Argument. osacompile -u -e 'say "Hello Joe"' -o /Users/Detlef/Desktop/hello.app Die Option -a steht für die Angabe der Zielarchitektur, was wiederum nur für ein Programm, also ein Skript mit der Endung app, von Belang ist. Ohne diese Angabe wird immer ein Universal-Binary erzeugt, welches auf beiden Systemen lauffähig ist. Erlaubt sind die Angaben i386 für Intel-Macs und ppc für PowerPC-Macs. Folgende Zeile erzeugt das Applet nicht als Universal-Binary, sondern speziell für Intel-Macs und läuft daher nur auf diesen: osacompile -a "i386" -e 'say "Hello Joe"' -o /Users/Detlef/Desktop/hello. app
osadecompile Dieser Befehl ist das Gegenstück zu osacompile. Wo osacompile einen Text zu einem Skript kompiliert, da geht osadecompile den umgekehrten Weg und zeigt Ihnen wieder den Source-Code an. osadecompile macht dabei genau das, was auch im Skripteditor geschieht, wenn Sie ein Skript kompilieren. Ihnen wird dort nach dem Übersetzen nämlich immer die dekompilierte Version des Skripts angezeigt (siehe Kapitel 3 Übersetzen). Dieser Befehl hat keine Optionen und erwartet nur die Angabe einer Datei. Die Datei muss als kompiliertes Skript vorliegen, also als scpt oder scptd oder als Programm, das nicht mit der Option Nur ausführbar gespeichert wurde. Die verwendete OSA-Sprache wird automatisch erkannt. Die Ausgabe erfolgt in der Standardausgabe, wenn keine Umleitung definiert wurde, also immer am Bildschirm: osadecompile /Users/Detlef/Desktop/hello.scpt zeigt Ihnen dann im Terminal den Inhalt des Skripts an, zum Beispiel: say "Hello Joe" Wenn die Ausgabe in einer Datei landen soll, müssen Sie also, wie in der Shell üblich, den Befehl in eine Datei umleiten, zum Beispiel mit >: osadecompile /Users/Detlef/Desktop/hello.scpt > /Users/Detlef/Desktop/ hello.txt
758
Unix
Kapitel 8
osascript Mit diesem Befehl können Sie ein OSA-Skript über das Terminal ausführen. Auch hier können Sie das Skript direkt in der Kommandozeile schreiben, wie bei osacompile mit dem -e Schalter. Sie können aber auch eine Datei angeben oder die Standardeingabe verwenden. Der Rückgabewert ist der letzte Inhalt der AppleScript-Variablen result. Von daher ist eventuell eine explizite Rückgabe mit return im Appleskript erforderlich. Wenn Sie im Terminal osascript schreiben und bestätigen, können Sie das auszuführende Skript direkt in der Standardeingabe eintippen. Jede Zeile bitte einzeln eingeben und mit [Return] bestätigen: osascript set someOne to "Hello Joe" say someOne Nach Abschluss mit [ctrl]+[D] wird das Skript kompiliert und ausgeführt. osascript kann also auch Text annehmen, der sich als eine OSA-Sprache kompilieren lässt, und erwartet nicht unbedingt ein bereits kompiliertes Skript. Mit der Option -e können Sie, wie bei osacompile, das Skript direkt im Terminal schreiben. Besteht das Skript aus mehreren Zeilen, ist -e für jede Zeile zu verwenden: osascript -e 'set someOne to "Hello Joe"' -e 'say someOne'
Abb. 8-2 Ein Appleskript kann auch in der Shell ausgeführt werden. Wenn Sie dem Befehl eine Datei folgen lassen, wird diese ausgeführt. Die Datei muss eine OSA-Sprache in Text oder kompilierter Form enthalten. Für Text wird sowohl die Standard-Kodierung Mac OS Roman als auch UTF-8 akzeptiert sowie Unix- oder Mac-Zeilenumbrüche. osascript /Users/Detlef/Desktop/hello.txt Dabei können Sie dem run-Handler in diesem Skript auch Argumente übergeben.
759
SmartBooks
AppleScript
Angenommen, das Skript in der Datei hello.txt lautet: on run args say "Hello " & item 1 of args as text end run Dann können Sie der Variablen args einen Wert übermitteln, indem Sie direkt nach Angabe der Datei den Wert folgen lassen: osascript /Users/Detlef/Desktop/hello.txt "Susan" Beachten Sie hier auch die Beschreibung im Kapitel 4 Skriptobjekte unter run script. Tipp Befehle, die auf ein grafisches Benutzerelement zugreifen, wie zum Beispiel display dialog, werden von osascript nicht akzeptiert. Die Verwendung wird von Apple auch nicht empfohlen. Trotzdem können Sie diese Beschränkung umgehen, indem Sie Dialoge im Skript immer an die System-Events richten: set someOne to "Heinz" tell application "System Events" activate display dialog "Hello " & someOne end tell Obiges Skript kann zum Beispiel von osascript ausgeführt werden, da sich das tell an das Programm System Events richtet. Ohne das tell würde sich osascript weigern, das Skript auszuführen. Die Option -l wird benötigt, wenn der Text keinen AppleScript-Code darstellt. Das betrifft nur Text und nicht kompilierte Skripts in anderen Sprachen. Die Sprache in kompilierten Skripts wird automatisch erkannt. Im folgenden Beispiel wird ein JavaScript ausgeführt: osascript -l "JavaScript" -e 'var a = "Hello Susan"' -e 'a;' oder als Datei: osascript -l "JavaScript" /Users/Detlef/Desktop/hello.txt Die verwendeten Sprachen müssen als OSA-Sprache im System installiert sein, was mit osalang überprüft werden kann. Mit der Option -s kann das Ausgabeformat beeinflusst werden. Die Ausgabe ist der Rückgabewert des Skripts. Als Argument ist hier nur ein String mit bis zu 4 Flags erlaubt, die durch die Buchstaben h, s, e und o dargestellt werden. Falls sich einzelne Flags widersprechen, behält der letzte Flag in Leserichtung seine Wirkung.
760
Unix
Kapitel 8
Standardmäßig wird der Rückgabewert als lesbarer Text zurückgeliefert. Das führt dazu, dass Listen und Records flach gemacht werden und eine Schachtelung nicht mehr nachvollziehbar ist. Wenn in einem Skript zum Beispiel der Rückgabewert eines gedrückten Knopfes zurückgeliefert wird, wie in dem Beispielskript im Kasten, erhalten Sie keinen Record zurück, sondern den Text daraus: osascript /Users/Detlef/Desktop/hello.txt button returned:OK Dieses Standardverhalten wird durch das Flag h gekennzeichnet. Obige Ausführung von osascript ist also identisch mit folgender mit -s als Parameter und h als Argument: osascript -s h /Users/Detlef/Desktop/hello.txt Hier die vier möglichen Flags in der Kurzübersicht: << h - dieses Flag ist Standard und bewirkt die Anzeige in Textform << s – bewirkt die Anzeige des Rückgabewertes in rekompilierbarer Quellform << e - Fehler im Skript auf die Standard-Fehlerausgabe leiten (Standard) << o - Fehler im Skript auf die Standardausgabe leiten Wenn Sie das Flag s verwenden, sieht der Rückgabewert von obigem Skript im Terminal so aus: osascript -s s /Users/Detlef/Desktop/hello.txt {button returned:"OK"} Damit haben Sie den ursprünglichen Record als Wert erhalten, der sich so auch gleich in einem Skript wieder verwenden lässt – deswegen »rekompilierbare Quellform«. Der Rückgabewert wird immer in der Standardausgabe, also am Bildschirm in der Shell, angezeigt. Das Flag e ist standardmäßig gesetzt, muss also nicht explizit angegeben werden. Tritt ein Fehler im Skript auf, wird dieser Fehler in der Standard-Fehlerausgabe angezeigt. Wenn diese nicht umgeleitet wurde, ist das normalerweise ebenfalls in der Shell. Im Folgenden wurde in der Datei zum Beispiel ein Anführungszeichen vergessen. Die Fehlermeldung von AppleScript wird samt Fehlernummer bis in die Shell durchgereicht: osascript -s e /Users/Detlef/Desktop/hello.txt /Users/Detlef/Desktop/hello.txt:109:109: script error: Expected ”" ” but found end of script. (-2741)
761
SmartBooks
AppleScript
Wenn Sie als Flag o setzen, werden Fehler auf die Standardausgabe umgeleitet und dort angezeigt. Wenn die Standardausgabe nicht umgeleitet wurde, wird der Fehler damit im Terminal angezeigt. osascript -s o /Users/Detlef/Desktop/hello.txt /Users/Detlef/Desktop/hello.txt:109:109: script error: Expected ”" ” but found end of script. (-2741) Das Flag o hat also nur Sinn, wenn entsprechend die Kanäle umgestellt werden. Im folgenden Beispiel wird die Standardausgabe in eine Datei umgeleitet. Die Fehler werden daher nicht mehr am Bildschirm angezeigt, sondern als Text der Datei err.txt hinzugefügt. osascript -s o /Users/Detlef/Desktop/hello.txt >> /Users/Detlef/Desktop/err.txt Ohne Angabe von -s o würden die Fehler weiterhin am Bildschirm im Terminal angezeigt. Da für das Ergebnis eines Skripts ebenfalls die Standardausgabe verwendet wird, landet dieses nun ebenfalls in der Datei err.txt. Tipp Wenn Fehler und Ergebnisse in getrennte Dateien gehen sollen, empfiehlt es sich, die Flags e und o nicht zu verwenden und stattdessen die Standardausgabe und Standardfehlerausgabe von Hand umzuleiten: osascript /Users/Detlef/Desktop/hello.txt >> /Users/Detlef/Desktop/ergebnis.txt 2>> /Users/Detlef/Desktop/err.txt Bei zwei Winkeln >> wird immer an die folgende Datei angefügt. Wenn Sie nur einen einzelnen Winkel > schreiben, wird die Datei jedes Mal komplett überschrieben. Bei beiden Formen, ob nur ein einzelner Winkel oder ein Doppelwinkel, wird die Datei erzeugt, falls sie noch nicht vorhanden ist. Die 2 steht dabei für den Fehlerkanal, eine optional angegebene 1 (1>>) immer für die Standardausgabe. Die 1 wird dabei aber meist weggelassen, da sie standardmäßig verwendet wird. Und damit alle drei Unix-Kanäle vollständig sind: Die 0 (null) steht für die Standardeingabe, wird dann aber in Verbindung mit einem Kleiner-Zeichen gebraucht (<) und dann meist ebenfalls weggelassen. Sie können auch mehrere Flags gleichzeitig verwenden, wobei natürlich nur sich nicht widersprechende Flags sinnvoll sind. Im Folgenden werden die Flags s und o gesetzt, um den Rückgabewert in kompilierbarer Form anzuzeigen und Fehler auf die Standardausgabe umzuleiten. Da der Rückgabewert ebenfalls immer auf der Standardausgabe angezeigt wird, werden beide in die Datei protokoll.txt umgeleitet. osascript -s so /Users/Detlef/Desktop/hello.txt >> /Users/Detlef/Desktop/protokoll.txt 762
Unix
Kapitel 8
Tipps zu do shell script Der Befehl do shell script ist kein Unix-Befehl. Es handelt sich vielmehr um einen Befehl der Standarderweiterungen von AppleScript. Beachten Sie daher die Beschreibung zu do shell script und seinen möglichen Parametern unter Miscellaneous Commands im Kapitel 5. Hier folgen nur noch zusätzliche Tipps und Hinweise zur Arbeit mit diesem Befehl. Der Befehl do shell script geht den umgekehrten Weg zu osascript. Mit osascript können Sie ein Appleskript in einer Unix-Shell ausführen. Mit do shell script können Sie einen Unix-Befehl in AppleScript ausführen. Beachten Sie auch die ausführliche Technote von Apple zu diesem Befehl (in englischer Sprache), die unter http://developer.apple.com/technotes/tn2002/tn2065.html einsehbar ist.
Skripts in anderen Sprachen Genau genommen können Sie nicht nur die Shell verwenden, sondern auch andere Skriptsprachen. Das hat eine sehr weitreichende Bedeutung. Mit do shell script haben Sie damit nämlich eine Schnittstelle zu anderen Sprachen wie Perl, Python oder Ruby. Wenn Sie zum Beispiel ein Python-Skript vorliegen haben, dann können Sie dieses direkt als Befehl im Terminal eingeben oder bei längeren Skripts als ausführbare Datei starten. Hier ein kleines Pythonskript, welches mit do shell script direkt an der Shell ausgeführt wird und welches die augenblickliche Uhrzeit mit einer Genauigkeit von Mikrosekunden zurückliefert. Da AppleScript nur eine Genauigkeit von Sekunden kennt, kann das in dem einen oder anderen Fall eine hilfreiche Ergänzung darstellen. Die folgenden Zeilen bitte im Skripteditor eingeben und ausführen: set getTime to ¬ "python -c 'import datetime\nprint datetime.datetime.now()'" set startTime to (do shell script getTime) -- Format des Rückgabewertes: "2008-08-13 20:28:26.564805" Hier wird der Python-Interpreter mit der Option -c aufgerufen. Diese Option erlaubt es, das Python-Skript direkt auf der Kommandozeile als Text anzugeben. Statt den Unix-Zeilenumbruch \n vor print zu verwenden, können Sie auch ein Semikolon schreiben.
763
SmartBooks
AppleScript
Power User Wenn das Skript schon als ausführbares Python-Skript vorliegt (mit chmod +x ausführbar gemacht wurde, siehe Anfang des Kapitels Das AppleScript-Shebang), können Sie auch direkt den Pfad angeben. Schreiben Sie das folgende Python-Skript als reinen Text in TextEdit und achten Sie beim Sichern darauf, dass Mac OS Roman Encoding verwendet wird, oder verwenden Sie einen Editor wie nano im Terminal. Geben Sie der Datei den Namen getTime.py und speichern Sie diese auf dem Schreibtisch ab. #!/usr/bin/python import datetime print datetime.datetime.now() Der Aufruf dieses Python-Skripts über do shell script geht dann im Skripteditor ganz einfach durch Aufruf der Datei: set startTime to (do shell script ¬ (quoted form of "/Users/Detlef/Desktop/getTime.py")) -- "2008-08-13 12:57:12.512568" Sie können im Shebang auch über env den Pfad zum Interpreter herausfinden, was den Vorteil hat, dass alle Pfade in der PATH-Umgebungsvariablen zur Suche nach dem Interpreter verwendet werden und nicht nur /usr/bin wie in obigem Beispiel. Das Shebang sieht dann so aus: #!/usr/bin/env python Das funktioniert natürlich auch mit osascript oder anderen Skriptsprachen. Für Perl und andere Sprachen funktioniert es ähnlich. Beachten Sie die entsprechende man-Seite zu den Interpretern python, perl, php oder ruby. Eine Vertiefung in andere Skriptsprachen liegt außerhalb dieses Buchthemas. Power User Besonders zu empfehlen ist es, ein Fremdskript, welches von einem Appleskript verwendet wird, im Bundle des Appleskripts abzulegen. So ist zum Beispiel ein ausführbares Pythonskript immer dabei und kann nicht verloren gehen. Mit path to resource können Sie dann im Bundle darauf zugreifen und es starten: do shell script (quoted form of ¬ (POSIX path of (path to resource "getTime.py")))
764
Unix
Kapitel 8
Standardeingabe Der Befehl do shell script kann nicht direkt mit der Standardeingabe der Shell arbeiten. Das bedeutet, dass man sich zum Beispiel mit einem echo weiterhelfen muss. Im folgenden Beispiel wird ein Text an den Shell-Befehl tr weitergereicht, welcher den Text untersucht und die Buchstaben aus dem ersten Argument gegen die aus dem zweiten austauscht. Hier wird dadurch erreicht, dass alles groß geschrieben wird: set theText to quoted form of "änderung" do shell script "echo " & theText & " | tr äöüa-z ÄÖÜA-Z" -- ÄNDERUNG Wenn der Text in einem Dokument vorliegt, kann auch dieses als Standardeingabe verwendet werden: Die Datei muss im Format UTF-8 vorliegen, damit auch die Umlaute umgewandelt werden! set theText to quoted form of "änderung" set theFile to quoted form of "/Users/Detlef/Desktop/hello.txt" do shell script "tr äöüa-z ÄÖÜA-Z" & "< " & theFile -- ÄNDERUNG
Werte über mehrere Aufrufe erhalten Jedes do shell script erzeugt eine neue Instanz der Shell. Sie können daher nicht erwarten, dass noch Werte des letzten Aufrufs in der Shell vorhanden sind. Sie können diese Beschränkung nur umgehen, indem Sie die Werte im Appleskript immer in eine Variable zurückliefern lassen oder in eine Datei schreiben, die Sie dann für den nächsten Befehl wieder auslesen. Alternativ können Sie in einem do shell script auch gleich mehrere Befehle abgeben. Diese müssen nur mit einem Semikolon voneinander getrennt werden: set com1 to "cd ~/Documents" set com2 to "ls -la" do shell script com1 & ";" & com2
Interaktive und dynamische Befehle Der Befehl do shell script ist nicht interaktiv. Sie können ihn daher nicht für Befehle wie telnet und ftp verwenden, die eine Interaktion erfordern oder für Befehle wie top, die dynamisch sind. Manchmal gibt es für diese Befehle aber auch eine Alternative, die nicht dynamisch oder interaktiv ist (bei top die Option -l1). Schauen Sie daher immer in die manSeiten des Befehls oder sehen Sie sich nach alternativen, nicht interaktiven Befehlen um. So können Sie statt ftp zum Beispiel auch curl verwenden. Folgendes do shell script lädt zum Beispiel den AppleScript Langauge Guide als PDF von der Apple-Webseite herunter:
765
SmartBooks
AppleScript
set theInput to quoted form of "http://developer.apple.com/documentation/AppleScript/Conceptual/Apple ScriptLangGuide/AppleScriptLanguageGuide.pdf" set theOutput to quoted form of "/Users/Detlef/Desktop/AppleScriptLanguageGuide.pdf" do shell script "curl " & theInput & "&> " & theOutput
Nicht auf Antwort warten Da so ein Download schon mal einige Zeit dauern kann, ist es auch möglich, das Appleskript nicht auf die Beendigung des Befehls warten zu lassen. Das können Sie erreichen, indem Sie den Befehl noch mit & abschließen: do shell script "curl " & theInput & "&> " & theOutput & " &" Ansonsten ist das Skript für die Dauer des Downloads blockiert. Der Befehl do shell script hat dann allerdings keinen Rückgabewert, und das Appleskript fährt direkt mit dem nächsten Befehl fort, während die Datei von der Shell weiter geladen wird. Für solch einen Hintergrundprozess müssen Standardausgabe und Standard-Fehlerausgabe immer in eine Datei (oder /dev/null) geleitet werden. Durch &> werden Fehlerausgabe und Standardausgabe oben in die Datei theOutput geleitet. Wenn beides getrennt bleiben soll, können Sie das so schreiben: set theInput to quoted form of "http://developer.apple.com/documentation/AppleScript/Conceptual/Apple ScriptLangGuide/AppleScriptLanguageGuide.pdf" set theOutput to quoted form of "/Users/Detlef/Desktop/AppleScriptLanguageGuide.pdf" set theErr to quoted form of "/Users/Detlef/Desktop/err.txt" do shell script "curl " & theInput & " > " & theOutput & " 2> " & theErr & " &"
766
Anhänge A - AppleScript Kurzübersicht 768 B - Quellen
807
SmartBooks
AppleScript
A - AppleScript Kurzübersicht Für die folgenden Tabellen gilt: << In nicht proportionaler Schrift stehen Worte, die genau so geschrieben werden müssen. << In [eckigen Klammern] finden sich optionale Elemente. Deren Angabe ist nur bei Bedarf erforderlich. Die eckigen Klammern werden nicht mitgeschrieben. << Platzhalter werden in kursiver Schrift geschrieben. Sie müssen gegen eine gültige Variable oder einen Ausdruck ersetzt werden. << Mit einem senkrechten Strich getrennte Begriffe, bei mehrwortigen Begriffen zusätzlich von einer Klammer umfasst, z. B. (count|number of), sind mit einem oder verknüpft. Nur einer der Begriffe kann verwendet werden. Die Klammern werden nicht mitgeschrieben. << Drei aufeinander folgende Punkte […] bedeuten, dass von dem davor stehenden Element beliebig viele Wiederholungen folgen können.
Reservierte Wörter Reservierte Wörter about above after against and apart from around as aside from at back before beginning behind
below beneath beside between but by considering contain(s) continue copy div does eighth else 768
end equal(s) error every exit false fifth first for fourth from front get given
global if ignoring in instead of into is it(s) last local me middle mod my
ninth not of on onto or out of over prop, property put ref, reference repeat return returning
Anhänge
Reservierte Wörter script second set seventh since sixth
some tell tenth that the then
third thru, through timeout times to transaction
true try until where while whose
with without
Flusskontrolle tell tell Objekt to Anweisung tell Objekt [Anweisung] […] end [tell] using terms from using terms from Anwendung [Anweisung] […] end [using terms from] if if BoolescherAusdruck then Anweisung if BoolescherAusdruck [then] [Anweisung] […] [else if BoolescherAusdruck [then] [Anweisung] […]] […] [else [Anweisung] […]] end [if]
Das else if kann beliebig oft vorkommen, muss aber immer vor einem eventuell vorhandenen else-Teil stehen. 769
SmartBooks
AppleScript
repeat repeat [Anweisung] […] end [repeat] repeat IntegerAusdruck [times] [Anweisung] […] end [repeat] repeat until BoolescherAusdruck [Anweisung] […] end [repeat] repeat while BoolescherAusdruck [Anweisung] […] end [repeat] repeat with Zählervariable from IntegerStartwert to IntegerStoppwert ¬ [by IntegerSchrittweite] [Anweisung] […] end [repeat] repeat with Zählervariable in Liste [Anweisung] […] end [repeat] Eine Schleife kann jederzeit mit der Anweisung exit [repeat] beendet werden. Bei einer IntegerSchrittweite im Minusbereich wird die Zählervariable von Startwert nach Stoppwert herunter gezählt.
770
Anhänge
try try [Anweisung] […] [on error [Fehlertext][number Fehlernummer][from VerursachendesObjekt]¬ [partial result Ergebnisliste][to ErwarteterTyp] [Anweisung] […]] end [error|try]
error error [Fehlertext][number Fehlernummer][from VerursachendesObjekt]¬ [partial result Ergebnisliste][to ErwarteterTyp]
considering / ignoring (Textvergleich) considering Attribut [,Attribut […] [and Attribut]]¬ [but ignoring Attribut [,Attribut […] [and Attribut]]] [Anweisung] […] end [considering] ignoring Attribut [,Attribut […] [and Attribut]]¬ [but considering Attribut [,Attribut […] [and Attribut]]] [Anweisung] […] end [ignoring] Attribut: case|diacriticals|hyphens|numeric strings|punctuation|white space considering / ignoring (application responses) considering|ignoring application responses [Anweisung] […] end [considering|ignoring]
771
SmartBooks
AppleScript
with timeout with timeout [of] Integer second[s] [Anweisung] […] end [timeout] with transaction with transaction [SessionObjekt] [Anweisung] […] end [transaction] Handler mit Positionsparametern on|to HandlerName([Parameter1Name[,Parameter2Name][…]]) [Anweisungen] […] end [HandlerName] Handler mit benannten Parametern on|to HandlerName [[of|in] DirekterParameterName]¬ [ASLabel ParamName][…]¬ [given BenutzerLabel:ParamName[,BenutzerLabel:ParamName][…]] [Anweisungen] […] end [HandlerName] ASLabel: about|above|against|apart from|around|aside from|at|below|beneath| beside|between|by|for|from|instead of|into|on|onto|out of|over|since| (thru|through)|under Rückgabewerte können explizit mit return [Ausdruck] bestimmt werden, ansonsten ist der Rückgabewert das Ergebnis der letzten Anweisung im Handler. Mit continue HandlerName[ParameterListe] kann die Ausführung an einen gleichnamigen Handler des Elternobjekts delegiert werden.
772
Anhänge
Skriptobjekte script [VariablenName] [property|prop parent : Elternobjekt] [property|prop PropertyName : Anfangswert] […] [Handlerdefinitionen] […] [Weitere Skriptobjekte] […] [Anweisungen] […] end [script]
Operatoren Arithmetische Operatoren +
-
*
/ ÷
Addition. Als binärer Operator addiert er die Zahlen links und rechts von ihm. Zu einem Datum können nur Ganzzahlen addiert werden. Als unärer Operator steht er links vor einer Zahl und gibt an, dass der Wert positiv ist. Fehlt üblicherweise und wird bei der Kompilierung entfernt, da alle Zahlen ohne expliziten unären Operator für negative Zahlen immer als positiv betrachtet werden. Operanden: date, integer, real Ergebnis: date, integer, real Subtraktion. Als binärer Operator subtrahiert er die rechte Zahl von der linken. Von einem Datum können nur Ganzzahlen abgezogen werden. Als unärer Operator steht er links vor einer Zahl und gibt damit an, dass die Zahl negativ ist. Operanden: date, integer, real Ergebnis: date, integer, real Multiplikation. Binär. Multipliziert die Zahlen links und rechts miteinander. Operanden: integer, real Ergebnis: integer, real Division. Binär. Dividiert die Zahl links durch die Zahl rechts von ihm. Das ���������������������������������������������������������������� auf einer deutschen Tastatur durch [alt]+[Umschalt]+[.] erZeichen ÷ wird zeugt. Operanden: integer, real Ergebnis: real
773
SmartBooks
AppleScript
Arithmetische Operatoren div
mod
^
Integrale Division. Binär. Dividiert die Zahl links durch die Zahl rechts von ihm. Liefert nur ganze Teile zurück. Operanden: integer, real Ergebnis: integer Restdivision. Modulo. Binär. Dividiert die Zahl links durch die Zahl rechts von ihm. Liefert als Ergebnis den nicht teilbaren Rest. Operanden: integer, real Ergebnis: integer, real Exponent. Binär. Setzt die Zahl links zum Wert der Zahl rechts hoch. Operanden: integer, real Ergebnis: real
Verknüpfungsoperator &
Binär. Verknüpft die Werte links und rechts von ihm. Ist der linke Operator text, wird versucht, den rechten Wert in text umzuwandeln und dann zu verbinden. Das Ergebnis ist dann text. Ist der linke Wert von der Klasse record, muss der rechte Wert von der Klasse record oder text sein. Das Ergebnis ist dann ein record. Bei jeder anderen Kombination ist das Ergebnis immer eine Liste. Operanden: beliebig Ergebnis: list, record, text
Referenzoperator [a] (ref [to]|reference to)
Unär. Liefert eine Referenz auf das rechts von ihm stehende Objekt zurück. Wird erst während der Laufzeit überprüft. Operand: beliebig Ergebnis: reference
Umwandlungsoperator as
Binär. Wandelt den links stehenden Wert in die rechts stehende Klasse um. Für eine Übersicht der von AppleScript unterstützten Möglichkeiten bitte die Tabelle Umwandlungen beachten. Umwandlungen sind nicht beliebig möglich und hängen davon ab, ob die entsprechende Anwendung sie unterstützt. Operanden: Rechts muss eine Klassenbezeichnung stehen. Der linke Operand muss sich in diese Klasse umwandeln lassen. Ergebnis: Das Ergebnis ist von der Klasse des rechten Operanden
774
Anhänge
Logische Operatoren not
and
or
Verneinung. Unär. Logisches Nicht. Wenn der rechte Operand true ergibt, wird false zurückgeliefert, wenn false, dann true. Operand: boolean Ergebnis: boolean Logisches Und. Binär. Verbindet die booleschen Werte links und rechts von ihm. Ergibt nur true, wenn beide Werte true sind. Wenn der erste Operand bereits false ergibt, wird der zweite daher nicht mehr geprüft. Operand: boolean Ergebnis: boolean Logisches Oder. Binär. Verbindet die booleschen Werte links und rechts von ihm. Ergibt true, wenn einer der beiden Werte true ist. Wenn der erste Operand bereits true ergibt, wird der zweite daher nicht mehr geprüft. Operand: boolean Ergebnis: boolean
Vergleichsoperatoren = equal[s] [is] equal [to]
≠ is not isn't is not equal [to] isn't equal [to] does not equal doesn't equal < [is] less than comes before Verneinungsformen: is not less than isn't less than does not come before doesn't come before
Gleichheit. Binär. Vergleicht den linken mit dem rechten Operanden. Ergibt true, wenn beide denselben Wert haben, ansonsten false. Operanden: beliebig Ergebnis: boolean Ungleichheit. Vergleicht den linken mit dem rechten Operanden. Ergibt true, wenn beide nicht denselben Wert haben, ansonsten false. Das Zeichen ≠ kann auf einer deutschen Tastatur mit dem Tastaturkürzel [alt]+[0] erzeugt werden. Operanden: beliebig Ergebnis: boolean Kleiner als. Binär. Ergibt true, wenn der linke Operand kleiner ist als der rechte, ansonsten false. Beide Operanden müssen von derselben Klasse sein. Wenn das nicht der Fall ist, wird versucht, den rechten Operanden in die Klasse des linken umzuwandeln. Operanden: date, integer, real, text Ergebnis: boolean
775
SmartBooks
AppleScript
Vergleichsoperatoren ≤ <= [is] less than or equal [to] Verneinungsformen: is not less than or equal [to] isn't less than or equal [to]
> [is] greater than comes after Verneinungsformen: is not greater than isn't greater than does not come after doesn't come after ≥ >= [is] greater than or equal [to] Verneinungsformen: is not greater than or equal [to] isn't greater than or equal [to]
776
Kleiner als oder gleich. Binär. Ergibt true, wenn der linke Operand kleiner ist als der rechte oder den gleichen Wert enthält, ansonsten false. Das Zeichen ≤ kann auf einer deutschen Tastatur mit dem Tastaturkürzel [alt]+[<] erzeugt werden. Beide Operanden müssen von derselben Klasse sein. Wenn das nicht der Fall ist, wird versucht, den rechten Operanden in die Klasse des linken umzuwandeln. Operanden: date, integer, real, text Ergebnis: boolean Größer als. Binär. Ergibt true, wenn der linke Operand größer ist als der rechte, ansonsten false. Beide Operanden müssen von derselben Klasse sein. Wenn das nicht der Fall ist, wird versucht, den rechten Operanden in die Klasse des linken umzuwandeln. Operanden: date, integer, real, text Ergebnis: boolean Größer als oder gleich. Binär. Ergibt true, wenn der linke Operand größer ist als der rechte oder den gleichen Wert enthält, ansonsten false. Das Zeichen ≥ kann auf einer deutschen Tastatur mit dem Tastaturkürzel [alt]+[Umschalt]+[<] erzeugt werden. Beide Operanden müssen von derselben Klasse sein. Wenn das nicht der Fall ist, wird versucht, den rechten Operanden in die Klasse des linken umzuwandeln. Operanden: date, integer, real, text Ergebnis: boolean
Anhänge
Inhaltsoperatoren start[s] with begin[s] with Verneinungsformen: does not start with doesn't start with end[s] with Verneinungsformen: does not end with doesn't end with
contain[s] Verneinungsformen: does not contain doesn't contain
is in is contained by Verneinungsformen: is not in is not contained by isn't contained by
Beginnt mit. Binär. Ergibt true, wenn der Operand zur Linken mit dem Operand zur Rechten beginnt, ansonsten false. Beide Operanden müssen von derselben Klasse sein. Wenn das nicht der Fall ist, wird versucht, den rechten Operanden in die Klasse des linken umzuwandeln. Operanden: list, text Ergebnis: boolean Endet mit. Binär. Ergibt true, wenn der Operand zur Linken mit dem Operand zur Rechten endet, ansonsten false. Beide Operanden müssen von derselben Klasse sein. Wenn das nicht der Fall ist, wird versucht, den rechten Operanden in die Klasse des linken umzuwandeln. Operanden: list, text Ergebnis: boolean Enthält. Binär. Ergibt true, wenn der Operand zur Linken den Operand zur Rechten enthält, ansonsten false. Beide Operanden müssen von derselben Klasse sein. Wenn das nicht der Fall ist, wird versucht, den rechten Operanden in die Klasse des linken umzuwandeln. Operanden: list, record, text Ergebnis: boolean Enthalten in. Binär. Ergibt true, wenn der Operand zur Rechten den Operand zur Linken enthält, ansonsten false. Beide Operanden müssen von derselben Klasse sein. Wenn das nicht der Fall ist, wird versucht, den linken Operanden in die Klasse des rechten umzuwandeln. Operanden: list, record, text Ergebnis: boolean
777
SmartBooks
AppleScript
Operatorreihenfolge Rangfolge
Operator
Auswertung
Art
1 2
innen nach außen unär
Gruppierung Plus- oder Minuszeichen vor einer Zahl Exponent Multiplikation und Division
6
() + ^ * / div mod + &
7
as
8
10 11
< ≤ > ≥ = ≠ not and
12
or
3 4
5
9
778
rechts nach links binär links nach rechts
binär links nach rechts binär links nach rechts binär links nach rechts binär keine Reihenfolge
Addition und Subtraktion
binär keine Reihenfolge unär binär links nach rechts binär links nach rechts
Gleichheit, Ungleichheit
Verknüpfungsoperator Umwandlungsoperator Vergleichsoperatoren
logisches Nicht logisches Und logisches Oder
Anhänge
Globale Eigenschaften (Konstanten) von AppleScript und current application Konstante
Beschreibung
AppleScript
Bezug auf das Skriptobjekt «script AppleScript», welches parent eines im Skripteditor geöffneten Skripts ist. Ermöglicht den Zugriff auf globale Propertys von AppleScript, selbst wenn der entsprechende Bezeichner im aktuellen Kontext bereits verwendet wird. Beispiel: text item delimiters of AppleScript AppleScript's version Die Klasse des Objekts, zum Beispiel: «script» Die Zwischenablage des aktuellen Programms Die erste Instanz in der Vererbungshierarchie eines Skripts. Das erste Objekt/Klasse, von dem alle anderen abstammen. Wird das Skript aus einem Editor oder Programm heraus gestartet, ist current application der Editor oder das Programm, zum Beispiel der Skripteditor oder iTunes. Ist das Skript als Programm abgespeichert worden, ist das Skriptprogramm seine eigene current application. Die Anzahl Sekunden eines Tages: 86400 Der boolesche Wert Unwahr
class clipboard current application
days false hours it linefeed
me minutes missing value parent
Die Anzahl Sekunden einer Stunde: 3600 Zielbezug. Steht für das aktuelle Ziel, zum Beispiel: application "Finder" Das Unix-Zeilenende ASCII 10 Als Escape-Zeichen: "\n" Selbstbezug. Steht für das aktuelle Skript, zum Beispiel: «script joe» Die Anzahl Sekunden einer Minute: 60 Platzhalter für fehlende Werte, zum Beispiel in einem record Die Eltern eines Skriptobjekts. Ein Skriptobjekt in einem Skript hat «script» (das im Editor geöffnete Skript) als parent, das Skript selber hat das «script AppleScript» als parent, welches wiederum current application als parent hat.
779
SmartBooks
AppleScript
Konstante
Beschreibung
pi quote
Die Zahl Pi: 3.14159265359 Das Zeichen " ASCII 34 Als Escape-Zeichen: "\"" Enthält immer das Ergebnis der letzten Anweisung Das Absatzende ASCII 13 Als Escape-Zeichen: "\r" Die aktuell im Programm sichtbare Auswahl Das Leerzeichen ASCII 32 Als Zeichen: " " Der Tabulator ASCII 9 Als Escape-Zeichen: "\t" Trennzeichen für Text Standardwert: {""} Der boolesche Wert Wahr
result return
selection space
tab
text item delimiters true version weeks
Die Version von AppleScript, zum Beispiel "2.0.1" Die Anzahl Sekunden in einer Woche: 604800
Bezugsformen Name
Beschreibung
Name
class [named] NamensText Wählt ein Objekt anhand seines Namens aus. Beispiel: window "Macintosh HD" mailbox named "Privat" application "Mail" tell app "Finder" to activate Finder window named "Macintosh HD" tell application "Mail" to get messages of mailbox "Privat"
780
Anhänge
Name
Beschreibung
ID
class id Ausdruck Wählt ein Objekt anhand seiner Property id aus. Funktioniert nur mit Programmobjekten, die über eine ID-Property verfügen. Beispiel:
Index
tell app "Finder" to activate Finder window id 33 tell application id "com.apple.finder" to activate class [index] integer integer(st|nd|rd|th) class (first|second|third|fourth|fifth|sixth|seventh|eighth|¬ ninth|tenth) class (last|front|back) class Wählt ein Objekt anhand seiner Position in einem Container aus. Ein negativer Index zählt vom Ende, statt vom Anfang. Beispiel:
Zufällig
item 2 of {1, 2.5, 3, 4.5} item index 3 of {1, 2.5, 3, 4.5} real -2 of {1, 2.5, 3, 4.5} 2nd word of "Klarheit, Kürze, Klang" third character of "ABC" front character of "ABC" some class Wählt ein zufälliges Objekt der angegebenen Klasse aus. Beispiel:
Mitte
some integer of {1, 2.5, 3, 4.5, 5} tell application "Mail" to get some message of inbox middle class Wählt das mittlere Objekt in einem Container aus. Die Mitte wird berechnet, indem die Hälfte der Anzahl der Objekte aufgerundet wird. Bei einer geraden Anzahl an Elementen wird daher das Element vor der Mitte ausgewählt. Diese Form findet nur sehr selten Verwendung. Beispiel: middle integer of {1, 2, 3, 4.5} tell application "Mail" to get middle message of inbox
781
SmartBooks
AppleScript
Name
Beschreibung
Property
propertyName Wählt eine Eigenschaft eines Objektes aus. Wenn implementiert, können alle Eigenschaften eines Objekts mit Abfrage der Eigenschaft properties ermittelt werden. Beispiel:
Relativ
tell application "Finder" Finder window "Macintosh HD"'s position end tell tell application "Mail" properties of message 1 of inbox end tell [class](before|[in] front of) Bezugsobjekt [class](after|[in] back of|behind) Bezugsobjekt Wählt ein Objekt oder eine Einfügeposition in einem Container anhand der Position eines anderen Objekts in diesem Container aus. Wenn [class] weggelassen wird, wird damit nur die Position (insertion point) bestimmt und kein Element im Container ausgewählt. Die Wörter before und in front of beziehen sich auf das Element vor dem Bezugsobjekt. Die Wörter after, in back of und behind beziehen sich auf das Element hinter dem Bezugsobjekt. Es können auch die Wörter beginning und front verwendet werden, um sich auf die erste Einfügeposition am Anfang eines Containers zu beziehen, sowie die Wörter end und back für die letzte Einfügeposition des Containers. Funktioniert nur dort, wo auch die Index-Referenzform funktioniert. Funktioniert nicht mit den grundlegenden AppleScript-Klassen wie list oder text. Beispiel: tell document 1 of application "TextEdit" word before word 2 character after character 2 copy word 5 to in front of word 1 copy word 1 of paragraph 1 to after word 3 of paragraph 2 copy word 5 to beginning copy word 5 to end end tell
782
Anhänge
Name
Beschreibung
Alle
every class classes Wählt alle Objekte der angegebenen Klasse aus. Beispiel:
Bereich
every integer of {1, 2.5, 3, 4.5} integers of {1, 2.5, 3, 4.5} tell application "Mail" to get every message of inbox tell application "Mail" to get messages of inbox every class from Anfangspunkt to Endpunkt classes from Anfangspunkt to Endpunkt class StartIndex (thru|through) StopIndex classes StartIndex (thru|through) StopIndex Wählt Objekte einer Klasse aus einem Bereich eines Containers aus. Für das erste Element kann auch beginning oder front verwendet werden und für das letzte end oder back. Ein negativer Index zählt von hinten. Beispiel:
Filter
every integer from 1 to 2 of {1, 2.5, 3, 4} integers from beginning to 2 of {1, 2.5, 3, 4} text -2 thru -4 of "Hallo" tell application "Finder" document files 1 through 3 of desktop end tell Objektreferenz whose|where BoolescherAusdruck Wählt alle Objekte oder Eigenschaften dieser Objekte aus, welche den Testkriterien im Booleschen Ausdruck entsprechen. Funktioniert nur bei Programmobjekten und dann auch nur, wenn dies von der Anwendung unterstützt wird. Funktioniert nicht mit den grundlegenden AppleScript-Typen wie list oder record. Beispiel: tell application "Mail" tell inbox every message whose sender contains "Admin" subject of first message where sender contains "Admin" end tell end tell
783
SmartBooks
AppleScript
Befehle Übersicht über alle Befehle aus dem Kern der AppleScript-Sprache und den Standarderweiterungen. Hat ein Befehl mehrere Parameter, so wird jeder auf einer neuen Zeile eingerückt dargestellt. Im Code wird natürlich alles auf einer Zeile geschrieben. Befehle activate application ASCII character integerVon0-255 ASCII number Text_NurEinZeichen beep [integer] choose application [with title text] [with prompt text] [multiple selections allowed boolean] [as application|alias] choose color [default color RGBcolor] choose file [with prompt text] [of type list_UniformTypeIdentifiersOderFileTypes] [default location alias] [invisibles boolean] [multiple selections allowed boolean] [showing package contents boolean] choose file name [with prompt text] [default name text] [default location alias]
784
Anhänge
Befehle choose folder [with prompt text] [default location alias] [invisibles boolean] [multiple selections allowed boolean] [showing package contents boolean] choose from list list [with title text] [with prompt text] [default items list] [OK button name text] [cancel button name text] [multiple selections allowed boolean] [empty selection allowed boolean] choose remote application [with title text] [with prompt text] choose URL [showing list_ServiceTypeConstantsOderBonjourServiceTypes] [editable URL boolean] clipboard info [for class] close access (alias|file|file descriptor) copy WertOderAusdruck to VariableOderVariablenmuster (count|number of) Ausdruck current date delay [number_Sekunden]
785
SmartBooks
AppleScript
Befehle display alert text [message text] [as informational|warning|critical] [buttons list_Knopfnamen] [default button text_Knopfname|integer_Knopfindex] [cancel button text_Knopfname|integer_Knopfindex] [giving up after integer_Sekunden] display dialog text [default answer text] [hidden answer boolean] [buttons list_Knopfnamen] [default button text_Knopfname|integer_Knopfindex] [cancel button text_Knopfname|integer_Knopfindex] [with title text] [with icon [stop|note|caution]|[text_ResName|integer_ResID]|[alias|file]] [giving up after integer_Sekunden] do shell script text [as class_desErgebnisses] [administrator privileges boolean] [user name text] [password text] [altering line endings boolean] get Ausdruck [as class_desErgebnisses] get eof (alias|file|file descriptor) get volume settings info for alias|file [size boolean] launch application list disks
786
Anhänge
Befehle list folder alias|file [invisibles boolean] load script alias|file localized string text [from table text_NameDerTextatei] [in bundle alias|file] log [WertOderAusdruck] mount volume text_NameOderURL [on server text] [in AppleTalk zone text] [as user name text] [with password text] offset of text in text open for access alias|file [write permission boolean] open location text_URL [error reporting boolean] path to [application|current application|frontmost application|it|me] [as alias|text]
787
SmartBooks
AppleScript
Befehle path to (apple menu|application suppor t|applications folder|control panels|control strip modules|desktop|desktop pictures folder|documents folder|downloads folder|extensions|favorites folder|Folder Action scripts|fonts|help|home folder|internet plugins|keychain folder|launcher items folder|library folder|modem scripts|movies folder|music folder|pictures folder|preferences|printer descriptions|printer drivers|printmonitor|public folder|scripting additions|scripts folder|shared documents|shared libraries|shutdown folder|sites folder|speakable items|startup disk|startup items|stationery|system folder|system preferences|temporary items|trash|users folder|utilities folder|voices|workflows folder) [from (system domain|local domain|network domain|user domain|Classic domain)] [as alias|text] [folder creation boolean] path to resource text [in bundle alias|file] [in directory text_NameDesOrdners] random number [from number] [to number] [with seed number] read (alias|file|file descriptor) [from integer_Byte] [for integer_Bytes] [to integer_Byte|eof] [before text_EinzelnesZeichen] [until text_EinzelnesZeichen] [using delimiter text_EinzelnesZeichen] [using delimiters list_MitEinzelnenZeichen] [as class] round real [rounding (up|down|toward zero|to nearest|as taught in school)] run [script|application]
788
Anhänge
Befehle run script text|alias|file [with parameters list] [in text_NameDerSkriptkomponente] say text [displaying text] [using text_NameDerSystemstimme] [waiting until completion boolean] [saving to alias|file] scripting components set VariableOderVariablenmuster to WertOderAusdruck set eof (alias|file|file descriptor) to integer_Bytes set the clipboard to anything set volume [number_Von0-7] [output volume integer_Von0-100] [input volume integer_Von0-100] [alert volume integer_Von0-100] [output muted boolean] store script script [in alias|file] [replacing yes|no|ask] summarize text|alias [in integer_AnzahlSätze] system attribute [text_Gestaltwert|text_Umgebungsvariable] [has integer_Bitmaske] system info
789
SmartBooks
AppleScript
Befehle the clipboard [as class] time to GMT write irgendetwas [to (alias|file|file descriptor)] [starting at integer_Byte] [for integer_Byte] [as class]
Basisklassen Klasse
Eigenschaften PropName (PropKlasse, Lese-/Schreibrechte) – Kurzbeschreibung der Property get = Leseberechtigung; set = Schreibberechtigung
alias
Referenz auf eine Datei, Ordner oder Dateisystem. Muss bereits existieren. Propertys: class (class, get) – Der Wert selbst ist immer von der Klasse alias. POSIX path (text, get) - Der POSIX-Pfad der Datei Eine Anwendung auf einem lokalen Rechner oder einem Server Propertys: class (class, get) – Der Wert selbst ist immer von der Klasse application frontmost (boolean, get) – Ist die Anwendung vorne? id (text, get) – Der Bundle-Identifier der Anwendung name (text, get) – Der Name der Anwendung running (boolean, get) – Läuft das Programm? version (text, get) - Die Programmversion Ein Wahrheitswert. Es gibt nur zwei Werte, die ohne Umwandlung als boolean erkannt werden: die globalen Konstanten true und false. Propertys: class (class, get) – Der Wert selbst ist immer von der Klasse boolean. Die Klasse eines Wertes. Alle Objekte haben diese Klasse auch als Eigenschaft. Propertys: class (class, get) – Der Wert selbst ist immer von der Klasse class.
application
boolean
class
790
Anhänge
Klasse
Eigenschaften PropName (PropKlasse, Lese-/Schreibrechte) – Kurzbeschreibung der Property get = Leseberechtigung; set = Schreibberechtigung
constant
Ein Schlüsselwort mit einem festen Wert. Kann nicht selbst definiert werden, sondern nur von AppleScript, Skripterweiterungen und Programmen. Propertys: class (class, get) – Der Wert selbst ist immer von der Klasse constant. Ein Zeitpunkt. Besteht aus Wochentag, Datum und Uhrzeit Propertys: class (class, get) – Der Wert selbst ist immer von der Klasse date. year (integer, get/set) – Vierstellige Jahreszahl month (constant, get/set) – Monat als Konstante. Mögliche Werte: January|February|March|April|May|June|July|August| September|October|November|December day (integer, get/set) – Tag des Monats weekday (constant, get) – Wochentag als Konstante. Mögliche Werte: Monday|Tuesday|Wednesday|Thursday|Friday|Saturday| Sunday hours (integer, get/set) – Der Stundenanteil der Uhrzeit minutes (integer, get/set) – Der Minutenanteil der Uhrzeit seconds (integer, get/set) – Der Sekundenanteil der Uhrzeit time (integer, get/set) – Die Anzahl Sekunden seit Mitternacht date string (text, get) – Der Datumsteil als langer Text short date string (text, get) – Der Datumsteil als kurzer Text time string (text, get) – Die Uhrzeit als Text Referenz auf eine Datei, einen Ordner oder ein Dateisystem. Muss noch nicht existieren. Propertys: class (class, get) – Der Wert selbst ist immer von der Klasse file. POSIX path (text, get) - Der POSIX-Pfad der Datei Eine Ganzzahl aus dem Bereich ±536870911 Propertys: class (class, get) – Der Wert selbst ist immer von der Klasse integer.
date
file
integer
791
SmartBooks
AppleScript
Klasse
Eigenschaften PropName (PropKlasse, Lese-/Schreibrechte) – Kurzbeschreibung der Property get = Leseberechtigung; set = Schreibberechtigung
list
Eine geordnete Menge von Werten. Die Werte werden als item bezeichnet. Propertys: class (class, get) – Der Wert selbst ist immer von der Klasse list. length (integer, get) – Die Anzahl der Elemente in der Liste rest (list, get) – Alle Elemente der Liste außer dem ersten reverse (list, get) – Alle Elemente der Liste in umgekehrter Reihenfolge Abstrakte Klasse, welche für integer oder real stehen kann. Propertys: class (class, get) – Der Wert selbst ist immer von der Klasse integer oder real. Pseudo-Klasse, siehe file! Eine Dezimalzahl aus dem Bereich ±1.797693e+308 Propertys: class (class, get) – Der Wert selbst ist immer von der Klasse real. Eine ungeordnete Menge von benannten Werten. Die einzelnen Namen/Werte-Paare werden als property bezeichnet. Der Zugriff auf die Werte erfolgt über den Namen. Neben der Klasse script die einzige Möglichkeit, eigene Propertys anzulegen. Propertys: class (class, get) – Der Wert selbst ist immer von der Klasse record. length (integer, get) – Die Anzahl der Elemente im record. Enthält die Adresse zu einem Objekt. Resultat des a reference to-Operators Propertys: Die Property class lässt sich bei einem reference-Objekt nicht abfragen, da jede Abfrage bei einer reference immer an das Zielobjekt weitergeleitet wird mit Ausnahme der Property contents. Sie wird verwendet, um eine reference wieder aufzulösen und wieder auf das Objekt selbst Bezug zu nehmen. Eine Liste mit drei Integerwerten im Bereich von 0 bis 65535. Die drei Werte stehen für die Farben Rot, Grün und Blau. Propertys: siehe list!
number
POSIX file real
record
reference
RGB color
792
Anhänge
Klasse
Eigenschaften PropName (PropKlasse, Lese-/Schreibrechte) – Kurzbeschreibung der Property get = Leseberechtigung; set = Schreibberechtigung
script
Eine Menge von Anweisungen, die als Gruppe ausgeführt werden kann. Propertys: class (class, get) – Der Wert selbst ist immer von der Klasse script. Eine geordnete Menge von Unicode-Zeichen. Die Klassen string und Unicode text sind Synonyme für text. Ein Text kann die Elemente character, word, paragraph, text item und text enthalten. Propertys: class (class, get) – Der Wert selbst ist immer von der Klasse text. id (integer|list (of integers), get) – Der dezimale Unicode-Wert der Zeichen length (integer, get) – Die Anzahl Zeichen im Text quoted form (text, get) – Der Text in einfachen Anführungszeichen für die nicht interpretierte Verwendung in einer Unix Shell Unit types ist keine Klasse an sich, sondern eine Gruppe von Maßeinheiten-Klassen, die alle nur die class-Property besitzen. Propertys: class (class, get) – Der Wert selbst ist immer von einer der folgenden Klassen: Längenmaße: centimetres, centimeters, feet, inches, kilometres, kilometers, metres, meters, miles, yards Flächenmaße: square feet, square kilometres, square kilometers, square metres, square meters, square miles, square yards Volumenmaße: cubic centimetres, cubic centimeters, cubic feet, cubic inches, cubic metres, cubic meters, cubic yards Flüssigkeitenmaße: gallons, litres, liters, quarts Gewichtsmaße: grams, kilograms, ounces, pounds Temperaturmaße: degrees Celsius, degrees Fahrenheit, degrees Kelvin
text
unit types
793
SmartBooks
AppleScript
Umwandlungen Von Klasse
In Klasse
alias
list (mit einem Element) text list (mit einem Element) integer list (mit einem Element) text list (mit einem Element) text list (mit einem Element) text list (mit einem Element) text list (mit einem Element) text list (mit einem Element) real text Abhängig von der Klasse des Elements in der Liste
application boolean
class constant date file integer
list (ein Element) list (mehrere Elemente) number POSIX file real record reference RGB color script text
794
text (nur wenn jedes Element der Liste in text umgewandelt werden kann!) (Es gibt keinen Wert mit dieser Klasse, sondern nur Werte der Klassen integer oder real.) (POSIX file ist eine Pseudo-Klasse von file, daher wie file.) integer (wird gerundet) list (mit einem Element) list (die Bezeichner aus dem record gehen verloren) (Abhängig von der Art des Objekts auf welches die Adresse zeigt) (RGB color ist eine Pseudo-Klasse von list, daher wie list.) list (mit einem Element) integer list (mit einem Element) real
Anhänge
Von Klasse
In Klasse
unit types
integer list (mit einem Element) real text (Unit types können innerhalb einer Kategorie – Längenmaße, Gewichtsmaße, etc. – ineinander umgewandelt werden.)
795
796
Reichweite lokaler Variablen
In den folgenden Diagrammen stehen die hellen Flächen für die Bereiche im Code, in denen die an dem Pfeil deklarierte Variable erreichbar ist.
Reichweite von Variablen
SmartBooks AppleScript
797
Reichweite einfacher Variablen
Anhänge
798
Reichweite globaler Variablen
SmartBooks AppleScript
799
1) Positionsabhängig! Funktioniert nur, wenn der Handler nach dem Skriptobjekt steht.
Reichweite von Propertys
Anhänge
SmartBooks
AppleScript
Mac OS Roman Kodierung ASCII Zeichen ASCII Zeichen ASCII Zeichen ASCII Zeichen ASCII Zeichen
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
(NUL) (SOH) (STX) (ETX) (EOT) (ENQ) (ACK) (BEL) (BS) (HT) (LF) (VT) (FF) (CR) (SO) (SI) (DLE) (DC1) (DC2) (DC3) (DC4) (NAK) (SYN) (ETB) (CAN) (EM) (SUB) (ESC)
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
800
(FS) (GS) (RS) (US) (SP) ! " # $ % & ' ( ) * + , . / 0 1 2 3 4 5 6 7
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
p q r s t u v w x y z { | } ~ (DEL) Ä Å Ç É Ñ Ö Ü á à â ä ã
Anhänge
ASCII Zeichen ASCII Zeichen ASCII Zeichen ASCII Zeichen ASCII Zeichen
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
å ç é è ê ë í ì î ï ñ ó ò ô ö õ ú ù û ü † ° ¢ £
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
§ • ¶ ß
® © ™ ´ ¨ ≠ Æ Ø ∞ ± ≤ ≥ ¥ µ ∂ ∑ ∏ π ∫ ª
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
º Ω æ ø ¿ ¡ ¬ √ ƒ ≈ ∆ « » … À Ã Õ Œ œ – — “ ”
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
‘ ’ ÷ ◊ ÿ Ÿ ⁄ € ‹ › fi fl ‡ · ‚ „ ‰ Â Ê Á Ë È Í Î
801
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
Ï Ì Ó Ô
Ò Ú Û Ù ı ˆ ˜ ¯ ˘ ˙ ˚ ¸ ˝ ˛ ˇ
SmartBooks
AppleScript
Key Codes Die Werte der folgenden Tabelle stammen aus der Header-Datei Events.h der Xcode-Entwicklungsumgebung. Die Werte in dieser Datei sind jedoch in hexadezimaler Schreibweise dargestellt und gelten für die amerikanische Tastatur. Hier daher eine dezimale Darstellungsweise für deutsche Tastaturen. Nicht alle Tastencodes lassen sich auch mit dem Befehl key code verwenden. Taste
Code Taste
Code Taste
Code Taste
Code
A B C D E F G H I J K L M N O P Q R S T U V W X Y (US: Z ) Z (US: Y ) Ä (US: ' ) Ö (US: ; ) Ü (US: [ )
0 11 8 2 14 3 5 4 34 38 40 37 46 45 31 35 12 15 1 17 32 9 13 7 6 16 39 41 33
30 42 43 47 44 50 10 18 19 20 21 23 22 26 28 25 29 27 24 53 122 120 99 118 96 97 98 100 101
109 103 111 105 107 113 106 64 79 80 90 48 57 56 59 58 55 49 51 36 60 61 62 63 74 72 73 82 83
84 85 86 87 88 89 91 92 65 71 81 75 67 78 69 76 114 115 116 117 119 121 123 124 125 126
+ (US: ] ) # (US: \ ) , . - (US: / ) < (US: `) ^ 1 2 3 4 5 6 7 8 9 0 ß (US: - ) ´ (US: = ) Escape F1 F2 F3 F4 F5 F6 F7 F8 F9
802
F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 Tab Caps Lock Shift Control Option Command Space Delete Return Right Shift Right Option Right Control Function Mute Volume up Volume down Keypad 0 Keypad 1
Keypad 2 Keypad 3 Keypad 4 Keypad 5 Keypad 6 Keypad 7 Keypad 8 Keypad 9 Keypad . Keypad Clear Keypad = Keypad / Keypad * Keypad Keypad + Keypad Enter Help Home Page Up Forward Delete End Page Down Left Arrow Right Arrow Down Arrow Up Arrow
Anhänge
AppleScript Fehlermeldungen error #
Fehlertext englisch
Fehlertext deutsch
-2700 -2701
Unknown error. Can’t divide by zero.
-2702
The result of a numeric operation was too large. can't be launched because it is not an application. isn't scriptable.
Unbekannter Fehler kann nicht durch Null geteilt werden. Das Ergebnis der Berechnung ist zu groß. kann nicht gestartet werden, da es kein Programm ist. unterstützt AppleScript nicht. Das Funktionsverzeichnis des Programms ist beschädigt. Der Stack ist übergelaufen. Die interne Tabelle ist übergelaufen. Es wurde versucht, einen Wert größer als erlaubt zu erstellen. Das Event-Verzeichnis des Programms konnte nicht gelesen werden. kann nicht gleichzeitig beachtet und ignoriert werden. Es können keine Operationen auf Texten mit mehr als 32 kB durchgeführt werden. Die Nachricht ist für den 7.0 Finder zu groß. <Sprachelement> kann nicht diesem <Sprachelement> folgen. Es wurde <Sprachelement> erwartet, aber ein <Sprachelement> wurde gefunden. Der -Parameter wurde mehr als ein Mal angegeben. Die -Eigenschaft wurde mehr als ein Mal angegeben.
-2703 -2704 -2705 -2706 -2707 -2708 -2709
-2720 -2721
-2729 -2740 -2741
-2750 -2751
The application has a corrupted dictionary. Stack overflow. Internal table overflow. Attempt to create a value larger than the allowable size. Can't get the event dictionary.
Can't both consider and ignore . Can't perform operation on text longer than 32K bytes. Message size too large for the 7.0 Finder. A can't go after this . Expected but found . The parameter is specified more than once. The property is specified more than once.
803
SmartBooks
AppleScript
error #
Fehlertext englisch
Fehlertext deutsch
-2752
The handler is specified more than once. The variable is not defined.
Die -Routine wurde mehr als ein Mal angegeben. Die Variable ist nicht definiert. kann nicht deklariert werden, da es sowohl eine lokale als auch eine globale Variable ist. Der „Exit“-Befehl befindet sich nicht in einer „repeat“-Schleife. Die „Tell“-Befehle sind zu tief verschachtelt. ist als formaler Parameter nicht zulässig. ist kein Parameter-Name für den Event <Event>. Ein Teil dieses Ausdrucks lieferte kein Ergebnis.
-2753 -2754
Can't declare as both a local and global variable.
-2755
Exit statement was not in a repeat loop. Tell statements are nested too deeply. is illegal as a formal parameter. is not a parameter name for the event <event>. No result was returned for some argument of this expression.
-2760 -2761 -2762 -2763
804
Anhänge
Fehlermeldungen des Betriebssystems error #
Fehlertext englisch
0 -34 -35
No error. Disk full. Disk wasn’t found.
-37 -38 -39 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -61 -108 -120 -124 -128 -192
Fehlertext deutsch
Kein Fehler Das Volume ist voll. Das Volume wurde nicht gefunden. Bad name for file. Ungültiger Dateiname für File wasn’t open. Die Datei ist nicht geöffnet. End of file error. Ende der Datei erreicht. Too many files open. Zu viele Dateien geöffnet. File wasn’t found. Die Datei wurde nicht gefunden. Disk is write protected. Das Volume ist schreibgeschützt. File is locked. Die Datei ist geschützt. Disk is locked. Das Volume ist geschützt. File is busy. Die Datei ist in Verwendung. Duplicate file name. Doppelter Dateiname für File is already open. Die Datei ist bereits geöffnet. Parameter error. Parameterfehler File reference number error. Fehler in der Dateinummer (File reference number) File not open with write permission. Die Datei ist nicht mit Schreibberechtigung geöffnet. Out of memory. Kein Speicher mehr verfügbar. Folder wasn’t found. Der Ordner wurde nicht gefunden. Disk is disconnected. Das Volume wurde deaktiviert. User cancelled. Vom Benutzer abgebrochen. A resource wasn’t found. Eine Ressource wurde nicht gefunden. 805
SmartBooks
AppleScript
error #
Fehlertext englisch
-600 -601
Application isn’t running Das Programm läuft nicht. Not enough room to launch applica- Es ist nicht genügend Speicher vertion with special requirements. fügbar, um das Programm mit besonderen Anforderungen zu öffnen. Application is not 32-bit clean. Das Programm ist nicht 32-Bit-fähig. More memory needed than is speci- Es wird mehr Speicher benötigt, als fied in the size resource. in der „size“-Ressource angegeben wurde. Application is background-only. Das Programm ist ein Hintergrundprozess. Buffer is too small. Der Puffer ist zu klein. No outstanding high-level event. Es wird kein High-Level-Event mehr erwartet. Connection is invalid. Die Verbindung ist ungültig. Not enough system memory to con- Es ist nicht genügend Systemspeinect to remote application. cher verfügbar, um eine Verbindung zum entfernten Programm aufzubauen. Remote access is not allowed. Zugriff von außen ist nicht zugelassen. isn’t running or program läuft nicht oder die Prolinking isn’t enabled. grammverbindungen sind deaktiviert. Can’t find remote machine. Der entfernte Computer wurde nicht gefunden. Invalid date and time . Datum und Uhrzeit sind ungültig: .
-602 -605
-606 -607 -608 -609 -904
-905 -906
-915 -30720
806
Fehlertext deutsch
Anhänge
B - Quellen Die Links auf den folgenden Seiten finden Sie auch direkt zum Anklicken auf der Webseite http://www.skripteditor.de.
AppleScript bei Apple Die AppleScript-Quellen bei Apple liegen fast ausnahmslos nur in englischer Sprache vor. << Die offizielle AppleScript-Seite mit einigen Beispielskripts: http://www.apple.com/applescript/ << AppleScript Seite zu den Image-Events: http://www.apple.com/applescript/imageevents/ << GUI-Scripting: http://www.apple.com/applescript/uiscripting/index.html << Grundlegende Handler von Apple: http://www.apple.com/applescript/sbrt/index.html << Für die offizielle AppleScript-Mailingliste (in englischer Sprache) kann man sich hier anmelden: http://www.lists.apple.com/mailman/listinfo/applescript-users Man bekommt dann alle neuen Beiträge in dieser Gruppe automatisch per E-Mail zugesandt. << Alte Beiträge kann man über folgenden Link im Archiv suchen und finden: http://www.lists.apple.com/archives/AppleScript-Users << Weitere Mailing-Listen von Apple mit Bezug zu Applescript sind die Listen Applescript-implementors für alle Programmierer, die ihre Programme skriptbar machen wollen, und AppleScript-Studio. Diese – und alle anderen Mailinglisten von Apple – sind immer über folgenden Link erreichbar: http://www.lists.apple.com/mailman/listinfo/
Links auf den Entwicklerseiten von Apple << Übersicht aller Dokumente, die einen Bezug zu AppleScript haben: http://developer.apple.com/referencelibrary/ScriptingAutomation/idxAppleScriptdate.html#doclist
807
SmartBooks
AppleScript
<< Der Link zum AppleScript Language Guide: http://developer.apple.com/documentation/AppleScript/Conceptual/ AppleScriptLangGuide/index.html << Der unverzichtbare UI Element Inspector für das GUI Scripting: http://developer.apple.com/samplecode/UIElementInspector/ << Release-Notes zu AppleScript 2.0 in Leopard: http://developer.apple.com/releasenotes/AppleScript/RN-AppleScript/index.html << Release-Notes zu älteren AppleScript-Versionen: http://developer.apple.com/releasenotes/ScriptingAutomation/RN-AppleScriptOlder/ index.html << Die Dokumentation zum Befehl do shell script: http://developer.apple.com/technotes/tn2002/tn2065.html << Übersicht und Einführung in die Grundlagen von AppleScript: http://developer.apple.com/documentation/AppleScript/Conceptual/AppleScriptX/ index.html << Der XML-RPC und SOAP Programming Guide: http://developer.apple.com/documentation/AppleScript/Conceptual/ soapXMLRPC/index.html << Wie ein Bundle organisiert ist, beantwortet der Bundle Programming Guide: http://developer.apple.com/documentation/CoreFoundation/Conceptual/CFBundles/ CFBundles.html << Uniform Type Identifiers zur Verwendung mit dem Befehl choose file: http://developer.apple.com/documentation/Carbon/Conceptual/understanding_utis << Bonjour Service Types zur Verwendung mit dem Befehl choose URL: http://developer.apple.com/qa/qa2001/qa1312.html << Die Gestalt Manager Reference zur Verwendung mit dem Befehl system attribute: http://developer.apple.com/documentation/Carbon/Reference/Gestalt_Manager/ << Dokumentation zu Metadata und Queries in Spotlight: http://developer.apple.com/documentation/Carbon/Reference/MetadataAttributesRef/ MetadataAttrRef.html http://developer.apple.com/documentation/Carbon/Conceptual/SpotlightQuery/ Concepts/QueryFormat.html << Dokumentation zu den Property List Keys zur Bearbeitung der Datei info.plist in einem Skriptprogramm-Bundle: http://developer.apple.com/documentation/MacOSX/Conceptual/BPRuntimeConfig/ Articles/PListKeys.html 808
Anhänge
<< Hilfreiche Einführung ins Konzept der Accessibility-API und den Roles für das GUI-Scripting: http://developer.apple.com/documentation/Accessibility/Conceptual/ AccessibilityMacOSX/ << Einführung in launchd und die man-Pages zu launchd als Webseite: http://developer.apple.com/macosx/launchd.html http://developer.apple.com/documentation/Darwin/Reference/ManPages/man8/ launchd.8.html http://developer.apple.com/documentation/Darwin/Reference/ManPages/man5/ launchd.plist.5.html
Links zu Automator << Automator-Aktionen mit AppleScript selbst erstellen: http://developer.apple.com/documentation/AppleApplications/Conceptual/ AutomatorTutorialAppleScript/index.html << Beispiel zu einer mit AppleScript erstellten Automator-Aktion: http://developer.apple.com/samplecode/DuplicateFinderItems/index.html
Links zu AppleScript Studio << Der AppleScript Studio Programming Guide: http://developer.apple.com/documentation/AppleScript/Conceptual/ StudioBuildingApps/index.html << AppleScript Studio Release-Notes für Leopard: http://developer.apple.com/releasenotes/AppleScript/RN-AppleScriptStudio/index.html << Die AppleScript Studio Terminology Reference: http://developer.apple.com/documentation/AppleScript/Reference/StudioReference/ index.html << Beispielprojekt zu AppleScript Studio: http://developer.apple.com/samplecode/ScriptView/index.html << Kleine Anleitung, wie man in AppleScript Studio auf Ressourcen im ProgrammBundle zugreift: http://developer.apple.com/qa/qa2006/qa1493.html
Links für Entwickler, die ihr Programm skriptbar machen wollen << Die Open Scripting Architecture Reference: http://developer.apple.com/documentation/Carbon/Reference/Open_Scripti_ Architecture/index.html 809
SmartBooks
AppleScript
<< Cocoa and AppleScript: From Top to Bottom: http://developer.apple.com/cocoa/applescriptforapps.html << Technical Note TN2106 – Scripting Interface Guidelines http://developer.apple.com/technotes/tn2002/tn2106.html << Der Cocoa-Scripting Guide: http://developer.apple.com/documentation/Cocoa/Conceptual/ ScriptableCocoaApplications/index.html << Der Apple Events Programming Guide: http://developer.apple.com/documentation/AppleScript/Conceptual/AppleEvents/ index.html << Apple Event Manager Reference: http://developer.apple.com/documentation/Carbon/Reference/Apple_Event_ Manager/index.html << Liste aller von Apple verwendeten Apple-Event-Raw-Codes: http://developer.apple.com/releasenotes/AppleScript/ASTerminology_AppleEventCodes/ TermsAndCodes.html
AppleScript im Internet Nicht nur Apple selber, auch der Rest der Internetwelt spricht hauptsächlich englisch, wenn es um AppleScript geht. Trotzdem gibt es auch eine rege AppleScript-Gemeinschaft in deutschsprachigen Landen, die sich unter anderem auf den folgenden Seiten austauscht. Die Links sind meine persönliche, ganz subjektive Auswahl. Es gibt sicher noch eine Reihe weiterer guter Links, und man möge mir daher verzeihen, wenn ich den einen oder anderen vergessen habe.
Deutschsprachige Webseiten << Die Webseite zum Buch mit allen Links, Codebeispielen, aktuellen Informationen, mit einem Forum für Fragen an den Autor und für den Austausch untereinander: http://www.skripteditor.de << Artikel von mir zum Thema AppleScript auf ratschlag24.com: http://www.ratschlag24.com/index.php/tag/applescript/ << Fischer-Bayern bietet seit Jahren allen AppleScript-Interessierten eine Anlaufstelle inklusive Forum und kostenlosem PDF für Einsteiger: http://www.fischer-bayern.de/applescript/ oder www.scriptmymac.de/
810
Anhänge
<< Das AppleScript-Forum bei Macuser: http://www.macuser.de/forum/forumdisplay.php?f=30 << Das AppleScript-Forum bei Apfeltalk: http://www.apfeltalk.de/forum/applescript-f56.html << Das AppleScript-Forum des Magazins PAGE: http://www.page-online.de/forum/viewforum/5/ << Die reichhaltige AppleScript-Fundgrube des Mac-Anwenders H=:o)LGI: http://hohabadu.de/?APPLESCRIPT << Das OSX-Entwicklerforum bietet auch eine Ecke für AppleScript, zusammen mit anderen Skriptsprachen - Eine hilfreiche Seite, wenn man über den AppleScript-Horizont hinausblickt: http://www.osxentwicklerforum.de/board.php?boardid=74
Internationale Links << Die zentrale Anlaufstelle für alles, was mit AppleScript zu tun hat, allerdings nicht besonders schön in der Navigation und über die Jahre zu einem undurchdringlichen Dschungel angewachsen: http://www.macscripter.net/ Dieser Link beherbergt unter einem Dach auch die folgenden Seiten: << Das zentrale Verzeichnis aller Skripterweiterungen: http://www.osaxen.com sowie unter anderem folgende Webseiten: http://scriptbuilders.net/ http://automatoractions.com/ << Doug Adams iTunes-Skripts: http://dougscripts.com/itunes/ << Weitere Links zu Automator: http://automatorworld.com/ http://automator.us/ << Usenet-Newgroups: news:alt.comp.lang.applescript oder über Google: http://groups.google.com/group/alt.comp.lang.applescript
811
SmartBooks
AppleScript
Software von Drittherstellern AppleScript-Editoren << Late Night Software, der Hersteller des Skript Debuggers und FaceSpan: http://latenightsw.com/ << Satimage, der Hersteller von Smile, deutsche Seite: http://www.satimage.fr/software/de/index.html ausführlichere englische Seite: http://www.satimage.fr/software/en/index.html
Entwicklungsumgebungen auf der Basis von AppleScript << AppleScript Studio (Teil der Xcode-Entwicklungsumgebung von Apple) kann nach Anmeldung für einen kostenlosen Basis-Entwickler-Account von http://developer.apple.com heruntergeladen werden. << FaceSpan von Late Night Software: http://www.latenightsw.com/
GUI << Skripterweiterung für erweiterte Möglichkeiten im grafischen Benutzerinterface von AppleScript: http://www.24usoftware.com Letzte Links zu HyperCard << http://www.hypercard.de/ << Der HyperCard Himmel: http://members.aol.com/hcheaven/
Entwicklungsumgebungen, die auf HyperCard basieren oder davon inspiriert wurden: << http://www.runrev.com << http://www.supercard.us << http://www.metacard.com << http://www.toolbook.com << und das freie HyperNext: http://www.tigabyte.com
OSA-Sprachen << JavaScript als OSA-Sprache: http://www.latenightsw.com/freeware/JavaScriptOSA/index.html
812
Anhänge
<< OSA-Sprachen als Skriptkomponenten von Philip Aker: http://www.vcn.bc.ca/~philip/osa << Python und Ruby als OSA-Sprache: http://appscript.sourceforge.net/ << Ruby als OSA-Sprache: http://rubyosa.rubyforge.org/ << Dokumentation zu den Python Macintosh Library Modules: http://www.python.org/doc/2.5.1/mac/mac.html << Das Perl-Archiv zur Suche nach Perl-Modulen, die mit AppleScript zu tun haben: http://cpan.perl.org/
AppleScript als CGI << Der ACGI-Dispatcher zur Verwendung von Appleskripts als CGI: http://www.sentman.com/acgi_dispatcher.html << Der SmileServer: http://www.satimage.fr/software/en/smileserver/index.html
Resource-Editoren << Hersteller des Resource-Editors Resorcerer: http://www.mathemaesthetics.com << Alternative Resource-Editoren: http://sourceforge.net/projects/resknife/ http://sourceforge.net/projects/rezilla/
Skriptmenüs, Kontextmenüs, Tastaturkürzel, Skriptstarter und Sonstiges << Bellhop zur Erstellung von Diensten mit AppleScript: http://www.xendai.com << ThisService zur Erstellung von Diensten mit AppleScript: http://wafflesoftware.net << OnMyCommand für AppleScript-Kontextmenüs und Shortcuts für Tastaturkürzel: http://free.abracode.com/cmworkshop/ << Big Cat AppleScript-Kontextmenü: http://www.ranchero.com/bigcat/ << DropScript und Platypus, um aus Shell-Skripts ein Droplet zu machen: http://www.wsanchez.net/software/ http://www.sveinbjorn.org/platypus 813
SmartBooks
AppleScript
<< Das Skript- und Kontextmenü OpenMenu X: http://www.artman21.com/en/openmenu_x/ << FastScripts Skriptmenü: http://www.red-sweater.com << Tastatursteuerung pur mit Quicksilver: http://www.blacktree.com << Makrorekorder iKey: http://scriptsoftware.com << Makrorekorder QuicKeys: http://www.startly.com oder http://www.cesoft.com << Dock-Manager DragThing: http://www.dragthing.com << CronniX zum Starten von Skripts zu einem bestimmten Zeitpunkt: http://www.abstracture.de << SkriptTimer: http://www.appsandmore.com << iDo Script Scheduler: http://www.sophisticated.com << Skriptstart beim Ruhezustand mit SnoozeRun: http://www.jadechord.com/ << Skriptstart beim Ruhezustand mit SleepWatcher: http://www.bernhard-baehr.de << Skriptstart per Bildschirmschoner mit ScriptSaver: http://swannman.wordpress.com/projects/scriptsaver/ << Skriptstarter Do Something When (DSW): http://www.azarhi.com/Projects/DSW/ << GUI-Interface als Skriptstarter mit den UI Actions: http://prefabsoftware.com/uiactions/ << Tastencode-Ermittlung mit Key Codes: http://www.manytricks.com/keycodes/ << Tastencode-Ermittlung mit Full Key Codes: http://softwares.bajram.com/utilities/ << man -Seiten in Safari betrachten mit Bwana: http://www.bruji.com/bwana/
814
Anhänge
<< Der UI Browser von Prefab für die komfortabelste Art des GUI-Scriptings: http://prefabsoftware.com/uibrowser/ << Schnippselchen, ein kleines, nützliches Programm zur Verwaltung von Codeschnippseln: http://myownapp.com/site/moapp2.0/freestuff/freestuff.php5
Wegen guter AppleScript-Anbindung gelobte Programme: << TextWrangler und BBEdit: http://www.barebones.com/products/ << RagTime http://www.ragtime.de << FileMaker http://www.filemaker.de
815
Index
SmartBooks
AppleScript
Index
A
Symbole ^............................................................................... 100 -................................................................................ 100 --.............................................................................. 108 ?............................................................................... 110 "................................................................................ 128 *................................................................................ 100 /............................................................................... 100 \\.............................................................................. 128 &...................................................124, 130, 174, 766 &>........................................................................... 766 #.............................................................................. 109 #!.................................................................... 109, 750 +................................................................................ 99 ÷.............................................................................. 100 <............................................................................... 762 <=............................................................................ 217 =..................................................................... 208, 209 >..................................................................... 216, 762 >=........................................................................... 216 >>............................................................................ 762 |............................................................................... 115 ≤.............................................................................. 217 ≥.............................................................................. 216 1st........................................................................... 133 2nd................................................................ 133, 159 3rd.......................................................................... 133 24U Appearance OSAX.................................... 529 .app.....................................................................75, 78 .applescript.............................................................. 80 /dev/null............................................................... 766 .DSStore................................................................. 687 June....................................................................... 195 .scpt........................................................................... 74 .scptd.........................................................................76 ¬-Zeichen............................................................. 112 818
Abbrechen.............................................................281 Abbruchbedingung............................................ 282 implizit..............................................................282 mit exit repeat.................................................282 return.................................................................291 try.......................................................................291 Abmeldung als Skriptstarter............................................... 676 about..................................................................... 364 above..................................................................... 364 Abrunden............................................................. 104 Absatzendezeichen............................................. 158 Abspielmodus...................................................... 692 Abstammung.............................................. 252, 432 Abstammungslinie............................................. 443 abstracture.de...................................................... 657 Abstrakte Klasse.................................................. 448 Accessibility-Framework......................... 700, 713 Accessibility Inspector....................................... 705 Accessibility Verifier........................................... 705 action.................................................. 695, 713, 739 activate...................................................64, 247, 704 adding folder items............................................ 397 Adressbuch.....................................................95, 684 AE.framework....................................................... 38 aete............................................................................46 AFP..............................................546, 547, 566, 623 after.......................................................139, 142, 265 against................................................................... 364 a href...................................................................... 695 aiff...........................................................................561 AirPort Base Station........................................... 547 AirPort Extreme USB Printer Sharing........... 547 AirTunes............................................................... 547 Aker, Philip............................................................. 40 Aktionen................................................................. 28 Aktive Ordner..................................................... 387 Aktivitätsanzeige................................................. 659 Akzentzeichen..................................................... 154 Alias.............................................................. 303, 504 alias as file............................................................. 507
Index
alias as list............................................................. 506 alias as POSIX path............................................ 507 alias as text........................................................... 506 alias file................................................................. 505 Alldritt, Mark.......................................... 81, 87, 523 anchor...................................................................702 and......................................................................... 234 bei cons./ign.................................................... 313 Anführungszeichen........................................... 126 Anmeldung als Skriptstarter................................................671 Anwendungen als Skriptersteller.............................................. 49 als Skriptstarter................................................. 49 aufzeichnungsfähige........................................ 48 mit Skriptaufhänger........................................ 50 nicht-skriptbare................................................ 48 per Skript modifizierbare............................... 50 skriptbare........................................................... 48 apart from............................................................ 364 API........................................................................... 38 aplt............................................................ 76, 79, 631 app........................................................................... 55 APPL..................................................................76, 79 Apple Developer Connection.............................86 Apple Event Codes............................................... 38 AppleEvent-Codes................................................71 Apple Event Manager.......................................... 38 Apple Events............................31, 34, 38, 288, 692 Apple Filing Protocol......................................... 547 apple menu.......................................................... 569 Apple Password Server...................................... 547 applescript://........................................................695 AppleScript.......................................................28, 40 AppleScript 1.10.................................................. 312 AppleScript 2.0.................................. 272, 273, 279 AppleScript.component................................ 38, 47 AppleScript Debugger X...............................59, 83 AppleScript-Dienstprogramm.......................... 89 AppleScriptKit Framework................................ 32 AppleScript Language Guide........................... 310 AppleScript-Menü.................................................95 AppleScript.rsrc......................................................47
AppleScript Studio......28, 31, 32, 34, 49, 85, 529 AppleScript URL................................................. 694 Applet................................................................75, 78 AppleTalk.............................................................. 567 applet.icns.............................................................. 79 application............................................................. 55 application „AppName“....................................568 application process.............................................713 applications folder.............................................. 569 Application Support.................................. 401, 569 appsandmore.com.............................................668 April....................................................................... 195 Aqua......................................................................... 84 Arbeitsablauf........................................................641 Arbeitsabläufe....................................................... 28 Arbeitsmappe...................................................... 250 Arbeitsverzeichnis.............................................. 755 architecture.......................................................... 715 a ref........................................................................ 285 a reference to...............................................284, 508 Arithmetische Operatoren................................. 99 around................................................................... 364 artist.............................................................. 366, 693 artman21.com..................................................... 647 as..................................................102, 169, 170, 177 ASCII character......................................... 154, 574 ASCII number............................................ 154, 575 aside from............................................................ 364 as integer.................................... 102, 150, 171, 210 as list.....................................................150, 170, 177 as number.............................................................171 as real....................................................102, 150, 171 as text................................................... 169, 178, 215 as warning............................................................332 at.................................................................... 364, 659 Atkinson, Bill......................................................... 29 attachable................................................................ 50 Attribute....................................................... 704, 713 Aufrunden............................................................ 104 Aufwachen........................................................... 677 Aufzeichnen........................................................... 59 aufzeichnungsfähig.............................................. 59 August................................................................... 195 819
SmartBooks
AppleScript
Ausführen............................................................... 54 auskommentieren..............................................110 Ausschalten als Skriptstarter............................................... 676 Auswahlbedingung............................................ 269 auswerfen.....................................................690, 691 autohide................................................................ 395 Automatischer Start........................................... 655 Automator..................................28, 32, 33, 49, 668 Kontextmenübefehl erstellen......................638 AX-Attribute........................................................ 713 AXAttribute.................................................717, 731 AXCancel.............................................................. 740 AXChildren................................................. 708, 723 AXConfirm..................................................740, 741 AXDecrement.............................................740, 741 AXEnabled........................................................... 723 AXFocused........................................................... 723 AXHelp................................................................. 723 AXIncrement....................................................... 740 AXMaxValue....................................................... 723 AXMinValue........................................................ 723 AXOpen................................................................ 740 AXOrientation.................................................... 724 AXParent.............................................................. 708 AXPosition........................................................... 724 AXPress................................................................. 740 AXRaise................................................................ 740 AXRole.............704, 706, 713, 716, 717, 724, 740 AXRoleDescription.................................. 723, 729 AXSelected........................................................... 724 AXShowMenu..................................................... 740 AXSize.......................................................... 724, 732 AXSubrole............................................................ 725 AXTitle.................................................................. 725 AXTopLevelUIElement.................................... 708 AXValue....................................................... 725, 733 azarhi.com............................................................692
B back........................................................................133 Background.........................................................670 820
background only................................................715 Backup..................................................................398 Bajram................................................................... 746 barebones.com.................................................... 674 Bash.............................................................. 674, 753 Baumansicht.......................................................... 82 BBEdit............................................. 49, 95, 167, 650 Bedienelemente.................................................. 704 Bedienungshilfen.........................................89, 700 Beenden.................................................................281 beep....................................................................... 529 Befehl duplicate............................................................401 im Funktionsverzeichnis...............................251 Befehle abfangen........................................................... 466 activate..................................................... 247, 704 ASCII character.............................................. 574 ASCII number................................................ 575 beep................................................................... 529 choose application.........................................530 choose color........................................... 518, 532 choose file............................................... 381, 533 choose file name............................................. 537 choose folder.......................................... 381, 538 choose from list..............................................540 choose remote application.................. 514, 544 choose URL..................................................... 545 click................................................................... 733 clipboard info.................................................. 585 close access......................................................588 continue........................................................... 463 copy.......................................................... 149, 424 count............................................... 146, 168, 180 current date.....................................................188 delay................................................ 203, 548, 703 display alert..................................................... 549 display dialog.................................................. 553 do shell script........................156, 510, 610, 763 duplicate........................................................... 399 exists..................................................................278 get......................................................................120 get eof................................................................ 604
Index
get volume settings........................................ 614 info for..................................................... 381, 563 key code............................................................745 keystroke..........................................................742 launch.......................................................386, 477 list disks............................................................ 564 list folder.................................................. 381, 565 load script.......................................370, 475, 607 localized string............................................... 576 log............................................................. 122, 140 mount volume................................................ 566 move...................................................................401 offset...................................................................581 open for access................................................ 586 open location..................................................622 path to...............................................................568 path to me........................................................ 474 path to resource............................ 475, 572, 764 perform............................................................ 739 quit..................................................................... 376 random number.................................... 106, 615 read....................................................................588 return................................................................ 347 round....................................................... 104, 616 run............................................................ 374, 418 run script................................................. 476, 608 say...................................................................... 559 scripting components...........38, 479, 609, 753 select..................................................................738 set.............................................................. 117, 140 set eof................................................................605 set the clipboard to........................................ 583 set volume........................................................ 617 store script...............................................471, 607 summarize........................................................581 system attribute.............................................. 619 system info..............................................190, 621 time to GMT...........................................202, 621 write...................................................................600 Befehlsziel.............................................................241 before...................................................139, 142, 265 beginning..........................133, 136, 141, 161, 265 begins with........................................................... 229
Begrüßungstext.....................................................61 Behauptung......................................................... 206 behind.......................................................... 139, 265 Behinderungen...................................................700 Bellhop.................................................................. 635 below..................................................................... 364 Benannte Parameter................................. 335, 363 beneath................................................................. 364 Benennungsregeln............................................. 114 Benutzer-Account.............................................. 334 Benutzer-ID................................................ 515, 545 Benutzer-Parameter.......................................... 364 Benutzerschnittstelle................................ 398, 699 Benutzerskripts..................................................... 93 Berechnungsreihenfolge................................... 102 Beschreibung..........................................................75 Beschreibungsbereich......................................... 62 beside.................................................................... 364 between................................................................ 364 Bezeichner...................................................114, 407 Bezeichnerklammer.......................................... 115 Bibliothek....................................... 42, 66, 334, 370 Bibliotheken.......................................................... 28 Big Cat................................................................... 646 Bildbearbeitung......................................... 397, 398 Bildbetrachtung.................................................. 394 Bild CD.................................................................690 Bildschirm............................................................ 185 Bildschirmkoordinaten.................................... 736 Bildschirmschoner als Skriptstarter...............................................682 Binärdaten............................................................ 585 binäre Daten........................................................ 589 binäre Operatoren..........208, 215, 223, 229, 234 Bindestriche................................................ 108, 309 Bitmapgrafiken..................................................... 84 BOM............................................591, 602, 603, 613 Bonjour........................................................ 545, 566 Bonjournamen.................................................... 515 Bonjour Service Type........................................ 546 boolean................................................................. 207 boolean as integer.............................................. 239 boolean as list...................................................... 239 821
SmartBooks
AppleScript
boolean as text.................................................... 239 boolesche Aussage............................................. 206 boolescher Wert................................................. 206 bounds.................................................344, 395, 396 Breakpoints............................................................ 83 Browser........................................................ 279, 718 Bruji....................................................................... 753 Bundle................................................76, 78, 80, 372 Bundleformat.........................................................76 Bundle Identifier.............................. 272, 695, 715 Bundle-Inhalt........................................................ 80 Bundle Programming Guide............................. 79 Bundlesignatur.................................................... 272 busy indicator......................................................718 but..........................................................................313 button....................................................................718 Bwana.................................................................... 753 by................................................................... 296, 364 Byte.........................................................................101 byte order mark...................................................591
C C++.......................................................................... 88 calculates folder sizes......................................... 254 Carbon.framework.............................................. 38 Carriage Return.................................................. 125 case........................................................................ 306 caution.................................................................. 557 cd............................................................................ 765 CD.......................................................................... 689 CD-Rohling.........................................................690 cell....................................................................72, 249 centimeters.......................................................... 519 centimetres.......................................................... 519 cepstral.................................................................. 559 character...................................................... 157, 159 character id................................152, 156, 158, 575 characters.................................................... 160, 168 checkbox...............................................................718 chmod..................................................675, 680, 751 choose application.............................................530 choose color................................................ 518, 532 822
choose file.................................................... 381, 533 choose file name................................537, 562, 587 choose folder.............................................. 381, 538 choose from list...................................................540 choose remote application...................... 514, 544 choose URL................................................ 545, 566 class..............................................101, 143, 155, 178 class furl................................................................ 509 Classic................................................................... 715 Classic domain.....................................................571 class of....................................................................361 click........................................................................ 733 Clipboard Commands...................................... 582 clipboard info...................................................... 585 close access...........................................................588 closing folder....................................................... 394 CMWorkshop..................................................... 642 Cocoa................................................................32, 34 Cocoa-Bibliotheken.............................................85 Codebausteine........................................... 278, 334 Codeformatierung............................................... 69 Code-Vervollständigung.....................................56 collapsed............................246, 256, 264, 266, 354 ColorSyncScripting............................................. 43 color well..............................................................718 column......................................................... 249, 718 column view........................................................270 com.adobe.pdf.................................................... 535 combo box...........................................................718 comes after........................................................... 216 comes before....................................................... 216 command down........................................ 742, 746 comma separated value.................................... 163 comment..................................................... 185, 270 Components....................................................38, 40 Computerskripts............................................91, 93 Conditionals........................................................ 278 connect................................................................. 673 considering................................................. 213, 306 considering application responses................. 203 considering case................................................. 214 considering/ignoring application responses.................................... 314
Index
case.................................................................... 306 diacriticals........................................................308 expansion......................................................... 309 hyphens............................................................ 309 numeric strings...............................................312 punctuation.....................................................310 verschachtelt.................................................... 313 white space........................................................311 considering numeric strings............................222 container..................................................... 245, 305 container window...............................................391 contains................................................................ 223 content......................................................... 299, 385 contents of...................................................287, 470 continuation character.......................................111 continue................................................................ 463 continue quit.............................................. 677, 693 control down.............................................. 742, 746 control panels...................................................... 569 control strip modules........................................ 569 copy.............................................113, 147, 149, 424 CoreServices.........................................43, 302, 398 CoreServices.framework.................................... 38 count............................................................ 146, 180 Cover Flow.................................................. 392, 629 cpan..........................................................................41 CR.......................................................................... 128 creator code..........................................................631 Creator-Code........................................................ 72 creator type................................................. 715, 755 critical....................................................................550 cron.......................................................657, 659, 666 CronniX................................................................ 657 crontab..........................................................655, 657 CSV........................................................................ 163 cubic centimeters............................................... 519 cubic centimetres............................................... 519 cubic feet.............................................................. 519 cubic inches......................................................... 519 cubic meters......................................................... 519 cubic metres......................................................... 519 cubic yards........................................................... 519 curl......................................................................... 765
current application............64, 405, 443, 446, 568 current applicaton..............................................450 current date.......................................................... 289 current view................................................ 261, 266
D DAAP.................................................................... 547 Daemon................................................................ 657 data............................................................... 585, 592 Database Events.................................................... 43 Data-Fork.......................................................73, 756 date as list............................................................. 204 date as number.................................................... 205 date as text............................................................ 204 Dateiauswahl....................................................... 533 Dateiformat CSV................................................................... 163 Programm....................................................61, 75 Programm-Bundle............................. 61, 78, 80 Skript................................................................... 74 Skript-Bundle.............................................76, 80 Text...................................................................... 80 Dateiformate..........................................................71 Dateikürzel......................................................72, 75 Dateinamensauswahl........................................ 537 Dateireferenznummer...................................... 586 Dateityp....................................................... 303, 716 Datensatz.............................................................. 172 date string.............................................................198 Datum................................................................... 189 rechnen mit.....................................................190 Datumsformat............................................ 189, 198 Datum & Uhrzeit............................................... 202 day................................................................. 191, 192 Debugging.......................................................55, 83 December............................................................. 195 deep copy............................................................. 149 defaults......................................................... 675, 676 degrees Celsius.................................................... 519 degrees Fahrenheit............................................. 519 degrees Kelvin..................................................... 519 dekompilieren................................................. 54, 71 823
SmartBooks
AppleScript
Dekompilierung................................................... 52 delay............................................................. 548, 703 Delegation.......................................... 443, 450, 464 delete.....................................................................688 deprecated................................................... 302, 360 description...................................62, 715, 723, 740 description.rtfd......................................................77 Designer............................................................... 704 desk accessory process......................................713 desktop............................................... 181, 245, 569 desktop-object.................................................... 245 desktop pictures folder..................................... 569 desktop position.................................................185 Developer-Account..............................................86 Developer Tools............................................86, 705 Dezimalkomma..................................................158 Dezimaltrenner..................................................170 Dezimalzahl.........................................................100 Dezimalzeichen..................................................100 diacriticals............................................................308 Diakritische Zeichen.........................................308 Dialog.................................................................... 553 Dictionaries........................................................... 28 Dictionary..................................................44, 66, 67 Dictionary Browser............................................. 82 Dienste.................................................................. 545 Dienste-Menü..................................................... 633 Digital Audio Access Protocol........................ 547 Digital Hub Scripting..................................43, 689 Digital Photo Access Protocol......................... 547 Directory services.............................................. 546 Direkter Parameter................................... 364, 366 Disabled....................................................... 662, 663 disk................................................................690, 691 Disk-Folder-File-Suite...................................... 303 disk items............................................................. 399 display alert................................................. 332, 549 display dialog..............................................553, 572 displayed name................................................... 715 Distributed compiler......................................... 547 div..................................................................100, 101 Division................................................................100 DMG...............................................................78, 690 824
Dock..........................256, 265, 266, 392, 394, 733 als Skriptstarter...............................................632 dock preferences........................................ 395, 733 documents folder............................................... 569 domain..................................................................570 Doppelklick.........................................................738 do shell script............................ 156, 510, 610, 763 Do Something When........................................ 692 Double...................................................................101 Download.............................................................. 43 downloads folder............................................... 569 DPAP..................................................................... 547 dplt...................................................................76, 631 Drag and Drop.................................................... 379 DragThing............................................................ 654 dragthing.com..................................................... 655 drawer...................................................................718 drehen...................................................................400 Droplet......................................................... 380, 756 aus Shellskript.................................................642 Vorlage...............................................................381 DropScript........................................................... 642 DSW...................................................................... 692 duplicate............................................. 399, 401, 402 DVD...................................................................... 689 DVD-Rohling.....................................................690
E echo....................................................................... 765 Eigenschaften...................................................... 173 character id......................................................152 class................................101, 143, 178, 192, 207 date string........................................................198 day.....................................................................192 hours.................................................................200 id............................................................... 152, 156 im Funktionsverzeichnis...............................251 length.............................................. 143, 156, 179 minutes.............................................................200 month............................................................... 195 name................................................................. 429 parent....................................................... 443, 446
Index
POSIX path............................................ 506, 509 quoted form.................................................... 156 rest............................................................ 143, 144 reverse...................................................... 143, 144 running................................................... 273, 279 seconds..............................................................201 short date string..............................................198 time................................................................... 199 time string.........................................................201 user locale........................................................190 version.............................................................. 244 weekday............................................................ 193 year.................................................................... 197 Eigentümer.......................................................... 186 Einfache Variablen.................................... 484, 488 Eingangslautstärke.............................................618 Einrückungen........................................................ 68 Einschlafen.......................................................... 677 Einwahl................................................................. 747 Einzug......................................................................56 eject................................................................690, 691 Elemente............................................................... 403 im Funktionsverzeichnis...............................251 Elements inherited from................................... 253 Eltern..................................................................... 443 explizite............................................................ 446 implizite.................................................. 443, 446 E-Mail.......................................................... 365, 684 end......................................133, 136, 141, 161, 242 Endlosschleife....................................281, 357, 397 ends with.............................................................. 229 Englisch.................................................................. 35 Entfernte Apple-Events............................ 511, 715 Entfernte Programmauswahl.......................... 544 Entfernte Rechner...............................................511 entire contents.........305, 359, 716, 717, 723, 728 Entwicklungsumgebung......................................86 EPPC.............................................................546, 547 EPPC-URL................................................. 512, 545 equal......................................................................208 Equalizer............................................................... 366 Ereignis................................................................. 373 Ergebnisbereich.................................................... 63
Erinnerungen...................................................... 656 error.......................................................................320 im try................................................................. 325 Parameter......................................................... 322 sofortiger Abbruch........................................ 329 Escape-Sequenzen............................................. 127 Ethernet................................................................ 673 Etikett.................................................................... 184 Event-Log............................................................. 262 Event-Protokoll......................................... 122, 325 Event-Protokoll-Bereich.................................... 64 Events.h................................................................ 802 every...................................137, 138, 162, 177, 268 im tell................................................................ 264 every item............................................................. 137 everyone............................................................... 186 everyones privileges........................................... 186 Excel......................................................................248 Existenz.................................................................278 exists............................................................. 278, 344 exit..........................................................................282 exit repeat.............................................................282 expansion............................................................. 309 Explorer.................................................................. 82 Exposé................................................................... 746 extensions............................................................ 569
F faceless..................................................................398 FaceSpan.............................. 28, 31, 34, 85, 87, 529 false........................................................................ 206 Farbpalette........................................................... 518 Farbprofil................................................................ 43 Farbräume.............................................................. 43 Farbwähler........................................................... 532 FastScripts............................................................ 653 FAT.......................................................................... 78 FAT32...................................................................... 73 favorites folder.................................................... 569 feet......................................................................... 519 Fehler.....................................................................320 abfangen........................................................... 324 825
SmartBooks
AppleScript
durchreichen................................................... 327 erzeugen...........................................................320 filtern.................................................................330 Fehlerdialog..........................................................321 Fehlerdialoge eigene.................................................................331 Fehlermeldung............................................321, 331 Fehlernummer........................................... 321, 325 Fehlertext.................................................... 321, 325 Fenster................................................................... 344 Fensteransicht.....................................................260 Fensterposition................................................... 396 Festplatte................................................................. 72 fetch interval........................................................673 file...........................................................................508 file as alias............................................................. 509 file as list................................................................ 509 file as POSIX path.............................................. 509 file as text.............................................................. 509 File commands........................................... 302, 562 file descriptor....................................................... 586 FileMaker.................................................. 49, 50, 96 file pointer............................................................ 586 File servers........................................................... 546 File Transfer Protocol........................................ 547 file type........................................303, 534, 716, 755 Finder.................................................. 181, 241, 302 finder reference as file....................................... 509 finder reference as text...................................... 507 Finder window........................................... 247, 248 Firefox................................................................... 279 first................................................................ 132, 159 Flächen.................................................................. 519 flow view...................................................... 270, 392 Flüssigvolumen................................................... 519 focused.................................................................. 723 folder......................................................................181 Folder Actions..................................................... 388 Folder Action scripts......................................... 569 Folder Action Scripts................................ 387, 389 Folder Actions Suite........................................... 388 folder constant....................................................568 Fontprofil................................................................ 43 826
fonts....................................................................... 569 Font-Synchronisierung....................................... 43 FontSyncScripting................................................ 43 for........................................................................... 364 Fork.......................................................................... 73 Formateinstellung..............................................170 Fortführungszeichen..........................................111 Fragezeichen........................................................110 Freigaben..............................................................630 from....................................................................... 364 from … to.................................................... 136, 169 front.............................................................. 133, 265 frontmost............................................................. 716 frontmost application........................................568 ftp........................................................................... 765 FTP...................................................... 546, 547, 623 FTP servers.......................................................... 546 Full Key Codes.................................................... 746 Füllwort................................................................ 365 Funktion............................................................... 333 Funktionsverzeichnis....44, 66, 67, 71, 183, 250, 251 Beschreibung.................................................. 252 Darstellung...................................................... 252 Formate...............................................................45 Übersicht...........................................................251 von AppleScript.................................................47 Funktionsverzeichnisse...................................... 28 furl......................................................................... 509
G Gabelung................................................................ 73 gallons................................................................... 519 Genauigkeit Zeitmessung.................................................... 188 Geräte....................................................................630 Gerätename......................................................... 512 Gesamtlautstärke................................................ 618 Geschwindigkeit................................................... 34 Gestalt................................................................... 619 Gestaltabfragen................................................... 619 get...........................................................................120 im repeat...........................................................301
Index
get eof.................................................................... 604 get volume settings............................................ 614 Gewicht................................................................ 519 given...................................................................... 367 Gleichheit............................................................. 208 global............................................................ 484, 495 Globale Variablen............................................... 495 GMT...................................................................... 202 Google................................................................... 638 Grafikbibliothek...........................................84, 398 grams..................................................................... 519 GraphicConverter........................ 49, 95, 304, 650 greater than.......................................................... 215 greater than or equal to..................................... 216 Greenwich Mean Time..................................... 202 größer als.............................................................. 215 Groß- und Kleinschreibung....56, 114, 213, 308 group.....................................................................718 group view............................................................270 grow area.............................................................. 719 Gruppe.................................................................. 186 GUI........................................................................ 398 GUI-Element...................................................... 704 GUI-Scripting......................................89, 694, 699 Gültigkeitsbereich.............................................. 483
H Handler................................................................. 333 adding folder items........................................ 397 Aufruf.............................................. 334, 353, 363 Aufruf mit my................................................. 354 class....................................................................361 closing folder................................................... 394 Definition........................................................ 333 idle..................................................................... 377 in Skriptobjekten............................................418 moving folder window................................. 396 on error............................................................. 325 open.................................................................. 379 opening folder................................................ 389 Parameterübergabe........................................341 Positionsparameter........................................ 335
Programm-...................................................... 373 quit..................................................................... 376 rekursiv............................................................. 356 removing folder items....................................401 reopen............................................................... 383 Rückgabewert................................................. 345 run............................................................ 373, 759 Variablen im.................................................... 340 von Mail........................................................... 317 has scripting terminology................................ 717 help............................................................... 569, 723 Hexadezimalwert...............................................152 HFS....................................................................72, 78 HFS-Pfad.............................................................. 504 High-Level-Awareness...................................... 715 Highlight..............................................................708 Hilfsgeräte......................................................89, 700 Hintergrund........................................................ 715 Hintergrundprozess...........................................670 HIToolbox.framework........................................ 38 Hochkomma.......................................................158 home folder......................................................... 569 hours............................................................ 191, 200 href......................................................................... 695 HTML.............................................................84, 697 HTTP............................................................546, 547 HTTP-Protokoll.................................................522 HTTPS.................................................................. 546 HyperCard..........................................29, 33, 85, 88 HyperNext..............................................................31 HyperTalk........................................................29, 85 Hypertext Transfer Protocol............................ 547 hyphens................................................................ 309
I i386............................................................... 715, 758 IBAN..................................................................... 525 iCal........................................................................... 50 als Skriptstarter...............................................655 iChat............................................................. 547, 683 iChat Instant Messaging Protocol.................. 547 icns......................................................................... 557 827
SmartBooks
AppleScript
Icon........................................................................ 556 Iconansicht...........................................................280 Icon-Ansicht........................................................ 266 Icon Composer.............................................79, 557 icon view...............................................................270 id...................................................152, 156, 258, 516 eines Programms...........................................272 idle......................................................................... 377 idle-Event.............................................................378 idle-Handler...................................... 377, 669, 694 idle-Intervall........................................................ 379 iDo Script Scheduler.........................................668 if.............................................................................. 274 als Block........................................................... 276 als Einzeiler..................................................... 274 geschachtelt.....................................................280 mit else.............................................................. 276 mit else if.......................................................... 277 mit else if und else.......................................... 277 ignoring................................................................ 213 Siehe auch considering iKey........................................................................ 654 image..................................................................... 719 Image Capture Sharing..................................... 547 Image Events........................................43, 302, 398 immutable................................................... 151, 285 in............................................................................ 366 in back of.....................................................139, 265 inches.................................................................... 519 incrementor......................................................... 719 inetd....................................................................... 659 info for........................................360, 381, 383, 563 info.plist...............................77, 272, 670, 677, 689 informational......................................................550 in front of.....................................................139, 265 inherits from........................................................ 253 Initialisierung...................................................... 114 Input...................................................................... 553 Inspector................................................................. 82 Instanz................................................................... 448 Instanzen..................................................... 436, 439 Instanzvariablen........................................ 447, 483 eine für alle......................................................448 828
instead of.............................................................. 364 Integer...........................................................100, 137 integer as boolean.............................................. 239 integer as list........................................................150 integer as real.......................................................102 integer as unit type.............................................520 integer, Größe.......................................................101 Intel........................................................................ 715 Intelligente Ordner............................................630 Interface Builder...........................................86, 642 Interface-Elemente............................................700 international text.................................................151 Interneteinwahl.................................................. 747 internet plugins................................................... 569 Internet Printing Protocol................................ 547 Internet Suite....................................................... 622 Interpreten........................................................... 694 Interpreter............................................................750 Interpunktionszeichen......................................310 into......................................................................... 364 IP-Adresse................................................... 312, 513 iPhoto Sharing.................................................... 547 IPP.......................................................................... 547 is.............................................................................208 is contained by.................................................... 224 is equal to............................................................. 207 is in......................................................................... 224 it......................................................64, 244, 453, 568 item................................................................132, 137 item n of item n.................................................. 134 items..............................................................135, 137 Iteration................................................................ 398 its................................................................... 244, 423 iTunes...........49, 95, 366, 406, 415, 417, 650, 692 iTunes Sharing.................................................... 547 iWork.....................................................................468
J jadechord.com/................................................... 677 Jahr......................................................................... 197 Java...................................................................35, 523 JavaScript..................................40, 59, 83, 480, 760
Index
JavaScript OSA....................................................480 JPEG......................................................................400 JPG........................................................................... 84
K Kalender...................................................... 188, 656 Kartenstapel........................................................... 29 Keine Rechte........................................................ 186 Kein Etikett.......................................................... 184 keychain folder................................................... 569 Keychain Scripting............................................... 43 key code.............................................. 703, 743, 745 keystroke..............................................................742 kilograms............................................................. 519 kilometers............................................................ 519 kilometres............................................................ 519 kind.............................................................. 303, 448 Klammerung....................................................... 102 Klasse action................................................................ 739 date....................................................................188 handler..............................................................361 machine....................................................512, 517 Klassen abstrakte...........................................................448 action................................................................ 713 alias.................................................................... 504 attribute............................................................ 713 boolean............................................................. 207 data........................................................... 585, 592 file......................................................................508 furl..................................................................... 509 im Funktionsverzeichnis...............................251 integer...............................................................102 international text.............................................151 list...................................................................... 143 number.............................................................138 POSIX file............................................... 475, 508 process..............................................................712 real......................................................................101 record....................................................... 172, 178 RGB color............................................... 517, 532
script................................................................. 403 string................................................................. 139 text................................................... 124, 155, 158 UI element....................................................... 717 unicode text......................................................151 Klassenhierarchie............................................... 252 Klassenstruktur..................................................... 82 Klassik-Umgebung............................................ 715 kleiner als.............................................................215 kmdItem-Codes..................................................631 kMDItemFSCreatorCode.................................631 kMDItemFSTypeCode......................................631 Kommentare.......................................................108 Kommentarzeichen --.......................................................................... 108 (*......................................................................... 109 *).......................................................................... 109 #.......................................................................... 109 kompilieren..................................................... 54, 71 Komponenten.................................................38, 40 Konstanten........................................................... 404 AppleScript...................................................... 167 April................................................................... 195 August............................................................... 195 days.....................................................................191 December........................................................ 195 February........................................................... 195 Friday ............................................................... 193 hours..................................................................191 January.............................................................. 195 July..................................................................... 195 June.................................................................... 195 linefeed............................................................. 126 March................................................................ 195 May.................................................................... 195 minutes..............................................................191 missing value................................................... 179 Monday............................................................ 193 my...................................................................... 167 November........................................................ 195 October............................................................ 195 quote................................................................. 126 result...................................................................121 829
SmartBooks
AppleScript
return................................................................ 125 Saturday .......................................................... 193 September........................................................ 195 space..................................................................125 Sunday ............................................................. 193 tab...................................................................... 125 text item delimiter......................................... 159 text item delimiters........................................162 Thursday . ........................................................ 193 version................................................................ 98 Tuesday............................................................. 193 Wednesday . .................................................... 193 weeks..................................................................191 Konstruktor................................................ 439, 478 Konstruktoren.................................................... 436 Kontextmenü................................ 57, 93, 110, 278 als Skriptstarter...............................................638 Kontrollstrukturen..............................................241 error...................................................................320 if......................................................................... 274 repeat.................................................................281 tell.......................................................................241 try...................................................................... 324 using terms from............................................ 316 with timeout.................................................... 317 with transaction............................................. 319 Koordinaten............................................... 396, 736 Kryptographie..................................................... 106 Kugelvolumen..................................................... 345 Kurzschlussauswertung........................... 235, 236
L Label............................................................. 661, 663 Labeled Parameters............................................ 363 label index................................................... 184, 256 Landeseinstellungen.......151, 157, 171, 189, 193, ...............................................................198, 201, 221 Längen.................................................................. 519 last................................................................. 133, 159 Late Night Software.......... 40, 49, 52, 82, 87, 250, .............................................................. 480, 483, 523
830
Laufwerk einbinden.........................................................690 Laufwerke............................................................. 564 Laufwerke einbinden........................................ 566 Laufzeitumgebung............................................. 406 launch...........................................................386, 477 LaunchAgent......................................655, 660, 686 launchctl............................................. 661, 663, 664 launchd..............................659, 661, 686, 687, 690 LaunchDaemon..................................................660 launchd.plist............................................... 661, 664 launcher items folder......................................... 569 Lautstärke.................................................... 617, 693 Layout................................................................... 397 LDAP.................................................................... 546 Leerlauf................................................................. 378 Leerstelle................................................................311 length........................................................... 144, 156 Lesezeichen.......................................................... 586 less than................................................................215 less than or equal to........................................... 217 library..............................................................66, 370 library folder........................................................ 569 Ligaturen.............................................................. 309 linefeed................................................126, 158, 311 Line Printer Daemon........................................ 547 Linux........................................................................35 list.................................................................. 137, 719 list as integer........................................................150 list as real..............................................................150 list as text.............................................................. 169 list disks................................................................ 564 Liste........................................................................130 Listenansicht........................................................270 Listenauswahl......................................................540 Listenindex.......................................................... 134 list folder.....................................360, 381, 383, 565 list view.................................................................270 list view options.................................................. 254 Literal.................................................................... 112 Literale Zahlen................................................................. 99 liters....................................................................... 519
Index
litres....................................................................... 519 load script...................................370, 475, 572, 607 local.......................................................................483 local domain.........................................................571 Localizable.strings.............................................. 577 localized string.................................................... 576 location.................................................................673 log.........................................................122, 140, 325 LoginHook.......................................................... 674 loginwindow....................................................... 674 LogoutHook........................................................ 676 Lokale Variablen........................................ 483, 485 Lokalisierung...................................................... 576 Long........................................................................101 löschen..................................................................688 LPD........................................................................ 547 LPR........................................................................ 547 ls............................................................156, 750, 765 LSBackgroundOnly.................................. 670, 689
M Mac (CR)................................................................ 80 machine........................................................512, 517 Macintosh Library Module................................41 Mac OS 7.1.1......................................................... 30 Mac OS 9.2..............................................................31 Mac OS Lateinisch..............................................591 Mac OS Roman.......................................... 574, 575 Mac OS X............................................................... 32 Mac OS X 10.2...................................................... 32 Mac OS X 10.4...................................................... 32 Mac OS X 10.5...................................................... 33 MacPython OSA Module...................................41 MacRoman Codierung..................................... 154 MacRoman-Codierung....................................110 MacRoman-Encoding.......................................151 MACS................................................................... 272 Mail......50, 95, 364, 385, 411, 541, 673, 684, 735 mailbox.........................................................364, 411 Mailregel.........................................................50, 684 main.scpt..........................................................77, 78 make...................................................................... 505
make new............................................................. 505 man..................................................................47, 752 Manytricks........................................................... 746 Maschinencode..............................................34, 54 Maßeinheiten......................................................520 Massenzuweisung............................ 175, 349, 352 Mathematik-Bibliotheken.................................. 84 Matsumoto, Satoshi........................................... 647 maximum value..........................................723, 741 mdfind..................................................................632 mdls.......................................................................632 me.........................................64, 243, 403, 453, 568 Media servers...................................................... 546 Mehrfachvererbung............................................. 28 menu..................................................................... 719 menu bar.............................................................. 719 menu bar item..................................................... 719 menu button........................................................720 menu item............................................................720 Menüzeile................................................................75 message........................................................ 364, 385 MetaCard................................................................31 Metadata Attributes........................................... 632 meters.................................................................... 519 Methoden.....................................................427, 447 eine für alle...................................................... 449 metres.................................................................... 519 Microsoft Excel................................................... 249 middle.........................................136, 139, 162, 265 middle item......................................................... 136 miles...................................................................... 519 minimum value..........................................723, 741 Minuten................................................................200 minutes........................................................ 191, 200 Miscellaneous Commands..............................610 missing value...............................................179, 411 Mitternacht.......................................................... 189 mod.......................................................................100 modem scripts.................................................... 569 Modul................................................................42, 70 Modulo.................................................................100 Monat.................................................................... 195 Monatskonstanten............................................. 196 831
SmartBooks
AppleScript
Monatsname........................................................ 195 Monatstag............................................................ 192 month.................................................................... 195 mount volume.................................................... 566 move............................................................. 401, 688 movies folder....................................................... 569 moving folder window..................................... 396 Multiplikation.....................................................100 music folder......................................................... 569 Musik CD.............................................................690 Musterzuweisung...................................... 349, 352 mutable........................................................ 148, 285 my.......................................167, 403, 406, 431, 453 Myst......................................................................... 29
N name...................................................................... 429 Name..................................................................... 173 named...................................................................258 name extension...................................................270 Namen.................................................................. 114 von Objekten.................................................. 257 Namenskonflikt............................................43, 115 Namensräume......................................43, 116, 483 nano....................................................................... 674 network domain..................................................571 Network File System.......................................... 547 Netzwerkeinstellungen..................................... 673 Netzwerkquellen................................................. 545 newline.................................................................128 News servers........................................................ 546 NFS................................................................546, 547 Nib-Dateien......................................................... 642 Nicht automatisch beenden.........................76, 79 Nichtstun..............................................................378 NNTP.................................................................... 546 none....................................................................... 186 not.......................................................................... 237 note........................................................................ 557 notifications.........................................................712 Notizzettel.......................................... 726, 742, 744 Not Sign.................................................................111 832
noun...................................................................... 253 November............................................................ 195 NTFS....................................................................... 73 number.................................................................138 number of....................................................146, 168 Numerics.osax...................................................... 84 numeric strings.......................................... 222, 312 Nur ausführbar........................................ 74, 76, 78 Nur ausführen....................................................... 79
O Objective-C.............................................. 33, 34, 85 Objekte.................................................................. 173 Objekthierarchie.............................. 181, 250, 254 Objektorientierte Programmierung.....422, 427, ..................................................... 428, 436, 447, 460 Objektorientierung.............................................. 28 Objektreferenz........................................... 285, 286 Objektvariablen.................................................. 645 October................................................................. 195 oder....................................................................... 234 of................................................................... 248, 366 offset.......................................................................581 of parent................................................................463 Oktober................................................................ 195 OMC..................................................................... 642 on........................................................................... 364 on adding folder items...................................... 397 on closing folder................................................. 394 on error................................................................. 325 on idle................................................................... 377 on moving folder window................................ 396 OnMyCommand...................................... 642, 650 on open................................................................. 379 on opening folder............................................... 389 on perform mail action..................................... 317 on quit................................................................... 376 on removing folder items..................................401 on reopen.............................................................383 on run....................................................................373 onto....................................................................... 364 OOP..........................422, 427, 428, 436, 447, 460
Index
open..................379, 477, 659, 662, 664, 666, 674 Open Directory.................................................. 547 open for access.................................................... 586 open-Handler..................................................... 379 opening folder..................................................... 389 open location.......................................................622 OpenMenu X............................................. 647, 650 Open Scripting Architecture............................. 38 OpenScripting.framework................................. 38 Open Scripting Framework............................... 38 Operatoren ^........................................................................... 100 -............................................................................ 100 *............................................................................ 100 /........................................................................... 100 &....................................................... 124, 130, 142 +............................................................................ 99 ÷.......................................................................... 100 =................................................................. 208, 209 >.......................................................................... 216 ≤.......................................................................... 217 ≥.......................................................................... 216 and..................................................................... 234 a reference to................................................... 284 arithmetische.................................................... 99 as........................................................................102 div......................................................................100 mod...................................................................100 not...................................................................... 237 or............................................................... 234, 235 Operatorreihenfolge..................................102, 237 option down............................................... 742, 746 or................................................................... 234, 235 Ordneraktionen......................33, 50, 90, 387, 685 adding folder items........................................ 397 closing folder................................................... 394 konfigurieren.................................................. 387 moving folder window................................. 396 opening folder................................................ 389 removing folder items....................................401 Ordnerauswahl...................................................538 Ordnerinformation........................................... 393 orientation........................................................... 724
Orte........................................................................630 OSA......................................................33, 38, 40, 59 osacompile.................................................. 752, 754 osadecompile............................................. 752, 758 osalang......................................................... 752, 753 osas..................................................................75, 631 osascript.....659, 666, 674, 680, 686, 750, 752, 759 OSA-Sprache........................................39, 758, 760 OSA-Sprachen.............................. 40, 83, 479, 753 osax.......................................................................... 42 osaxen..................................................................... 44 ounces................................................................... 519 outline...................................................................720 out of..................................................................... 364 over........................................................................ 364 override................................................................ 457 owner.................................................................... 516
P Pages..............................................................468, 517 Paketinhalt.......................................................76, 78 pane.......................................................................702 paragraph...................................158, 159, 161, 168 Parameter als Pattern................................................ 349, 352 Benannte.......................................................... 363 Benutzer-......................................................... 364 Direkter................................................... 364, 366 dokumentieren...............................................338 im Handler...................................................... 335 mit given..................................................364, 367 mit with/without...................................364, 368 Position............................................................. 335 Übergabe per Referenz..................................341 parent.................................432, 443, 455, 468, 470 partial result.........................................................322 path........................................................................ 679 path to...................................................................568 path to me......................................................64, 474 path to resource.................64, 475, 557, 572, 764 Pattern.......................................................... 349, 352 Pause...................................................................... 548 833
SmartBooks
AppleScript
PDF.......................................................................... 84 PDL Data Stream................................................ 547 perform................................................................. 739 perform mail action........................................... 684 Perl.................... 34, 40, 41, 94, 290, 636, 666, 763 Perl-Skript............................................................ 167 Pfade relativ................................................................510 physical size......................................................... 187 pictures folder..................................................... 569 pid................................................................. 515, 545 Pixie....................................................................... 736 Platypus................................................................ 642 playlist.......................................................... 366, 406 PList-Keys.............................................................671 Plugin...................................................................... 70 PNG......................................................................... 84 point...................................................................... 186 Polymorphismus....................................... 460, 463 pop up button......................................................720 position........................................................ 270, 724 Positionsparameter............................................ 335 POSIX file.................................................... 475, 508 POSIX file as alias............................................... 505 POSIX path................................................. 506, 509 POSIX-Pfad....................................... 305, 505, 640 Postleitzahlen...................................................... 312 pounds.................................................................. 519 PowerPC............................................................... 715 ppc................................................................ 715, 758 PPPoE-Status....................................................... 747 Präpositionen...................................................... 363 Prefab..........................................694, 705, 709, 746 prefabsoftware.com........................................... 694 Prefab UI Actions............................................... 694 preferences........................................................... 569 Preset..................................................................... 366 printer descriptions........................................... 569 printer drivers..................................................... 569 printmonitor....................................................... 569 privileges.............................................................. 186 process......................................................... 514, 712 Processes Suite........................................... 700, 712 834
ProgramArguments................................. 662, 663 Programmauswahl.............................................530 Programmieren.....................................................36 Programmpfad.................................................... 715 Programmskripts................................................. 94 progress indicator...............................................720 Project Builder...................................................... 32 prop....................................................................... 407 properties.....................................................407, 491 im Funktionsverzeichnis...............................251 Properties inherited from................................. 253 properties of.........................................................181 property................................................................173 Abfragen........................................................... 412 Definition........................................................ 407 eine für alle......................................................448 name................................................................. 429 parent....................................................... 443, 455 Persistenz................................................ 414, 434 properties.........................................................412 Reichweite................................................484, 491 Sichtbarkeit...................................................... 413 Zuweisung.......................................................410 Property List Editor... 46, 77, 660, 670, 686, 690 Property list file......................................................46 Property List Keys...............................................671 Property Lists........................................................ 33 PropertyLists......................................................... 84 Protokoll............................................................... 393 protokollieren......................................................122 Prototyping............................................................ 34 Prozess-ID.................................................. 515, 545 Prozessor-Architektur....................................... 715 public.content.....................................................535 public folder........................................................ 569 public.image........................................................535 public.jpeg............................................................535 public.movie........................................................535 public.text.............................................................535 public.tiff..............................................................535 Punkt- vor Strichrechnung.............................. 102 py-appscript...........................................................41 PyOSA.................................................................... 40
Index
Python.......33, 34, 40, 41, 94, 290, 636, 666, 763
Q quarts.................................................................... 519 Query.................................................................... 632 QueueDirectories.......................................686, 687 QuicKeys..................................................... 654, 700 Quicksilver........................................................... 654 quit......................................................................... 376 quit-Handler.............................................. 376, 676 quote...................................................................... 126 quoted form......................................................... 156
R radio button.........................................................720 radio group..........................................................720 RagTime.............49, 50, 71, 91, 96, 405, 415, 650 RagTime-6-Hilfsmittel........................................96 ranchero.com...................................................... 646 random number........................................ 106, 615 with seed.......................................................... 107 range......................................................................290 RAOP.................................................................... 547 Rappenrundung................................................. 106 rb-appscript............................................................41 rc.....................................................................659, 681 read........................................................................588 read only............................................. 183, 186, 254 read write.............................................................. 186 real................................................................ 100, 138 real as integer.......................................................102 real as list..............................................................150 real as unit type...................................................520 real, Größe............................................................101 Rechnerstart........................................................ 676 Rechtschreibprüfung......................................... 735 recipient................................................................ 385 record.................................................................... 174 recordable........................................................48, 59 record as list......................................................... 177 record-Literal......................................................172
red-sweater.com................................................. 653 Referenz................................................................ 132 als Zitat............................................................. 287 auflösen............................................................ 299 Auflösung......................................................... 286 in Schleifen...................................................... 283 vom Anwender............................................... 286 vom Programm.............................................. 285 Referenzen........................................................... 283 in Schleife......................................................... 299 vergleichen...................................................... 287 Referenzformen.................................................. 132 Alle..................................137, 162, 177, 264, 268 Beliebig..........................136, 162, 176, 177, 264 Bereich.............................................135, 160, 265 Filter.................................................................. 266 ID....................................................................... 258 Index................................................132, 159, 257 Mitte........................................136, 162, 176, 264 Name................................................................. 257 Property........................................................... 176 Relativ..............................................139, 142, 265 some.................................................................. 107 ref to....................................................................... 285 Register................................................................. 362 Reguläre Ausdrücke....................................84, 167 Regular Expressions.......................................... 167 Reichweitenbegrenzung................................... 483 Reihenabfrage......................................................631 Reihenfolge für sortierte Listen.......................221 Reine Daten..........................................................631 Rekursion............................................................. 356 Rekursivität.......................................................... 305 Relative Pfade......................................................510 relevance indicator.............................................720 Remote...................................................................511 Remote AppleEvents......................................... 547 Remote applications.......................................... 546 Remote Audio Output Protocol..................... 547 remote events...................................................... 715 Remote I/O USB Printer Protocol................. 547 Remote Login...................................................... 547 remote procedure call........................................522 835
SmartBooks
AppleScript
removing folder items........................................401 reopen................................................................... 383 reopen-Handler.................................................. 383 repeat......................................................................281 forever................................................................281 geschachtelt..................................................... 304 n times...............................................................291 until...................................................................292 while.................................................................. 294 with.................................................................... 294 with … by......................................................... 296 with in Liste..................................................... 297 ResEdit.....................................................................46 Reservierte Wörter............................................. 115 ResKnife..................................................................46 Resorcerer...............................................................46 Resource-Editor....................................................46 Resource-Fork........................................ 46, 73, 756 Resource-ID........................................................ 757 Resource Manager................................................46 Resources..........................................77, 78, 80, 474 Resource-Type.................................................... 757 Ressourcen........................................................... 474 rest................................................................. 143, 144 Restdivision.........................................................100 result.......................................................63, 121, 345 return..........................................125, 158, 345, 347 im idle-Handler..............................................378 Return....................................................................311 reveal.....................................................................702 reverse.......................................................... 143, 144 Revolution.......................................................31, 85 Rezilla.......................................................................46 RGB color.................................................... 517, 532 RGB-Farben........................................................ 517 r/o......................................................... 183, 248, 254 role................................................................ 716, 724 Rollen.................................................................... 704 rotate..................................................................... 399 rotieren................................................................. 399 round............................................................ 104, 616 rounding as taught in school......................................... 104 836
down................................................................. 104 to nearest.......................................................... 104 toward zero...................................................... 104 up....................................................................... 104 round to nearest...................................................171 row................................................................ 249, 720 RS232...................................................................... 84 rsrc............................................................................46 RTFD....................................................................... 62 RTSP...................................................................... 546 Ruby................................... 33, 40, 41, 94, 636, 763 Rubyforge................................................................41 RubyOSA................................................................41 Rückgabevariable............................................... 345 Rückgabewert...............................................64, 345 als Pattern........................................................ 349 explizit.............................................................. 347 implizit.............................................................. 345 Rückmeldung...................................................... 314 Rückübersetzung.................................................. 52 Rückverweis................................................ 286, 299 Ruhezustand.........................................................681 als Skriptstarter............................................... 677 run................................................................ 373, 418 RunAtLoad........................................ 662, 663, 674 runden......................................................... 104, 616 run-Handler........................................................ 373 running........................................................ 273, 279 run script..................................................... 476, 608
S Safari...................................................................... 279 Satimage..........................................49, 81, 101, 167 Satimage.osax........................................................ 84 say.......................................................................... 559 scale....................................................................... 399 Schachtelung....................................................... 256 Schaden................................................................698 Schleifenoptimierung..................... 283, 288, 360 Schleifenvariable....................................... 295, 298 Schleifenzähler.................................................... 295 Schlüsselbund....................................................... 43
Index
Schnittstellen digitale................................................................ 84 serielle................................................................. 84 Schreibweisen....................................................... 55 script.....................................................173, 403, 415 script AppleScript...................................... 405, 445 Script Debugger........................49, 52, 81, 82, 250 Script Editor Scripts............................................. 93 Scripting-Addition............................................ 167 Scripting Additions.............................. 28, 42, 569 Scripting Bridge.................................................... 33 Scripting Commands........................................ 606 scripting components...............38, 479, 609, 753 scripting definition...............................................47 ScriptSaver...........................................................682 scripts folder........................................................ 569 scriptsoftware.com............................................. 654 script suite...............................................................46 scriptSuite...............................................................46 scriptTerminology................................................46 scroll area..............................................................721 scroll bar................................................................721 sdef............................................................................47 second...................................................................132 seconds..................................................................201 Secure Shell.......................................................... 547 Seitenleiste als Skriptstarter...............................................630 Sekunden.................................................... 190, 199 Selbstaufruf.......................................................... 357 Selbstzuweisung................................................. 119 select......................................................................738 selected................................................................. 724 selection...............................................505, 518, 641 sender...................................................317, 364, 385 September............................................................ 195 Server Admin...................................................... 547 Servername..........................................................513 Services.................................................................633 session parameter...............................................320 set.................................................113, 140, 147, 174 set eof....................................................................605 settable..................................................................732
set the clipboard to.............................................583 set volume............................................................ 617 sh.............................................................................. 40 shared documents.............................................. 569 shared libraries....................................................570 Sharing...................................................................511 Sharing & Zugriffsrechte.................................. 186 Shebang.................................................33, 109, 750 sheet...............................................................249, 721 Shell.............................................................. 156, 752 Shellskript......................................................94, 109 shift down................................................... 742, 746 Short.......................................................................101 short-circuiting...................................................235 Shortcuts..................................................... 642, 650 short date string..................................................198 short name........................................................... 716 short user name..........................................333, 393 shutdown folder..................................................570 Sicherung............................................................. 314 Sicherungskopie.................................................398 Sichtbarkeit von Variablen.................................................. 483 since....................................................................... 364 sips.........................................................................398 sites folder............................................................570 size................................................................ 187, 724 skalieren............................................................... 399 Skript aufzeichnen....................................................... 59 ausführen........................................................... 54 debuggen............................................................ 55 übersetzen......................................................... 54 Skriptassistent.................................................56, 68 Skriptbausteine......................................................57 Skript-Bundles...................................74, 77, 78, 80 Skripteditor..............................35, 49, 52, 253, 278 Skripterweiterung im Bundle.......................................................... 44 Skripterweiterungen......................................28, 42 Skriptkomponenten............................................ 38 Skriptmenü......................................................91, 92
837
SmartBooks
AppleScript
Skriptobjekt als Element...................................................... 446 Bestandteile..................................................... 403 Eigenschaften.................................................. 404 Skriptobjekte....................................................... 415 als Werte........................................................... 424 definieren......................................................... 415 Hierarchie........................................................ 446 im Bundle........................................................ 474 Individualisierung......................................... 439 Initialisierung......................................... 425, 434 Instanzen erzeugen........................................ 439 laden.................................................................. 475 Reihenfolge............................................. 435, 448 run-Handler....................................................418 speichern...........................................................471 vergleichen...................................................... 429 Verschachtelung.................................... 446, 448 Skriptordner............................................. 92, 93, 94 Skript-Timer............................................... 668, 669 Skriptwächter............................................. 676, 692 Sleeping.................................................................678 SleepWatcher.......................................................678 slider..............................................................721, 741 SMB...............................................................546, 567 Smile....................49, 50, 81, 83, 85, 101, 167, 529 SmileLab.................................................... 52, 81, 83 SnoozeRun.......................................................... 677 SOAP............................................................ 522, 524 some.................107, 136, 139, 162, 176, 177, 264 some item............................................................. 136 Sommerzeit..........................................................202 sophisticated.com..............................................668 sound.....................................................................693 Sourceforge......................................................41, 46 space......................................................................125 Spaces.................................................................... 746 speakable items...................................................570 splitter....................................................................721 splitter group........................................................721 Spotlight.......................................................185, 631 Spotlight-Kommentar.................... 185, 270, 393 Sprachausgabe.................................................... 559 838
Sprache........................................................ 560, 735 Spracherkennung...............................................560 square feet............................................................ 519 square kilometers............................................... 519 square kilometres............................................... 519 square meters...................................................... 519 square metres...................................................... 519 square miles......................................................... 519 square yards......................................................... 519 SSH........................................................................ 547 Stack........................................................................ 29 StandardAdditions......................................43, 527 Standardausgabe....................................... 758, 762 Standardeingabe.................................................762 Standarderweiterungen....................................302 Standardfehlerausgabe......................................762 Standardhandler.................................................373 Standard-Skripteditor......................................... 89 Standard-Skriptsprache...................................... 40 Stapel....................................................................... 29 Start als Skriptstarter................................................671 Startbildschirm..................................................... 75 StartCalendarInterval....................................... 666 Startdialog........................................ 61, 76, 79, 758 StartInterval................................................ 662, 663 startly.com............................................................ 654 Startobjekte..........................................................672 StartOnMount....................................................690 starts with............................................................. 229 startup disk..................................................181, 570 StartupItem................................................. 668, 678 startup items........................................................570 Startwert............................................................... 295 static text...............................................................721 stationery..............................................................570 Statusleiste............................................................ 266 Step into.................................................................. 83 Steuerleiste............................................................. 53 Steuerung............................................................... 58 Steuerungsleiste..................................... 41, 58, 333 Steuerzeichen.......................................................311 Steuerzeichenkonstanten.................................125
Index
Stimme.................................................................. 559 stop........................................................................ 557 Stoppwert............................................................. 295 store script....................................................471, 607 string....................................................124, 139, 177 String Commands.............................................. 574 string id.................................................................153 strings.................................................................... 577 Stummschaltung................................................618 subject...................................................................385 subrole...................................................................725 Subroutine............................................................333 Substantiv.............................................................253 Substantive...........................................................363 Subtraktion..........................................................100 Suchen...................................................................581 Suchen und Ersetzen......................................... 166 sudo....................................................................... 675 Suffixe.......................................................................71 Suites............................................................ 251, 528 summarize............................................................581 Supercard............................................................... 85 SuperCard...............................................................31 Swann, Matt.........................................................682 Symbolleiste.................................................... 53, 67 als Skriptstarter...............................................628 System 7 Pro.......................................................... 30 system attribute.................................................. 619 system domain.....................................................571 Systemeinstellungen................170, 189, 202, 221 Bedienungshilfen...........................................700 Benutzer........................................................... 672 CDs & DVDs.................................................. 689 Datum & Uhrzeit............................................621 Landeseinstellungen...................................... 745 Netzwerk.......................................................... 673 Schreibtisch & Bildschirmschoner.............741 Sharing..............................................................511 Softwareaktualisierung . .............................. 744 Tastatur & Maus..............................................701 Ton................................................... 614, 618, 738 System Events............ 43, 302, 388, 534, 700, 712 System Events Suite............................................701
system folder.......................................................570 system info..........................................333, 393, 621 system preferences.............................................570 SystemStarter.......................................................668 Systemstimmen..................................................560 SystemUIServer.................................................. 747
T Tab..................................................................125, 311 Tabelle................................................................... 290 Tabellenkalkulationen....................................... 290 tab group...............................................................721 table.................................................................72, 721 Tabulator.............................................................. 125 Tabulatoren............................................................ 68 Tag.......................................................................... 192 Tagesnamen......................................................... 193 Tageszahl.............................................................. 192 Tastatureinstellungen........................................ 744 Tastaturkurzbefehle............................................701 Tastaturkürzel...................................................... 637 Tastaturlayout...................................................... 743 Tastatur & Maus...................................................701 Tastaturmenü............................................. 151, 745 Tastaturübersicht.................................................151 Tastencode........................................................... 746 Tausendertrenner............................................... 158 Tcl............................................................................. 40 tell............................................................................241 auf application.................................................271 auf application id........................................... 273 auf Bereich....................................................... 265 auf id..................................................................258 auf index........................................................... 257 auf Namen....................................................... 257 auf Objekte...................................................... 257 auf Objektreferenz......................................... 259 auf POSIX-Pfad.............................................. 273 Hierarchie................................................247, 251 implizit..............................................................242 mit every.......................................................... 264 mit middle....................................................... 264 839
SmartBooks
AppleScript
mit some.......................................................... 264 mit whose......................................................... 266 relativ................................................................ 265 Tell Context Inspector......................................... 82 telnet...................................................................... 765 TELNET.......................................................546, 547 Telnet hosts.......................................................... 546 Temperatur.......................................................... 519 temporary items.................................................570 Terminal............................................. 398, 661, 750 text....................................................... 124, 138, 158 TEXT....................................................................... 80 text area.................................................................722 text as boolean....................................................240 text as date............................................................205 text as finder reference......................................508 text as integer...............................................170, 171 text as list.............................................................. 169 text as number............................................170, 171 text as real.....................................................170, 171 TextEdit........................................................ 289, 406 text field................................................................722 Textformatierungen..............................................53 text from............................................................... 169 text id.....................................................................153 text item................................................................ 159 text item delimiter.............................................. 159 text item delimiters.........162, 194, 196, 221, 243 case.................................................................... 307 diacriticals........................................................308 hyphens............................................................310 numeric strings...............................................312 OS-Unterschiede............................................308 punctuation.....................................................310 white space........................................................311 text items.....................................................162, 222 Textlineal.................................................................61 text of.....................................................................161 Textverarbeitungen............................................ 290 TextWrangler....................................49, 94, 95, 674 that......................................................................... 266 the.......................................................................... 365 third.............................................................. 132, 159 840
ThisService.................................................. 635, 650 through............................................... 135, 160, 364 thru...................................................... 135, 160, 364 Thursday .............................................................. 193 time........................................................................ 199 timeout................................................................. 317 Timer..................................................................... 669 time string.............................................................201 time to GMT...............................................202, 621 Titelleiste............................................................... 266 title......................................................................... 725 to............................................................................ 364 Tonausgang.......................................................... 618 Toneffekte............................................................. 529 tool bar.........................................................722, 728 toolbar visible............................................. 261, 266 ToolBook.................................................................31 top.......................................................................... 765 ToyS...................................................................75, 80 tr............................................................................. 765 track..................................................... 366, 417, 693 Transaktionen..................................................... 319 trash.......................................................................570 true......................................................................... 206 try........................................................................... 324 Tuesday................................................................. 193 Type-Code............................................................. 72 type identifier...................................................... 534 Typisierung....................................................28, 113
U Überladen............................................................ 460 Überschreiben.................414, 423, 457, 459, 466 übersetzen.............................................................. 54 Uhrzeit.................................................................. 189 UI Browser..........................................705, 709, 746 uid................................................................. 515, 545 UI element...................................................713, 717 UI Element Inspector........................................ 705 UI Element Inspectors...................................... 694 UI Element Scripts............................................. 700 Umgebung............................................................ 673
Index
Umgebungsvariable.................................. 619, 679 Umrechnungen................................................... 520 Umwandlung......................................102, 169, 177 alias as file........................................................ 507 alias as list......................................................... 506 alias as POSIX path....................................... 507 alias as text....................................................... 506 file as alias........................................................ 509 file as list........................................................... 509 file as POSIX path.......................................... 509 file as text.......................................................... 509 finder reference as file................................... 509 finder reference as text.................................. 507 integer as unit type.........................................520 POSIX file as alias.......................................... 505 real as unit type...............................................520 script as list...................................................... 429 text as finder reference..................................508 unit type as integer.........................................520 unit type as list.................................................521 unit type as real...............................................520 unit type as text...............................................521 unit type as unit type.....................................520 unäre Operatoren............................................... 237 und......................................................................... 234 under..................................................................... 364 Ungleichheit........................................................ 209 Unicode...................... 33, 110, 151, 156, 308, 575 Dezimalwert.................................................... 152 Hexadezimalwert...........................................152 unicode text..........................................................151 unicode text id....................................................153 Unicode-Zeichen................................................131 Uniform Type Identifiers.................................. 535 unit type as integer.............................................520 unit type as list.....................................................521 unit type as real...................................................520 unit type as text....................................................521 unit type as unit type.........................................520 unit types.............................................................. 519 Universal-Binary................................................ 758 Universal Time............................................202, 621 unix device identifier.........................................690
unix id................................................................... 716 Unix (LF)................................................................ 80 Unix-Zeilenumbruch........................................ 126 unsichtbare Dateien.................................. 303, 535 unwahr.................................................................. 206 Upload.....................................................................43 URL Access Scripting...........................................43 URL-Auswahl..................................................... 545 URL-Kodierung........................................ 513, 694 USB-Stick.......................................................78, 691 user domain..........................................................571 User-ID................................................................. 516 User Interaction.................................................. 529 user locale.............................................................190 users folder...........................................................570 using terms from....................................... 316, 514 UT.......................................................................... 202 UTF-8.....................................................................591 UTF-16........................................................ 591, 613 UTI........................................................................ 535 utilities folder......................................................570
V value............................................................. 725, 732 value indicator.....................................................722 Variablen............................................................... 113 Einfache................................................... 484, 488 Globale.................................................... 484, 495 Lokale...................................................... 483, 485 properties.................................................484, 491 Variablenzuweisungen...................................... 117 Vektorgrafiken....................................................... 84 Verb........................................................................ 253 Verbinden mit dem Internet............................................ 673 Vererbung............................................................. 443 Vererbungslinie................................................... 443 Vergleich............................................................... 206 Vergleichsoperatoren contains............................................................ 223 equal, is, =........................................................ 207 greater, less, >, <..............................................215 841
SmartBooks
AppleScript
starts with, ends with.................................... 229 Verknüpfungsoperator...................................... 124 Verlauf der Ergebnisse..........................................65 Verlauf des Event-Protokolls..............................65 Verlaufsfenster.................................................65, 70 Verschachtelungstiefe........................................ 305 verschieben..........................................................688 version................................................................... 244 Versionsnummern............................................. 312 Vervollständigen....................................................56 Verzeichnisstruktur.............................................. 72 Verzögerung......................................................... 548 Video DVD.......................................................... 690 visible...................................................303, 385, 716 voices.....................................................................570 Volumen............................................................... 519 Vordergrund........................................................ 716 Vorschau............................................. 713, 725, 734 Vorschaubild........................................................ 629 Vorsicht................................................................. 698
W wafflesoftware.net............................................... 635 wahr....................................................................... 206 Wahrheitswert..................................................... 206 Waking up............................................................ 678 Warndialog.......................................................... 549 warning.................................................................550 Warnton................................................................ 529 Warnton-Lautstärke.......................................... 618 warten auf Antwort..................................................... 317 WatchPaths..................................................686, 687 WebDAV File System........................................ 547 Webserver............................................................. 397 Web servers.......................................................... 546 Wednesday .......................................................... 193 weekday................................................................ 193 weeks......................................................................191 Werkzeugleiste........................................... 260, 269 where..................................................................... 266 white space...................................................157, 311 842
whose........................................................... 266, 726 Wildcards............................................................. 167 window................................................................. 722 Window classes................................................... 248 windows............................................................... 266 Windows.................................................................35 Windows (CRLF)................................................. 80 Windows-Freigaben.......................................... 567 Winkler, Dan......................................................... 29 Wirkungsbereich................................................ 483 with timeout........................................................ 317 with transaction.................................................. 319 Wochenbeginn.................................................... 193 Wochentag........................................................... 193 Wochentagszahl.................................................. 193 word.............................................................. 157, 159 words............................................................ 160, 168 Workflow...............................................33, 639, 668 workflows folder.................................................570 Workflow-Variablen.............................................33 Workgroup Manager......................................... 547 Wortgrenze.......................................................... 157 Worttrenner......................................................... 157 write.......................................................................600 write only.............................................................. 186 wsanchez.net....................................................... 642 würfeln.................................................................. 343
X X11-Umgebung.................................................. 703 x-Achse................................................................. 185 Xcode.................................. 32, 77, 79, 85, 529, 705 xendai.com........................................................... 635 xinetd.................................................................... 659 XML.............................................46, 47, 77, 84, 660 XMLLib.osax......................................................... 84 XML Property List............................................. 663 XML-RPC................................................... 522, 523 Xserve RAID....................................................... 547 xTalk.........................................................................31
Index
Y y-Achse................................................................. 185 yards...................................................................... 519 year........................................................................ 197
Z Zahlliterale............................................................. 99 Zeichenpalette......................................................151 Zeilenende............................................................. 80 Zeilennummerierung.......................................... 82 Zeilenumbruch....................................68, 125, 158 Zeit................................................................ 189, 199 Zeitmessung........................................................ 289 Zeitspanne...........................................................190 Zeitzone................................................................ 202 Zeitzonen..............................................................621 Ziel..........................................................................241 Zielbestimmung................................................. 244 Zip............................................................................ 78 Zufallszahlen....................................................... 106 Zufallszitat............................................................ 525 Zugriff für Hilfsgeräte.......................................700 Zusammenfassen................................................581 Zuweisungsoperation........................................ 174 Zwischenablage................................................... 582
Bildnachweis – Illustrationen Fotolia: alle © Seite 23: Andres Rodriguez –Seite 51: mipan – Seite 97: velusariot – Seite 627: picture-optimize – Seite 699: cubens – Seite 767: Tjall – Seite 817: mipan iStockphoto: alle © Cover u. Seite 3: Alija / Dangerousdee – Seite 27: geopaul – Seite 37: 4x6 – Seite 527: stdemi – Seite 749: mstay
843