100 Languages Speedrun: Episode 36: AppleScript
Tags: osx, apple, applescript
Published: 2021-12-27 00:12:34

AppleScript is a small language Apple included in OSX to automate some tasks.

It's almost unknown, even though knowing a few things about it could be quite useful for a lot of OSX users.

AppleScript uses atrocious "natural language" like syntax.

### How to use AppleScript

For simple commands you can just type them in the shell. As you can probably guess these change audio volume to 0% and 100% respectively:

```
$ osascript -e 'set volume 0'
$ osascript -e 'set volume 100'
```

Since it's just shell command you can also put them in shell scripts like these:

```
#!/bin/bash

osascript -e 'set volume 0'
```

```
#!/bin/bash

osascript -e 'set volume 100'
```

Or you can use it like a regular Unix scripting language. Weirdly, this was not supported for most of AppleScript's existence. AppleScript was introduced in 1993, and only OSX 10.5 in 2007 added support for this:

```
#!/usr/bin/env osascript

set volume 0
```

```
#!/usr/bin/env osascript

set volume 100
```

### Hello, World!

The `say` command uses the terrible default synthesizer voice:

```
#!/usr/bin/env osascript

say "Hello, World!"
```

### Dialogs

You can display simple dialogs. Here's some code asking user if they prefer cats or dogs:

```
#!/usr/bin/env osascript

display alert "Cats or Dogs?" buttons {"Cats!", "Dogs!"}
set animal to button returned of the result
if animal is "Cats!" then
  say "meow"
else
  say "woof woof"
end if
```

![Cats or Dogs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sw60x7huw4bvazgdv0zl.png)

Notice all the weird English-like syntax. If you think this will make coding easier, that's really not how it turned out. All AppleScript coding involves a lot of trial and error to get your syntax accepted, with no clear rules. It was an experiment that convincingly failed.

### Control applications

In principle AppleScript can do a lot to control applications. For example this opens new window in Chrome, then presses Cmd-T, types URL, and presses enter:

```
#!/usr/bin/env osascript

tell application "System Events"
  tell process "Google Chrome"
    click menu item "New Window" of menu "File" of menu bar 1
    activate
  end tell
  delay 0.5
  # Cmd-T to open a new tab
  keystroke "t" using command down
  # Type something
  keystroke "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  # Press enter
  key code 36
end tell
```

In practice this kind of code is extremely unreliable, so if possible you should try other solutions first - in case of Chrome there's tons of much better APIs for it already.

### FizzBuzz

Here's AppleScript FizzBuzz. For some reason `log` prints to `stderr` instead of `stdout`:

```
#!/usr/bin/env osascript

on fizzbuzz(n)
  if n mod 15 is 0 then
    return "FizzBuzz"
  else if n mod 5 is 0 then
    return "Buzz"
  else if n mod 3 is 0 then
    return "Fizz"
  else
    return n as string
  end if
end fizzbuzz

repeat with n from 1 to 100
  log fizzbuzz(n)
end repeat
```

### FizzBuzz Dialog

But that's boring. Let's display a dialog, and then actually say the result. To keep the program simple I skipped all the error handling, so it will just crash if you give it wrong input.

```
#!/usr/bin/env osascript

on fizzbuzz(n)
  if n mod 15 is 0 then
    return "FizzBuzz"
  else if n mod 5 is 0 then
    return "Buzz"
  else if n mod 3 is 0 then
    return "Fizz"
  else
    return n as string
  end if
end fizzbuzz

set userInput to (display dialog "Enter a number to fizzbuzz:" default answer "")
set userNumber to (text returned of userInput) as integer
say fizzbuzz(userNumber) using "Victoria"
```

![FizzBuzz Dialog](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/08c4ok38bl8qlpmlkyhv.png)

### Should you use AppleScript?

Not really. It was always a bad language, scripts break every OSX or application upgrade, and nowadays a lot of it is locked for "security" reasons, or just stopped working. Writing anything in AppleScript is exercise in painful trial and error, both on API side, and language syntax side.

Occasionally there could be a task which cannot be done in any other way, so it might be good to be aware of AppleScript as the last resort.

### Code

[All code examples for the series will be in this repository](https://github.com/taw/100-languages-speedrun).

[Code for the AppleScript episode is available here](https://github.com/taw/100-languages-speedrun/tree/master/episode-36-applescript).