Learning & Using AppleScript & JavaScript for Automation (JXA)

I didn't know that would always be true. I do now.
But I was posting the count to confirm it was a string. :smile:

Thanks for the examples. Added to my Dash snippet lib. :smile:

Hey JM,

If you're trying to figure out a variable's class in AppleScript then you can just ask:

set x to "Now is the time for all good men to come to the aid of their country."
set myVarClass to class of x

-Chris

1 Like

Did you take the same typing class in high school that I did? :smile:
That's where I learned that phrase as a sample text for typing.

Thanks for the test for variable class. I still think of "variable type". It is these changes in standard programming terms that still throws me with AppleScript.

Thanks.

I just bought this Kindle book for $8. It is highly rated (5✮).
###A Smarter Way to Learn JavaScript

###The ultimate learn-by-doing approach

Written for beginners, useful for experienced developers who want to sharpen their skills and don't mind covering some ground they already know. (Feel free to skip early chapters that cover elementary topics like alerts, variables, and strings). Step-by-step, you learn the fundamentals of JavaScript as well as some advanced concepts including constructors and prototypes.

The book is extremely user-friendly. It assumes no programming experience. Chapters cover only as much as the average learner can absorb in ten minutes, so you're never asked to eat an elephant. Explanations are in plain, nontechnical English that people of all backgrounds can readily understand. With ample coding examples and illustrations.

The most important part: free, online, interactive exercises paired with each chapter.
and more . . .

1 Like

My apologies for posting so much, but I'm finding this book to be very exciting.
A very interesting quote from the book A Smarter Way to Learn JavaScript

If you embrace this method of learning, you’ll get the hang of HTML and CSS in less time than you might expect. And the knowledge will stick. You’ll catch onto concepts quickly. You’ll be less bored, and might even be excited. You’ll certainly be motivated. You’ll feel confident instead of frustrated. You’ll remember the lessons long after you close the book.

Is all this too much for a book to promise? Yes, it is. Yet I can make these promises and keep them, because this isn’t just a book. It’s a book plus 1,800 interactive online exercises. I’ve done my best to write each chapter so it’s easy for anyone to understand, but it’s the exercises that are going to turn you into a real HTML coder.

1 Like

Chris, would you mind pointing us to a reference, or educating us as to the difference, and when we should use the "process" statement?

Thanks.

Hey JM,

Look in the System Events AppleScript dictionary.

You will find an application class, but that is actually for the System Events application itself — not applications in general.

When System Events talks to another application it talks to the application process class.

People get so used to writing normal AppleScript tell-blocks for apps that they automatically write a normal one and forget to add process within a System Events tell-block. It's a common error I've made a few times and seen many, many times.

Like other applications you have to learn the tricks of using the System Events.app.

-Chris

Thanks. I didn't know that. I'm sure I've made this error many times. :smile:

So is there ever a case when you would use the "tell application" without the "process" inside of a System Events tell?

Hey JM,

Not really.

That would be just like writing a normal tell-block to talk to an app.

tell application "System Events"
  set myPath to path to it
  tell application "BBEdit"
    set doc01Name to name of document 1
  end tell
end tell

This does work, but placing app-tell blocks within app-tell blocks is considered to be bad practice and often throws sandboxing warnings in the Console.

Canonical syntax would be:

tell application "System Events"
  set myPath to path to it
end tell

tell application "BBEdit"
  set doc01Name to name of document 1
end tell

System Events was created many years ago to fill in a bunch of holes in AppleScript — instead of just fixing AppleScript in general. It's very powerful if somewhat clumsy.

tell application "System Events"
  tell application process "BBEdit"
    set frontmost to true
    set bbeditIsScriptable to has scripting terminology
    set bbeditUnixID to unix id
  end tell
end tell

-Chris

Chris, what is the best practice for returning data from an AppleScript to KM?

Is this OK?
It works fine. I was just wondering. . . :smile:

[quote=“ccstone, post:29, topic:1545”]
System Events was created many years ago to fill in a bunch of holes in AppleScript — instead of just fixing AppleScript in general. It’s very powerful if somewhat clumsy.[/quote]

tell application "System Events"
  tell application process "BBEdit"
    set frontmost to true
    set bbeditIsScriptable to has scripting terminology
    set bbeditUnixID to unix id
  end tell
end tell

So, are you saying that that script would not work if you removed the BBEdit stuff from the System Events tell block?
I don’t get the value of the SE tell block here?

Hey JM,

You're making the very mistake conceptually that I was talking about in practice.

All of the values and commands in the script are relative to the BBEdit process Object — IN System Events — none of those values or commands are available to the BBEdit application.

Look at the application process class in the System Events dictionary in the Script Editor (or Applescript Editor on 10.9.x).

If you want to see the variables in action open the Log History window in Script Editor and select the 'Replies' panel.

tell application "System Events"
  get has scripting terminology of application process "BBEdit"
    --> true
  get unix id of application process "BBEdit"
    --> 650
end tell
Result:
650

Note that the gets reference the application process "BBEdit" — not the application "BBEdit". Each get in this script represents the assignment of the gotten value to a variable.

Or you can roll-your-own viewer:

tell application "System Events"
  tell application process "BBEdit"
    set frontmost to true
    set bbeditIsScriptable to has scripting terminology
    set bbeditUnixID to unix id
  end tell
end tell

{"bbeditIsScriptable = ", bbeditIsScriptable, return, "bbeditUnixID = ", bbeditUnixID} as text

You can also put log statements in the code to show things in the Script Editor result-viewer.

Like:

log bbeditIsScriptable

Or in context:

tell application "System Events"
  tell application process "BBEdit"
    # set frontmost to true
    set bbeditIsScriptable to has scripting terminology
    log "bbeditIsScriptable = " & bbeditIsScriptable
    set bbeditUnixID to unix id
    log "bbeditUnixID = " & bbeditUnixID
  end tell
end tell

Or you can spend real money on Script Debugger and have a real variable inspector:

-Chris

1 Like

Thanks.

I wasn't making a mistake, I was asking a question because I didn't understand. :smile:
I did not know that the commands you listed were NOT available to the BBEdit app.

Now that you have explained that, it makes perfect sense. :wink:

Where do I find the list of commands for an app that are only available as a process in a SE tell block?

You can browse the methods and properties of scriptable application objects by opening the (.sdef) ‘dictionary’ file for them.

For example with Script Editor > File > Open Dictionary

( You could start by browing the .sdef dictionary for System Events.app )

Thanks, I'm well aware of that. :laughing:
Maybe I'm missing it, but I don't see anything in the Dictionary that lists the System Events enabled commands. Can you please point me to that?

Thanks.

Hey JM,

What you've done is fine, however it's good practice to use an explicit return statement.

tell application "Microsoft Outlook'
  set oMsg to selection
  set strsubject to subject of oMsg
end tell

return strsubject

It will work fine if you leave it implicit, but I don't like to leave anything in the hands of the result variable — and the return statement lets you read what the output is supposed to be at a glance instead of having to read the code to figure it out.

When I make multiple variable assignments from AppleScript I tend to do something like this:

------------------------------------------------------------
tell application "Keyboard Maestro Engine"
  try
    set value of variable "Test1" to "I am nuts!"
  on error
    make new variable with properties {name:"Test1", value:"I am nuts!"}
  end try
end tell
------------------------------------------------------------

But let's make that easier by using a handler:

------------------------------------------------------------
setKMVar("Test1", "I am nuts!")
setKMVar("Test2", "Or am I?")

on setKMVar(varName, varValue)
  tell application "Keyboard Maestro Engine"
    try
      set value of variable varName to varValue
    on error
      make new variable with properties {name:varName, value:varValue}
    end try
  end tell
end setKMVar
------------------------------------------------------------

Note that if you use a handler-call within an application-tell-block you need to reference it like so:

setKMVar("Test1", "I am nuts!") of me

OR

my setKMVar("Test1", "I am nuts!")

-Chris

Thanks, Chris. I figured you'd have some best practices.

Have you ever thought about writing a book?

Hey JM,

There aren't System Events enabled commands. System Events is in itself an app.

You have to open the System Events.app dictionary.

File > Open Dictionary.

Wait for it to populate — which can take a while.

Select 'System Events' from the resulting dialog.

Smart scripters add System Events to the Library Panel.

-Chris

Not quite sure what you mean by 'commands' there.

applicationProcessapplication process is the name of a class

Perhaps the over-helpful 'Englishness` of Applescript confuses this by allowing spaces in the middle of class names ?

It's really just one class name, with no relationship to the separate Application class. Think of it as a single word with a space introduced in the middle.

(The top level of the SE application object exposes a collection of elements of this class)

1 Like

Hey JM,

I think I misunderstood what you were asking. Please be more specific.

-Chris