geztting the first word/letter of a list of tiddlers

258 views
Skip to first unread message

Jean-Pierre Rivière

unread,
Oct 26, 2020, 1:41:29 PM10/26/20
to TiddlyWiki
I have a liste of tiddlers (got with something like filter="[tag[foo]]") of which I want the first word/letter.

For only the last single title I get the first word with 
filter="[tag[Chrome]last[]splitregexp[\W]!is[blank]first[]]"

Now, how to get it for all the titles, entirely within a single filter if possible (I'd rather avoid a list widget to achieve that)? Definitely something to do with subfilter. But no, I still can't get it. Frustrating. My initial coding:

<$set name="chrome" value="[tag[Chrome]]">
<list filter="[subfilter<chrome> splitregexp[\W]!is[blank]first[]]"/>
</$set>

but the result is empty. I does not seems so different to the addsuffix example to me...

So in my local copy of the official wiki, I do the following:

<$set name="chrome" value="[tag[Chrome]]">
<<.operator-example 13 "[subfilter<chrome> splitregexp[\W]!is[blank]first[]]">>
<<.operator-example 29 "[subfilter<chrome> addprefix[tidd ]]">>
<<.operator-example 37 "[subfilter<chrome> prefix[S]]">>
<<.operator-example 42 "[subfilter<chrome>]">>
</$set>

examples 13, 29 and 37 produce an empty result. Last example 42 just show that the tagging is producing some results, namely:

"Noteself" by Danielo Rodríguez
"savetiddlers" Extension for Chrome and Firefox by buggyj
Emergency Tiddler Export
Saving on TiddlySpot
Saving to a Git service
Saving via a Minimal Ruby Server
Saving via WebDAV
Saving with the HTML5 fallback saver
TiddlyDrive Add-on for Google Drive by Joshua Stubbs
TiddlyWiki Cloud
Timimi: WebExtension and Native Host by Riz

I think the solution could constitute a precious third example for the subfilter examples tiddler.  (especially, one with Saving repeated, one with just one Saving)

Regards.



Mark S.

unread,
Oct 26, 2020, 2:00:52 PM10/26/20
to TiddlyWiki
There are two mistakes in this:

<list filter="[subfilter<chrome> splitregexp[\W]!is[blank]first[]]"/>

1. It should be $list.  2. There is a space in front of splitregexp.

Unfortunately, using a subfilter won't allow you to process the tiddlers the way you want. You will need a nested loop, with the outer list finding the tiddlers and the inner list extracting the first word.

Jean-Pierre Rivière

unread,
Oct 26, 2020, 6:10:59 PM10/26/20
to TiddlyWiki
good points. OK, I'll do the rwo lists imbicated. Yet, I cannot see why I get exactly the same results in the two lists below.


<$set name="chrome" value="[tag[Chrome]]">
<$list filter="[subfilter<chrome>lowercase[]sentencecase[]splitregexp[\W]!is[blank]addprefix[ * ]]"/>
</$set>

<$set name="chrome" value="[tag[Chrome]]">
<$list filter="[tag[Chrome]lowercase[]sentencecase[]splitregexp[\W]!is[blank]addprefix[ * ]]"/>
</$set>

which is

* noteself * by * danielo * rodr * guez * savetiddlers * extension * for * chrome * and * firefox * by * buggyj * Emergency * tiddler * export * Saving * on * tiddlyspot * Saving * to * a * git * service * Saving * via * a * minimal * ruby * server * Saving * via * webdav * Saving * with * the * html5 * fallback * saver * Tiddlydrive * add * on * for * google * drive * by * joshua * stubbs * Tiddlywiki * cloud * Timimi * webextension * and * native * host * by * riz

And same with

<$set name="chrome" value="[tag[Chrome]]">
<$list filter="[subfilter<chrome>lowercase[]sentencecase[]splitregexp[\W]!is[blank]first[]]"/>
</$set>

<$set name="chrome" value="[tag[Chrome]]">
<$list filter="[tag[Chrome]lowercase[]sentencecase[]splitregexp[\W]!is[blank]first[]]"/>
</$set>

where the result is:

noteself

(from ~"noteself" by danielo rodríguez~)

What's the use of subfilter in real life? It seems such a strange beast. I'm really confused. I wish there be an equivalent of map() found in functional language. I thought subfilter was just that but visibly it is not.

with map I would code:
<$set name="chrome" value="[tag[Chrome]]">
<$list filter="[subfilter<chrome>lowercase[]sentencecase[]splitregexp[\W]!is[blank]first[]]"/>
</$set>

In fact, I'm perplex when reading the subfilter help and the examples don't help me. In particular, I am at odds with the input and the parameter S. S is said to be a filter expression. And the outpur is the selection of titles returned from the subfilter S. Let's see.

in the complete filter below, what is the input and what is the parameter S?

[subfilter[one two three]addsuffix[!]]

input should be: every tiddlers (but system tiddlers).
S is <<one two three>> and so S is a collection of three tiddler titles.
The output of subfilter is S, right?
Although it does not seems so because [[one two three]addsuffix[!]] does not produce the same result ("one two three!" instead of "one! two! three!").

Eric Shulman

unread,
Oct 26, 2020, 6:47:44 PM10/26/20
to tiddl...@googlegroups.com
On Monday, October 26, 2020 at 3:10:59 PM UTC-7, Jean-Pierre Rivière wrote:
What's the use of subfilter in real life? It seems such a strange beast. I'm really confused. I wish there be an equivalent of map() found in functional language. I thought subfilter was just that but visibly it is not.

The subfilter operator allows you to use a variable to specify some piece of filter syntax.  Thus, if you wanted to have different filters based on a field value, you could write:
<$set name="F" filter="[{!!setting}match[somevalue]]" value="[somefilter]" emptyValue="[someotherfilter]">
<$list filter="[subfilter
<F>]"/>
</$set>
Note in the above example, I've used the "conditional variable assignment" form of $set (see https://tiddlywiki.com/#SetWidget)

in the complete filter below, what is the input and what is the parameter S?
[subfilter[one two three]addsuffix[!]]
input should be: every tiddlers (but system tiddlers).
S is <<one two three>> and so S is a collection of three tiddler titles.
Although it does not seems so because
[[one two three]addsuffix[!]]
does not produce the same result ("one two three!" instead of "one! two! three!").

The first syntax -- using subfilter[one two three] -- specifies three tiddler titles.
The second syntax -- using [one two three] -- specifies a single text string.

To get the same results as subfilter[one two three] you could use enlist[...], like this:
[enlist[one two three]addsuffix[!]]

Le lundi 26 octobre 2020 à 19:00:52 UTC+1, Mark S. a écrit :
Unfortunately, using a subfilter won't allow you to process the tiddlers the way you want. You will need a nested loop, with the outer list finding the tiddlers and the inner list extracting the first word.

What Mark has suggested -- using nested lists -- is this:
<$list filter="[tag[Chrome]]">
   <$list filter="[
<currentTiddler>splitregexp[\W]!is[blank]first[]]"/>
</$list>

-e

TW Tones

unread,
Oct 26, 2020, 6:51:59 PM10/26/20
to TiddlyWiki
Jean-Pierre,

Please do say what you want to do with the first word / letter ?
  • Below are some examples that should solve your issues
  • Filters as a rule generate one output so I like to focus on the selected tiddler then process it later.

Thanks for sharing code that works on TiddlyWiki.com, my examples do so as well.

If it is only for some display purpose you can keep the list focused on the selected tiddlers and use triple curly braces (filtered Transclusions) 

<$list filter="[tag[TableOfContents]]">
   {{{ [all[current]split[]first[]] }}}, {{{ [all[current]split[ ]first[]] }}}, <$link/>
<br>
</$list>

You can also use HTML

<style>
p
.uppercase {
  text
-transform: uppercase;
}

p
.lowercase {
  text
-transform: lowercase;
}

p
.capitalize {
  text
-transform: capitalize;
}
</style>


<$list filter="[tag[TableOfContents]]">
<p class="uppercase"><<currentTiddler>></p>
<p class="lowercase"><<currentTiddler>></p>
<p class="capitalize"><<currentTiddler>></p>
<hr>
</$list>

But if you need the 1st letter and first word as variables do this.

<$list filter="[tag[TableOfContents]]">
   <$set name=1st value={{{ [all[current]split[]first[]] }}}>
   <$set name=1stWord value={{{ [all[current]split[ ]first[]] }}}>
        <<1st>> <<1stWord>> <$link/><br>
   </$set></$set>
</$list>

Regards
Tones

Mark S.

unread,
Oct 26, 2020, 6:53:30 PM10/26/20
to TiddlyWiki
subfilter doesn't do "map" or any of those neat things. It just allows a variable that you may have constructed outside the main filter to be used as an additional filter. Personally I haven't found it to be that useful.

