Determine if currentTiddler contains any tags provided in a list

I need a filter that will tell me if the current tiddler contains any tag from a list of tags. This list of tags are in a text field of a tiddler named $:/tags/caption/title

Any help would be appreciated. Thanks,

Craig

Try this:

{{{ [enlist{$:/tags/caption/title}] :filter[<..currentTiddler>tag<currentTiddler>] +[then[yes]limit[1]] }}}

Notes:

  • It is assumed that the $:/tags/caption/title text field contains a space-separated list of tag values and, if a tag contains spaces, it is enclosed in doubled square brackets.
  • In the :filter[...] run, <..currentTiddler> refers to the tiddler in which the entire filter expression is being applied, while <currentTiddler> refers to each of the “target” tag values enlisted from the text field of $:/tags/caption/title.
  • For each matching tag (if any) found by the :filter[...] run, a literal value of ‘yes’ is produced.
  • The limit[1] ensures that the final result of the entire filter expression will be either a single “yes” (indicating a matching tag was found), or no value (indicating no matching tags were found).

enjoy,
-e

3 Likes

Just because variety is the spice o’ life:

{{{ [{!!title}tags[]] :intersection[enlist{$:/tags/caption/title}] +[join[]then[yes]] }}}

And if we read that filter left to right: for the current tiddler, get the tiddler’s tag titles. Intersect the tiddler’s tag titles with a list of titles from this other tiddler. If there is intersection of one or more titles, then return “yes”.

4 Likes

Is this the start of a new forum section named “WikiText filter code golf”?

Here’s yet another way to do it:

{{{ [enlist{$:/tags/caption/title}tagging[]match{!!title}then[yes]] }}}

Could be shortened to this if the tiddler $:/tags/caption/title was using the list field instead of the text field:

{{{ [list[$:/tags/caption/title]tagging[]match{!!title}then[yes]] }}}
3 Likes

You might also want to check out this thread:

I’ve been using the augmented enlist operator very extensively ever since, to avoid filter constructs like above and make the code more readable. Nowadays, this might be doable in a similarly neat way with a function, though the JS filter operator will be faster.

5 Likes

Oh man, we could easily play code golf/ping-pong in any thread.

The beauty o’ TiddlyWiki: we can solve a problem in various ways because of TW’s flexibility, and the right way for any one of us is the way that matches the way one happens to think.

Thank you. Much appreciated.

Thanks for all the replies. I asked MS Copilot this question, and the code result was not usable.

Aside: I implemented a template to show either tiddler title or tiddler caption with the title in smaller fontsize in tiddler header. I wanted the user to be able to identify tiddlers where they want the caption field vs the title shown in the tiddler header. Previously, I had this hard coded for a person tiddler. With this solution, they can now configure tiddlers (by providing a list of tags in the configuration section) to do this.

Eg of person tiddler shown using title of the tiddler:

…and an example of the tiddler shown using the caption field (with the title under caption):

I just thought I would add, when writting filters for tags we have a set of operators for tag handling. We can assume that these operators should provide an oportunity to test tags. In this case however we are comparing one list (in a tiddler) with the list of tags, however we only need one to match.

  • So the question changes to handling two lists not tags specificaly
  • This does suggest the opportunity to add one or two more tag related filters to help with such tests. eg [intags[]] returns each of the input titles that is in the tags list.
    • So the below would read `[special.tags[]intags[]]’
  • And !intags[] would return titles not in the tags.
\function special.tags() [enlist{$:/tags/caption/title}]
\function special.tags() Learning Filters
\function current.tags() [enlist{!!tags}]
\function current.tags() [all[current]tags[]]

* {{{ [special.tags[]] :intersection[current.tags[]] }}} all intersections if any
* {{{ [special.tags[]] :intersection[current.tags[]] +[limit[1]] }}} only one intersection if any, logical yes.

  • When comparing more than one list, it is the most compeling reason, to start using filter run prefixes, in this case :intersection.
  • Note the last function definition is used, and above documents alternative filters.
  • If you are going to use “special.tags[]” elsewhere perhaps make it a global function.
  • By defining such filter functions the resulting filters become clear language.

I will explore making a simpler and generic way to test if there is an intersection between two sets/lists where one is the input to the function.

Here I abstract this further (add to above functions)

\function in.function(function) :intersection[function<function>]

*  {{{ [special.tags[]] [in.function[current.tags]] +[limit[1]] }}}

the in.function could also be in.function.list, ie any function that generates a list. We add the +[limit[1]] only to turn it into a test for any (or none) and not “a list of all” in the list that match.