From 7397f4fa3a89ed7a9c31e109dac40728ee5afeb1 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Sun, 9 Mar 2025 16:50:48 +0000 Subject: [PATCH] Support for saving result lists in a variable Extend let filter run prefix to store list of results, and add varlist operator for accessing variables as a list. We already had partial support for variables returning a list of values in order for functions to work, now we extend it so that any variable can be used to store a list We should extend the set widget so that it returns a result list that can be accessed with the varlist operator --- core/modules/filterrunprefixes/let.js | 2 +- core/modules/filters/varlist.js | 30 +++++++++++++++++ core/modules/widgets/widget.js | 33 +++++++++++++++---- .../data/let-filter-prefix/ResultList.tid | 12 +++++++ 4 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 core/modules/filters/varlist.js create mode 100644 editions/test/tiddlers/tests/data/let-filter-prefix/ResultList.tid diff --git a/core/modules/filterrunprefixes/let.js b/core/modules/filterrunprefixes/let.js index 64c2a411f..8f877b18c 100644 --- a/core/modules/filterrunprefixes/let.js +++ b/core/modules/filterrunprefixes/let.js @@ -25,7 +25,7 @@ exports.let = function(operationSubFunction,options) { var inputSource = widget.wiki.makeTiddlerIterator(results.toArray()); // Assign the result of the subfunction to the variable var variables = {}; - variables[name] = operationSubFunction(inputSource,widget)[0] || ""; + variables[name] = operationSubFunction(inputSource,widget); // Clear the results results.clear(); // Return the variables diff --git a/core/modules/filters/varlist.js b/core/modules/filters/varlist.js new file mode 100644 index 000000000..e8677dbf5 --- /dev/null +++ b/core/modules/filters/varlist.js @@ -0,0 +1,30 @@ +/*\ +title: $:/core/modules/filters/varlist.js +type: application/javascript +module-type: filteroperator + +Retrieve the value of a variable as a list + +[all[shadows+tiddlers]] + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +/* +Export our filter function +*/ +exports.varlist = function(source,operator,options) { + // Check for common optimisations + var variableInfo = options.widget.getVariableInfo(operator.operand); + if(variableInfo) { + return options.wiki.makeTiddlerIterator(variableInfo.resultList); + } else { + return []; + } +}; + +})(); diff --git a/core/modules/widgets/widget.js b/core/modules/widgets/widget.js index 14e90ba2d..844f1a35d 100755 --- a/core/modules/widgets/widget.js +++ b/core/modules/widgets/widget.js @@ -83,7 +83,7 @@ Widget.prototype.execute = function() { /* Set the value of a context variable name: name of the variable -value: value of the variable +value: value of the variable, can be a string or an array params: array of {name:, default:} for each parameter isMacroDefinition: true if the variable is set via a \define macro pragma (and hence should have variable substitution performed) options includes: @@ -93,8 +93,10 @@ options includes: */ Widget.prototype.setVariable = function(name,value,params,isMacroDefinition,options) { options = options || {}; + var valueIsArray = $tw.utils.isArray(value); this.variables[name] = { - value: value, + value: valueIsArray ? (value[0] || "") : value, + resultList: valueIsArray ? value : [value], params: params, isMacroDefinition: !!isMacroDefinition, isFunctionDefinition: !!options.isFunctionDefinition, @@ -164,6 +166,9 @@ Widget.prototype.getVariableInfo = function(name,options) { resultList = this.wiki.filterTiddlers(value,this.makeFakeWidgetWithVariables(variables),options.source); value = resultList[0] || ""; } else { + if(variable.resultList) { + resultList = variable.resultList; + } params = variable.params; } return { @@ -313,7 +318,7 @@ Widget.prototype.getStateQualifier = function(name) { }; /* -Make a fake widget with specified variables, suitable for variable lookup in filters +Make a fake widget with specified variables, suitable for variable lookup in filters. Each variable can be a string or an array of strings */ Widget.prototype.makeFakeWidgetWithVariables = function(variables) { var self = this, @@ -321,7 +326,12 @@ Widget.prototype.makeFakeWidgetWithVariables = function(variables) { return { getVariable: function(name,opts) { if($tw.utils.hop(variables,name)) { - return variables[name]; + var value = variables[name]; + if($tw.utils.isArray(value)) { + return value[0]; + } else { + return value; + } } else { opts = opts || {}; opts.variables = variables; @@ -330,9 +340,18 @@ Widget.prototype.makeFakeWidgetWithVariables = function(variables) { }, getVariableInfo: function(name,opts) { if($tw.utils.hop(variables,name)) { - return { - text: variables[name] - }; + var value = variables[name]; + if($tw.utils.isArray(value)) { + return { + text: value[0], + resultList: value + }; + } else { + return { + text: value, + resultList: [value] + }; + } } else { opts = opts || {}; opts.variables = $tw.utils.extend({},variables,opts.variables); diff --git a/editions/test/tiddlers/tests/data/let-filter-prefix/ResultList.tid b/editions/test/tiddlers/tests/data/let-filter-prefix/ResultList.tid new file mode 100644 index 000000000..ee9e8e800 --- /dev/null +++ b/editions/test/tiddlers/tests/data/let-filter-prefix/ResultList.tid @@ -0,0 +1,12 @@ +title: LetFilterRunPrefix/ResultList +description: Using the "let" filter run prefix to store result lists, not just single values +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +<$text text={{{ :let:varname[all[tiddlers]] [varlist[varname]sort[]join[,]] }}}/> ++ +title: ExpectedResult + +

$:/core,ExpectedResult,Output

\ No newline at end of file