applescriptlineapplescript-objc

Converting to one line AppleScript


I have a series of AppleScript commands I need to implement into a single line of AppleScript. The code is below.

delay 2
tell application "System Events" to keystroke "foo"
tell application "System Events" to keystroke return

Solution

  • You can combine the two keystroke commands into a single one by concatenating your strings together:

    tell app "System Events" to keystroke "foo" & return
    

    But that still leaves you with one command and a statement (delay and tell … to …).

    Effectively, AppleScript’s statement separator is a line break. In modern AppleScript the line breaks can be either CR, LF, or CRLF (respectively: old-Mac-, Unix-, or DOS-style). There is no convenient way write a multi-statement line (like foo; bar; baz; in C, Perl, Ruby, et cetera).

    For your specific request, you can combine the two in a really ugly way by using delay as a part of an expression.

    tell application "System Events" to keystroke "" & (delay 2) & "foo" & return
    

    This is ugly because delay technically returns no value, but we are able to concatenate it with an empty string without causing an error.

    The problem is that such a construction is not very “general purpose”. You may not always be able to turn any command into an expression in the same way (and you can not use statements like tell as a part of an expression1). For a bit more brevity (and obfuscation), you can write the last bit as "foo" & return & (delay 2). It still runs in the same order (delay first) because each part of the concatenation expression must be evaluated before it can be built into a single value for the keystroke command.

    1 Short of putting them in a string given to run script that is. Even then, some statements (loops, try/catch, etc.) are always multi-line; though you can get around that by using escaped line breaks or concatenation and one of the line break constants (as follows).

    You could use run script with a string argument and use the backslash2 escapes to represent the line breaks.

    run script "delay 0.1\ntell app \"System Events\" to keystroke \"foo\" & return"
    

    AppleScript Editor may translate the escape notation into a literal unless you have “Escape tabs and line break in string” enabled in its Editing preferences (available in 10.5 and later). You could always use the return constant and concatenation instead of the in-string-literal/escape-notation.

    run script "delay 0.1" & return & "tell app \"System Events\" to keystroke \"foo\" & return"
    

    2 If you are going to represent such strings inside an Objective C string literal (as one of your comments might imply), then you will have to escape the backslashes and double quotes for Objective C, also (…& \"tell app \\\"System…).

    Or, if you are ultimately trying to run the code with osascript, then you can use the fact that each instance of -e will become a separate line to put it all on a single shell command line.

    osascript -e 'delay 2' -e 'tell app "System Events" to keystroke "foo" & return'