From ad575efdcc4d03f9d09bf72defe0e8146164d34f Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" Date: Sat, 25 Apr 2020 15:22:24 +0100 Subject: [PATCH] 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 --- core/modules/filters/sortsub.js | 27 ++++++++++++++----- editions/test/tiddlers/tests/test-filters.js | 10 +++++++ .../tiddlers/filters/sortsub Operator.tid | 4 ++- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/core/modules/filters/sortsub.js b/core/modules/filters/sortsub.js index 82de59f8f..f556bfafc 100644 --- a/core/modules/filters/sortsub.js +++ b/core/modules/filters/sortsub.js @@ -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]",anchorWidget).join(",")).toBe("one,hasList,TiddlerOne,has filter,$:/TiddlerTwo,Tiddler Three,$:/ShadowPlugin,a fourth tiddler,filter regexp test"); expect(wiki.filterTiddlers("[!sortsub:number]",anchorWidget).join(",")).toBe("filter regexp test,a fourth tiddler,$:/ShadowPlugin,$:/TiddlerTwo,Tiddler Three,TiddlerOne,has filter,hasList,one"); expect(wiki.filterTiddlers("[sortsub:string]",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]",anchorWidget).join(",")).toBe("$:/ShadowPlugin,filter regexp test,$:/TiddlerTwo,Tiddler Three,a fourth tiddler,has filter,hasList,TiddlerOne,one"); expect(wiki.filterTiddlers("[sortsub:string]",anchorWidget).join(",")).toBe("one,TiddlerOne,hasList,has filter,$:/ShadowPlugin,a fourth tiddler,Tiddler Three,$:/TiddlerTwo,filter regexp test"); expect(wiki.filterTiddlers("[!sortsub:string]",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]",anchorWidget).join(",")).toBe("$:/TiddlerTwo,Tiddler Three,TiddlerOne,a fourth tiddler"); }); } diff --git a/editions/tw5.com/tiddlers/filters/sortsub Operator.tid b/editions/tw5.com/tiddlers/filters/sortsub Operator.tid index 8a4981f44..0e48e29bc 100644 --- a/editions/tw5.com/tiddlers/filters/sortsub Operator.tid +++ b/editions/tw5.com/tiddlers/filters/sortsub Operator.tid @@ -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: