Create a list filter using tags that begin with / end with / contain a certain string

I want to create a list filter for a group of tags that begin with a specific string and in the general use case, end with or contains a string. e.g., include all tiddlers with tags beginning with “opt”. I’ve searched for prefix/suffix but didn’t see anything in the context of tags.

If I need to include a space character in the string, does that change the solution? I am willing to change my tagging style to use _ instead of spaces.

Thanks

Filter operators work on whatever input you give them: frequently this will be lists of titles, but it could just as easily be lists of tags, or field values, or indexes, or arbitrary strings you’ve just made up on the spot. This means that your initial intuition was correct, and the prefix/suffix/search operators will be part of your solution.

Try this, which should give you all tiddlers tagged with a tag beginning with “opt”

<$list filter="[all[tags]!is[system]prefix:caseinsensitive[opt]tagging[]]">

</$list>

What’s happening here:

  • all[tags] sets the initial filter domain to tags (the default is all[tiddlers]. Many (but not all) tags are also tiddlers, but we want to catch the ones that aren’t, and we don’t care about non-tag tiddlers that start with “opt”.
  • !is[system] will remove anything beginning with $:/, the system prefix; these tags/tiddlers are mostly used for layout and other UI structure. You can omit this if you do want to include system tags (and if you’re filtering by prefix, system tags will be removed by the next step anyway, but I’ve included it for potential filters using suffix / search instead.)
  • Next, we add the prefix step (or suffix, or search to find the string anywhere in the tag). prefix and suffix are case-sensitive by default, so prefix[opt] would find “option” but not “Option”. search is case-insensitive by default, so you can use search:title[opt] to find “option” or “Option”, or search:title:casesensitive[op] to find “option” only. (Note that “title” refers to the unmodified output of the previous step; even though we’re looking for tags, it’s the title (name) of the tag that we’re concerned with, not, for example, its text or list field.)
  • You could stop at this point if you only wanted a list of the tags themselves, but if what you’re looking for is the tiddlers that have these tags, you’ll want to add tagging[], which finds all tiddlers tagged with any its input values - in this case, any tag beginning with “opt”.

You should be able to switch out the prefix operator for suffix or search depending on your needs; the general principal will be the same.

  • Space characters in the string aren’t a problem at all for prefix and suffix.
  • For search, you’ll want to use search:title:literal,casesensitive to capture literal strings including a space; otherwise, the search operator will treat space-separated strings as separate tokens to be searched for and will ignore the space itself. (This may be useful to you in other cases, but is probably not what you want here.)
2 Likes

Thank you etardiff for the detailed response. I applied your suggestion to a filter looking for tags starting with "c " and it worked as expected.

<$list filter="[all[tags]!is[system]prefix:caseinsensitive[c ]tagging[]]">

However, I also wanted to further limit the returned list by placing another tag in front. Again, I believe I’m missing the basics in filter construction. This did not work when I inserted [KBA]:

<$list filter="[all[tags]!is[system][KBA]prefix:caseinsensitive[c ]tagging[]]">

I suspect it’s because the context is already all[tags] but I’m not sure what to do with it next.

Are you looking for tiddlers that have the “KBA” tag and any tag beginning with “c”? If so, try this:

<$list filter="[all[tags]!is[system]prefix:caseinsensitive[c ]tagging[]tag[KBA]]">

Assuming I’ve understood the goal correctly, you’ll want to use the same first part of the filter run ([all[tags]!is[system]prefix:caseinsensitive[c ]tagging[]) to get an initial list of titles, then add tag[KBA] to cut it down to down to those with the “KBA” tag.

As a general rule, you’ll never see two sets of bracketed items in a row within a filter; they must be separated by a filter operator, or the filter will treat whatever is in the second pair of brackets only as the new context for the rest of the filter, ignoring whatever came before it.

1 Like

I worked exactly as you said and as I needed.
Thanks again for the help!

Also since tiddlers with the prefix “c” are not system tiddlers I think you can remove !is[system].

Once more to the well…

I dropped !is[system] - thanks @TW_Tones
Next, I tried modifying the prefix, which works, from

<$list filter="[all[tags]prefix:caseinsensitive[c]tagging[]tag[KBA]]">

to a negated prefix

<$list filter="[all[tags]!prefix:caseinsensitive[c]tagging[]tag[KBA]]">

but the results are the same as not having the prefix part at all

<$list filter="[all[tags]!is[system]tagging[]tag[KBA]]">

I don’t have your test data, perhaps you can give a test case using TiddlyWiki.com ?

  • In the first filter <$list filter="[all[tags]prefix:caseinsensitive[c]tagging[]tag[KBA]]"> it relys on the fact that system tiddlers are not included because they begin with $ not c
  • In the second filter, it should list every tag without the prefix c or C, that is, a simple negation is insufficient if you don’t want system tags. You need to reintroduce the !is[system]
    • Have you tried the test without case insensitive? to see what’s happening?
  • Note that unless you add sort at the end the results will have upper and lowercase apart.
  • Are you sure about the third filter “same as not having the prefix part at all” the only this missing should be ones beginning “C” and all the other conditions.
  • What do you expect tagging[]tag[KBA] to do?