Repository: TiddlyWiki/TiddlyWiki5 (JavaScript)

Issue:
[IDEA] provide index, revIndex and length variables in :map prefix
In the `:map` filter run prefix, we should provide access to `index`, `revIndex` and `length` variables as we already do in the `:reduce` filter run prefix.

Finding myself using `:reduce` even when `:map` would be more appropriate, as I need the `index` variable.


Discussion:
Thanks @saqimtiaz, I hadn't noticed the omission, but definitely worth fixing.
It is my own oversight when adding the `:map` prefix. Created an issue so I remember this for when I have the time to create a PR.



Patch:
diff --git a/core/modules/filterrunprefixes/map.js b/core/modules/filterrunprefixes/map.js
index a70f6b0f4a3..a47763c116a 100644
--- a/core/modules/filterrunprefixes/map.js
+++ b/core/modules/filterrunprefixes/map.js
@@ -15,7 +15,8 @@ Export our filter prefix function
 exports.map = function(operationSubFunction,options) {
 	return function(results,source,widget) {
 		if(results.length > 0) {
-			var inputTitles = results.toArray();
+			var inputTitles = results.toArray(),
+				index = 0;
 			results.clear();
 			$tw.utils.each(inputTitles,function(title) {
 				var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{
@@ -25,12 +26,19 @@ exports.map = function(operationSubFunction,options) {
 								return "" + title;
 							case "..currentTiddler":
 								return widget.getVariable("currentTiddler");
+							case "index":
+								return "" + index;
+							case "revIndex":
+								return "" +  (inputTitles.length - 1 - index);
+							case "length":
+								return "" + inputTitles.length;
 							default:
 								return widget.getVariable(name);
 						}
 					}
 				});
 				results.push(filtered[0] || "");
+				++index;
 			});
 		}
 	}
diff --git a/editions/tw5.com/tiddlers/filters/syntax/Map Filter Run Prefix (Examples).tid b/editions/tw5.com/tiddlers/filters/syntax/Map Filter Run Prefix (Examples).tid
index b7ade6b3860..d84ef4897dd 100644
--- a/editions/tw5.com/tiddlers/filters/syntax/Map Filter Run Prefix (Examples).tid
+++ b/editions/tw5.com/tiddlers/filters/syntax/Map Filter Run Prefix (Examples).tid
@@ -1,5 +1,5 @@
 created: 20210618134753828
-modified: 20210618140945870
+modified: 20211029082538212
 tags: [[Filter Syntax]] [[Filter Run Prefix Examples]] [[Map Filter Run Prefix]]
 title: Map Filter Run Prefix (Examples)
 type: text/vnd.tiddlywiki
@@ -14,3 +14,6 @@ Replace the input titles with the caption field if it exists, otherwise preserve
 For each title in a shopping list, calculate the total cost of purchasing each item:
 
 <<.operator-example 2 "[tag[shopping]] :map[get[quantity]else[0]multiply{!!price}]">>
+
+For each title in a shopping list, prefix it with its position in the list:
+<<.operator-example 2 "[tag[shopping]] :map[<currentTiddler>addprefix[-]addprefix<index>]">>
\ No newline at end of file
diff --git a/editions/tw5.com/tiddlers/filters/syntax/Map Filter Run Prefix.tid b/editions/tw5.com/tiddlers/filters/syntax/Map Filter Run Prefix.tid
index a2f09bc3a14..30282e1caae 100644
--- a/editions/tw5.com/tiddlers/filters/syntax/Map Filter Run Prefix.tid
+++ b/editions/tw5.com/tiddlers/filters/syntax/Map Filter Run Prefix.tid
@@ -1,5 +1,5 @@
 created: 20210618133745003
-modified: 20210618134747652
+modified: 20211029025541750
 tags: [[Filter Syntax]] [[Filter Run Prefix]]
 title: Map Filter Run Prefix
 type: text/vnd.tiddlywiki
@@ -14,6 +14,14 @@ Each input title from previous runs is passed to this run in turn. The filter ru
 
 Note that within the filter run, the "currentTiddler" variable is set to the title of the tiddler being processed. This permits filter runs like `:map[{!!price}multiply{!!cost}]` to be used for computation. The value of currentTiddler outside the run is available in the variable "..currentTiddler".
 
+The following variables are available within the filter run:
+
+* ''currentTiddler'' - the input title
+* ''..currentTiddler'' - the value of the variable `currentTiddler` outside the filter run.
+* ''index'' - <<.from-version "5.2.1">> the numeric index of the current list item (with zero being the first item in the list).
+* ''revIndex'' - <<.from-version "5.2.1">> the reverse numeric index of the current list item (with zero being the last item in the list).
+* ''length'' - <<.from-version "5.2.1">> the total length of the input list.
+
 Filter runs used with the `:map` prefix should return the same number of items that they are passed. Any missing entries will be treated as an empty string. In particular, when retrieving the value of a field with the [[get Operator]] it is helpful to guard against a missing field value using the [[else Operator]]. For example `[get[myfield]else[default-value]...`.
 
 [[Examples|Map Filter Run Prefix (Examples)]]
\ No newline at end of file


Test patch:
diff --git a/editions/test/tiddlers/tests/test-prefixes-filter.js b/editions/test/tiddlers/tests/test-prefixes-filter.js
index c43ee697688..e6c418d84f9 100644
--- a/editions/test/tiddlers/tests/test-prefixes-filter.js
+++ b/editions/test/tiddlers/tests/test-prefixes-filter.js
@@ -384,6 +384,8 @@ describe("'reduce' and 'intersection' filter prefix tests", function() {
 		expect(wiki.filterTiddlers("[tag[shopping]] :map[get[description]else{!!title}]").join(",")).toBe("A square of rich chocolate cake,a round yellow seed,Milk,Rice Pudding");
 		// Return the first title from :map if the filter returns more than one result
 		expect(wiki.filterTiddlers("[tag[shopping]] :map[tags[]]").join(",")).toBe("shopping,shopping,shopping,shopping");
+		// Prepend the position in the list using the index and length variables
+		expect(wiki.filterTiddlers("[tag[shopping]] :map[get[title]addprefix[-]addprefix<length>addprefix[of]addprefix<index>]").join(",")).toBe("0of4-Brownies,1of4-Chick Peas,2of4-Milk,3of4-Rice Pudding");
 	});
 });