I'm a Python programmer who switched to Mac OS X. Being nerd and needing to automate common tasks, the learning of the AppleScript language was unavoidable. To speed up the process I've took some notes, comparing the new commands to Python statements. The result is this document.
As the name says, it's intended for Python programmers. But if you're an applescripter interested in Python you may also learn a lot.
Python | AppleScript |
---|---|
indexes start with 0 | indexes start with 1 |
string comparison considers case | string comparison ignores case |
# comments | -- comments |
command # half-line comment | command -- half-line comment |
""" multiline comment block (sort of) """ |
(* multiline comment block *) |
a = 5 | set a to 5 |
a = "foo" | set a to "foo" |
print "Hello World" | display dialog "Hello World" |
syslog.syslog(msg) or print >>sys.stderr, msg |
log(msg) |
print "\a" | beep |
say "Hello World" | |
Data types | |
type("foo").__name__ | class of "foo" |
None | missing value |
True, False | true, false |
2 | 2 |
"foo" or 'foo' |
"foo" |
"""foo bar""" |
"foo bar" |
[ 1, 2, 3 ] | { 1, 2, 3 } |
( 1, 2, 3 ) | |
{ "foo": "bar" } | { foo: "bar" } |
str(5) | 5 as text |
int("5") | "5" as integer |
float(5) | 5 as real |
float("5") | "5" as real |
list("foo") | characters of "foo" |
"".join([ "f","o","o" ]) | { "f","o","o" } as text |
"".join([str(x) for x in [ 1, 2, 3 ]]) | { 1, 2, 3 } as text |
String | |
S = "" | set S to "" |
S = "foo" | set S to "foo" |
len(S) |
length of S or count S |
S[2] | item 3 of S |
S[len(S)/2] | middle item of S |
S[random.randint(0, len(S)-1)] | some item of S |
S[2:-2] | items 3 thru -3 of S as text |
S + "foo" | S & "foo" |
S.index("z") or S.find("z") |
offset of "z" in S |
S.startswith("z") | S starts with "z" |
S.endswith("z") | S ends with "z" |
S.count("z") | User function countSubstring() |
S.split() | words in S |
S.split()[2] | word 2 of S |
S.split(":") |
set AppleScript's text item delimiters to ":" text items of S set AppleScript's text item delimiters to "" |
":".join(LIST) |
set AppleScript's text item delimiters to ":" LIST as text set AppleScript's text item delimiters to "" |
S.lstrip() | User function lstripString() |
S.rstrip() | User function rstripString() |
S.strip() | User function stripString() |
S.lower() | User function lowerString() |
S.upper() | User function upperString() |
S.capitalize() | User function capitalizeString() |
S.replace() | User function replaceString() |
"z" in S | "z" is in S |
\\ \" \t \n \r | \\ \" \t \r space tab return |
S = "foo\nbar" | set S to "foo" & return & "bar" |
S = """foo "bar" baz""" | set S to "foo \"bar\" baz" |
List | |
L = [] | set L to {} |
L = [ 77, "foo", True ] | set L to { 77, "foo", true } |
L = [ 1, [ 2, [ 3 ]]] | set L to { 1, { 2, { 3 }}} |
len(L) |
length of L or count L |
[x for x in L if isinstance(x, int)] | integers in L |
[x for x in L if isinstance(x, str)] | strings in L |
L[2] | item 3 of L |
L[2][2] | item 3 of item 3 of L |
L[len(L)/2] | middle item of L |
L[random.randint(0, len(L)-1)] | some item of L |
newlist = L[:] |
set newlist to every item of L or copy L to newlist |
L[2:-2] | items 3 thru -3 of L |
L + [ 1, 2 ] or L.extend([ 1, 2 ]) |
L & { 1, 2 } |
L.append("foo") |
set the end of L to "foo" or copy "foo" to the end of L |
L[2] = "foo" | set item 3 of L to "foo" |
del L[2] | set L to items 1 thru 2 of L & items 4 thru -1 of L |
L.index("foo") | User function getListItemIndex() |
L.count("foo") | User function countListItem() |
L.pop(0) |
first item of L set L to rest of L |
L.pop(0) ; L[:] | rest of L |
L.reverse() | reverse of L |
L.sort() | |
"foo" in L | "foo" is in L |
L[0] == "foo" | L starts with "foo" |
L[-1] == "foo" | L ends with "foo" |
Dictionary / Record | |
D = {} | set D to {} |
D = { "foo":"bar", "spam":"eggs" } | set D to { foo:"bar", spam:"eggs" } |
len(D) |
length of D or count D |
D["foo"] | foo of D |
D["foo"] = "bar" | set foo of D to "bar" |
D + { "foo":"bar" } or D.update({ "foo":"bar" }) |
D & { foo:"bar" } |
newdic = D.copy() | copy D to newdic |
del D["foo"] | |
D.keys() | |
D.values() | |
D.has_key() | |
D["foo"] == "bar" | foo of D is "bar" |
D.get("foo") == "bar" | { foo:"bar" } is in D |
Expressions | |
1 + 1 | 1 + 1 |
1 - 1 | 1 - 1 |
1 * 1 | 1 * 1 |
1 / 1 | 1 div 1 |
1.0 / 1.0 |
1 / 1 or 1 ÷ 1 |
1 % 1 | 1 mod 1 |
1 ** 1 | 1 ^ 1 |
(2 + 4) * 2 | (2 + 4) * 2 |
1 == 1 |
1 = 1 or 1 is equal 1 |
1 != 1 |
1 ≠ 1 or 1 is not equal 1 |
1 > 1 |
1 > 1 or 1 is greater than 1 |
1 < 1 |
1 < 1 or 1 is less than 1 |
1 >= 1 |
1 >= 1 or 1 ≥ 1 or 1 isn't less than 1 |
1 <= 1 |
1 <= 1 or 1 ≤ 1 or 1 isn't greater than 1 |
1 is 1 | 1 is 1 |
1 is not 1 | 1 is not 1 |
1 is 1 or 2 is 2 | 1 is 1 or 2 is 2 |
1 is 1 and 2 is 2 | 1 is 1 and 2 is 2 |
(1 is 1) and (2 is 2) | (1 is 1) and (2 is 2) |
Conditionals | |
if VAR == 1: print "OK" | if VAR = 1 then display dialog "OK" |
if VAR == 1: print "OK" |
if VAR = 1 then display dialog "OK" end if |
if VAR == 1: print "OK" else: print "Error" |
if VAR = 1 then display dialog "OK" else display dialog "Error" end if |
if VAR < 10: print "Need more!" elif VAR > 20: print "Too much!" else: print "It's OK" |
if VAR < 10 then display dialog "Need more!" else if VAR > 20 then display dialog "Too much!" else display dialog "It's OK" end if |
Loops | |
for i in LIST: print i |
repeat with i in LIST display dialog i end repeat |
while 1: break |
repeat exit repeat end repeat |
while 1: continue |
|
while VAR is False: # do something |
repeat while VAR is false -- do something end repeat |
while VAR is not False: # do something |
repeat until VAR is false -- do something end repeat |
for i in range(10): # do something |
repeat 10 times -- do something end repeat |
for i in range(1, 10, 2): # do something |
repeat with i from 1 to 10 by 2 -- do something end repeat |
Functions | |
def add_numbers(a, b): return a + b |
on add_numbers(a, b) return a + b end add_numbers |
five = add_numbers(2, 3) | set five to add_numbers(2, 3) |
def optional(a=0, b=""): | |
Class / Script | |
class FooBar(Father): VAR = 0 def setValue(self, val): self.VAR = val |
script FooBar property parent : Father property VAR : 0 on setValue(val) set my VAR to val end setValue end script |
myFoo = FooBar() myFoo.setValue(5) myData = myFoo.VAR |
copy FooBar to myFoo tell myFoo to setValue(5) set myData to VAR of myFoo |
File Read/Write | |
F = open("/tmp/foo") TXT = F.read() F.close() |
set F to "/tmp/foo" as POSIX file set TXT to read F |
F = open("/tmp/foo") LINES = F.readlines() F.close() |
set F to "/tmp/foo" as POSIX file set LINES to read F using delimiter (ASCII character 10) |
F = open("/tmp/foo", "w") F.write("Hello!\n") F.close() |
set F to "/tmp/foo" as POSIX file set F to open for access F with write permission write "Hello!" & return to F close access F |
Path (requires tell app "Finder") |
|
os.path.isfile(F) | file F exists |
os.path.isdir(F) | folder F exists |
os.path.abspath(F) | file F as text |
os.path.dirname(F) | folder of file F as text |
os.path.basename(F) | name of file F |
F.split(os.path.extsep)[-1] | name extension of file F |
os.stat(F)[6] | size of file F |
pwd.getpwuid(os.stat(F)[4])[0] | owner of file F |
grp.getgrgid(os.stat(F)[5])[0] | group of file F |
open(newfile, "w").write(open(F).read()) | duplicate file F to file newfile |
os.rename(F, newfile) | set name of file F to newfile |
os.unlink(F) | delete file F |
Date & Time | |
time.asctime() | current date as string |
T = time.localtime() | set T to current date |
T = time.strptime( "Jan 31, 2005 17:59", "%b %d, %Y %H:%M" ) |
set T to date "Jan 31, 2005 17:59" |
orig = time.mktime(time.strptime( "Jan 31, 2005 17:59", "%b %d, %Y %H:%M" )) plus = time.mktime(time.strptime( "4 3 2 1970", "%d %H %M %Y" )) T = time.localtime(orig+plus) |
set orig to date "Jan 31, 2005 17:59" set plus to 4 * days + 3 * hours + 2 * minutes set T to orig + plus |
time.strftime("%A", T) | weekday of T |
time.strftime("%d", T) | day of T |
time.strftime("%B", T) | month of T |
time.strftime("%m", T) | month of T as integer |
time.strftime("%Y", T) | year of T |
time.strftime("%X", T) | time string of T |
time.strftime("%x", T) | date string of T |
fmt = "%H*3600 + %M*60 + %S" eval(time.strftime(fmt, T)) |
time of T -- Seconds since midnight |
Other | |
try: # do something except: # do something |
try -- do something on error -- do something end try |
try: # do something except error, errmsg: # do something |
try -- do something on error errMsg number errNum -- do something end try |
os.system("ls /etc/ | head -n 1") | do shell script "ls /etc/ | head -n 1" |
global VAR | global VAR |
eval("4 + 4") | run script "4 + 4" |
chr(64) | ASCII character 64 |
ord("@") | ASCII number "@" |
time.sleep(10) | delay 10 |
random.randint(5, 10) | random number from 5 to 11 |
foo, bar = 1, 2 | set {foo, bar} to {1, 2} |
D = {"foo":1, "bar":2 } var1, var2 = D["foo"], D["bar"] |
set {var1, var2} to {foo, bar} of {foo:1, bar:2} |
[ 0, 1, { "foo":"bar" }][2]["foo"][0] | character 1 of foo of item 3 of {0, 1, {foo:"bar"}} |
import foo foo.do_something() |
set foo to load script "foo.scpt" tell foo to do_something() |
"a" == "A" # returns False |
"a" = "A" -- returns true considering case "a" = "A" -- returns false end considering |
"1 2 3 4" == "1234" # returns False |
"1 2 3 4" = "1234" -- returns false ignoring white space "1 2 3 4" = "1234" -- returns true end ignoring |
sys.exit() | tell me to quit |
Handy functions
The AppleScript language is very limited on data handling. The programmer must build his own tools (functions) to have Python-like functionality to manage strings and lists.
countSubstring()
-- Counts how many times a string appears in a text -- Note: Its splits the text by the substring and count the items -- on countSubstring(theText, theSubstring) set AppleScript's text item delimiters to theSubstring set counter to (count of every text item of theText) - 1 set AppleScript's text item delimiters to "" return counter end countSubstring
lstripString()
-- Trims the provided string from the text's beginning -- on lstripString(theText, trimString) set x to count trimString try repeat while theText begins with the trimString set theText to characters (x + 1) thru -1 of theText as text end repeat on error return "" end try return theText end lstripString
rstripString()
-- Trims the provided string from the text's ending -- on rstripString(theText, trimString) set x to count trimString try repeat while theText ends with the trimString set theText to characters 1 thru -(x + 1) of theText as text end repeat on error return "" end try return theText end rstripString
stripString()
-- Trims the provided string from the text's boundaries -- Note: Requires the lstripString and rstripString functions -- on stripString(theText, trimString) set theText to lstripString(theText, trimString) set theText to rstripString(theText, trimString) return theText end stripString
lowerString() / upperString() / capitalizeString()
-- Translate characters of a text -- Note: Pass the From and To tables as strings (same lenght!) -- on translateChars(theText, fromChars, toChars) set the newText to "" if (count fromChars) is not equal to (count toChars) then error "translateChars: From/To strings have different lenght" end if repeat with char in theText set newChar to char set x to offset of char in the fromChars if x is not 0 then set newChar to character x of the toChars set newText to newText & newChar end repeat return the newText end translateChars -- Convert a text case to lower characters -- Note: Requires the translateChars function -- on lowerString(theText) set upper to "ABCDEFGHIJKLMNOPQRSTUVWXYZ" set lower to "abcdefghijklmnopqrstuvwxyz" return translateChars(theText, upper, lower) end lowerString -- Convert a text case to upper characters -- Note: Requires the translateChars function -- on upperString(theText) set lower to "abcdefghijklmnopqrstuvwxyz" set upper to "ABCDEFGHIJKLMNOPQRSTUVWXYZ" return translateChars(theText, lower, upper) end upperString -- Capitalize a text, returning only the first letter uppercased -- Note: Requires translateChars, lowerString and upperString -- on capitalizeString(theText) set firstChar to upperString(first character of theText) set otherChars to lowerString(characters 2 thru -1 of theText) return firstChar & otherChars end capitalizeString
replaceString()
-- Replace all occurences of one string for another in a text -- The trick here is to change the internal delimiter, -- spliting and joining the text -- on replaceString(theText, oldString, newString) set AppleScript's text item delimiters to oldString set tempList to every text item of theText set AppleScript's text item delimiters to newString set theText to the tempList as string set AppleScript's text item delimiters to "" return theText end replaceString
getListItemIndex()
-- Returns the integer index of a list item (zero if not found) -- on getListItemIndex(theList, theItem) repeat with i from 1 to count of theList if item i of theList is theItem then return i end repeat return 0 end getListItemIndex
countListItem()
-- Returns the total count of a specific item in a list -- on countListItem(theList, theItem) set counter to 0 repeat with i from 1 to count of theList if item i of theList is equal to theItem then set counter to counter + 1 end if end repeat return counter end countListItem
Thank You Very Much!
This document was reviewed and got valuable contributions from:
- Alfredo Kojima
- André Ruiz
- Osvaldo Santana Neto
- Rudá Moura
- Ryan Wilcox
- Sérgio Bruder
— EOF —