Fischer-Bayern.de
Letztes Update: 07.05.2005 | 11:20:30 Uhr
Handler - Was ist das? 
Peter Fischer


Handler - Immer wieder liest man davon, aber was ist das eigentlich? Die Antwort darauf lautet einfach: Ein Handler ist ein Teil Ihres Skriptprogramms. Man spricht auch von Subroutinen oder Unterroutinen. Handler dienen dazu, ein Skript zu strukturieren und können Ihnen viel Schreibarbeit ersparen. Selbst wenn Sie bisher noch keinen Handler explizit definiert haben, haben Sie schon einen Handler benutzt.

Beispiel:

set x to 5

"Wo bitte ist denn hier ein Handler?" werden Sie fragen. Nun, ich beginne diesen Artikel gleich mit einer Besonderheit, nämlich mit einem impliziten Handler. Alles was sich auf oberster Ebene des Skripts befindet, gehört zum 'run'-Handler. Dieser 'run'-Handler wird automatisch aufgerufen, wenn das Skript gestartet wird.

Es handelt sich um einen impliziten Handler, da Sie ihn nicht extra definiert haben. Er existiert einfach dadurch, dass sie ausführbaren Code in das Skript geschrieben haben.

Sicherlich haben Sie schon einmal ein Skript benutzt, auf das man Dateien oder Ordner ziehen konnte, die dann vom Skript bearbeitet wurden. Ein solches Skriptprogramm heißt 'Droplet' und ist eine überaus praktische Sache.

Damit so ein Droplet funktioniert, braucht es einen weiteren speziellen Handler - den 'open'-Handler.

on open theFileList
    -- ausführbarer Code    
end open

Es gibt noch einige weitere spezielle Handler, wir wollen es aber einmal bei diesen beiden belassen, da sie vorerst genügen, um uns den Sinn von selbstdefinierten Handlern zu zeigen.

Nehmen wir einmal an, Sie wollen ein Skript schreiben, das sowohl als Droplet, als auch als Applet benutzt werden kann. Es soll also funktionieren, wenn man Dateien und/oder Ordner darauf zieht und es soll funktionieren, wenn man es per Doppelklick startet.

Dazu ist noch eine Information über Droplets bzw. den 'open'-Handler wichtig: Referenzen zu den Dateien oder Ordnern, die auf das Droplet gezogen werden, landen in einer Liste, die wiederum in einer Variablen abgelegt wird. D.h. wir müssen bei der Definition des 'open'-Handlers gleich eine entsprechende Variable angeben, sonst wird unser Skript nicht funktionieren.

on open theFileList

theFileList ist diese Variable. Sie können hier natürlich jeden beliebigen Variablennamen benutzen.

Nun wäre das Material zur Bearbeitung also an das Droplet übergeben. Wir wollten aber, dass das Skript auch per Doppelklick funktioniert. Folglich müssen wir dafür sorgen, dass uns in diesem Fall auch eine Möglichkeit geboten wird, Dateien und/oder Ordner auszuwählen. Dies kann mit 'choose file' oder 'choose folder' geschehen. Seit AppleScript 1.9.2 ist es hiermit möglich, auch mehrere Dateien oder Ordner auszuwählen. Wir könnten das Skript also so beginnen:

tell application "Finder"
    set theFileList to {choose folder}
    --
ausführbarer Code
end tell

Ich habe hier 'choose folder' zwischen geschweifte Klammern gesetzt, damit das Ergebnis eine Liste ist. Somit herrschen hier die gleichen Bedingungen wie bei einem 'open'-Handler, an den ja, wie bereits erwähnt, eine Liste mit Referenzen übergeben wird. Die geschweiften Klammern braucht man nicht, wenn man die Option 'multiple selections allowed' benutzt, da hier das Ergebnis automatisch eine Liste ist, selbst wenn nur ein einziges Objekt ausgewählt wurde.

tell application "Finder"
    set theFileList to choose folder with multiple selections allowed
    --
ausführbarer Code
end tell

Unser Skript sieht nun bereits so aus:

tell application "Finder"
    set theFileList to choose folder with multiple selections allowed
    --
ausführbarer Code
end tell

on open theFileList
    -- ausführbarer Code
end open

Nun fügen wir noch etwas Code hinzu. Das Skript soll in einem Dialog den Namen des ersten Objekts anzeigen, das auf das Droplet gezogen wurde bzw. das wir im Dialog ausgewählt hatten. In der Variablen 'theFileList' befindet sich eine oder mehrere Referenzen auf Finder-Objekte (Ordner, Dateien). Um an den Namen eines Objekts zu kommen, müssen wir deshalb den Finder bemühen. Im 'run'-Handler haben wir schon einen Finder-Tell-Block, der uns im 'open'-Handler noch fehlt. Wir ergänzen unser Skript also folgendermaßen:

tell application "Finder"
    set theFileList to choose folder with multiple selections allowed
    
set theName to the name of item 1 of theFileList
    
display dialog theName
end tell

on open theFileList
    tell application "Finder"
        set theName to the name of item 1 of theFileList
        
display dialog theName
    end tell
end open

Nun kommen wir langsam zum Kern dieses Artikels. Wie Sie sehen, sind in unserem Skript nun die Zeilen

        set theName to the name of item 1 of theFileList
        
display dialog theName

doppelt vorhanden. Das mag ja bei unserem Beispiel nicht so tragisch sein. Allerdings erledigt unser Beispielskript auch keine besonders nennenswerte Aufgabe. Bei einem ernsthaften Projekt kommt sicherlich mehr Code zusammen, den Sie dann doppelt eingeben müssen. Nun, dank Copy und Paste ist das ja auch nicht weiter schlimm - jedoch wird Ihr Skript immer unübersichtlicher. Code, den Sie mehrmals im Skript benötigen gehört in einen extra Handler.

