diff --git a/core/modules/widgets/let.js b/core/modules/widgets/let.js index 2b2886530..2cde66fde 100644 --- a/core/modules/widgets/let.js +++ b/core/modules/widgets/let.js @@ -49,7 +49,7 @@ LetWidget.prototype.computeAttributes = function() { self = this; this.currentValueFor = Object.create(null); $tw.utils.each($tw.utils.getOrderedAttributesFromParseTreeNode(this.parseTreeNode),function(attribute) { - var value = self.computeAttribute(attribute), + var value = self.computeAttribute(attribute,{asList: true}), name = attribute.name; // Now that it's prepped, we're allowed to look this variable up // when defining later variables @@ -59,7 +59,7 @@ LetWidget.prototype.computeAttributes = function() { }); // Run through again, setting variables and looking for differences $tw.utils.each(this.currentValueFor,function(value,name) { - if (self.attributes[name] !== value) { + if (!$tw.utils.isArrayEqual(self.attributes[name],value)) { self.attributes[name] = value; self.setVariable(name,value); changedAttributes[name] = true; @@ -72,8 +72,10 @@ LetWidget.prototype.getVariableInfo = function(name,options) { // Special handling: If this variable exists in this very $let, we can // use it, but only if it's been staged. if ($tw.utils.hop(this.currentValueFor,name)) { + var value = this.currentValueFor[name]; return { - text: this.currentValueFor[name] + text: value[0] || "", + resultList: value }; } return Widget.prototype.getVariableInfo.call(this,name,options); diff --git a/core/modules/widgets/letlist.js b/core/modules/widgets/letlist.js deleted file mode 100644 index bcc2b6dbf..000000000 --- a/core/modules/widgets/letlist.js +++ /dev/null @@ -1,91 +0,0 @@ -/*\ -title: $:/core/modules/widgets/letlist.js -type: application/javascript -module-type: widget - -This widget allows defining multiple variables as lists, allowing -the later variables to depend upon the earlier ones - -\*/ -(function(){ - -/*jslint node: true, browser: true */ -/*global $tw: false */ -"use strict"; - -var Widget = require("$:/core/modules/widgets/widget.js").widget; - -var LetListWidget = function(parseTreeNode,options) { - // Initialise - this.initialise(parseTreeNode,options); -}; - -/* -Inherit from the base widget class -*/ -LetListWidget.prototype = new Widget(); - -/* -Render this widget into the DOM -*/ -LetListWidget.prototype.render = function(parent,nextSibling) { - this.parentDomNode = parent; - this.computeAttributes(); - this.execute(); - this.renderChildren(parent,nextSibling); -}; - -LetListWidget.prototype.computeAttributes = function() { - // Before computing attributes, we must make clear that none of the - // existing attributes are staged for lookup, even on a refresh - var changedAttributes = {}, - self = this; - this.currentValueFor = Object.create(null); - $tw.utils.each($tw.utils.getOrderedAttributesFromParseTreeNode(this.parseTreeNode),function(attribute) { - var value = self.computeAttribute(attribute,{asList: true}), - name = attribute.name; - // Now that it's prepped, we're allowed to look this variable up - // when defining later variables - if(value !== undefined) { - self.currentValueFor[name] = value; - } - }); - // Run through again, setting variables and looking for differences - $tw.utils.each(this.currentValueFor,function(value,name) { - if (!$tw.utils.isArrayEqual(self.attributes[name],value)) { - self.attributes[name] = value; - self.setVariable(name,value); - changedAttributes[name] = true; - } - }); - return changedAttributes; -}; - -LetListWidget.prototype.getVariableInfo = function(name,options) { - // Special handling: If this variable exists in this very $let, we can - // use it, but only if it's been staged. - if ($tw.utils.hop(this.currentValueFor,name)) { - var value = this.currentValueFor[name]; - return { - text: value[0] || "", - resultList: value - }; - } - return Widget.prototype.getVariableInfo.call(this,name,options); -}; - -/* -Refresh the widget by ensuring our attributes are up to date -*/ -LetListWidget.prototype.refresh = function(changedTiddlers) { - var changedAttributes = this.computeAttributes(); - if($tw.utils.count(changedAttributes) > 0) { - this.refreshSelf(); - return true; - } - return this.refreshChildren(changedTiddlers); -}; - -exports["letlist"] = LetListWidget; - -})(); diff --git a/editions/test/tiddlers/tests/data/letlist-widget/SelfReference.tid b/editions/test/tiddlers/tests/data/letlist-widget/SelfReference.tid deleted file mode 100644 index 3ad4026b6..000000000 --- a/editions/test/tiddlers/tests/data/letlist-widget/SelfReference.tid +++ /dev/null @@ -1,19 +0,0 @@ -title: LetListWidget/SelfReference -description: Using self references with the "letlist" widget -type: text/vnd.tiddlywiki-multiple -tags: [[$:/tags/wiki-test-spec]] - -title: Output - -<$letlist - original={{{ [all[tiddlers]sort[]] }}} - varname={{{ [varlist[original]] }}} -> -<$text text={{{ [varlist[varname]] +[join[-]] }}}/> - -+ -title: ExpectedResult - -

-$:/core-ExpectedResult-Output -

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/letlist-widget/Simple.tid b/editions/test/tiddlers/tests/data/letlist-widget/Simple.tid deleted file mode 100644 index 6a31d2189..000000000 --- a/editions/test/tiddlers/tests/data/letlist-widget/Simple.tid +++ /dev/null @@ -1,16 +0,0 @@ -title: LetListWidget/Simple -description: Simple usage of the "letlist" widget -type: text/vnd.tiddlywiki-multiple -tags: [[$:/tags/wiki-test-spec]] - -title: Output - -<$letlist varname={{{ [all[tiddlers]sort[]] }}}> -<$text text={{{ [varlist[varname]] +[join[-]] }}}/> - -+ -title: ExpectedResult - -

-$:/core-ExpectedResult-Output -

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/letlist-widget/MultiValuedFunction.tid b/editions/test/tiddlers/tests/data/multi-valued-variables/MultiValuedFunction.tid similarity index 66% rename from editions/test/tiddlers/tests/data/letlist-widget/MultiValuedFunction.tid rename to editions/test/tiddlers/tests/data/multi-valued-variables/MultiValuedFunction.tid index 57879407f..228c42bf4 100644 --- a/editions/test/tiddlers/tests/data/letlist-widget/MultiValuedFunction.tid +++ b/editions/test/tiddlers/tests/data/multi-valued-variables/MultiValuedFunction.tid @@ -1,5 +1,5 @@ -title: LetListWidget/Simple -description: Simple usage of the "letlist" widget +title: MultiValuedVariables/Functions +description: Multi-valued functions type: text/vnd.tiddlywiki-multiple tags: [[$:/tags/wiki-test-spec]] @@ -7,9 +7,9 @@ title: Output \function myfunc() [all[tiddlers]sort[]] -<$letlist varname=<>> +<$let varname=<>> <$text text={{{ [varlist[varname]] +[join[-]] }}}/> - + + title: ExpectedResult diff --git a/editions/test/tiddlers/tests/data/multi-valued-variables/Simple.tid b/editions/test/tiddlers/tests/data/multi-valued-variables/Simple.tid new file mode 100644 index 000000000..ebaf11901 --- /dev/null +++ b/editions/test/tiddlers/tests/data/multi-valued-variables/Simple.tid @@ -0,0 +1,17 @@ +title: MultiValuedVariables/Simple +description: Simple usage of multivalued assignments with the "let" widget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +<$let varname={{{ [all[tiddlers]sort[]] }}} + varname2=<>> +<$text text={{{ [varlist[varname2]] +[join[-]] }}}/> + ++ +title: ExpectedResult + +

+$:/core-ExpectedResult-Output +

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/test-widget-getVariableInfo.js b/editions/test/tiddlers/tests/test-widget-getVariableInfo.js index 7273a6dce..9d2084b58 100644 --- a/editions/test/tiddlers/tests/test-widget-getVariableInfo.js +++ b/editions/test/tiddlers/tests/test-widget-getVariableInfo.js @@ -77,7 +77,7 @@ describe("Widget module", function() { expect(childNode.getVariableInfo("$my.widget", {allowSelfAssigned:true}).params).toEqual([{name:"w",default:"ww"}]); // no params expected - expect(childNode.getVariableInfo("abc", {allowSelfAssigned:true})).toEqual({text:"def"}); + expect(childNode.getVariableInfo("abc", {allowSelfAssigned:true})).toEqual({text:"def", resultList: [ "def" ]}); // debugger; Find code in browser diff --git a/editions/tw5.com/tiddlers/variables/Multi-Valued Variables.tid b/editions/tw5.com/tiddlers/variables/Multi-Valued Variables.tid new file mode 100644 index 000000000..302f6f084 --- /dev/null +++ b/editions/tw5.com/tiddlers/variables/Multi-Valued Variables.tid @@ -0,0 +1,16 @@ +title: Multi-Valued Variables +created: 20250307212252946 +modified: 20250307212252946 +tags: Concepts Variables + +<<.from-version "5.3.7">> In ordinary usage, [[variables|Variables]] contain a single spinnet of text. With the introduction of multi-valued variables. it is now possible to store a list of multiple values in a single variable. When accessed in the usual way, only the first value is returned, but the [[varlist Operator]] can be used to access all the values. This makes the existence of multi-valued variables largely invisible unless you specifically need to use them. + +The <<.wid let>> widget also allows [[multi-valued variables|Multi-Valued Variables]] to be set in one operation, each to the complete list of results obtained from evaluating an attribute. + +For example: + +``` +<$letlist varname={{{ [all[tiddlers]sort[]] }}}> +<$text text={{{ [varlist[varname]] +[join[-]] }}}/> + +``` diff --git a/editions/tw5.com/tiddlers/variables/Variables.tid b/editions/tw5.com/tiddlers/variables/Variables.tid index 43387eb4f..62fd661e0 100644 --- a/editions/tw5.com/tiddlers/variables/Variables.tid +++ b/editions/tw5.com/tiddlers/variables/Variables.tid @@ -1,13 +1,15 @@ created: 20141002133113496 -modified: 20240422084347375 +modified: 20250307212252946 tags: Concepts WikiText title: Variables type: text/vnd.tiddlywiki !! Introduction -* A <<.def variable>> is a ''snippet of text'' that can be accessed by name. -* The text is referred to as the variable's <<.def value>>. +* A <<.def variable>> is a ''snippet of text'' that can be accessed by name +* The text is referred to as the variable's <<.def value>> + +<<.from-version "5.3.7">> In ordinary usage, variables contain a single spinnet of text. With the introduction of [[Multi-Valued Variables]] it is now possible to store a list of multiple values in a single variable. When accessed in the usual way, only the first value is returned, but the [[varlist Operator]] can be used to access all the values. This makes the existence of multi-valued variables largely invisible unless you specifically need to use them Variables are defined by [[widgets|Widgets]]. Several core widgets define variables, the most common being the <<.wlink LetWidget>>, <<.wlink SetWidget>> and <<.wlink ListWidget>> widgets. diff --git a/editions/tw5.com/tiddlers/widgets/LetListWidget.tid b/editions/tw5.com/tiddlers/widgets/LetListWidget.tid deleted file mode 100644 index 6a265d34a..000000000 --- a/editions/tw5.com/tiddlers/widgets/LetListWidget.tid +++ /dev/null @@ -1,26 +0,0 @@ -title: LetListWidget -created: 20250307212252946 -modified: 20250307212252946 -tags: Widgets -caption: letlist - -! Introduction - -<<.from-version "5.3.7">> The <<.wid letlist>> widget allows multiple variables to be set in one operation, each to the list of results from evaluating an attribute. It is similar to the <<.wlink LetWidget>> widget but assigns the complete list of results to a multi-valued variable instead of just the first result. - -! Content and Attributes - -The content of the <<.wid letlist>> widget is the scope for the value assigned to the variable. - -|!Attribute |!Description | -|//{attributes}// |Each attribute name specifies a variable name. The attribute value is a list that is assigned to the variable | - -The <<.wid letlist>> is primarily intended to be used with the filtered attribute syntax. This enables the result list of a filter to be assigned to a multi-valued variable: - -``` -<$letlist varname={{{ [all[tiddlers]sort[]] }}}> -<$text text={{{ [varlist[varname]] +[join[-]] }}}/> - -``` - -Attributes are evaluated in the order they are written. Attributes with the same name are allowed. Each time a duplicate attribute is encountered, it will replace the existing value set by the earlier duplicate. diff --git a/editions/tw5.com/tiddlers/widgets/LetWidget.tid b/editions/tw5.com/tiddlers/widgets/LetWidget.tid index b27306cfb..5a6e42434 100644 --- a/editions/tw5.com/tiddlers/widgets/LetWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/LetWidget.tid @@ -1,12 +1,12 @@ title: LetWidget created: 20211028115900000 -modified: 20221001094658854 +modified: 20250307212252946 tags: Widgets caption: let ! Introduction -<<.from-version "5.2.1">> The <<.wid let>> widget allows multiple variables to be set in one operation. In some situations it can result in simpler code than using the more flexible <<.wlink SetWidget>> widget. It differs from the <<.wlink VarsWidget>> widget in that variables you're defining may depend on earlier variables defined within the same <<.wid let>>. +<<.from-version "5.2.1">> The <<.wid let>> widget allows more than one variable to be set in one operation. In some situations it can result in simpler code than using the more flexible <<.wlink SetWidget>> widget. It differs from the <<.wlink VarsWidget>> widget in that variables you're defining may depend on earlier variables defined within the same <<.wid let>>. ! Content and Attributes @@ -19,6 +19,18 @@ Attributes are evaluated in the order they are written. Attributes with the same <<.note """<<.from-version "5.2.4">> There is no longer any restriction on using variable names that start with the $ character.""">> +! Multi-Valued Variables + +<<.from-version "5.3.7">> The <<.wid let>> widget also allows [[multi-valued variables|Multi-Valued Variables]] to be set in one operation, each to the complete list of results obtained from evaluating an attribute. + +Almost all operations that work with variables only consider the first item in the list. The [[varlist Operator]] gives access to the complete list of results. For example: + +``` +<$letlist varname={{{ [all[tiddlers]sort[]] }}}> +<$text text={{{ [varlist[varname]] +[join[-]] }}}/> + +``` + ! Examples Consider a case where you need to set multiple variables, where some depend on the evaluation of others.