How to limit filter prefix scope?

I have these tiddlers

aaa tagged foo
bbb tagged foo and tagged bar
ccc tagged bar

These two filter expressions result in partially identical output. (Never mind that the testing if a tiddler that is tagged foo has the tag foo. That is not the issue.)

<$list filter='[tag[foo]] :map[<currentTiddler>tag[foo]]'/>

<$list filter='[tag[bar]] :map[<currentTiddler>tag[bar]]'/>

…result in:

aaa
bbb
bbb
ccc

I want to merge these two filters to avoid duplicate output. But if I naively do:

<$list filter='
	[tag[foo]] :map[<currentTiddler>tag[foo]]
	[tag[bar]] :map[<currentTiddler>tag[bar]]	'>

</$list>

…then the second :map also operates on the output from the first filter run and removes aaa.

In my real case, I do need to use the :map filter prefix because the preceding filter steps are more complex, so the :map operations must not be omitted (…AFAICT)

QUESTION: Can the second :map be restricted to only operate on the things in its own filter run?

Here’s a TW with the above that I test on.

Various attempts:

Bracketing the second run gives syntax error:

[tag[foo]] :map[<currentTiddler>tag[foo]]  [[tag[bar]] :map[<currentTiddler>tag[bar]]]

I think the following syntax would make a lot of sense, i.e to omit the space before :map to indicate that it should operate only on the direct output from the previous step… but nope:

[tag[foo]] :map[<currentTiddler>tag[foo]]
[tag[bar]]:map[<currentTiddler>tag[bar]]

…nor…

[tag[foo]] :map[<currentTiddler>tag[foo]]
[tag[bar]:map[<currentTiddler>tag[bar]]

…and this I guess the following only maps currentTidder onto the current tiddler and thereafter checks if it is tagged bar… but I’m not sure why there is no output:

[tag[foo]] :map[<currentTiddler>tag[foo]]
[tag[bar]:map<currentTiddler>tag[bar]]

Anyway, is there a way to scope filter prefixes?

I think the most important sentence it this one:

So I think you need to work with variables, that store the 2 lists and then combine those variables with a second filter.

At the moment filter runs don’t save any “lists” as internal variables.

1 Like

Thank you. Would that require nested filters (i.e listwidgets) then, rather than two serial ones?

You can use $set widgets to get each filter result and save it in a variable, and then use [enlist<list1>] [enlist<list2>] to combine those results, like this:

<$set name="list1" filter="[tag[foo]] :map[<currentTiddler>tag[foo]]">
<$set name="list2" filter="[tag[bar]] :map[<currentTiddler>tag[bar]]">
<$list filter="[enlist<list1>] [enlist<list2>]">
 ...
</$list>
</$set>
</$set>
4 Likes

Eric was faster :wink: exactly that … But it also depends on your real usecase. … But it may give you a hint

Guys - mucho thanko! I think this will solve it. :smiley:

This should also work with subfilters, I think, like so:

\define filter1() [tag[foo]] :map[<currentTiddler>tag[foo]]
\define filter2() [tag[bar]] :map[<currentTiddler>tag[bar]]

<$list filter='[subfilter<filter1>] [subfilter<filter2>]'/>

But it’s basically the same thing: assigning two variables. In this case, not the result but the filter itself is stored in them. Here, the variables can be defined globally and do not need to be in the correct context of e.g. currentTiddler, if your “real” filter makes use of that…

Which one you’ll use mainly depends on preference.

Have a nice day
Yaisog

2 Likes

Thanks! This variant is more aligned with the coming pragma intended to be exclusively for filters (…which is not to be named the \filter pragma, if I recall) so your variant makes it easier to update to this syntax later on.

You can also use macro text substitution to define filters in a filter run, as I’ve learned recently thanks to saqimtiaz :

\define printf(text) $text$ 

<$list filter="""
[subfilter<printf "[tag[foo]] :map[{!!title}tag[foo]]">]
[subfilter<printf "[tag[bar]] :map[{!!title}tag[bar]]">] 
""" />
3 Likes