Cleaning Up Variables at the end of sub-macros

Since I’ll probably be using JXA for this process, perhaps the easiest and clearest to both the user and the programmer is to follow JavaScript conventions. In that case, I would hope to use the users RegEx entry as the literal RegEx expression in JavaScript. See any issues with that?

OK, thanks. No problem. Each user can decide for him/herself whether or not to use this, or any other macro.

Personally, I think I will find it very useful, and will use it to replace my current practice of calling a sub-macro at the end of every macro. While having some kind of concurrency lock would be helpful, by using an Alert at the start of the cleanup macro I can avoid the concurrency issue.

I’ll answer that in a second - I just thought of something. Regular Expressions use “escapes” all the time, and I’m concerned about what KM will do to some of them. For instance, if you have a backslash-n, will it become a newline instead? You’ll probably need to do some experimentation with this. Sounds like a PITA. Better you than me. :smile:

Back to your question:

You’ll need to use code like this:

var s = "/te.t/i";
var regexp = eval("new RegExp(" + s + ")");
console.log("my Test".search(regexp));

The first line is just setting up the string, like you might get it from KM. In this case, it’s looking for “te” followed by any character followed by “t”, with the flag for ignore case. It was just the first thing that popped into my mind.

The second line is the thing that does all the work. It creates a new “RegExp” object (which is basically the same thing as if I had just hard-coded /te.t/i with no quotes).

I use an “eval” statement, which is a nasty little thing that converts the string into actual JavaScript, and runs it. The reason why “eval” is also known as “evil” is because it can execute literally any JavaScript code, and if you were to use it in a normal internet-facing web page, you’d be totally asking to get hacked. Fortunately, that’s not a problem here - If someone wants to hack this, they have access to the actual source code, so I think that’d be the better way to go - at least if I were the hacker. :slight_smile:

The last line just proves it works.

Of course, there are other ways to do this, but this is the simplest, my long-winded explanation notwithstanding. :blush:

Oh, one more thing. I totally want to use this macro. I just have to figure out how, since I have stuff running all the time. I might just use it on demand - not sure yet. There’s got to be a solution I haven’t thought of yet. This is just too good to pass up.

Thanks for the heads-up.

I think this issue is solved using the new option for Set Variable: "Process Nothing":

I was thinking of doing exactly that. Thanks for the confirmation.

Awesome!

Hey Folks,

You realize you can do something like this?

tell application "Keyboard Maestro Engine"
   set value of variables whose name ends with "_tmp" to "%Delete%"
end tell

-Chris

_[EDIT: Changed typo “.tmp” to “tmp” – thanks Dan!]

7 Likes

A good “find”. Thanks.

Chris -

I wouldn’t have thought a variable name could include a period. The Wiki says

Variable names must start with a letter, and then can contain letters, numbers, spaces, or underscores.

Plus, I wouldn’t feel comfortable using a period even if it does happen to work now, because of potential conflicts with things like .Left, etc.

What’s your thoughts.

It’s certainly not my style.

I tend to use camelCase just because I’m in the habit of doing so in AppleScript and JXA/JS.

However, I do sometimes use underscores, and I could see the utility of using “_tmp”, as in “macroName_tmp

I agree. If I were going to try to delete variables like this, I would use underscores.

But again, the problem with something like this is it deletes all variables that end with “_tmp” (or whatever), not just those used by a specific macro.

Now that I’m using DND__ at the start of the variable names for variables I want to persist, and I’m still prefixing the variable names with something to tie them to the macro (like “minst” that I’m working on right now), I can pretty safely do this:

tell application "Keyboard Maestro Engine"
    set value of variables whose name starts with "minst" to "%Delete%"
end tell

(I just figured this out. I’m slow.)

So, I’ve got that going for me. :slight_smile:

Hey Dan,

You’re right. I meant to type an underscore.

-Chris

1 Like

You can use starts with, contains, or ends with, so you have a reasonable amount of flexibility.

1 Like

For anyone who cares, here’s an example of how to do this in JXA:

var kme = Application("Keyboard Maestro Engine");
kme.variables
    .whose({ name: { _beginsWith: "minst" } }).name()
    .forEach(function(varName) {
        kme.setvariable(varName, { to: "%Delete%" });
    });

Notice the _beginsWith specifier. You can see a whole bunch more of these specifiers (or whatever the correct term for them is), for example _contains and _endsWith, at OS X 10.10 Release Notes and search for “Filtering Arrays”, which is near the top.

1 Like

Is there a means to detect file attachment failures to mail messages using Chrome Gmail?

Context:

I've adopted the practice of deleting no longer needed variables at the end of my macros.

However, if the macro encounter errors, I may wish to avoid the deletion based upon some detectable condition.
Group.kmactions (1.5 KB)

Hey @KM_Panther,

You said it right there detectable condition.

You might be able to see it with JavaScript.

You might be able to see it by getting the source of the page and searching for “Attachment Failed”.

You can get the page text (NOT the source) with AppleScript and parse it.

tell application "Safari"
   tell front document
      set safariPageText to its text
   end tell
end tell

** You can get the page source with “its source” instead of “its text”.

You can parse for “Attachment Failed” or the attachment file name(s). This works to find the file names – I just tried it. I can’t force an attachment to fail though, so I can’t test for that.

The trick here would be the timing of the scan(s) after attaching the files.

The advantage of scanning for the attachment file name(s) is that you can keep scanning until they are found (with a timeout) and continue only after they are seen.

-Chris

Not deleting the variables in the case where the macro fails is a good idea.

You can probably detect the “Attachment failed” text by looking at the text of the web page. Something like Execute JavaScript in Chrome document.documentElement.innerHTML and search that.

Alternatively you could use Find Image on Screen, but text will likely be faster and more reliable.

Hey @KM_Panther,

Whups, I forgot you were using Chrome.

This should work:

tell application "Google Chrome"
   tell active tab of front window
      set visibleText to execute javascript "document.documentElement.innerText"
   end tell
end tell

And of course you can use the bare JavaScript in either an Execute a JavaScript in Google Chrome action or an Execute a JavaScript in Safari Keyboard Maestro action.

-Chris

Chris & Peter,

As an aside, In order to get the image of the attachment failure for posting, I forced the failure by turning off my WiFi radio while the file was being attached. You may not have been able to do that for your testing.

Also, I used the attachment failure as an example, but I suppose there could be other reasons for the email failure (e.g. incorrect address syntax). Is there any way to capture a code or something that indicates the message was successfully sent like the message below that appears?

I have been learning AppleScript, but not JavaScript. I'll try your suggestions.

Thanks for your continued assistance!

Anthony

Chris & Peter,

It works great!

Most, if not all, Actions that encounter an error will automatically cause the Macro to abort, UNLESS you have unchecked one of these:

  • Timeout aborts macro
  • Failure aborts macro

Of course, if the KM Action has no way of knowing whether or not some external software (app, macOS, etc) has a failure, then this will not work.

For example, KM Action "Execute an AppleScript " does NOT abort even if the script returns an error.
So, in all my AppleScript and JXA scripts, I return “[ERROR]\n” and the error message. I then have a KM Group (set of actions) that check for the error and handle accordingly:

I just uploaded this macro (which is really just a Group Action) that I use:

###MACRO: KM Group Action to Handle Script Error