Can't apply my JS Macro result into the filter.

51 views
Skip to first unread message

Shareda

unread,
Oct 15, 2020, 2:29:25 AM10/15/20
to TiddlyWiki
If I take the value from a tiddler field  like {{!!add.filter}}  then it works fine but I need to check and clean this value before it goes to the filter. Otherwise [search:text:regexp{!!add.filter}] crashes my wiki if it contains "||" somewhere or "|" at the edge. There shoud be more checks but I start with this one.

So i've made JS macro and checked its results - ok. It replaces || to | and removes | prefix an suffix
...
exports.run = function(regexp) {    
    regexp= regexp.replace(/([\|\\\{\}]){2,}/g, "$1");
    regexp= regexp.replace(/^([\|]){1,}/g, "");
    regexp= regexp.replace(/([\|]){1,}$/g, "");
    return regexp;
}; 

But when I 
\define validFilter()<$macrocall $name="validateregexp" regexp={{!!add.filter}}/>
and change filter
[search:text:regexp{!!add.filter}]
to 
[search:text:regexp<validFilter>]
then the second filter always returns nothing even if {!!add.filter} and <validFilter> are equal and the first filter works correctly.

I would like to understand why. And how I should apply my macro to the filter.





Eric Shulman

unread,
Oct 15, 2020, 4:07:05 AM10/15/20
to tiddl...@googlegroups.com
On Wednesday, October 14, 2020 at 11:29:25 PM UTC-7, Shareda wrote:
\define validFilter()<$macrocall $name="validateregexp" regexp={{!!add.filter}}/>
and change filter
[search:text:regexp{!!add.filter}]
to 
[search:text:regexp<validFilter>]
then the second filter always returns nothing even if {!!add.filter} and <validFilter> are equal and the first filter works correctly.

This is, perhaps, the most frequently misunderstood concept in TiddlyWiki:

*** Macros are NOT functions ***

They do not "evaluate their contents and return the results".   Rather, they just perform TWO actions:

1) replace occurrences of $param$ with corresponding values passed as macro parameters
2) replace occurrences of $(variable)$ with corresponding values of variables define outside the macro

After doing these replacements, the macro's literal contents are inserted in place of the macro call itself.
It is then up to the calling context to do any rendering (aka, "wikification") of the results.

Thus, your second filter becomes:
[search:text:regexp<$macrocall $name="validateregexp" regexp={{!!add.filter}}/>]
and filter operators do NOT process widgets.  Thus, the regexp filter operator sees it's parameter
as a reference to a variable named "$macrocall".  In addition, variable references inside filters do
not allow use of arguments, so the rest of the $macrocall -- the $name... and regexp... parts -- are ignored.

In effect, your filter is:
[search:text:regexp<$macrocall>]
and since there is no variable named "$macrocall", it is trying to match a blank pattern which,
of course, produces no results.

To actually get the rendered results of the validateregexp $macrocall, you need to use the
<$wikify> widget to process and capture the *output* of the validFilter() macro into a variable,
and then use that variable in the filter.  Something like this:

<$wikify name="thefilter" text=<<validFilter>>>
...
[search:text:regexp
<theFilter>]
...
</$wikify>

I hope this explanation doesn't make your head explode.  :)

Let me know how it goes...

-e

Shareda

unread,
Oct 15, 2020, 6:24:29 AM10/15/20
to TiddlyWiki
Eric, thanks for the clarity in my head! I assumed that the problem was the difference between a field and a macro from a filter point of view, but I did not understand exactly. I understand now. ...
Tested, IT IS OK! Yes! :)

So there are 
1. validateregexp.js macro module
2. \define validFilter()<$macrocall $name="validateregexp" regexp={{!!add.filter}}/>
3. <$wikify name="thefilter" text=<<validFilter>>>
4. use in filter expression

If that's optimal way to use such macro then I should implement it in another 3 places that I have
  

четверг, 15 октября 2020 г. в 14:07:05 UTC+6, Eric Shulman:
Reply all
Reply to author
Forward
0 new messages