If they're important to you then you may want to back them up regularly using a method other than Time Machine.
I think I've scragged all my variables once or twice over the years, and I know I've occasionally deleted one or more by mistake that I really didn't want to have to rebuild.
I've used Time Machine at least once to restore all of my variables.
I think don't save important information in variables.
I have no plans to change this behaviour. For almost all users, variables are entirely transient.
Variables are never a great place to save important information - if you have important information, store it somewhere, like in a macro and set the variable that way. Or backup your macros (which would be relatively easy to write a macro to do). And if you really have to, quit Keyboard Maestro and Keyboard Maestro Engine and restore the variables from a backup (and if you don't have a full disk backup system, then you absolutely should resolve that before worrying about Keyboard Maestro variables).
I can't think of any other application that has Undo into Preference settings, and for example in Mail this is far more tragic than Keyboard Maestro variables.
Hi Peter,
Is it possible then to show a confirmation window when users attempt to delete ==multiple== variables? Of course it can be a setting for users to turn it off if they don’t want the confirmation window.
It’s not that the values are too important to lose and unrecoverable. It will take some time to recover them. And I want to prevent it from happening if possible. A confirmation window will definitely help.
@Martin - This may not be the answer you want but to protect yourself, from yourself, you can create a confirmation macro within Keyboard Maestro. It's similar to swallowing the cmd-Q command to protect you from Quitting an application accidentally. This one is simple enough to create without @peternlewis 's intervention.
Modify this to taste - This is in a Keyboard Maestro Group (i.e. while using Keyboard Maestro):
That's a great idea.
The only issue with your macro is that (I'm just guessing by looking at your screenshot), the macro will swallow the delete key.
If "true", the macro will fall into endless loop.
If "false", the macro will do nothing.
but this can be fixed by replacing the delete action with clicking the delete menu item.
I may just put the conditions as macro group condition so that the is not triggered in the KM Editor.
@kcwhat did a good job on this, but I personally would find it too intrusive.
I've had a specific macro that rebuilds my ENV_PATH variable, since the day I first deleted it accidentally. The path is complicated, and I didn't want to have to reconstitute it again by hand:
So I've taken this thread as a nudge to write a variable backup script. It makes a snapshot of variables whose names start with "DND_" or "ENV_", and this is easily adjusted.
Each snapshot is saved to its own date-stamped folder in a given root snapshots folder.
I'll probably set this to run automatically at least once every week or two and give it a manual hotkey trigger as well.
AppleScript Code
--------------------------------------------------------
# Auth: Christopher Stone <scriptmeister@thestoneforge.com>
# dCre: 2021/10/08 21:53
# dMod: 2021/10/08 21:53
# Appl: Keyboard Maestro Engine
# Task: Create Snapshots of KM Variables Whose Names Start with the Given Prefixes.
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @ASObjC, @Keyboard_Maestro_Engine, @Create, @Snapshots, @Variables, @Prefixes
--------------------------------------------------------
use AppleScript version "2.4" --» Yosemite or later
use framework "Foundation"
use scripting additions
--------------------------------------------------------
set variableSnapShotsFolderPath to "~/Documents/Keyboard Maestro Stuff/Variable Snapshots – KM/"
set variableSnapShotsFolderPath to ((current application's NSString's stringWithString:variableSnapShotsFolderPath)'s stringByExpandingTildeInPath) as text
set snapshotFolderName to "Variable Snapshot – " & (my formatDate:(current date) usingFormat:"y-dd-MM › HH.mm.ss")
set snapshotFolderPath to variableSnapShotsFolderPath & "/" & snapshotFolderName
its createDirectoryAtPathWithIntermediates:snapshotFolderPath
tell application "Keyboard Maestro Engine"
set varList to variables whose ¬
name starts with "DND_" or ¬
name starts with "ENV_"
repeat with theVariable in varList
set tempVarName to name of theVariable
set tempVarContent to value of theVariable
if tempVarName contains ":" then
set tempVarName to (its cngStr:":" intoString:";" inString:tempVarName)
end if
set tempVarPath to snapshotFolderPath & "/" & tempVarName & ".txt"
my writeTextToFileNS(tempVarPath, tempVarContent)
end repeat
end tell
--------------------------------------------------------
--» HANDLERS
--------------------------------------------------------
on cngStr:findString intoString:replaceString inString:dataString
set anNSString to current application's NSString's stringWithString:dataString
set dataString to (anNSString's stringByReplacingOccurrencesOfString:findString withString:replaceString ¬
options:(current application's NSRegularExpressionSearch) range:{0, length of dataString}) as text
end cngStr:intoString:inString:
--------------------------------------------------------
on createDirectoryAtPathWithIntermediates:thePath
set {theResult, theError} to current application's NSFileManager's defaultManager()'s createDirectoryAtPath:thePath ¬
withIntermediateDirectories:true attributes:(missing value) |error|:(reference)
if not (theResult as boolean) then
set errorMsg to theError's localizedDescription() as text
error errorMsg
end if
end createDirectoryAtPathWithIntermediates:
--------------------------------------------------------
on formatDate:theDate usingFormat:formatString
set theFormatter to current application's NSDateFormatter's new()
theFormatter's setLocale:(current application's NSLocale's localeWithLocaleIdentifier:"en_US_POSIX")
theFormatter's setDateFormat:formatString
set theString to theFormatter's stringFromDate:theDate
return theString as text
end formatDate:usingFormat:
--------------------------------------------------------
on writeTextToFileNS(posixPath, fileContent)
set theNSString to current application's NSMutableString's stringWithString:fileContent
set {theResult, theError} to theNSString's writeToFile:posixPath atomically:true encoding:(current application's NSUTF8StringEncoding) |error|:(reference)
if theResult is false then error (theError's localizedDescription() as text) number 100
theNSString's deleteCharactersInRange:{0, theNSString's |length|()}
end writeTextToFileNS
--------------------------------------------------------
I advise people who are saving critical data permanently or semi-permanently to save it in text files rather than variables.
It's easy to read them into a temporary variable (local or instance) for use in a macro, and it gives you a big layer of protection from accidental deletion.
Woooo @ccstone ! Your AppleScript is Jedi level mastery! Sheesh! I made a macro to recreate the deleted variable (This will be variables, in the future, as Peter indicated previously). I love being the student!