Regular expressions to search for any tiddler title, and only that title

Hi I wanted to search all text fields for the a string in a variable such as <<currentTiddler>> for example $:/tags/ViewTemplate but a standard search returns tiddlers that include $:/tags/ViewTemplate/something or $:/tags/ViewTemplatesomething.

In this case since $ and / are special characters we have to use the “escaperegexp Operator” however if this was a tiddler title with any other valid characters in it, some of those will need to be escaped. And as you know there are not many restrictions on tiddler titles.

Warning: avoid using any of the characters | [ ] { } in tiddler titles

But now the question is how can we reliably construct a regular expression that can test for a variable title name and not when it is only part of the title. How can we detect where the string ends if we are permitted to use most characters in a tiddler title?

  • We can assume any of these | [ ] { } represent the start or end of a title, along with whitespace newlines there are other characters that may indicate string is a substring of a longer name.
  • We need to both escape the string but also add more regular expression codes around that string.

So I am not sure how to do this?

Any assistance appreciated.

This should do it. Detailed regexp info can be found at https://regexp.info

^ … start of text
$ … end of text
(?i) … TW specific → case insensitive

trim[] … eliminates leading and trailing spaces in user input

\function f.getRegexp() "^" [{input}trim[]escaperegexp[]] "$" "(?i)" +[join[]]

<$edit-text tiddler="input" class="tc-max-width" tag="input"/>

<<f.getRegexp>>

<$list filter="[all[shadows+tiddlers]] :filter[<currentTiddler>regexp<f.getRegexp>]" >
<<currentTiddler>>
</$list>

I think I can learn some things from your example @pmario but your solution varies from my requirment enough for me to be unsure. I want to search the text field.

But if I do this;

<$list filter="[all[shadows+tiddlers]search:text[$:/tags/ViewTemplate]]">

</$list>

on Tiddlywiki.com I get this;

$:/config/ViewTemplateBodyFilters/core-ui-tags
$:/core/ui/ControlPanel/ViewTemplateBody
$:/core/ui/ControlPanel/ViewTemplateSubtitle
$:/core/ui/ControlPanel/ViewTemplateTags
$:/core/ui/ControlPanel/ViewTemplateTitle
$:/core/ui/EditTemplate/body/preview/output
$:/core/ui/ViewTemplate
$:/core/ui/ViewTemplate/body
$:/core/ui/ViewTemplate/subtitle
$:/core/ui/ViewTemplate/subtitle/default
$:/core/ui/ViewTemplate/tags
$:/core/ui/ViewTemplate/tags/default
$:/core/ui/ViewTemplate/title
$:/plugins/tiddlywiki/dynannotate/examples/viewtemplate
$:/config/OriginalTiddlerPaths
$:/core
$:/plugins/tiddlywiki/dynannotate
New Tiddler
Plugin Types
Release 5.2.3
SystemTag: $:/tags/ViewTemplate
SystemTag: $:/tags/ViewTemplate/Subtitle

If you look inside each of these tiddlers some contain $:/tags/ViewTemplate others do not, but contain $:/tags/ViewTemplateTagsFilter and other matches. I want to eliminate those.

Of course this is a specific input search $:/tags/ViewTemplate but would like to to be true for many cases. I see how your solution wraps any escaped search string, with the other regexp, but I am not sure that other reexp is what I need. To start with it can start at the begining of a line or with any whitespace or other characters, and end the same way, but not if special characters are included in the input search text that can be in a title.

  • I suspect there is no universal regular expression I can use.

Your thread title says: Regular expressions to search for any tiddler title, and only that title – So I did answer that one.


Within text it is more complex, since the end of the string is not so simple.

So [ |\]] the outer [...] define a set of definitions. The content <space>or<close bracket> = \] the first close bracket needs to be escaped with a backslash.

But I am not sure if this regexp finds all of the occurrences. More tests will be needed.

\function f.getRegexp() [{input}escaperegexp[]]  "[ |\]](?i)" +[join[]]

<$edit-text tiddler="input" class="tc-max-width" tag="input"/>

<<f.getRegexp>>

<$list filter="[all[shadows+tiddlers]] -[[$:/core]] :filter[<currentTiddler>regexp:text<f.getRegexp>]" >
<$link/><br>
</$list>

Edit: I did remove the [[$:/core]], because it is not useful to search there

Yes, Search for the title and only that title, in the title, text field, even other fields I suppose, but not others that only have the current title as prefix. I suppose that is easy to confuse given titles are the primary key.

Actually I just remembered Relink already does this and includes some additional filters, the answer may be in there.

  • I am fine with searching titles only, resorting to regexp is only needed when searching for titles in the “free form” text in my mind.

Although I thought it will an important use for regular expressions, finding titles in other tiddlers, when the are not links, like tags in filters, or documentation.

Actually searching the core shadow tiddlers is important because it can support people exploring how tiddlywiki does something, so they Can 1. Learn and research tiddlywiki 2. They can hack or configure it.

  • To be able to find a title every where it is used, and not get false positives, especially system tags, would be great.

I actually suspect there is no deterministic way to search for only a specific string/titles that can be anything permitted in titles and can be prefixes/suffixes. Perhaps each needs to be found and inspected manually?

I suppose we can add {} to the possible terminators, but is it a reasonable assumption to include ' " backticks and space or etc… because these can be in titles. I suppose if they are they are in the title, or outside the title and terminating it.

With your help and ChatGPT I now have this. Needs further testing

\define regexp.prefix() (?:^|[\s{}\|\['"`\]])
\define regexp.suffix() (?=$|[\s{}\|\['"`\]])
\function f.getRegexp()  [<regexp.prefix>] [<string>escaperegexp[]] [<regexp.suffix>] +[join[]]

<<f.getRegexp>>

[[Test tiddler $:/Import]]

{{Test tiddler $:/Import}}

<$let string="$:/tags/ViewTemplate">
<$list filter="[all[shadows+tiddlers]!has[draft.of]] -$:/core -[[$:/config/OriginalTiddlerPaths]] :filter[<currentTiddler>regexp:text<f.getRegexp>]">
<h2><$link/></h2><$text text={{!!text}}/><br>
</$list>
</$let>

I am building a set of test tiddlers

Note it will not find Text$:/tags/ViewTemplate, fair enough I suppose, but the parser does turn $:/tags/ViewTemplate into a link.