From 6b4e5c74ad34d006266afb56f48f611b06555bc3 Mon Sep 17 00:00:00 2001 From: Mario Pietsch Date: Mon, 21 Feb 2022 16:05:34 +0100 Subject: [PATCH] Add "some" flag to search operator (#6293) --- core/modules/filters/search.js | 1 + core/modules/wiki.js | 24 ++++++++++-- editions/test/tiddlers/tests/test-filters.js | 37 ++++++++++++++++++- .../tiddlers/filters/examples/search.tid | 7 +++- editions/tw5.com/tiddlers/filters/search.tid | 19 +++++----- 5 files changed, 72 insertions(+), 16 deletions(-) diff --git a/core/modules/filters/search.js b/core/modules/filters/search.js index adcb076a0..dcb534c07 100644 --- a/core/modules/filters/search.js +++ b/core/modules/filters/search.js @@ -40,6 +40,7 @@ exports.search = function(source,operator,options) { invert: invert, field: fields, excludeField: excludeFields, + some: hasFlag("some"), caseSensitive: hasFlag("casesensitive"), literal: hasFlag("literal"), whitespace: hasFlag("whitespace"), diff --git a/core/modules/wiki.js b/core/modules/wiki.js index a784a5d43..99abe6b47 100755 --- a/core/modules/wiki.js +++ b/core/modules/wiki.js @@ -1201,23 +1201,28 @@ Return an array of tiddler titles that match a search string text: The text string to search for options: see below Options available: - source: an iterator function for the source tiddlers, called source(iterator), where iterator is called as iterator(tiddler,title) + source: an iterator function for the source tiddlers, called source(iterator), + where iterator is called as iterator(tiddler,title) exclude: An array of tiddler titles to exclude from the search invert: If true returns tiddlers that do not contain the specified string caseSensitive: If true forces a case sensitive search field: If specified, restricts the search to the specified field, or an array of field names anchored: If true, forces all but regexp searches to be anchored to the start of text excludeField: If true, the field options are inverted to specify the fields that are not to be searched + The search mode is determined by the first of these boolean flags to be true literal: searches for literal string whitespace: same as literal except runs of whitespace are treated as a single space regexp: treats the search term as a regular expression - words: (default) treats search string as a list of tokens, and matches if all tokens are found, regardless of adjacency or ordering + words: (default) treats search string as a list of tokens, and matches if all tokens are found, + regardless of adjacency or ordering + some: treats search string as a list of tokens, and matches if at least ONE token is found */ exports.search = function(text,options) { options = options || {}; var self = this, t, + regExpStr="", invert = !!options.invert; // Convert the search string into a regexp for each term var terms, searchTermsRegExps, @@ -1244,7 +1249,18 @@ exports.search = function(text,options) { searchTermsRegExps = null; console.log("Regexp error parsing /(" + text + ")/" + flags + ": ",e); } - } else { + } else if(options.some) { + terms = text.trim().split(/ +/); + if(terms.length === 1 && terms[0] === "") { + searchTermsRegExps = null; + } else { + searchTermsRegExps = []; + for(t=0; t <$macrocall $name=".operator-example" n="8" eg="[!is[system]search::literal,casesensitive[The first]]" ie="non-system tiddlers containing a case-sensitive match for the literal phrase <<.word 'The first'>>"/> <$macrocall $name=".operator-example" n="9" eg="[search:caption,description:casesensitive,words[arch]]" ie="any tiddlers containing a case-sensitive match for the word `arch` in their <<.field caption>> or <<.field description>> fields"/> +<$macrocall $name=".operator-example" n="10" eg="[search:tags:some[how test]]" ie="any tiddlers containing at least 1 of the search terms in the field: <<.field tags>>"/> +<$macrocall $name=".operator-example" n="11" eg="[search:tags:some,casesensitive[how test]]" ie="any tiddlers containing at least 1 of the case-sensitive search terms in the field: <<.field tags>>"/> +<$macrocall $name=".operator-example" n="12" eg="[search:tags,title:some,anchored[how test]]" ie="any tiddlers containing at least 1 of anchored search terms in the fields: <<.field tags>> and <<.field title>>"/> + + diff --git a/editions/tw5.com/tiddlers/filters/search.tid b/editions/tw5.com/tiddlers/filters/search.tid index 3aba89bf1..94d9d3222 100644 --- a/editions/tw5.com/tiddlers/filters/search.tid +++ b/editions/tw5.com/tiddlers/filters/search.tid @@ -1,15 +1,15 @@ +caption: search created: 20140410103123179 -modified: 20190731212738712 +modified: 20211129120739275 +op-input: a [[selection of titles|Title Selection]] +op-neg-output: those input tiddlers in which <<.em not>> all of the search terms can be found +op-output: those input tiddlers in which <<.em all>> of the search terms can be found in the value of field <<.place F>> +op-parameter: one or more search terms, separated by spaces, or a literal search string +op-purpose: filter the input by searching tiddler content +op-suffix: the <<.op search>> operator uses a rich suffix, see below for details tags: [[Filter Operators]] [[Common Operators]] [[Field Operators]] [[Negatable Operators]] title: search Operator type: text/vnd.tiddlywiki -caption: search -op-purpose: filter the input by searching tiddler content -op-input: a [[selection of titles|Title Selection]] -op-suffix: the <<.op search>> operator uses a rich suffix, see below for details -op-parameter: one or more search terms, separated by spaces, or a literal search string -op-output: those input tiddlers in which <<.em all>> of the search terms can be found in the value of field <<.place F>> -op-neg-output: those input tiddlers in which <<.em not>> all of the search terms can be found <<.from-version "5.1.18">> The search filter operator was significantly enhanced in 5.1.18. Earlier versions do not support the extended syntax and therefore do not permit searching multiple fields, or the ''literal'' or ''casesensitive'' options. @@ -38,7 +38,8 @@ The available flags are: ** ''literal'': considers the search string to be a literal string, and requires an exact match ** ''whitespace'': considers the search string to be a literal string, but will consider all runs of whitespace to be equivalent to a single space. Thus `A B` matches `A B` ** ''regexp'': treats the search string as a regular expression. Note that the ''regexp'' option obviates the need for the older <<.olink regexp>> operator. -** ''words'': (the default) treats the search string as a list of tokens separated by whitespace, and matches if all of the tokens appear in the string (regardless of ordering and whether there is other text in between) +** ''words'': (the default) treats the search string as a list of tokens separated by whitespace, and matches if ''all of the tokens'' appear in the string (regardless of ordering and whether there is other text in between) +** ''some'': <<.from-version "5.2.1">> treats the search string as a list of tokens separated by whitespace, and matches if ''at least one'' of the tokens appear in the string * ''casesensitive'': if present, this flag forces a case-sensitive match, where upper and lower case letters are considered different. By default, upper and lower case letters are considered identical for matching purposes. * ''anchored'': <<.from-version "5.1.20">> anchors the search to the start of the string (applies to ''whitespace'', ''literal'' and ''words'' modes)