beginning AppleScript question

I'm a programmer so I shouldn't have any trouble understanding AppleScript, but I must be missing something fundamental. I wanted to write a script that types some text in a LibreOffice window, and according to many examples I have found on the web, I should write something like


tell application "LibreOffice" to keystroke "foo"


However this gets me the error "Can't get keystroke 'foo'"


I'm just a bit confused. Why is it trying to *get* something?

MacBook Pro (Retina, 15-inch, Mid 2015), OS X El Capitan (10.11.6)

Posted on Aug 9, 2016 4:55 PM

Reply
19 replies

Aug 9, 2016 5:45 PM in response to mike1127

That would depend on the particular app.

Every App has its own Dictionary of commands. You have to look at the Dictionary for the App to see what commands it takes

System Events responds to the keystroke command, but it is kind of a universal program, so you have to make sure the thing you want the keystroke to appear in is frontmost.

For example, this will put text into a new TextEdit document.

tell application "TextEdit"

activate

make new document

tell application "System Events"

keystroke "Hello, World!"

end tell

end tell

The outer Tell block sets up a new document in TextEdit which was told to come to the front with "activate."

The inner Tell block instructs "System Events" to type the keys passed as a string.

You can run commands with System Events, also.

tell application "TextEdit"

activate


make new document

tell application "System Events"

keystroke "Hello, World!"

keystroke "s" using command down

end tell

end tell

That will add the text to a new document and send the Save command (cmd-s).


To view an App's Dictionary, use the Open Dictionary command from the File menu and find the App. If it is grayed out, it doesn't have a Dictionary and can't be scripted except as shown above with System Events.

Aug 9, 2016 8:17 PM in response to Barney-15E

I'm a programmer and I am frustrated with AppleScript. It's "natural language" syntax is so different than a programming language. For instance the role that identifiers play is not obvious from the syntax, at least to a programmer's eye. Just to give one example, I might see the identifier "window" but wonder -- is it a field of a variable, an actual variable, some kind of qualifier or filter? A reserved word? A syntactical or structural word? And what is the order of precedence of all these qualifiers and access fields?


The whole idea that "natural language" is easier to comprehend kind of falls by the wayside as soon as you have to put parentheses around a sub-clause. Then you have to explain operator precedence to this hypothetical newbie Mac user who somehow isn't able to understand programming syntax but is supposed to be able to get up quickly writing scripts because they are "natural language."


So what is UI Scripting? If it's a regular programming language I will find it infinitely easier.

Aug 9, 2016 8:44 PM in response to mike1127

A window is like a class. You can send messages to a class with a Tell block.

tell window 1 of application TextEdit to close.


A property in AppleScript is like an instance variable or method of a class. Some properties can be set, but others are read only.

Elements are like properties that are classes in and of themselves.

User uploaded file

User uploaded file

UI scripting is clicking menus and buttons with a script.

Click menu 3 of menu 2 of menubar 3 of application "Foo"

Click button 3 of tab group 4 of window 3 of ...

Aug 9, 2016 8:54 PM in response to Barney-15E

Instead of

let myWindow = TextEdit.Windows(1)
myWindow.titled = true
myWindow.name = "Foo"

You would

tell application "TextEdit"
     set myWindow to window 1 of windows
     set titled of myWindow to true
     set title of myWindow to "Foo"
end tell


The latter makes more sense to someone who doesn't understand dot-syntax or whatever property-escaping syntax is used.

The Swift-like syntax is likely more readable than Objective-C, but still is not as obvious to someone who has no object-oriented programming experience.

Aug 9, 2016 9:09 PM in response to mike1127

I don't know what the AppleScript Dictionary for Emacs is. I don't know if it understands what a window is.

If I substitute "TextEdit" for "Emacs" it runs just fine.

Every App has its own AppleScript "API." You have to learn each. Many stick with similar conventions, but you can't just assume any given app understands what a "window" is or that the App is actually AppleScriptable.


As you can see in this snippet, the color coding indicates what is understood by the app (not Script Editor or AppleScript itself)

tell application "TextEdit"

repeat with windowId from 1 to 2

if name of window windowId is "left" then

activatewindowwindowId

end if

end repeat

end tell


AppleScript knows that application is a class

It shows that TextEdit knows that name is a property of a window and that windowId is a variable.

It knows that TextEdit can activate a window class object.

Aug 9, 2016 9:18 PM in response to mike1127

This was the first book I read on AppleScript and I think it did a pretty good job, but I wasn't familiar with anything beyond Basic and Fortran when I read it.

Danny Goodman's Applescript Handbook: Danny Goodman ...


This is a good site for learning and seeing examples: http://www.macscripter.net


This MacTech publication is for converting from VBA to AppleScript in Office, it may help in understanding some idiosyncrasies: Converting VBA Macros to AppleScript in Microsoft Office - MacTech


Then there's this: http://macosxautomation.com/applescript/

Aug 9, 2016 9:22 PM in response to Barney-15E

It looks like Emacs is unscriptable. I found some web pages that said to script unscriptable programs, in general you need to use System Events.


I tried this script:


tell application "Emacs"

activate

end tell

tell application "System Events"

get windows

end tell


It printed {} seeming to indicate that Emacs has no windows even though it obviously has two of them at the time I ran the script. What do you think is wrong with this?

Aug 9, 2016 9:30 PM in response to mike1127

How about

get windows of process "Emacs"


Again, System Events is global, and it has no windows of its own.

You essentially activated Emacs, then asked System Events for its own windows.


You seem to be thinking about it linearly and not objectively.


Both application "Emacs" and application "System Events" are objects that respond to messages

get windows only applies to the object "System Events" whose class is "application"

Since you provided no other context, it can only assume you want to know about its windows.

Aug 9, 2016 9:40 PM in response to mike1127

Your AppleScript was essentially,

Emacs.activate()

return "System Events".Windows()


If that is not clear, why would the class "System Events" know anything about the windows of class "Emacs"?


EDIT: Maybe this is better phrasing:

Why would calling the Windows method of "System Events" know to give you information about the windows of another class which you did not specify?

Aug 9, 2016 9:42 PM in response to Barney-15E

This



tell application "System Events"

get windows of process "Emacs"

end tell


also returns an empty list.


I have no Earthly idea what your comment about "linearally/objectively" means, but all I'm hoping for is some consistency. For instance, one would hope that there are some basic similarities between all applications, some consistent principles. One possible principle would be that all applications have windows. That doesn't seem like a stretch. So it's a problem is there is an application (clearly referred to by the word "application") that doesn't have any windows, namely "System Events."


Okay, so let's say it doesn't have any windows, let's say we have no choice about that. Then why does the command "get windows" return an empty list rather than give an error message? The latter would be a better way of handling such inconsistencies.


As far as the appeal of "natural language" I would agree that these scripts are easier to READ for beginners, but as far as WRITING scripts, what helps is consistency and simplicity to the rules. Typical programming syntax is simple and consistent and doesn't involve any redundant syntactical words, nor does it have multiple ways of doing things when one way would be simpler.

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

beginning AppleScript question

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.