Making VoiceOver announce the time and date on your Mac

Important

This guide is outdated and may not provide accurate information for current use cases. It is being retained as a recognition of the author's contribution, but it should be regarded as archived.

By Chris Norman, 18 June, 2014

This is an updated and refined version of this guide, now that I've learned a little more, and stopped being so confused.

So we all know about the keyboard commander, and how you can make it read the time when you press option + t, but I personally find that method really really slow. In addition, for me at least, the date doesn't even read some times. So I set to making my own solution.

So, if you've got VoiceOver controllable by Applescript (in the General tab), you can make it say stuff etc.

Note: The reason this is v2 of this guide, is the following run from AppleScript editor, although working, will not work...

tell application "voiceover" to output "Hello world."

This is because AppleScript editor makes VoiceOver say "Run", after the script has been executed, thus you don't hear what you told VoiceOver to say.

Anyways, here's my updated time script, which you just need to point a keyboard command, quicknav key, or any other trigger of your choosing towards:

tell application "VoiceOver" to output (do shell script "date +\"%d %h %Y, %H %M %S\"")

In addition, as a bonus for me being so stupid and not getting VoiceOver to talk before, here's my other scripts:

Battery.scpt:
tell application "VoiceOver" to output (do shell script "pmset -g batt")

Disk Usage.scpt:
tell application "VoiceOver" to output (do shell script "df -h | head -2 | tail -1")

Date Reader.scpt:
tell application "VoiceOver" to output (do shell script "date +\"%d %h %Y, %H %M %S\"")

Memory.scpt:
tell application "VoiceOver" to output (do shell script "memory_pressure | grep \"memory free\"")

Ping.scpt:
tell application "VoiceOver" to output (do shell script "if ping -c1 bbc.co.uk > /dev/null;
then msg=\"up\";
else msg=\"down\";
fi;
echo \"Net is $msg\"")

Note: You have to send ping's output to /dev/null (nowhere), otherwise VoiceOver reads all that too.

Enjoy, and happy hacking.

Disclaimer

The article on this page has generously been submitted by a member of the AppleVis community. As AppleVis is a community-powered website, we make no guarantee, either express or implied, of the accuracy or completeness of the information.

Options

Comments

By Jeff Wheatley on Wednesday, September 21, 2016 - 16:03

I like Chris's scripts so much that I spent some time to add a bit of filtering to the output so I get the most important info. Chris, I hope you do not mind my steeling and revising your great work!

To use these scripts, as Chris explains in the original post, use the Script Editor to cut / paste each of these into a separate file. Then use the VoiceOver Utility's Keyboard Commander to assign keystrokes to each of these AppleScripts.

If you wish to extend or change these scripts, note that the bulk of the work is done by the UNIX shell scripting embedded in the VoiceOver output command (date, grep, cut, memory_pressure, etc.). If you know shell script, you can enhance / come up with other useful scripts to create.

-- Time of Day
tell application "VoiceOver" to output (do shell script "date +\"%l %M %p, %A %d %h %Y\"")
-- Example result: 3:47 PM, Sunday 18 September 2016
-- Google the UNIX date syntax to learn the meaning of the various %x items if you want to change the output.

-- Battery Status
tell application "VoiceOver"
output (do shell script "pmset -g batt | grep InternalBattery | cut -d ' ' -f 3-4")
delay 1
output (do shell script "pmset -g batt | grep drawing | cut -d ' ' -f 4-")
end tell
-- Example result: 61%, Discharging, Battery Power

-- Disk Free
tell application "VoiceOver"
output (do shell script "df -h | head -2 | tail -1 | tr -s ' ' | cut -d ' ' -f 4")
end tell
-- Example result: 122Gi
-- read this as 122G; not sure why the i is appended...

-- Working memory free%
tell application "VoiceOver"
output (do shell script "memory_pressure | grep \"memory free\" | cut -d ' ' -f 5")
end tell
-- Example result: 58%

Hope you find this useful...

By PaulMartz on Wednesday, April 21, 2021 - 16:03

I've discovered sometimes these scripts simply stop working. To fix, try opening the VO Utility and toggling the checkbox to allow AppleScript to control VoiceOver.

The script stopped working again after the upgrade to 11.3.1. Again, opening the VO Utility and toggling the checkbox to allow AppleScript to control VoiceOver remedied the issue.

By glassheart on Monday, June 21, 2021 - 16:03

Chris? If this works with the battery status and such? You my friend are going to be a lifesaver! I've been looking for those scripts for years now! Thank you thank you thank you!

By Jason on Wednesday, January 31, 2024 - 16:03

Hello!

I'm not sure if Chris is still active here, as the last post I found was in 2015, but I came across these AppleScript scripts and wanted to extend my thanks. With the rapid pace of technology, I encountered a few bugs when trying these scripts on the latest macOS. I've updated them for compatibility and want to share these tweaks with my fellow VoiceOver users.

The main issue was with quotes in shell commands within the scripts; they need to be "escaped" with a backslash (\). This is a small but crucial adjustment to ensure the scripts run smoothly. Here’s a straightforward example to illustrate this fix:

  • Incorrect syntax (without escaped quotes):
    tell application "VoiceOver" to output (do shell script "echo "I don't want green eggs and ham, Samantha I am."")
  • Correct syntax (with escaped quotes):
    tell application "VoiceOver" to output (do shell script "echo \"I don't want green eggs and ham, Samantha I am.\"")

This correction is essential for the scripts to work as intended, allowing VoiceOver to accurately relay the scripted message.

For those who are not as familiar with scripting, this change ensures that special characters, like quotes within a shell command, are correctly interpreted by preceding them with a backslash (). This tells the AppleScript interpriter to pass them on as part of the shell command. In the incorrect version, there are so many quotes its hard to keep track of which quote is part of the shell command, and which isn't.

Below, you'll find the updated scripts. If you're using TextEdit to create these scripts, be aware that it might save in a format that can't be run. Here's how to make sure the scripts are saved correctly.

  1. open a new document in TextEdit.
  2. Paste the script in the empty file. This should start with the word "tell".
  3. To be sure the file is saved as a text file, press Command Shift T. VO will say: "make ritch text" or "make plain text". Keep cycling, Command Shift T, until VO says "make plain text".
  4. To save your script in TextEdit, press Command S, or go to Save in the file menu.
  5. Paste the name of the file here, including the ".scpt" at the end. Note, this is the first line of each group.
  6. set the location to save the file, and press the Save button.

Updated Scripts:

Battery.scpt

tell application "VoiceOver" to output (do shell script "pmset -g batt")

Date Reader.scpt

tell application "VoiceOver" to output (do shell script "date +\"%d %h %Y, %H %M %S\"")

Disk Usage.scpt

tell application "VoiceOver" to output (do shell script "df -h | head -2 | tail -1")

Memory.scpt

tell application "VoiceOver" to output (do shell script "memory_pressure | grep \"memory free\"")

Ping.scpt

tell application "VoiceOver" to output (do shell script "if ping -c1 google.com > /dev/null; then msg=\"up\"; else msg=\"down\"; fi; echo Net is $msg.") ```

Happy hacking!

By Kevin Shaw on Wednesday, January 31, 2024 - 16:03

I've updated the battery script to filter the output so you will get the percentage and charging status only without the extraneous ID numbers and so on.

tell application "VoiceOver"
set batteryInfo to do shell script "pmset -g batt"
set batteryPercentage to word 11 of batteryInfo
set chargingStatus to word 12 of batteryInfo
set outputString to "Battery power: " & batteryPercentage & " percent, " & chargingStatus
output outputString
end tell
the output will sound like this:
"Battery power: 36%, discharging"