Can the suffix of an operator be given a variable?

Can the suffix of an operator be given as a variable?

For example I would like to do the following [[tiddlername]contains:<fieldname><currentTiddler>]

  • That is I want to provide the “fieldname” as a variable <fieldname> to the contains operator, where I want to test if the current tiddler is in that field/.
  • I am only aware of the simpler version;

For example [[tiddlername]contains:myfield<currentTiddler>]

I should possibly know this, but it escapes me today;

Well, not in the most obvious way.

'' Hardcoded field and value'':
<<list-links filter:"[tag[Test Contains]contains:a[2]]" >>

''Hardcoded field, dynamic value'':
<$let field="a", value="2">
<<list-links filter:"[tag[Test Contains]contains:a<value>]" >>
</$let>

''Dynamic field and value'':
<$let field="a", value="2">
<<list-links filter:"[tag[Test Contains]contains:<field><value>]" >>
</$let>

yields:

Hardcoded field and value:

Hardcoded field, dynamic value:

Dynamic field and value:

with

[ 
    {"title": "Foo", "tags": "[[Test Contains]]", "f": "1", "o": "2 3"},
    {"title": "Bar", "tags": "[[Test Contains]]", "b": "1", "a": "2", "r": "3"},
    {"title": "Baz", "tags": "[[Test Contains]]", "b": "1", "a": "2", "z": "3"},
    {"title": "Qux", "tags": "[[Test Contains]]", "q": "1", "u": "2", "x": "3"}
]

TestContains.json (1.0 KB)

Maybe there’s some other syntax?

Thanks for illustrating it.

Try this:

''Dynamic field and value'':
<$let field="a" value="2" contains=`[contains:$(field)$[$(value)$]]`>
<<list-links filter:"[tag[Test Contains]filter<contains>]" >>
</$let>

-e

6 Likes

Thanks @EricShulman that would work thanks. I need to see if I can happily integrate it (traditional macro) with my 5.3.x custom widget and procedures.

  • Or perhaps a similar approach using the new substitute operator?

This is my working solution, a macro defined within a custom widget

\define not-in-list-indicator() ^^{{{ [<listTiddler>!contains:$(field)$[$(currentTiddler)$]then[ +]] }}}^^

Do you mean add something like this;

If you want to use a variable to set a value in a “filter Operators” suffix you can do so using the substitution features of a traditional macro definition as follows;

\define containsfilter() [contains:$(field)$[$(value)$]]`

You can use this as [filter<containsfilter>] or construct it inside a larger macro.

1 Like

This seems to point to a missing bit of documentation. I love the linked railroad diagrams for the various parts of the Filter syntax. But suffix is sitting alone, undefined. I’d offer to create it, but I don’t know what actually can go in there.

Another version with that change:

TestContains2.json (1.2 KB)

No, although that would be useful too.

I was talking about the railroad diagrams starting with Filter Expression.

I feel like we have no good definition for suffix or what’s allowed in it. This doesn’t seem to make much sense to me to have missing, so I’m guessing it’s an oversight, not a conscious decision. But I could well be wrong.

1 Like

I found sufficient documentation of the suffix in the operator documentation in question. Only some operators have a suffix, but so can filter runs such as “Map Filter Run Prefix” uses a suffix but not others.

  • Note the tiddler “Filter Expression” tiddler is only talking about it at the “filter run level” however it does not mention suffix’s
  • Yes if not added to the syntax we should at least add a note about them.

The railroad diagrams are a useful way of seeing what sorts of text is a valid example of a type. For instance, Filter Parameter makes it very clear that these are syntactically correct:

  • [foo]
  • {bar}
  • <baz>

but these are not:

  • )qux(
  • [corge>
  • {{{grault}}}

It would be useful to have such documentation for suffixes.

There is a pending PR: Improve Filter Syntax documentation #7368

See this preview

@pmario That was a good initiative, but those tiddlers are quite old, and the changes may need to be revisited.

To take the solution here and add it to the documentation “the suffix of an operator being a variable” we need to see if there is another way

  • than the use of \define although this works it demands a deprecated method
    • Although I am starting to see the deprecated method as fine for simple substitutions.
  • or design a new method (speculation)

Before adding notes, either in high level documentation and/or “Filter operators” that use a suffix.

Similarly we need to discuss the use of a suffix in high level documentation and/or “Filter Runs” that use a suffix.

I will have a closer look;

Filter Step describes the suffix on operators and opens if you click on suffix

  • It is here I may document the lesson from this thread.

Visiting the documentation reminds me of something I would like to improve;

  • They often do not explain how to use more than hardcoded values
  • Some are so minimalist as to be hard to understand.

Do not use \define – Use Eric’s method or may be a function using the new substitution method.

\define and text substitutions cannot be cached and should not be used anymore for “user facing” examples or here in the threads.

Oops, Thanks @pmario Because I was reading related documentation, I fell back to the \define rather than the;

<$let contains=`[contains:$(field)$[$(value)$]]`[contains:$(field)$[$(value)$]]` ...
...
... filter<contains>
...
  • That is the other way.
  • Although in most cases we possible only need [contains:$(field)$<value>] untested.
  • It may also be possible to use a “function and the substitute operator”, Again Untested.

So to generalise the solution

To provide a “Variable” suffix to a filter operator, you will need to use substitution, as a result you will need to use a let/set/vars widget to set a variable to the desired “filter definition” and using the backtick Substituted Attribute Values to substitute the value.

  • Once you have the required “filter definition” you can use it in your main filter using either the filter operator, subfilter operator or in a “filter run”?
<$let field="a" value="2" contains=`[contains:$(field)$<value>]`>

This is marginally better than my initial response, in that <value> will allow the target field to include items that have square brackets… except if they are surrounded by matching doubled square brackets, because the list field being processed will treat those as list item delimiters rather than literal text.

-e

I did see that back in the day, and very much approved the concept. (I can’t look now; vercel is blocked at GigantiCorp where I work.) That of course brought back up the breadcrumbs discussion, and I now remember that I wanted to spend more time on that. So many things to do!

-------- OT

Yea – It’s sad – I did completely remove the breadcrumbs code from the docs and did put it into a plugin. I wanted to publish the plugin with the new docs and include enough templates with the plugin, that it can be imported into tw-com. So the breadcrumbs, which are now named “trails”, will just work with the docs at tw-com.

I intended to create a video with the new docs at tw-com and my trails-plugin. But no new docs → no plugin promoted → no video :confused: