This macro group allows you to quickly switch the smart quotes style (in System Preferences > Keyboard > Text) according to the language you are writing in.
The macro group consists of a main macro and several “trigger” macros that let you set the specific quotes style. A trigger macro just calls the main macro and passes a parameter to it.
This makes it easy for you to set your custom trigger for each quote style (hotkey, typed string, or both). You can also launch the macros from the group palette.
By default is has these settings:
Language | Quotes | String trigger |
---|---|---|
English, Spanish | “abc”, ‘abc’ | ;qen |
German | „abc“, ‚abc‘ | ;qde |
French | « abc », ‹ abc › | ;qfr |
German (Chevrons) | »abc«, ›abc‹ | ;qdec |
Switzerland (de, fr, it) | «abc», ‹abc› | ;qch |
Spanish (Latinas) | «abc», ‘abc’ | ;qes |
Typewriter (Code) | "abc", 'abc' | ;qty |
Toggle Smart Quotes & Dashes | — | ;qqq |
Of course, this is a language selection that suits my personal needs. But it is very easy to customize it:
- At the beginning of the AppleScript (the large if…then…else block) set your desired quotes combination, as you find it in the pop-up menu in System Preferences.
- The value of the
theLanguage
variable is what you have to pass via the trigger macro parameter.
- The value of the
- Adapt the trigger macro accordingly and set the typed string / hotkey trigger.
Set Smart Quotes via System Prefs Macros.kmmacros (22.9 KB)
Requires KM 8.0.3+; tested on macOS 10.13.
As always with GUI scripts, if you are using a non-English system you may have to adapt the names of GUI elements to your system language.
Main macro:
One of the trigger macros:
The AppleScript:
set SPwasRunning to false
set counter to 0
tell application "Keyboard Maestro Engine"
set theLanguage to getvariable "Local Language" instance system attribute "KMINSTANCE"
end tell
if theLanguage is "en" then
set {dQuote, sQuote} to {"“abc”", "‘abc’"}
else if theLanguage is "de" then
set {dQuote, sQuote} to {"„abc“", "‚abc‘"}
else if theLanguage is "fr" then
set {dQuote, sQuote} to {"« abc »", "‹ abc ›"}
else if theLanguage is "es" then
set {dQuote, sQuote} to {"«abc»", "‘abc’"}
else if theLanguage is "de-alt" then
set {dQuote, sQuote} to {"»abc«", "›abc‹"}
else if theLanguage is "CH" then
set {dQuote, sQuote} to {"«abc»", "‹abc›"}
else if theLanguage is "none" then
set {dQuote, sQuote} to {"\"abc\"", "'abc'"}
end if
tell application id "com.apple.systempreferences"
if running then set SPwasRunning to true
reveal anchor "Text" of pane id "com.apple.preference.keyboard"
end tell
tell application id "com.apple.systemevents"
tell application process "System Preferences"
repeat until title of first window is "Keyboard"
delay 0.1
set counter to counter + 1
if counter > 40 then
display alert "Failed to open the Keyboard pane of System Preferences!"
error number -128
end if
end repeat
tell first window
tell tab group 1
if theLanguage is "toggle" then
tell checkbox "Use smart quotes and dashes"
click # Toggle
# if value is not 0 then click # Disable
end tell
else
tell checkbox "Use smart quotes and dashes"
if value is not 1 then click
end tell
tell pop up button 1
perform action "AXShowMenu"
tell menu 1
click menu item dQuote
end tell
end tell
tell pop up button 2
perform action "AXShowMenu"
tell menu 1
click menu item sQuote
end tell
end tell
end if
end tell
end tell
end tell
end tell
if not SPwasRunning then tell application id "com.apple.systempreferences" to quit
Technical note (and question):
As you see, the macro works by ugly GUI scripting.
A more elegant way would be to set the preferences directly via UserDefaults, for example…
Bash:
defaults write -globalDomain NSUserQuotesArray -array "« " " »" "‹ " " ›"
Swift:
CFPreferencesSetValue("NSUserQuotesArray" as CFString, ["« " " »" "‹ " " ›"] as CFPropertyList, kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost)
Both methods work fine, but with a big caveat: If the text editor was already running I had to restart it to make it recognize the new settings, which defeats the purpose of the macro to switch quickly. So I decided to go the GUI way.
If anybody knows how to set GlobalDomain preferences in a way that they get pushed to running applications then I will happily rewrite the macro.
Update (Oct 18, 2017 at 10:02 UTC)
- Added a timeout while waiting for the Keyboard preferences pane.