[[tag[HelloThere]subfilter<variable-with-filter-that-does-other-things>]



[subfilter[one two three]addsuffix[!]]


Is same as 

"one two three +[addsuffix[!]]"
 
so the result is

one!
two!
three!

It doesn't filter out all tiddlers -- it generates three "tiddlers" (one, two, three).

The problem with splitregexp is that it splits ALL the tiddlers it receives and puts out all the pieces. 

With the split tool in https://github.com/Jermolene/TiddlyWiki5/pull/2963 you could do this in one list statement.

Anyway, here's some code that does sort of what you want, but for TiddlyWiki.com :

\define my-splitting-headache()
<$set name="chrome" value="[tag[HelloThere]]">
<$list filter="[subfilter<chrome>]" >
<$list filter="[<currentTiddler>splitregexp[\W]!is[blank]first[]]"/>
</$list>
</$set>
\end

<$wikify text=<<my-splitting-headache>> name=headache>
<$list filter="[<headache>sort[]]" />
</$wikify>



Note that there are two listed lists inside a macro. These lists find all your tiddlers defined by <chrome>, split them one by one, and the result is returned.

The macro is invoked by the Wikify widget, so that the combined results are rendered and turned back into a single list. Those results are in turned sorted by the final list widget.
 
HTH

TW Tones

unread,
Oct 26, 2020, 7:57:45 PM10/26/20
to TiddlyWiki
Mark,

One compelling use of the subfilter is to access a list and apply it to another;

\define system-tags() text title modified modifier created creator tags list list-after list-before caption type

<$list filter="[fields[]!subfilter<system-tags>]">

</$list>

The advantage being you can create global macros to use as a list.

That list can be used directly
<$list filter="[subfilter<system-tags>]">

</$list>

So this is in fact a way to do "named" filters for use as needed.

So you can use this method to create logically named filters.

\define chapters() [tag[TableOfContents]]

<$list filter="[subfilter<chapters>]">

</$list>

Also I will point out that the pre-release includes a new operator https://tiddlywiki.com/prerelease/#filter%20Operator

One of the key advantages of the subfilter is that it can use a macro which defines a "full filter" that can be used on its own;
<$list filter=<<chapters>> >

</$list>
But also have it become part of another filter as in my first example this demands the subfilter operator.

So we could have am alternate name for subfilter "named filters".

Regards
Tones

Jean-Pierre Rivière

unread,
Oct 27, 2020, 8:39:03 PM10/27/20
to TiddlyWiki
I'm not really understanding what your code below aim to achieve (although I tried it):

\define system-tags() text title modified modifier created creator tags list list-after list-before caption type

<$list filter="[fields[]!subfilter<system-tags>]">
</$list>

I got unexisting tiddlers, or macros tiddlers but with incomplete names and all seems rather random.

As such, I've been unable to understand your further points. Except that the new filter operator seems interesting, although not as easy to use as one would like to. For instance, this does not seems to work:

\define finish-by-iki() [get[title]suffix[iki]]
<<.operator-example 42 "[tag[HelloThere]+filter<finish-by-iki>]">>

The output is empty while I wanted to see at least:
A Gentle Guide to TiddlyWiki
Discover TiddlyWiki
Some of the things you can do with TiddlyWiki
Ten reasons to switch to TiddlyWiki

An other problem is that my filters attempts do not only consider the outpur of the left part but all the tiddlers.

TW Tones

unread,
Oct 27, 2020, 9:28:01 PM10/27/20
to TiddlyWiki
Jeanne-Pierre,

On Wednesday, 28 October 2020 11:39:03 UTC+11, Jean-Pierre Rivière wrote:
I'm not really understanding what your code below aim to achieve (although I tried it):

\define system-tags() text title modified modifier created creator tags list list-after list-before caption type

<$list filter="[fields[]!subfilter<system-tags>]">
</$list>

I got unexisting tiddlers, or macros tiddlers but with incomplete names and all seems rather random.

What you got is a list of all fields in the current tiddlywiki except for those in the defined subfilter.

This expands on the use of the subfilter that mark raised.

Field names can be treated as titles but if they don't exist as tiddlers, then they do not exist.
 

As such, I've been unable to understand your further points. Except that the new filter operator seems interesting, although not as easy to use as one would like to. For instance, this does not seems to work:

\define finish-by-iki() [get[title]suffix[iki]]
<<.operator-example 42 "[tag[HelloThere]+filter<finish-by-iki>]">>

This works
\define finish-by-iki() [get[title]suffix[iki]]
<<.operator-example 42 "[tag[HelloThere]subfilter<finish-by-iki>]">>

The only difference here is the "sub"

A Gentle Guide to TiddlyWiki
Discover TiddlyWiki
Some of the things you can do with TiddlyWiki
Ten reasons to switch to TiddlyWiki

You will with my code above

Tones

Jean-Pierre Rivière

unread,
Oct 27, 2020, 9:53:17 PM10/27/20
to TiddlyWiki

After some more work, I have seen this:

\define themorama() [tag[thème]]

<$list filter="[subfilter<themorama>]+[get[theme]]">
$$$ <$link/>
</$list>

<$list filter="[tag[thème]get[theme]]">
(T) <$link/>
</$list>

the two list have the same functionnality. The syntax is different. Other than a question of taste, or of giving a meaningful name to a complex filter preceding the get operator in my example, it seems that subfilter has no other intterest, isn't it?

Le mardi 27 octobre 2020 à 00:57:45 UTC+1, TW Tones a écrit :

Jean-Pierre Rivière

unread,
Oct 27, 2020, 10:19:27 PM10/27/20
to TiddlyWiki
Great! This example really explains subfilter to me. Also shows what you tell about named filter. It should made it to the official documentation IMHO.

although I 't try (yet) to see the differences between subfilter and the newer filter to come, because it would be disastrous for my peace of mind :-)

Many thanks for your help all of you! How patient are you!!!

Jean-Pierre Rivière

unread,
Oct 28, 2020, 3:50:40 AM10/28/20
to TiddlyWiki
<$list filter="[tag[TableOfContents]]">
   <$set name=1st value={{{ [all[current]split[]first[]] }}}>
   <$set name=1stWord value={{{ [all[current]split[ ]first[]] }}}>
        <<1st>> <<1stWord>> <$link/><br>
   </$set></$set>
</$list>

is really what I wanted to know how to do. I failed to spot your message. Many thanks Tones!

Jean-Pierre Rivière

unread,
Oct 28, 2020, 4:06:39 AM10/28/20
to TiddlyWiki
Now that I know how to fetch the first letter of a given tiddler title, I am not up to my task alas. Because the bit of code shown to me is unable to permit me to have list of all initial letters with only one of each letter concerned. This means I need to have firsthand all the initial inside my filter, not within a list widget.

And there lays the limit of subfilter: it is not able to do that, although I thought to understand it could. This is the never ending story, or am I so dumb?

Here is my latest code (without letter unification yet):

\define first-char() [split[]first[]]
\define glossary-entries() [tag[glossaire]subfilter<first-char>]
<$list filter=<<glossary-entries>>> * <$link/></$list>

it returns only the first letter of the first tiddler!

what I want to acheive finally, is generate something like (see that all letters are not there):

[[A]] [[B]] [[C]] [[D]] [[E]] [[F]] [[G]] [[I]] [[L]] [[M]] [[O]] [[P]] [[R]] [[S]] [[T]] [[U]] [[V]] [[Z]]

TW Tones

unread,
Oct 28, 2020, 8:05:28 AM10/28/20
to TiddlyWiki
Jean-Pierre ,

Its late here in Sydney, so I can look at this tomorrow, if no one else has, however can I suggest you try an come at this from a different direction!
Alternatively can I suggest it will be easier for you if you state
Please do say what you want to do with the first word / letter ?
The conversation has being driven by the code that has not being working for you, but it is not clear to me, perhaps others what it is you want to do.

Please state your requirement in plain language so we can respond to you requirement, rather than the code that is not working for you.

A tip to consider lists generate lists of titles, once you have those tittle you can do what every you want yo each title inside the list widget.

If instead you want a list of all letters in the alphabet, with a list of tiddlers beginning with that letter then you should have a alphabet list as an outer list, and a letters beginning with that letter in an inner list.

Only then see if you can combine them into a single filter, if you must.
<$list filter="A B C D E F G I L M O P R S T U V Z" variable=firstchar >
Then
<$list filter=[tag[glossaire]prefix
<firstchar>sort[]]">


</$list>
</$list>

But I am still not sure what you want.

Regards
Tones

Thomas Stone

unread,
Nov 1, 2020, 8:04:52 AM11/1/20
to TiddlyWiki
Can you provide some sample data that shows what the TW filter is doing, and then an example of what you would like it to do?

Eric Shulman

unread,
Nov 1, 2020, 8:34:56 AM11/1/20
to TiddlyWiki
On Tuesday, October 27, 2020 at 6:53:17 PM UTC-7, Jean-Pierre Rivière wrote:
Other than a question of taste, or of giving a meaningful name to a complex filter preceding the get operator in my example, it seems that subfilter has no other intterest, isn't it?


... if you wanted to have different filters based on a field value, you could write:
<$set name="F" filter="[{!!setting}match[somevalue]]" value="[somefilter]" emptyValue="[someotherfilter]">
<$list filter="[subfilter
<F>]"/>
</$set>
Note in the above example, I've used the "conditional variable assignment" form of $set (see https://tiddlywiki.com/#SetWidget)

-e

Jean-Pierre Rivière

unread,
Nov 18, 2020, 8:19:38 AM11/18/20
to TiddlyWiki
As a final reply to this post, I can now show you a working solution, complete within my project: elaborating a glossary entry for French.

\define all-initials()
<$list filter="[tag[glossaire]]">
   <$set name=1st value={{{ [all[current]split[]first[]] }}}>
      <<1st>>
   </$set>
</$list>
\end

\define glossaryList()
<$wikify name="all-letters" text=<<all-initials>>>
<$list filter="[<all-letters>uppercase[]split[É]join[E]split[]each:value[]!is[missing]]" variable="letter">
  <$link to=<<letter>>/>
</$list>

<$list filter="[<all-letters>uppercase[]split[É]join[E]split[]each:value[]!is[missing]]" variable="letter">
<h3><$link to=<<letter>>/></h3>
<$set name="entries" filter="[<letter>addprefix[{{]addsuffix[}}]]">
<<entries>>
</$set>
</$list>
</$wikify>
\end

A bit of conundrum yet: I have been required to duplicated the $list filter="[<all-letters>uppercase[]split[É]join[E]split[]each:value[]!is[missing]]" variable="letter"> because I have not been able to use its results one way or another (wikify, variable... no way).

But the things that really was strange is that I could not transclude the tidler of any given letter (like "A" or "M") with

<$transclude tiddler=<<letter>>/>

because its transclude all the letters instead (and not even that, because the E was missing entries beginning by "é" which the real "E" tiddler has). And the only working way to generate the {{<<letter>>}} syntax that would work was through the filter of a variable. How strange!

This kind of quirks realling make things much slower than what you would think they have too.

TW Tones

unread,
Nov 18, 2020, 6:06:24 PM11/18/20
to TiddlyWiki
Jean-Pierre,

Thanks for sharing back. Just remember  {{<<letter>>}}  is overloading the shortcut syntax for transcludes, when we use shortcuts they are typically less featured and we need to resort to the long forms such as the transclude widget. However as you become experienced with filters the triple curly braces "filtered transcludes", is a powerful method. See the reference I am building.   

the thing with a filtered transclude {{{ filter }}} is and field tiddler or content can be used to generate the result of the filter. eg
{{{ [<letter>get[text]] }}} would retrieve the text of the letter tiddler, Here we have access in the filter to control the result, and triple curly bracces can provide values to parameters in widgets param={{{ filter }}} including $macrocall to access macros.

Regards
Tones

Sylvain Naudin

unread,
Nov 28, 2020, 6:10:47 PM11/28/20
to TiddlyWiki
Bonsoir Jean-Pierre, Hi Tones,

I'm playing with a simple phone book / member organisation tool.
Here the last share version : https://tw5.xyz/Annuaire/annuaire.html

1/ I'm wondering If I could put some of your code to create an index, like you idea with first letter from tiddler, that would be great ; I've try a but failed..

2/ I've a second wish, to auto-complete initials from concatenate 2 fields values (like SN for Sylvain Naudin), you will see avatar what I'm mean.

If you have some idea's to achieve this, I'll be happy :)

Cheers,
Sylvain

Jean-Pierre Rivière

unread,
Dec 1, 2020, 2:55:01 PM12/1/20
to TiddlyWiki
@Sylvain

1) of course you can use my code!

2) you could have a dictionnary when key "SN" would be valued at "Sylvain Naudin" but that would not do for two people with the same initial. Alternatively, you could have several values for SN, a bit like a hash-table can have internally. Then you could propose a choice. I'm currently having a problem which can be formally near of your problem. 

As for the dictionnary, I mean:

SN: [[Sylvain Naudin]] [[Sophie Nivelles]] [[Serge Nalaud]]

and I am using this code, than you would adapt to your needs:

<$set name=regsep value="([\[][\[]|^)([^\]]*)([\]][\]] *|$)">
<$list filter="[{!!themes}splitregexp<regsep>]" variable="people"/>
</$set>
Reply all
Reply to author
Forward
0 new messages