Passing a filter to a macro, when the filter includes replaceable parameters

Passing a filter to a macro, when the filter includes replaceable parameters

  • I would like to be able to pass filters to macros that make reference other replicable parameters in the macro. eg

Please consider the following macro

\define fieldname-value-select-macro(fieldname filter)
<$select field="$fieldname$"> default={{!!$fieldname$}}>
<$list filter='[all[shadows+tiddlers]each[$fieldname$]get[$fieldname$]sort[]]'>
<option value=<<currentTiddler>>><$view field='title'/></option>
</$list>
</$select>
\end

<<fieldname-value-select-macro caption>>
  • This works on tiddlywiki.com
  • Here you can set the caption on the current tiddler to any of the existing caption values (unlikely use)
  • Note how the select widget uses the filter below
    • [all[shadows+tiddlers]each[$fieldname$]get[$fieldname$]sort[]]
    • This filter obtains all the existing values from $fieldname$

What does not work

  • If I was to pass the filter above in a parameter to the macro, the macro would look like this
    • <<fieldname-value-select-macro caption "[all[shadows+tiddlers]each[$fieldname$]get[$fieldname$]sort[]]">>
  • This does not work because the filter parameter includes $fieldname$ which is not replaced by the value in the macro parameter fieldname (in this case caption)
    • if I used filter="$filter$" in the selects list widget.

Desired result

  • To make the above work out of the box, no doubt if even possible requiring a core change
    • The $filter$ would need to be expanded, then the $fieldname$ within that expanded before passing to the list widget.
    • Arguably any parameter would need to be expanded until if does not contain any other $param$
  • A smart workaround to achieve the same result
    • I believe if I set variables I can pass a filter that will be interpreted correctly (untested today) eg
      • [all[shadows+tiddlers]each<fieldname>get<fieldname>sort[]] but what chance is there we can use the suggested approach?

Thanks in advance for your considered response

Hi @TW_Tones, this worked for me on tiddlywiki.com:

\define fieldname-value-select-macro(fieldname filter)
<$select field="$fieldname$"> default={{!!$fieldname$}}>
<$list filter="[subfilter<__filter__>]">
<option value=<<currentTiddler>>><$view field='title'/></option>
</$list>
</$select>
\end

<<fieldname-value-select-macro caption "[all[shadows+tiddlers]each<__fieldname__>get<__fieldname__>sort[]]">>

Note the use of subfilter and the parameter-as-variable syntax, as described in https://tiddlywiki.com/#Macro%20Definitions%20in%20WikiText.

Have a nice day
Yaisog

1 Like

Thanks, I never found a use for the <__paramname__> format until NOW!

Sweet as.

If I understood the developer discussions correctly, then macros using the $…$ substitution cannot be cached internally, whereas the parameter-as-variable syntax can. So, depending on how often that macro is called and how big your wiki is, this can make a difference in responsiveness of your wiki.
I believe the context of these discussion was the tag chooser and the several macros that are called for each tag in the dropdown to determine its colors. I don’t remember if it was here or on Google Groups or GitHub, though…

Personally, I try to avoid the $…$ and $(…)$ substitutions whenever possible.

Have a nice day
Yaisog

1 Like

First thanks so much for the <__varname__> tip, this is the first compelling case I have found

Now my macro looks like this below

  • Note how the filter default is set but can be used in the macro making use of different values of the fieldname variable.
    • filter:"[all[shadows+tiddlers]each<__fieldname__>get<__fieldname__>sort[]]"
  • Now the macro calling this one, can provide an alternate filter containing <__paramname__>'s
  • All that remains is to check I am not restricted in other filter forms including field and text references and regular variables (I do not expect so as only substitution’s had this issue).
\define fieldname-value-select-macro(fieldname filter:"[all[shadows+tiddlers]each<__fieldname__>get<__fieldname__>sort[]]")
<$select field="$fieldname$"> default={{!!$fieldname$}}>
<$list filter="""[subfilter<__filter__>]""" >
<option value=<<currentTiddler>>><$view field='title'/></option>
</$list>
</$select>

Thanks for your perspective @Yaisog

FYI: I have not applied this rule and not yet come across any performance issues including in large and complex wikis.

  • This maybe because I tend to apply this to a subset of tiddlers and when in currentTiddler
  • I also write macros with parameters using $…$ and $(…)$ where they are a static string, that influences the macro by restricting the tiddlers in a list.
  • I expect if I used the filter [tag[$tagname$]] it can still leverage the tag cache.

That’s right.

It is possible to avoid this construction most of the times. But using it for “string” concatenation it is still very convenient and simple to use.

That is true, though I often use something like

{{{ [[literal string]] [<string-variable>] ... +[join[]] }}}

for that, as it is both very flexible (e.g. add space between strings) and semantic, and doesn’t need an extra \define.

Have a nice day
Yaisog

Yes Using filtered transclusions makes even more sense now our filters have even more operators.

  • I use the above form including with a +[join[ ]] ie contains a space especially to construct tooltips
  • However using this in a set let or var or in a “$set filter=” makes more sense if you want to use the result more than once.

A proposed changes in the works are likely to allow a new form of concatenation/replaceable/substitution unfortunately it is not clear to me which is the best link to this.

1 Like