I'm trying to create a tiddler that's an alphabetical list of all the tiddlers in my tiddlywiki. I've gotten it to work to a certain point with this code:
A
<<list-links "[prefix[A]][removeprefix[The ]]+[prefix[A]]">>
B
<<list-links "[prefix[B]][removeprefix[The ]]+[prefix[B]]">>
C
<<list-links "[prefix[C]][removeprefix[The ]]+[prefix[C]]">>
What I've done here is that some of my tiddlers are prefixed with the word "The ", so I'm removing the prefix and just using non-prefixed name of the tiddler to display in the index. This is also working fine, it's finding all the tiddlers, stripping out the leading "The " if there is one and then creating a link to a tiddler.
Here is the problem, instead of linking to the actually tiddler, such as "The Mytiddler", it's creating a link to "Mytiddler" instead, which doesn't exist.
Is there a way to display the non-prefixed tiddler name in the list, but have it link to the actual tiddler?
This is a case for the filter
, subfilter
, and sortsub
operators, which let you run another filter on the contents of a filter without affecting the values in the main filter pipeline.
Here's a complete solution:
\define myprefix(letter) [removeprefix[The ]prefix[$letter$]]
\define mysort() [search-replace::regexp[^The ],[]]
\define render-letter(letter) <<list-links "[filter<myprefix $letter$>] [prefix[$letter$]] +[sortsub<mysort>]">>
<$list filter="A B C D E F G H I J K L M N O P Q R S T U V W X Y Z" variable="currentLetter">
<<currentLetter>>
<$macrocall $name="render-letter" letter=<<currentLetter>>/>
</$list>
And an explanation (not in order):
\define render-letter(letter) <<list-links "[filter<myprefix $letter$>] [prefix[$letter$]] +[sortsub<mysort>]">>
First we create a macro to render each letter. Rather than using the removeprefix
filter operator, we delegate to the filter we called myprefix
:
\define myprefix(letter) [removeprefix[The ]prefix[$letter$]]
The result is that the first filter run matches everything prefixed with The
and the specified letter, but its outputs are the actual tiddler names, rather than the tiddler names with the prefix removed.
We actually don't need to use filter
at all here, because the removeprefix
operator is not necessary – just as effective would be [prefix[The $letter$]]
. But I've left this in to demonstrate the use of filter
, since if you were trying to do something a little more complicated, this solution might not work.
At the end of the pipeline we use sortsub
to combine all of the runs into a single properly sorted list. The filter used for sortsub
represents the key the items will be sorted on, and in this case we do a regular expression search and replace, replacing The
at the start of any tiddler names in the list with nothing:
\define mysort() [search-replace::regexp[^The ],[]]
You can easily handle additional cases in the regex here (e.g., by separating them with |
), if you added other runs for removed prefixes.)
This accomplishes everything in your original question, but to produce a complete version of this tiddler, here's an easy way to render this for every letter:
<$list filter="A B C D E F G H I J K L M N O P Q R S T U V W X Y Z" variable="currentLetter">
<<currentLetter>>
<$macrocall $name="render-letter" letter=<<currentLetter>>/>
</$list>
Our “filter” here is just a list of “tiddler names”, which presumably don't actually exist in your wiki but will be iterated through in sequence in the body of the $list
widget. For each one we call the render-letter
macro on that letter, and you have your alphabetical list of tiddlers subdivided by letter.