Applescript for keyboard system preferences pane

I'm trying to write an applescript to get me to a specific section of the system preferences - Keyboard > Shortcuts > App Shortcuts and click on the "+", choose a specific app, enter Menu Title and enter "F key" in to their respective fields. Here is what I have so far:

tell application "System Preferences"
    activate
    set current pane to pane id "com.apple.preference.keyboard"
    delay 1
    tell application "System Events"
        click radio button "Shortcuts" of tab group 1 of window "Keyboard" of application process "System Preferences"
        delay 1
        select row 8 of table 1 of scroll area 1 of splitter group 1 of tab group 1 of window 1 of application process "System Preferences"
        click radio button "+" of tab group 1 of window "Keyboard" of application process "System Preferences"
    end tell
end tell

This gets me to the App Shortcuts portion of the Keyboard prefs pane, but I can't click on the "+" button to go further. Is there a way to click on "+", choose an application, fill in the Menu Title and Keyboard Shortcut fields?

Thanks for any help.


Solution 1:

You will not need your AppleScript code as this provides a complete and proper solution for the UI Scripting of System Preferences for the use case you are wanting to achieve.

The example AppleScript code, shown below, was tested in Script Editor under macOS Catalina and macOS Big Sur with Language & Region settings in System Preferences set to English (US) — Primary and worked for me without issue1.

  • 1 Assumes necessary and appropriate setting in System Preferences > Security & Privacy > Privacy have been set/addressed as needed.

Note that because this is using UI Scripting, it is necessary to allow it to run without doing anything else until the script finishes.

The example AppleScript code is commented and you should only need to set the value of the menu item title, application name, and keyboard shortcut based on the coded example using Photos.

Example AppleScript code:

--  # Set the value for appName and menuItemTitle, as in the example below.

set appName to "Photos"
set menuItemTitle to "Keep Sorted By Title"

--  # Set the keyboard shortcut in the setKeyboardShortcut() handler.

to setKeyboardShortcut()
    tell application "System Events" to ¬
        keystroke "t" using {option down, command down}
end setKeyboardShortcut



--  ######################################################
--  # The code below should only be edited as necessary. #
--  ######################################################


--  # Check to see if System Preferences is 
--  # running and if yes, then close it.
--  # 
--  # This is done so the script will not fail 
--  # if it is running and a modal sheet is 
--  # showing, hence the use of 'killall' 
--  # as 'quit' fails when done so, if it is.
--  #
--  # This is also done to allow default behaviors
--  # to be predictable from a clean occurrence.

if running of application "System Preferences" then
    try
        tell application "System Preferences" to quit
    on error
        do shell script "killall 'System Preferences'"
    end try
    delay 0.1
end if

--  # Make sure System Preferences is not running before
--  # opening it again. Otherwise there can be an issue
--  # when trying to reopen it while it's actually closing.

repeat while running of application "System Preferences" is true
    delay 0.1
end repeat

--  # Get the fully qualified POSIX pathname of the target .plist file.

set thePropertyListFilePath to ¬
    the POSIX path of ¬
        (path to preferences from user domain as string) & ¬
    ".GlobalPreferences.plist"

--  # Get the value of AppleKeyboardUIMode to determine if the
--  # 'Use keyboard navigation to move focus between controls'
--  # checkbox is checked on the System Preferences >  
--  # Keyboard > Shortcuts tab.

tell application "System Events" to ¬
    tell the property list file thePropertyListFilePath to ¬
        set keyboardNavigation to the value of ¬
            the property list item "AppleKeyboardUIMode"

if keyboardNavigation = 0 then
    --  # Check the checkbox.
    my toggleKeyboardNavagition()
end if

--  # Open System Preferences to the 
--  # Shortcuts tab of the Keyboard pane.

tell application "System Preferences"
    activate
    reveal anchor "shortcutsTab" of ¬
        pane id "com.apple.preference.keyboard"
end tell

tell application "System Events"
    tell window 1 of ¬
        application process "System Preferences"
        
        --  # Wait until necessary UI element is available.
        
        set i to 0
        repeat until exists ¬
            checkbox 1 of ¬
            tab group 1
            delay 0.1
            set i to i + 1
            if i ≥ 30 then return
        end repeat
        
        --  # Select App Shortcuts.
        --  # This is wrapped in a try 
        --  # statement as a workaround.
        
        try
            select (rows of ¬
                table 1 of ¬
                scroll area 1 of ¬
                splitter group 1 of ¬
                tab group 1 whose ¬
                value of ¬
                static text 1 is ¬
                "App Shortcuts")
        end try
        
        --  # Wait until necessary UI element is available.
        
        set i to 0
        repeat until exists ¬
            button 1 of ¬
            group 1 of ¬
            tab group 1
            delay 0.1
            set i to i + 1
            if i ≥ 30 then return
        end repeat
        
        --  # Click the [+] button.
        
        click button 1 of ¬
            group 1 of ¬
            tab group 1
        
        --  # Wait until necessary UI element is available.
        
        set i to 0
        repeat until exists ¬
            text field 2 of sheet 1
            set i to i + 1
            if i ≥ 30 then return
        end repeat
        
        --  # Fill in the Sheet with the menu item title,
        --  # application name, and keyboard shortcut.
        
        set value of text field 2 of sheet 1 to menuItemTitle
        delay 0.2
        click pop up button 1 of sheet 1
        delay 0.2
        click menu item appName of menu 1 of pop up button 1 of sheet 1
        delay 0.2
        key code 48 --  # Tab key
        delay 0.2
        my setKeyboardShortcut()
        delay 0.2
        click button "Add" of sheet 1
        
    end tell
end tell

if keyboardNavigation = 0 then
    --  # Uncheck the checkbox if it
    --  # was previously unchecked.
    my toggleKeyboardNavagition()
end if

delay 0.2

tell application "System Preferences" to quit


--  # Handler #

--  # Toggles checkbox: 'Use keyboard navigation 
--  # to move focus between controls'

on toggleKeyboardNavagition()
    tell application "System Preferences"
        activate
        reveal anchor "shortcutsTab" of ¬
            pane id "com.apple.preference.keyboard"
    end tell
    tell application "System Events"
        tell front window of ¬
            application process "System Preferences"
            set i to 0
            repeat until (exists checkbox 1 of tab group 1)
                delay 0.1
                set i to i + 1
                if i ≥ 30 then return
            end repeat
            click checkbox 1 of tab group 1
        end tell
    end tell
end toggleKeyboardNavagition

Note: The example AppleScript code is just that and sans any included error handling does not contain any additional error handling as may be appropriate. The onus is upon the user to add any error handling as may be appropriate, needed or wanted. Have a look at the try statement and error statement in the AppleScript Language Guide. See also, Working with Errors. Additionally, the use of the delay command may be necessary between events where appropriate, e.g. delay 0.5, with the value of the delay set appropriately.