mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-11-23 10:07:19 +00:00
Add numeric maths filter operators
There are other ways we could add maths to TW5 (including @EvanBalster's awesome https://github.com/EvanBalster/TiddlyWikiFormula) but the approach here has the merit of simplicity because it reuses the existing filter evaluation mechanism. That means that it's not ordinary "2+2" maths, it's a unique list processing language... Docs to come Fixes #254
This commit is contained in:
parent
5e9fc661a9
commit
0ea00b59b0
130
core/modules/filters/math.js
Normal file
130
core/modules/filters/math.js
Normal file
@ -0,0 +1,130 @@
|
||||
/*\
|
||||
title: $:/core/modules/filters/math.js
|
||||
type: application/javascript
|
||||
module-type: filteroperator
|
||||
|
||||
Filter operators for math. Unary/binary operators work on each item in turn, and return a new item list.
|
||||
|
||||
Sum/product/maxall/minall operate on the entire list, returning a single item.
|
||||
|
||||
Note that strings are converted to numbers automatically. Trailing non-digits are ignored.
|
||||
|
||||
* "" converts to 0
|
||||
* "12kk" converts to 12
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.negate = makeNumericBinaryOperator(
|
||||
function(a) {return -a}
|
||||
);
|
||||
|
||||
exports.abs = makeNumericBinaryOperator(
|
||||
function(a) {return Math.abs(a)}
|
||||
);
|
||||
|
||||
exports.ceil = makeNumericBinaryOperator(
|
||||
function(a) {return Math.ceil(a)}
|
||||
);
|
||||
|
||||
exports.floor = makeNumericBinaryOperator(
|
||||
function(a) {return Math.floor(a)}
|
||||
);
|
||||
|
||||
exports.round = makeNumericBinaryOperator(
|
||||
function(a) {return Math.round(a)}
|
||||
);
|
||||
|
||||
exports.trunc = makeNumericBinaryOperator(
|
||||
function(a) {return Math.trunc(a)}
|
||||
);
|
||||
|
||||
exports.sign = makeNumericBinaryOperator(
|
||||
function(a) {return Math.sign(a)}
|
||||
);
|
||||
|
||||
exports.add = makeNumericBinaryOperator(
|
||||
function(a,b) {return a + b;}
|
||||
);
|
||||
|
||||
exports.subtract = makeNumericBinaryOperator(
|
||||
function(a,b) {return a - b;}
|
||||
);
|
||||
|
||||
exports.multiply = makeNumericBinaryOperator(
|
||||
function(a,b) {return a * b;}
|
||||
);
|
||||
|
||||
exports.divide = makeNumericBinaryOperator(
|
||||
function(a,b) {return a / b;}
|
||||
);
|
||||
|
||||
exports.remainder = makeNumericBinaryOperator(
|
||||
function(a,b) {return a % b;}
|
||||
);
|
||||
|
||||
exports.max = makeNumericBinaryOperator(
|
||||
function(a,b) {return Math.max(a,b);}
|
||||
);
|
||||
|
||||
exports.min = makeNumericBinaryOperator(
|
||||
function(a,b) {return Math.min(a,b);}
|
||||
);
|
||||
|
||||
exports.sum = makeNumericArrayOperator(
|
||||
function(accumulator,value) {return accumulator + value},
|
||||
0 // Initial value
|
||||
);
|
||||
|
||||
exports.product = makeNumericArrayOperator(
|
||||
function(accumulator,value) {return accumulator * value},
|
||||
1 // Initial value
|
||||
);
|
||||
|
||||
exports.maxall = makeNumericArrayOperator(
|
||||
function(accumulator,value) {return Math.max(accumulator,value)},
|
||||
-Infinity // Initial value
|
||||
);
|
||||
|
||||
exports.minall = makeNumericArrayOperator(
|
||||
function(accumulator,value) {return Math.min(accumulator,value)},
|
||||
Infinity // Initial value
|
||||
);
|
||||
|
||||
function makeNumericBinaryOperator(fnCalc) {
|
||||
return function(source,operator,options) {
|
||||
var result = [],
|
||||
numOperand = parseNumber(operator.operand);
|
||||
source(function(tiddler,title) {
|
||||
result.push(stringifyNumber(fnCalc(parseNumber(title),numOperand)));
|
||||
});
|
||||
return result;
|
||||
};
|
||||
};
|
||||
|
||||
function makeNumericArrayOperator(fnCalc,initialValue) {
|
||||
initialValue = initialValue || 0;
|
||||
return function(source,operator,options) {
|
||||
var result = [];
|
||||
source(function(tiddler,title) {
|
||||
result.push(title);
|
||||
});
|
||||
return [stringifyNumber(result.reduce(function(accumulator,currentValue) {
|
||||
return fnCalc(accumulator,parseNumber(currentValue));
|
||||
},initialValue))];
|
||||
};
|
||||
};
|
||||
|
||||
function parseNumber(str) {
|
||||
return parseFloat(str) || 0;
|
||||
}
|
||||
|
||||
function stringifyNumber(num) {
|
||||
return num + "";
|
||||
}
|
||||
|
||||
})();
|
@ -361,6 +361,20 @@ describe("Filter tests", function() {
|
||||
expect(wiki.filterTiddlers("[list[TiddlerSeventh]before[MissingTiddler]]").join(",")).toBe("a fourth tiddler");
|
||||
});
|
||||
|
||||
it("should handle the math operators", function() {
|
||||
expect(wiki.filterTiddlers("[[2]add[2]]").join(",")).toBe("4");
|
||||
expect(wiki.filterTiddlers("[[4]subtract[2]]").join(",")).toBe("2");
|
||||
expect(wiki.filterTiddlers("[[24]divide[8]]").join(",")).toBe("3");
|
||||
expect(wiki.filterTiddlers("[[355]divide[113]sign[]multiply[4]]").join(",")).toBe("4");
|
||||
expect(wiki.filterTiddlers("[[355]divide[113]add[0.5]round[]multiply[4]]").join(",")).toBe("16");
|
||||
expect(wiki.filterTiddlers("1 2 3 4 +[sum[]]").join(",")).toBe("10");
|
||||
expect(wiki.filterTiddlers("1 2 3 4 +[product[]]").join(",")).toBe("24");
|
||||
expect(wiki.filterTiddlers("1 2 3 4 +[maxall[]]").join(",")).toBe("4");
|
||||
expect(wiki.filterTiddlers("1 2 3 4 +[minall[]]").join(",")).toBe("1");
|
||||
expect(wiki.filterTiddlers("1 2 3 4 +[max[2]]").join(",")).toBe("2,2,3,4");
|
||||
expect(wiki.filterTiddlers("1 2 3 4 +[min[2]]").join(",")).toBe("1,2,2,2");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user