1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-06-23 13:53:15 +00:00

Add new "regexp" filter operator

Fixes #762
This commit is contained in:
Jermolene 2014-09-09 15:57:41 +01:00
parent 04a5f7f002
commit f4fff7a330
5 changed files with 100 additions and 19 deletions

View File

@ -0,0 +1,68 @@
/*\
title: $:/core/modules/filters/regexp.js
type: application/javascript
module-type: filteroperator
Filter operator for regexp matching
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.regexp = function(source,operator,options) {
var results = [],
fieldname = (operator.suffix || "title").toLowerCase(),
regexpString, regexp, flags = "", match,
getFieldString = function(tiddler,title) {
if(tiddler) {
return tiddler.getFieldString(fieldname);
} else if(fieldname === "title") {
return title;
} else {
return null;
}
};
// Process flags and construct regexp
regexpString = operator.operand;
match = /^\(\?([gim]+)\)/.exec(regexpString);
if(match) {
flags = match[1];
regexpString = regexpString.substr(match[0].length);
} else {
match = /\(\?([gim]+)\)$/.exec(regexpString);
if(match) {
flags = match[1];
regexpString = regexpString.substr(0,regexpString.length - match[0].length);
}
}
regexp = new RegExp(regexpString,flags);
// Process the incoming tiddlers
if(operator.prefix === "!") {
source(function(tiddler,title) {
var text = getFieldString(tiddler,title);
if(text !== null) {
if(!regexp.exec(text)) {
results.push(title);
}
}
});
} else {
source(function(tiddler,title) {
var text = getFieldString(tiddler,title);
if(text !== null) {
if(!!regexp.exec(text)) {
results.push(title);
}
}
});
}
return results;
};
})();

View File

@ -97,6 +97,14 @@ describe("Filter tests", function() {
expect(wiki.filterTiddlers("[!is[system]!field:modifier[JoeBloggs]]").join(",")).toBe("Tiddler Three,a fourth tiddler,one");
});
it("should handle the regexp operator", function() {
expect(wiki.filterTiddlers("[regexp[id]]").join(",")).toBe("TiddlerOne,$:/TiddlerTwo,Tiddler Three,a fourth tiddler");
expect(wiki.filterTiddlers("[!regexp[id]]").join(",")).toBe("one");
expect(wiki.filterTiddlers("[regexp[Tid]]").join(",")).toBe("TiddlerOne,$:/TiddlerTwo,Tiddler Three");
expect(wiki.filterTiddlers("[regexp[(?i)Tid]]").join(",")).toBe("TiddlerOne,$:/TiddlerTwo,Tiddler Three,a fourth tiddler");
expect(wiki.filterTiddlers("[!regexp[Tid(?i)]]").join(",")).toBe("one");
});
it("should handle the field operator with a regular expression operand", function() {
expect(wiki.filterTiddlers("[modifier/JoeBloggs/]").join(",")).toBe("TiddlerOne");
expect(wiki.filterTiddlers("[modifier/Jo/]").join(",")).toBe("TiddlerOne,$:/TiddlerTwo,Tiddler Three,a fourth tiddler,one");

View File

@ -1,5 +1,5 @@
created: 20140210141217955
modified: 20140725091312363
modified: 20140909134102102
tags: dev
title: TiddlerFilter Formal Grammar
type: text/vnd.tiddlywiki
@ -34,15 +34,7 @@ Whitespace is matched with javascript "\s+", which matches space, tab, carriage
''<opt-operator-suffix>'' ::= ''<string>'' | ""
''&lt;operand&gt;'' ::= "[" ''&lt;search-string&gt;'' "]" | "{" ''&lt;indirect-search-string&gt;'' "}" | "<" ''&lt;variable-name-string&gt;'' ">" | ''&lt;regex&gt;''
''&lt;regex&gt;'' ::= "/" ''&lt;string&gt;'' "/" ''&lt;opt-regex-args&gt;''
''&lt;opt-regex-args&gt;'' ::= "(" ''&lt;regex-args&gt;'' ")" | ""
''&lt;regex-args&gt;'' ::= ''&lt;regex-arg&gt;'' | ''&lt;regex-arg&gt;'' ''&lt;regex-args&gt;''
''&lt;regex-arg&gt;'' ::= "m" | "y" | "g" | "i"
''&lt;operand&gt;'' ::= "[" ''&lt;search-string&gt;'' "]" | "{" ''&lt;indirect-search-string&gt;'' "}" | "<" ''&lt;variable-name-string&gt;'' ">"
''&lt;string&gt;'' ::= ''&lt;string-type-1&gt;'' | ''&lt;string-type-2&gt;'' | ...

View File

@ -0,0 +1,21 @@
created: 20140909134102102
modified: 20140909134102102
tags: filters
title: FilterOperator: regexp
type: text/vnd.tiddlywiki
The ''regexp'' filter operator filters tiddlers that match a regular expression.
Regular expressions are a way of encoding complex string matching criteria. The format is defined fully in [[this Mozilla reference|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions]].
The regexp filter operator takes a fieldname as the optional suffix (defaulting to `title`).
The regular expression itself can start or end with an optional string to specify flags in the format `(?flags)` where flags can be "g", "m" or "i". Only the "i" flag is generally useful: it forces the match to be case-insensitive (ie upper and lower case letters are considered the same).
For example:
|!Filter String |!Description |
|`[all[tiddlers]regexp[EggCup]]` |Selects all tiddlers that have the CamelCase string "EggCup" in their title |
|`[all[tiddlers]regexp[eggcup(?i)]]` |Selects all tiddlers that have the string "eggcup" in their title (ignoring case) |
|`[all[tiddlers]regexp:modified[eggcup(^2014)]]` |Selects all tiddlers that have the string "eggcup" in their title (ignoring case) |

View File

@ -1,5 +1,5 @@
created: 20140410101941871
modified: 20140725103229640
modified: 20140909134102102
tags: introduction
title: Introduction to Filters
type: text/vnd.tiddlywiki
@ -77,14 +77,6 @@ If a filter operator is written with angle brackets around the operand then it i
(Note that the `currentTiddler` variable is used to track the current tiddler).
! Regular Expression Operands
The "field" filter also accepts [[regular expressions|http://en.wikipedia.org/wiki/Regular_expression]] with the syntax `/regexp/(modifier)`. For example:
* `[field:title/example/]`: searches for all tiddlers having "example" in their title
* `[field:title/example$/]`: `$` is an "anchor" for the end of the text so that "example" has to be at the end of the title
* `[field:text/summer|winter/(i)]`: Searches for tiddlers containing "summer" or "winter", ignoring case
! ORing Multiple Filter Operators
You can use multiple filter operations at once. This example selects all tiddlers that are either tagged "introduction" or "demo":