Wir können uns also daran machen, den Skriptcode auszulagern. Zuerst brauchen wir jedoch einen eigenen Handler. Ein Handler beginnt meistens mit 'on' gefolgt vom Namen des Handlers und zwei runden Klammern. Innerhalb dieser runden Klammern können Parameter an den Handler übergeben werden. Den Namen des Handlers können Sie sich selbst ausdenken. Es gelten hierbei die gleichen Regeln wie für Variablennamen.

Alternativ zu 'on' könnte man auch 'to' benutzen. 'on' ist jedoch am gebräuchlichsten. Auch für die Parameterübergabe gibt es weitere Möglichkeiten, die ich hier jedoch lieber nicht aufführe, damit es nicht zu verwirrend wird. Ich will mich hier auf die Methode beschränken, die man in den meisten Skripten antreffen wird.

Ich habe den Handler 'GetFileName' getauft, so hat man gleich eine Vorstellung davon, was in diesem Handler erledigt wird. Unser Skript sieht jetzt so aus:

on run
    set theFileList to choose folder with multiple selections allowed
    
GetFileName(theFileList) -- Aufruf des Handlers
end run

on open theFileList
    GetFileName(theFileList) -- Aufruf des Handlers
end open

on GetFileName(DateiListe)
    tell application "Finder"
        set theName to the name of item 1 of DateiListe
        
display dialog theName
    end tell
end GetFileName


Aufruf des Handlers

Der 'run'-Handler wird aufgerufen, wenn wir das Skript per Doppelklick starten. Der 'open'-Handler tritt in Aktion, sobald wir Dateien oder Ordner auf das Droplet ziehen. Wie wird aber nun unser eigener Handler gestartet? Antwort: Gar nicht, solange wir ihn nicht extra aufrufen.

Der Aufruf besteht darin, dass wir an der Stelle im Skript, wo wir die jeweilige Funktion des Handlers benötigen, seinen Namen schreiben gefolgt von runden Klammern. Innerhalb dieser runden Klammern können wir Parameter übergeben - das muss aber nicht unbedingt sein. Es hängt davon ab, was unser Handler erledigen soll. In unserem Fall übergeben wir die komplette Liste der Referenzen an den Handler.

Wir können ruhig mehrere Parameter an einen Handler übergeben. Die verschiedenen Parameter trennen wir durch Komma voneinander.

    set theFileList to choose folder with multiple selections allowed
    
set meinName to "Peter"
    
GetFileName(theFileList, meinName) -- Aufruf des Handlers

Wenn wir mehr Parameter übergeben als der Handler erwartet, fallen die zusätzlichen Parameter unter den Tisch. Übergeben wir weniger Parameter als erwartet, lässt sich das Skript nicht kompilieren.

Beispiel mit einem zusätzlichen Parameter, der jedoch ignoriert wird:

set theFileList to choose folder with multiple selections allowed
set meinName to "Peter"
GetFileName(theFileList, meinName) -- Aufruf des Handlers

on GetFileName(DateiListe)
    tell application "Finder"
        set theName to the name of item 1 of DateiListe
        
display dialog theName
        
display dialog meinName -- Fehler: Variable "meinName" nicht definiert
    end tell
end GetFileName

Mit der Definition eines eigenen Handlers haben wir eine Funktion unseres Skripts geschaffen, die wir von jeder beliebigen Stelle aus aufrufen können. Woran man dabei jedoch immer denken sollte: Es ist eine Funktion unseres Skripts! Setzt man den Handleraufruf in einen Tell-Block, der an ein Programm gerichtet ist, kommt es zu einer Fehlermeldung.

Beispiel:

tell application "Finder"
    DialogAnzeigen()
end tell

on DialogAnzeigen()
    display dialog "Hallo"
end DialogAnzeigen

Sie werden mit folgender Fehlermeldung belohnt:

Wie bereits erwähnt, handelt es sich bei unserem Handler um eine Funktion des Skripts. Der Aufruf wurde jedoch an den Finder gerichtet, der verständlicherweise damit nichts anfangen kann. Doch dieser Fehler kann ganz leicht behoben werden. Wir benutzen das Wort 'my' vor dem Handleraufruf. Somit wird klargestellt, dass es sich um eine Funktion handelt, die innerhalb des Skripts zu suchen ist.

tell application "Finder"
    my DialogAnzeigen()
end tell

on DialogAnzeigen()
    display dialog "Hallo"
end DialogAnzeigen

Dies war nun eine kleine Einführung in das Thema Handler bzw. Subroutinen. An dieser Stelle möchte ich jedoch noch einmal auf unser erstes Skript zurück kommen. Sie müssen den 'run'-Handler natürlich nicht genauso gestalten wie den 'open'-Handler. Denkbar wäre z.B. auch, dass im 'run'-Handler bestimmte Einstellungen für ein Droplet gemacht werden, die in Property-Variablen abgelegt werden.

Ich habe das Beispiel jedoch nicht aus Bequemlichkeit, sondern mit voller Absicht so gewählt. Wenn Sie im 'run'-Handler die gleichen Bedingungen schaffen wie im 'open'-Handler und dann die eigentliche Arbeit des Skripts in einem selbstdefinierten Handler ausführen lassen, können Sie ein Droplet sehr gut debuggen. Sie können das Skript schließlich im Skripteditor ablaufen lassen und die jeweiligen Schritte im Event-Protokoll mitverfolgen.




Peter Fischer



 

 

Workshop



snow@fischer-bayern.de

Ebene 1