A Quick Way to Undo (Such as Deleting Variables) in the Preference?

Hi,

I wanted to delete the value for a variable, but accidentally deleted all variables (⌘Adelete).

image

Thankfully, I have TimeMachine backup a few days ago.

This got me to think:

Is there a way to undo any operation in the Preference?

I tried "Revert Macro at Editor Launch" and it won't recover the variables. It would have been disastrous if I did not have TimeMachine backup.

Hey Martin,

Nyet.

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.

@peternlewis – what do you think?

-Chris

1 Like

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.

2 Likes

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):


Delete Prevention.kmmacros (3.9 KB)

3 Likes

Thanks a lot @kcwhat.

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.

Thanks again. That's helpful!

This one will probably work better. I did a quick test initially. But I just wanted to give you an idea.


Delete Prevention.kmmacros (4.4 KB)

I can confirm this solution works.

Making a macro group with these conditions (I included the "Clipboard panel):

image

Put this macro in it:

Confirm before Deletion.kmmacros (2.9 KB)

1 Like

There you have it. Don't go leaving the gas stove on and lighting a match ok? :smiley: .

3 Likes

Hey Guys,

@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:

/opt/local/bin:/opt/local/sbin:/Users/chris/perl5/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Library/TeX/texbin:

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.

-Chris

3 Likes

Hi Chris,

A big :+1: to you. Thanks for sharing this AppleScript.
I changed the backup path and made my first backup.
I will make more DND variables in the future. :wink:

2 Likes

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!

Recreate Variable from Backup.kmmacros (7.0 KB)

Thank you for teaching!

KC

2 Likes