Cleaning Up Variables at the end of sub-macros

How about using what’s already used in a few of KM’s actions: a leading “^” means it’s a regex?

By the way, I like your way of doing this better than what I was thinking of.


I just posted a feature request for Peter to add Read-Write locks. These would be perfect for handling the concurrency issue.

It would mean adding a read-lock to the beginning of all affected macros, but there’s almost no overhead. The cleanup macro would try to acquire a write-lock.

Macros that get the read-lock would not hinder each other. It’s only the write-lock that blocks anything.

So when the cleanup macro tries to get the write-lock, it would block until no macros held a read-lock. Once it got the write-lock, any other macros would block trying to get the read-lock, until the cleanup macro was done.

I hope that makes sense. I never tried to explain it before - I know how it works, but putting it in words isn’t easy!

I like that, except that the "^" symbol means start of string in RegEx. So what if my RegEx pattern was for something in the middle of the string?

I suppose you could use something like this:

^.*Text_to_match

I'm such a RegEx amateaur that I don't want to preclude anything.
I'll defer to you on this.

Didn’t we have a discussion recently about the fact there are a few places where “^” at the start of search term caused KM to treat it as a regular expression? I thought so, anyway. That’s why I was thinking about using that here.

OK, so the question is:
If a “^” is at the start of a variable to delete, do I treat that just as an indicator that what follows is a RegEx, or do I include the “^” as part for the RegEx?

I know KM uses this elsewhere, but it is confusing to me.
I’d rather have a symbol that indicates this line is a RegEx, and that symbol is NOT part of the RegEx.

Some options that occur to me are:

  • A symbol as a prefix or suffix that is NOT part of the RegEx
  • A verbose prefix, like “regex:”
  • I suppose you could use a simple prefix like “r:” (case insensitive)
  • OR, you could use the somewhat standard of inclusion in slashes, like /.*SomeString.*/
    • A prefix and suffix of “/” indicates a RegEx
    • Everything between the slashes is the RegEx

As I write this, I am developing a preference for the last method, as being unambiguous and consistent with existing standards.

Your thoughts?

It's true that enclosing a regex in "/" is an existing standard. So that's probably a good one to follow.

So the next question is, what about regex flags? Do you use KM's standard of prefixing the expression with something like "(?i)", or do you try and support the regex standard, which is to follow the closing "/" with flags, as in "/match/i"

I should let you know up front that I don't think I'll be using this macro unless we can resolve the concurrency issue. So I'm very happy to help figure it out with you, but I wanted to be open about my intentions.

Yes, and if you don't need that anchoring, just add .*:

^.*Whatever

which is exactly equivalent to not having the ^ in the regex.

2 Likes

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)