|
8 | 8 | // document. |
9 | 9 | // |
10 | 10 | // The option can be set to true to simply enable it, or to a |
11 | | -// {minChars, style, showToken} object to explicitly configure it. |
12 | | -// minChars is the minimum amount of characters that should be |
| 11 | +// {minChars, style, wordsOnly, showToken, delay} object to explicitly |
| 12 | +// configure it. minChars is the minimum amount of characters that should be |
13 | 13 | // selected for the behavior to occur, and style is the token style to |
14 | 14 | // apply to the matches. This will be prefixed by "cm-" to create an |
15 | | -// actual CSS class name. showToken, when enabled, will cause the |
16 | | -// current token to be highlighted when nothing is selected. |
| 15 | +// actual CSS class name. If wordsOnly is enabled, the matches will be |
| 16 | +// highlighted only if the selected text is a word. showToken, when enabled, |
| 17 | +// will cause the current token to be highlighted when nothing is selected. |
| 18 | +// delay is used to specify how much time to wait, in milliseconds, before |
| 19 | +// highlighting the matches. |
17 | 20 |
|
18 | 21 | (function(mod) { |
19 | 22 | if (typeof exports == "object" && typeof module == "object") // CommonJS |
|
28 | 31 | var DEFAULT_MIN_CHARS = 2; |
29 | 32 | var DEFAULT_TOKEN_STYLE = "matchhighlight"; |
30 | 33 | var DEFAULT_DELAY = 100; |
| 34 | + var DEFAULT_WORDS_ONLY = false; |
31 | 35 |
|
32 | 36 | function State(options) { |
33 | 37 | if (typeof options == "object") { |
34 | 38 | this.minChars = options.minChars; |
35 | 39 | this.style = options.style; |
36 | 40 | this.showToken = options.showToken; |
37 | 41 | this.delay = options.delay; |
| 42 | + this.wordsOnly = options.wordsOnly; |
38 | 43 | } |
39 | 44 | if (this.style == null) this.style = DEFAULT_TOKEN_STYLE; |
40 | 45 | if (this.minChars == null) this.minChars = DEFAULT_MIN_CHARS; |
41 | 46 | if (this.delay == null) this.delay = DEFAULT_DELAY; |
| 47 | + if (this.wordsOnly == null) this.wordsOnly = DEFAULT_WORDS_ONLY; |
42 | 48 | this.overlay = this.timeout = null; |
43 | 49 | } |
44 | 50 |
|
|
81 | 87 | } |
82 | 88 | var from = cm.getCursor("from"), to = cm.getCursor("to"); |
83 | 89 | if (from.line != to.line) return; |
| 90 | + if (state.wordsOnly && !isWord(cm, from, to)) return; |
84 | 91 | var selection = cm.getRange(from, to).replace(/^\s+|\s+$/g, ""); |
85 | 92 | if (selection.length >= state.minChars) |
86 | 93 | cm.addOverlay(state.overlay = makeOverlay(selection, false, state.style)); |
87 | 94 | }); |
88 | 95 | } |
89 | 96 |
|
| 97 | + function isWord(cm, from, to) { |
| 98 | + var str = cm.getRange(from, to); |
| 99 | + if (str.match(/^\w+$/) !== null) { |
| 100 | + if (from.ch > 0) { |
| 101 | + var pos = {line: from.line, ch: from.ch - 1}; |
| 102 | + var chr = cm.getRange(pos, from); |
| 103 | + if (chr.match(/\W/) === null) return false; |
| 104 | + } |
| 105 | + if (to.ch < cm.getLine(from.line).length) { |
| 106 | + var pos = {line: to.line, ch: to.ch + 1}; |
| 107 | + var chr = cm.getRange(to, pos); |
| 108 | + if (chr.match(/\W/) === null) return false; |
| 109 | + } |
| 110 | + return true; |
| 111 | + } else return false; |
| 112 | + } |
| 113 | + |
90 | 114 | function boundariesAround(stream, re) { |
91 | 115 | return (!stream.start || !re.test(stream.string.charAt(stream.start - 1))) && |
92 | 116 | (stream.pos == stream.string.length || !re.test(stream.string.charAt(stream.pos))); |
|
0 commit comments