Sort authors via last name in Tiddlywiki - tiddlywiki

It would be good to sort lists using an author's last name.
I have this code in one of the tiddlers, it lists all the tiddlers tagged 'author' and sorts alphabetically:
<$list filter='[tag[author]sort[title]]'>
</$list>
e.g.
Adam Robinson
Andrew Adonis
Benjamin Franklin
Dale Carnegie
Daniel Priestley
George Leonard
I would like the list to be sorted by last name, so it looks like this:
Adonis, Andrew
Carnegie, Dale
Franklin, Benjamin
Leonard, George
Priestley, Daniel
Robinson, Adam
Any ideas how to do this?

Easy option: Add a ByLastName field populated the way you want and sort on that.
Medium option: Introduce the notion of generated fields into tiddlywiki.
Hard option: Modify the sort filter to call a macro with whatever data you specify and then sort the original list based on the result.

In recent versions of TiddlyWiki, you can do this with the sortsub operator, which sorts based on the results of applying a filter expression to the inputs. Note that when you use this operator (or any other operator that takes a subfilter), you have to define the subfilter using a macro, or there's no way for TiddlyWiki to tell which square brackets are part of the main filter and which are part of the subfilter.
Here's a minimal working version:
\define myfilt() [split[ ]last[]]
<$list filter="[tag[author]sortsub<myfilt>]">
...
</$list>
To get the display to show up as "Lastname, Firstname", as in your example, rather than just showing the title of the tiddler as is:
\define myfilt() [split[ ]last[]]
<$list filter="[tag[author]sortsub<myfilt>]">
<$set name=formattedName value={{{ [all[current]split[ ]last[]addsuffix[, ]] [all[current]split[ ]butlast[]] +[join[]] }}}>
<$link to=<<currentTiddler>>><<formattedName>></$link><br>
</$set>
</$list>
We calculate the new format using a filter in {{{ triple curly braces }}} and assign it to a variable (note the use of butlast[] rather than first[] so that if someone has more than two names, the middle ones go on the end rather than disappearing). Then we create a link whose text is that new formatted version, and whose target is the original tiddler name.

Related

How to use a logical operator in WikiText to select a tiddler with one OR another tag?

The TiddlyWiki documentation provides an example of the tag operator:
[tag[task]]
This selects all tiddlers that have been tagged as task.
How though would one select all tiddlers tagged with one OR another tag; so for instance I want to select all tiddlers that are tagged either dog or cat? None of the below attempts succeed:
[tag[cat]||[dog]]
[tag[cat]OR[dog]]
[tag[cat, dog]]
For context, I'm looking to use this within a list, along the lines of:
<$list filter="[tag[cat]||[dog]]">
<$view field="title"/>
</$list>
A bit late but in case it's still useful...
There are various ways to combine the results of different lists, and in this case one just needs the simple union of lists which is represented with a space between two filter expressions:
<$list filter="[tag[cat]] [tag[dog]]">
<$view field="title"/>
</$list>
The document about filters is rich but a bit messy, I think that this is explained in "Introduction to filter notation" but there are other relevant parts in "Filter expression", also here and possibly in other places.

In a Tiddler, how to list all its fields and their values?

Using TiddlyWiki, I'm trying to show, in a specific Tiddler, a subset of all the fields of that tiddler, with their values.
The problem is, while I'm able to list all the relevant fields' names, I cannot print their value.
My current code is:
<$list filter="[fields[]prefix[Result_]sort[title]]" template="$:/zx/ListFieldItemTemplate"/>
... which aims to list all the fields starting with Result_.
The (simplified) template $:/zx/ListFieldItemTemplate is:
<div>
<$view field="title"/>
</div>
My fear is that the list widget is only sending the names of the fields, not the values, which means there's no way to get that value from the template. So I may need to somehow send the values, too. But I don't know how.
One possibility is to use a macro.
In your tiddler, put the following macro call:
<<myMacro prefix:"Result_">>
(The aim is to filter the fields only to those starting with "Result_".)
Then, create a new tiddler, whose name is not important, but which must contain the tag $:/tags/Macro to make that macro globally available. And in that tiddler, write the following code:
\define myMacro(prefix:"")
<$list filter="[fields[]prefix[$prefix$]sort[title]]" variable="fieldName">
<<fieldName>>
====
<$view field=<<fieldName>>/>
</$list>
\end
This will output something like:
Result_MyFieldName1 ==== MyFieldValue1
Result_MyFieldName2 ==== MyFieldValue2
Result_MyFieldName3 ==== MyFieldValue3
Result_MyFieldName4 ==== MyFieldValue4
Of course, you can then modify the macro to use your own formatting.
This is an old thread, but maybe someone will find this useful:
Loop through all fields and list name/value:
<$list filter="[fields[]] -[[title]] -[[text]] -[[tags]] -[[created]] -[[modified]]" variable="fieldname">
<> = <$view field=<> />
</$list>

How do I define a SemgrexPattern in Stanford API, to match nodes' text without using {lemma:...}?

I am working with the edu.stanford.nlp.semgrex and edu.stanford.nlp.tress.semgraph packages and am looking for a way to match nodes with a text value other than the lemma: directive.
I couldn't find all possible attribute names in javadoc for SemgrexPattern, only those for lemma, tag, and relational operators - is there a comprehensive list available?
For example, in the following sentence
My take-home pay is $20.
extracting the 'take-home' node is not possible using
(SemgrexPattern.compile( "{lemma:take-home}"))
.matcher( "My take-home pay is $20.").find()
yields false, because take-home is deemed not to be a lemma.
What do I need to do to match nodes with non-lemma, arbitrary text?
Thanks for any advice or comment.
Sorry - I realize that {word:take-home} would work in the example above.
Thanks..

xpath return all non-blank text nodes not descendant of `a`, `style` or `script`

What expression would select all text nodes which are:
not blank
not inside a, or script or style?
Use:
//*[not(self::a or self::script or self::style)]/text()[normalize-space()]
Not only is this expression shorter than the one in the currently accepted answer, but it also may be much more efficient.
Do note that the expression doesnt use any (back/up)-ward axes at all.
This should do, assuming "not inside" means the text node is not supposed to be a descendant of an "a" or "script" or "style" element. If "not inside" only means not supposed to be a child then use parent::a and so on instead of ancestor::a.
//text()[normalize-space() and not(ancestor::a | ancestor::script | ancestor::style)]
I used Dimitre Novatchev's answer, but then i stumbled upon the problem described by the topic starter:
not descendant of a, style or script
Dimitre's answer excludes style tag but includes its children.
This version excludes also style, script, noscript tags and their descendants:
//div[#id='???']//*[not(ancestor-or-self::script or ancestor-or-self::noscript or ancestor-or-self::style)]/text()
Anyway, thanks to Dimitre Novatchev.

using xpath to obtain complex values

Given the following, I'd like to extract VarVal1, VarVa5 and VarText where FixedVals are, well, fixed :)
<TypeA Attr1="VarVal1">
<TypeB Attr2="FixedVal2">
<TypeC Attr3="FixedVal3">
<TypeD Attr4="FixedVal4" Attr5="VarVal5">
VarText
</TypeD>
</TypeC>
</TypeB>
</TypeA>
Notice that the big problem for me is that the context is important. I want the complete pattern. There may be other TypeA nodes, but I'm not interested in their values unless they're followed by
<TypeB Attr2="FixedVal2">
<TypeC Attr3="FixedVal3">
<TypeD Attr4="FixedVal4" Attr5="VarVal5">
VarText
</TypeD>
</TypeC>
</TypeB>
In other words, what I'm interested in is a set of tripletts, each of them in the form of (VarVal1, VarVal5, VarText)
These XPath expressions:
//TypeA
[TypeB[#Attr2="FixedVal2"]
/TypeC[#Attr3="FixedVal3"]
/TypeD[#Attr4="FixedVal4"]]
/#Attr1
Then those already posted:
//TypeA
/TypeB[#Attr2="FixedVal2"]
/TypeC[#Attr3="FixedVal3"]
/TypeD[#Attr4="FixedVal4"]
/#Attr5
And
//TypeA
/TypeB[#Attr2="FixedVal2"]
/TypeC[#Attr3="FixedVal3"]
/TypeD[#Attr4="FixedVal4"]
You could also combine them with | union set operator. But depending on the host language, you should better select the TypeA elements you want (first expression with out last /#Attr1 part) and then query each of those to extract the remaining values.
I think you need a couple of queries for this (could be wrong though)
for VarVal1
//TypeA/#Attr1
for VarVal5
//TypeA
/TypeB[#Attr2="FixedVal2"]
/TypeC[#Attr3="FixedVal3"]
/TypeD[#Attr4="FixedVal4"]
/#Attr5
Think these should do the trick
EDIT - missed VarText!
//TypeA
/TypeB[#Attr2="FixedVal2"]
/TypeC[#Attr3="FixedVal3"]
/TypeD[#Attr4="FixedVal4"]

Resources