Update sortsub to evaluate the subfilter for each item in the list

See the discussion here https://groups.google.com/d/msg/tiddlywiki/BqUFQ3v-fZw/U0F04CFFBQAJ
This commit is contained in:
jeremy@jermolene.com 2020-04-25 15:22:24 +01:00
parent 685157266d
commit ad575efdcc
3 changed files with 33 additions and 8 deletions

View File

@ -16,17 +16,30 @@ Filter operator for sorting by a subfilter
Export our filter function
*/
exports.sortsub = function(source,operator,options) {
// Collect the input titles
var inputTitles = [];
// Compile the subfilter
var filterFn = options.wiki.compileFilter(operator.operand);
// Collect the input titles and the corresponding sort keys
var inputTitles = [],
sortKeys = [];
source(function(tiddler,title) {
inputTitles.push(title);
var r = filterFn.call(options.wiki,function(iterator) {
iterator(options.wiki.getTiddler(title),title);
},{
getVariable: function(name) {
if(name === "currentTiddler") {
return title;
} else {
return options.widget.getVariable(name);
}
}
});
sortKeys.push(r[0] || "");
});
// Pass them through the subfilter to get the sort keys
var sortKeys = options.wiki.filterTiddlers(operator.operand,options.widget,options.wiki.makeTiddlerIterator(inputTitles));
// Rather than sorting the titles array, we'll sort the indexes so that we can consult both arrays
var indexes = [];
while(inputTitles.length > indexes.length) {
indexes.push(indexes.length);
var indexes = new Array(inputTitles.length);
for(var t=0; t<inputTitles.length; t++) {
indexes[t] = t;
}
// Sort the indexes
var compareFn = $tw.utils.makeCompareFunction(operator.suffix,{defaultType: "string",invert: operator.prefix === "!"});

View File

@ -92,6 +92,8 @@ function setupWiki(wikiOptions) {
title: "TiddlerOne",
text: "The quick brown fox in $:/TiddlerTwo",
tags: ["one"],
cost: "123",
value: "120",
authors: "Joe Bloggs",
modifier: "JoeBloggs",
modified: "201304152222"});
@ -99,6 +101,8 @@ function setupWiki(wikiOptions) {
title: "$:/TiddlerTwo",
text: "The rain in Spain\nfalls mainly on the plain and [[a fourth tiddler]]",
tags: ["two"],
cost: "42",
value: "190",
authors: "[[John Doe]]",
modifier: "John",
modified: "201304152211"});
@ -106,12 +110,16 @@ function setupWiki(wikiOptions) {
title: "Tiddler Three",
text: "The speed of sound in light\n\nThere is no TiddlerZero but TiddlerSix",
tags: ["one","two"],
cost: "56",
value: "80",
modifier: "John",
modified: "201304162202"});
wiki.addTiddler({
title: "a fourth tiddler",
text: "The quality of mercy is not drained by [[Tiddler Three]]",
tags: [],
cost: "82",
value: "72",
empty: "not",
modifier: "John"});
wiki.addTiddler({
@ -669,6 +677,7 @@ function runTests(wiki) {
var anchorWidget = rootWidget.children[0];
rootWidget.setVariable("sort1","[length[]]");
rootWidget.setVariable("sort2","[get[text]else[]length[]]");
rootWidget.setVariable("sort3","[{!!value}divide{!!cost}]");
expect(wiki.filterTiddlers("[sortsub:number<sort1>]",anchorWidget).join(",")).toBe("one,hasList,TiddlerOne,has filter,$:/TiddlerTwo,Tiddler Three,$:/ShadowPlugin,a fourth tiddler,filter regexp test");
expect(wiki.filterTiddlers("[!sortsub:number<sort1>]",anchorWidget).join(",")).toBe("filter regexp test,a fourth tiddler,$:/ShadowPlugin,$:/TiddlerTwo,Tiddler Three,TiddlerOne,has filter,hasList,one");
expect(wiki.filterTiddlers("[sortsub:string<sort1>]",anchorWidget).join(",")).toBe("TiddlerOne,has filter,$:/TiddlerTwo,Tiddler Three,$:/ShadowPlugin,a fourth tiddler,filter regexp test,one,hasList");
@ -677,6 +686,7 @@ function runTests(wiki) {
expect(wiki.filterTiddlers("[!sortsub:number<sort2>]",anchorWidget).join(",")).toBe("$:/ShadowPlugin,filter regexp test,$:/TiddlerTwo,Tiddler Three,a fourth tiddler,has filter,hasList,TiddlerOne,one");
expect(wiki.filterTiddlers("[sortsub:string<sort2>]",anchorWidget).join(",")).toBe("one,TiddlerOne,hasList,has filter,$:/ShadowPlugin,a fourth tiddler,Tiddler Three,$:/TiddlerTwo,filter regexp test");
expect(wiki.filterTiddlers("[!sortsub:string<sort2>]",anchorWidget).join(",")).toBe("filter regexp test,$:/TiddlerTwo,Tiddler Three,a fourth tiddler,$:/ShadowPlugin,has filter,hasList,TiddlerOne,one");
expect(wiki.filterTiddlers("[[TiddlerOne]] [[$:/TiddlerTwo]] [[Tiddler Three]] [[a fourth tiddler]] +[!sortsub:number<sort3>]",anchorWidget).join(",")).toBe("$:/TiddlerTwo,Tiddler Three,TiddlerOne,a fourth tiddler");
});
}

View File

@ -13,7 +13,9 @@ op-suffix-name: T
op-output: the input, sorted into ascending order by the result of evaluating subfilter <<.param S>>
op-neg-output: the input, sorted into reverse order by the result of evaluating subfilter <<.param S>>
The list of input titles are passed to the subfilter. The subfilter transforms the input titles into the form needed for sorting. For example, the subfilter `[length[]]` transforms each input title in the number representing its length, and thus sorts the input titles according to their length.
Each item in the list of input titles is passed to the subfilter in turn. The subfilter transforms the input titles into the form needed for sorting. For example, the subfilter `[length[]]` transforms each input title in the number representing its length, and thus sorts the input titles according to their length.
Note that within the subfilter, the "currentTiddler" variable is set to the title of the tiddler being processed. This permits subfilters like `[{!!value}divide{!!cost}]` to be used for computation.
The suffix <<.place T>> determines how the items are compared and can be: