Cleaning Up Variables at the end of sub-macros

This is what I was referring to:[quote="Tom, post:2, topic:4561"]
in case of draft/temporary macros with prefixes like ω or zzz that sorts the variables at the very end of the list.
[/quote]

Ooh, I like that idea. I like it a lot.

I'm not sure about adding individual variables to the list, because I'd still have to remember to do that. But some version of the naming conventions we've all talked about might be just the ticket.

Hmm. Hmmm. Hmm (that's me thinking).

The point is it would support both, for those that want to specify the name and for those that want to use prefixes.

What I like the most is that there is very, very little overhead. Only requires each Macro to have one simple Action: Set Variable "DND__Vars_To_Delete" (or whatever you choose) to append the variables and/or prefixes used by that macro. No sub-macro required.

No, I get it.

But here’s what I’m thinking. If, and I know it’s a big if, but bear with me for a minute - if I had a naming convention that could be matched using a regex of some kind, then it would be simple to create a timed macro that deletes all variables matching the regex. In fact, with it being a regex, anyone with a naming convention that can identify to-be-deleted variables could use the “timed cleanup” macro.

Does that make sense?

Makes perfect sense. Great idea.

Except I just thought of a major downside. The timed cleanup macro could delete variables that are in use by a currently-running macro.

Good point. Could the cleanup macro check for running macros, and pause until there are none (or reschedule itself for later)?

Probably, but there’s nothing to guarantee that a macro won’t start running while the cleanup macro is running.

Well, I hate to do this, but you could have the cleanup macro popup a request to continue when it starts, and then a notice when it is done.

Or perhaps something with a semaphore, but I’d have to think about that one.

Dan, do you plan to implement this (the cleanup macro) soon?
I was going to, but no sense in both of us developing the same macro.
I’m good with either way.

No, not until I work out the multi-threading issue. Go for it! Just make it so we can define our own regex, if that’s the way you’re going to code it.

Yeah, I was going to include RegEx expressions, but haven't determined how to denote them in the list. I'm thinking something like this for the Variable list:

Text without an asterisk or backquote at the end is treated a full variable name

FullVariableName
ThisIsPrefix*
ThisIsRegEx`

Here I used the backquote to denote RegEx. What would be better?

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: