Eventually managed to compute the intersection of two filters outputs !

100 views
Skip to first unread message

Eric N.

unread,
May 6, 2020, 7:14:52 AM5/6/20
to TiddlyWiki
I was stuck in my dev because I couldn't output the intersection of two filters, each made of several runs. I didn't find a built-in function to do so, and I couldn't find a satisfying solution online. But I eventually found my own solution, shared here.

Say I want to get all the tiddlers that satisfy the following conditions (toy example here, could also have a pair of very complex filters):

(has tag Todo OR starts with "a") AND (has tag Howto OR starts with "al")

This is computed by the following code, where the output list is enlist<setAinterB>, which is displayed by the list-links macro.

<$set name="filterA" filter="[tag[Todo]] [all[]prefix[a]]">
<$set name="filterB" filter="[tag[Howto]] [all[]prefix[al]]">
<$set name="setAunionB" filter="[enlist<filterA>] [enlist<filterB>]">
<$set name="setAnotB" filter="[enlist<filterA>] -[enlist<filterB>]">
<$set name="setBnotA" filter="[enlist<filterB>] -[enlist<filterA>]">
<$set name="setAinterB" filter="[enlist<setAunionB>] -[enlist<setAnotB>] -[enlist<setBnotA>]">

<<list-links "[enlist<setAinterB>sort[]]">>

</$set>
</$set>
</$set>
</$set>
</$set>


Caveat : if a filter output contains double brackets (say a tiddler named "oh what a [[bad]] name") it breaks the enlist processing, and you won't have the correct output.


Best,
Eric
Message has been deleted

Mohammad

unread,
May 6, 2020, 7:49:23 AM5/6/20
to TiddlyWiki
Hi Eric,

 Thank you for sharing!

 Looking in TW-Scripts you can find two great resources for working with filters:


 
and I alos would like to add the great interactive playground by Eric Shulman


These are three wonderful sources for learning filters and of course the holly TW-Scripts :-) :-)

--Mohammad

A Gloom

unread,
May 6, 2020, 11:43:31 PM5/6/20
to TiddlyWiki
Mohammad

