1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2025-04-08 11:46:40 +00:00

Dispense with the letlist widget

What this PR actually does is rename the letlist widget to "let". The result is the same as using the letlist widget, but it is backwards compatible by virtue of the fact that all existing ways to access variables will only see the single value for the variable.
This commit is contained in:
Jeremy Ruston 2025-03-18 12:46:31 +00:00
parent a31df85894
commit 0db188f365
11 changed files with 62 additions and 165 deletions

View File

@ -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);

View File

@ -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;
})();

View File

@ -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[-]] }}}/>
</$letlist>
+
title: ExpectedResult
<p>
$:/core-ExpectedResult-Output
</p>

View File

@ -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[-]] }}}/>
</$letlist>
+
title: ExpectedResult
<p>
$:/core-ExpectedResult-Output
</p>

View File

@ -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=<<myfunc>>>
<$let varname=<<myfunc>>>
<$text text={{{ [varlist[varname]] +[join[-]] }}}/>
</$letlist>
</$let>
+
title: ExpectedResult

View File

@ -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=<<varname>>>
<$text text={{{ [varlist[varname2]] +[join[-]] }}}/>
</$let>
+
title: ExpectedResult
<p>
$:/core-ExpectedResult-Output
</p>

View File

@ -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

View File

@ -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[-]] }}}/>
</$letlist>
```

View File

@ -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.

View File

@ -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[-]] }}}/>
</$letlist>
```
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.

View File

@ -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[-]] }}}/>
</$letlist>
```
! Examples
Consider a case where you need to set multiple variables, where some depend on the evaluation of others.