I’m trying to find all tiddlers containing a particular header. Specifically to find “!! Related” (without the quotation marks).
I tried all sorts of filters, but I couldn’t make it work and I would appreciate your help.
I’m trying to find all tiddlers containing a particular header. Specifically to find “!! Related” (without the quotation marks).
I tried all sorts of filters, but I couldn’t make it work and I would appreciate your help.
Have you tried this:
<$list filter="[search:text[!! Related]]"><$link/><br></$list>
-e
Thank you for the suggestion. Unfortunately it also lists other instances where the word “related” appears inside a tiddler, irrespective of capitalization. I wanted specifically the “!! Related” text to be the filter criterion (!! being a heading level before the word “Related”).
EDIT: Based on my testing the “!!” affects the result. If I do the search with three"!" I get a different number of tiddlers than with two “!”.
By default, the search
filter operator uses the :words
flag value (see https://tiddlywiki.com/#search%20Operator).
treats the search string as a list of tokens separated by whitespace, and matches if all of the tokens appear in the string (regardless of ordering and whether there is other text in between)
However, for your purposes, you want to treat the search string as a single literal value to be matched exactly (including the whitespace). Thus, you need to use the :literal
flag value, like this:
<$list filter="[search:text:literal[!! Related]]"><$link/><br></$list>
-e
Unfortunately it still lists many tiddlers with text !!! Related
which is not exactly what I’m looking for.
Ok… if you only want to match “!! Related” when it occurs at the start of a line, you can use a :regexp
search, like this:
<$list filter="[search:text:regexp[^!! Related|\n!! Related]]"><$link/><br></$list>
Note that it uses two alternative patterns:
Alternatively, if you want to find “!! Related” anywhere (including when it is not at the start of a line), you could write:
<$let re="[^!]!! Related">
<$list filter="[search:text:regexp<re>]"><$link/><br></$list>
The [^!]
pattern means any character that is NOT a “!”. Note that filter syntax makes it impossible to directly specify a regular expression pattern that contains square brackets because the square brackets are used by the filter syntax itself as delimiters around literal parameter values. The solution is to first store the pattern in a variable (e.g., <$let re="...">
), and then reference that variable as the search
operator’s parameter.
-e
Perfect answer. Thank you!!! (Note the ! in my thanks )
I think we can simplify this using the multiline regex flag, m
. However, AFAICT, this is not available in the search
operator. (Are there good reasons for this?) But we can do it using the regexp
operator like this:
<$list filter="[regexp:text[(?m)^!! Related]]"><$link/><br></$list>
The m
operator lets ^
match the beginning of each line, and not just the beginning of the text.
This has two subtle problems. First, this will actually match the tiddler it’s in, because the text !! Related
is right there in the filter inside the tiddler. Presumably we don’t want that, unless the tiddler happens to match for other reasons.
This is easy enough to fix by escaping some characters. The likely suspects are the !
s.
We could write
<$let re="[^!]\!\! Related">
instead and fix that problem. (This is true in the earlier snippet as well.)
The other one is still more subtle. The [^!]
matches the character before the target text, but only if it’s not a !
. But what if there’s no character before it? This fails if !! Related
is the first thing in the text
field.
We can fix this using a lookbehind assertion in the regular expression.
<$list filter="[search:text:regexp[(?<!\!)\!\! Related]]"><$link/><br></$list>
(?<!\!)\!\! Related
is probably best seen as (?<!!)!! Related
with some escape characters added for the reason above. And (<!!)
is a negative lookbehind, (<our-pattern>)
, which says that the text behind our otherwise matching area does not match the pattern. Here our pattern is just !
(or escaped as \!
.) So this can be read as, "the text !! Related
so long as its not immediately preceded by !
".