you need to make a filters reference tiddler at TWScripts (if you hadn't already) containing the following info you posted here (and belopw)


 


These are three wonderful sources for learning filters and of course the holly **TW-Scripts**

**  link to a tiddler with a list of all TWScripts filter info tiddlers

Eric N.

unread,
May 7, 2020, 12:36:06 AM5/7/20
to TiddlyWiki
Thanks Mohammad, I'll check it out !

TonyM

unread,
May 7, 2020, 12:38:23 AM5/7/20
to TiddlyWiki
Eric N

Thanks for sharing, I thought I would turn it into a macro because it is a general type of solution.

\define intersect(filter1 filter2)
<$set name="filterA" filter="$filter1$">
<$set name="filterB" filter="$filter2$">

<$set name="setAunionB" filter="[enlist<filterA>] [enlist<filterB>]">
<$set name="setAnotB" filter="[enlist<filterA>] -[enlist<filterB>]">
<$set name="setBnotA" filter="[enlist<filterB>] -[enlist<filterA>]">
<$set name="setAinterB" filter="[enlist<setAunionB>] -[enlist<setAnotB>] -[enlist<setBnotA>]">
<<list-links "[enlist<setAinterB>sort[]]">>
</$set></$set></$set></$set></$set>
\end

<<intersect "[tag[Todo]] [all[]prefix[a]]" "[tag[Howto]] [all[]prefix[al]]">>

But I avoid the list-links macro because its a fixed format
The following lists only tiddler titles, using the default list widget behaviour, but it easy to present things differentl
\define intersect(filter1 filter2)
<$set name="filterA" filter="$filter1$">
<$set name="filterB" filter="$filter2$">

<$set name="setAunionB" filter="[enlist<filterA>] [enlist<filterB>]">
<$set name="setAnotB" filter="[enlist<filterA>] -[enlist<filterB>]">
<$set name="setBnotA" filter="[enlist<filterB>] -[enlist<filterA>]">
<$set name="setAinterB" filter="[enlist<setAunionB>] -[enlist<setAnotB>] -[enlist<setBnotA>]">
<$list filter="[enlist<setAinterB>sort[]]">

</$list>
</
$set></$set></$set></$set></$set>
\end

For example place this in the blank line above
  <$link/>,

or you could add another parameter and use this template
\define intersect(filter1 filter2 template:"defaulttemplate")
<$set name="filterA" filter="$filter1$">
<$set name="filterB" filter="$filter2$">

<$set name="setAunionB" filter="[enlist<filterA>] [enlist<filterB>]">
<$set name="setAnotB" filter="[enlist<filterA>] -[enlist<filterB>]">
<$set name="setBnotA" filter="[enlist<filterB>] -[enlist<filterA>]">
<$set name="setAinterB" filter="[enlist<setAunionB>] -[enlist<setAnotB>] -[enlist<setBnotA>]">
<$list filter="[enlist<setAinterB>sort[]]" template="$template$">

</$list>

</$set></$set></$set></$set></$set>
\end

Enjoy the possibilities


Regards
Tony

Eric N.

unread,
May 7, 2020, 1:32:10 AM5/7/20
to TiddlyWiki
Thanks TonyM that's very handy !

Would you know if there is a way to return the intersection set as a variable for later reuse ?
Then I wouldn't have to decide upfront what to do with the intersection in the macro.

I mean something like:
f=intersect("[tag[Todo]] [all[]prefix[a]]", "[tag[Howto]] [all[]prefix[al]]")

<<
list-links "[enlist< $f$ >sort[]]">>

<$list filter="[enlist<setAinterB>sort[]]"
>
<$link/>
</$list>

...

But with the proper way to use variables, functions, macros, parameters, .... (what these elements are and how to use them in different contextes is still unclear to me)

Cheers !

Mohammad

unread,
May 7, 2020, 2:30:39 AM5/7/20
to TiddlyWiki
Hi A Gloom,
 They are listed in TW-Scripts! But as you said I will create a tiddler references all of them.

A Gloom

unread,
May 7, 2020, 3:19:08 AM5/7/20
to TiddlyWiki
Mohammad
 

 They are listed in TW-Scripts! But as you said I will create a tiddler references all of them.

Excellent-- you have so much content now-- having summary/quick reference tiddlers may keep ppl from getting overwhelmed by search results in TWScripts-- I used the idea Tobias' Solutions index page had-- each topic tag had an index page.

TonyM

unread,
May 7, 2020, 4:09:41 AM5/7/20
to TiddlyWiki
Eric,

You need to wikify the result of a complex macro before feeding it into the next widget otherwise the macro code is included.
  • One way to conceptualise this is;
    • tiddlywiki always tries and passes the un-wikified result along so it can be "evaluated" at the last moment
  • Use the wikify at the last minute or in the wikitext that is using the result. Unfortunately you can't move the wikify widget into a macro
    • because it too will not be evaluated
  • Remember - If you supply a complex macro  rather than a simple variable to a widget as a parameter it is like saying
    Evaluate the widget, no wait first Evaluate the Parameter then evaluate the widget. See second example below
  • If First you wikify it it becomes a simple variable with the result as already evaluated so looks more like a simple variable. 

;Macro Result

<<intersect "[tag[Todo]] [all[]prefix[a]]" "[tag[Howto]] [all[]prefix[al]]">>
<hr>

;Macro used as input to the text widget
<$text text=<<intersect "[tag[Todo]] [all[]prefix[a]]" "[tag[Howto]] [all[]prefix[al]]">>/>
<hr>

;Use as Variable after wikifying
<$wikify name=result text="""<<intersect "[tag[Todo]] [all[]prefix[a]]" "[tag[Howto]] [all[]prefix[al]]">>""" >
<$text text=<<result>>/
>
</$wikify>

Regards
Tony

Eric N.

unread,
May 7, 2020, 7:20:13 AM5/7/20
to TiddlyWiki
Tony,
That was very helpful !!

As my intent is to use the result in a list widget, I went with 

1/ returning this in the macro :
<$list filter="[enlist<setAinterB>sort[]]">
  <$text text="[["/>{{!!title}}<$text text="]]"/>
</$list>

2/ storing the result with wikify :
<$wikify name=result text="""<<intersect "[tag[Todo]] [all[]prefix[a]]" "[tag[Howto]] [all[]prefix[al]]">>""" >

3/ using the result in various ways :
<<result>>

<$text text=<<result>>/>

and in a list, my initial intent:
<$list filter=<<result>> >

;{{!!title}}
:{{!!tags}}

</$list>

Works perfectly, thanks again ! 

Eric N.

TonyM

unread,
May 7, 2020, 8:03:20 AM5/7/20
to TiddlyWiki
And eventually close the wikify </$wikify>

good stuff thanks for sharing your original work

Tony

Reply all
Reply to author
Forward
0 new messages