Skip to content

Commit

Permalink
Add support for wildcard patterns
Browse files Browse the repository at this point in the history
  • Loading branch information
wooorm committed Aug 8, 2018
1 parent abd8b03 commit 6cabeaa
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 21 deletions.
20 changes: 11 additions & 9 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ function search(tree, phrases, handler, options) {
var dashes = settings.allowDashes || false
var literals = settings.allowLiterals
var config = {allowApostrophes: apos, allowDashes: dashes}
var byWord = {}
var byWord = {'*': []}
var length
var index
var key
var firstWord

if (!tree || !tree.type) {
throw new Error('Expected node')
Expand Down Expand Up @@ -54,14 +53,15 @@ function search(tree, phrases, handler, options) {
var node = siblings[position]
var count = siblings.length
var queue = [node]
var expression = phrase.split(C_SPACE).slice(1)
var length = expression.length
var expressions = phrase.split(C_SPACE).slice(1)
var length = expressions.length
var index = -1
var expression

/* Move one position forward. */
position++

/* Iterate over `expression`. */
/* Iterate over `expressions`. */
while (++index < length) {
/* Allow joining white-space. */
while (position < count) {
Expand All @@ -76,6 +76,7 @@ function search(tree, phrases, handler, options) {
}

node = siblings[position]
expression = expressions[index]

/* Exit if there are no nodes left, if the
* current node is not a word, or if the
Expand All @@ -84,9 +85,10 @@ function search(tree, phrases, handler, options) {
if (
!node ||
node.type !== T_WORD ||
normalize(expression[index], config) !== normalize(node, config)
(expression !== '*' &&
normalize(expression, config) !== normalize(node, config))
) {
return null
return
}

queue.push(node)
Expand All @@ -109,7 +111,7 @@ function search(tree, phrases, handler, options) {
}

word = normalize(node, config)
phrases = own.call(byWord, word) ? byWord[word] : []
phrases = byWord['*'].concat(own.call(byWord, word) ? byWord[word] : [])
length = phrases.length
index = -1

Expand All @@ -124,7 +126,7 @@ function search(tree, phrases, handler, options) {

/* Handle a phrase. */
function handlePhrase(phrase) {
firstWord = normalize(phrase.split(C_SPACE, 1)[0], config)
var firstWord = normalize(phrase.split(C_SPACE, 1)[0], config)

if (own.call(byWord, firstWord)) {
byWord[firstWord].push(phrase)
Expand Down
12 changes: 7 additions & 5 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# nlcst-search [![Build Status][travis-badge]][travis] [![Coverage Status][codecov-badge]][codecov]

Search for patterns in an [NLCST][nlcst] tree.
Search for patterns in an [NLCST][] tree.

## Installation

Expand Down Expand Up @@ -74,10 +74,12 @@ Tree to search in ([`Node`][node]).
###### `patterns`

Patterns to search for (`Array.<string>` or `Object`).
If an `Object`, uses its keys. Each pattern is a space-delimited list of
words, where each word is [normalize][]d to remove casing, apostrophes,
and dashes. Spaces in a pattern mean zero or more white space nodes in
the tree.
If an `Object`, uses its keys as patterns.
Each pattern is a space-delimited list of words, where each word is
[normalize][]d to remove casing, apostrophes, and dashes.
Spaces in a pattern mean zero or more white space nodes in the tree.
Instead of a word, it’s also possible to use a wildcard symbol (`*`, an
asterisk), that matches any word in a pattern (`alpha * charlie`).

###### `handler`

Expand Down
30 changes: 23 additions & 7 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@ var tree = {
}

test('search(tree, patterns, handle)', function(t) {
t.plan(68)

t.throws(
function() {
search()
Expand Down Expand Up @@ -176,15 +174,15 @@ test('search(tree, patterns, handle)', function(t) {
* is provided the tree contains “hell” but not “he’ll”
* or “he'll”. */
t.throws(function() {
search(tree, ['hell'], null)
search(tree, ['hell'])
}, 'should find non-apostrophe words when `allowApostrophes` is absent')

t.throws(function() {
search(tree, ['he’ll'], null)
search(tree, ['he’ll'])
}, 'should find smart apostrophe words when `allowApostrophes` is absent')

t.throws(function() {
search(tree, ["he'll"], null)
search(tree, ["he'll"])
}, 'should find dumb apostrophe words when `allowApostrophes` is absent')

t.throws(function() {
Expand Down Expand Up @@ -214,11 +212,11 @@ test('search(tree, patterns, handle)', function(t) {
/* The tree contains “selfservice” but not “self-service” */

t.throws(function() {
search(tree, ['selfservice'], null)
search(tree, ['selfservice'])
}, 'should find non-dash words when `allowDashes` is absent and `allowApostrophes` is absent')

t.throws(function() {
search(tree, ['self-service'], null)
search(tree, ['self-service'])
}, 'should find dash words when `allowDashes` is absent and `allowApostrophes` is absent')

t.throws(function() {
Expand Down Expand Up @@ -309,6 +307,22 @@ test('search(tree, patterns, handle)', function(t) {
})
}, 'should find dash words when `allowDashes` is false and `allowApostrophes` is true')

t.throws(function() {
search(tree, ['this * selfservice'])
}, 'should support wild cards (#1)')

t.doesNotThrow(function() {
search(tree, ['that * selfservice'])
}, 'should support wild cards (#2)')

t.throws(function() {
search(tree, ['* selfservice'])
}, 'should support wild cards (#3)')

t.doesNotThrow(function() {
search(tree, ['* zelfzervice'])
}, 'should support wild cards (#4)')

t.doesNotThrow(function() {
search(tree, ['mellow'])
}, 'shouldn’t find literals by default')
Expand All @@ -321,4 +335,6 @@ test('search(tree, patterns, handle)', function(t) {
},
{allowLiterals: true}
)

t.end()
})

0 comments on commit 6cabeaa

Please sign in to comment.