-
Notifications
You must be signed in to change notification settings - Fork 29
Expand file tree
/
Copy pathquery.ts
More file actions
67 lines (57 loc) · 1.93 KB
/
Copy pathquery.ts
File metadata and controls
67 lines (57 loc) · 1.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
type Query = {
text: string
position: number
}
type QueryOptions = {
lookBackIndex: number
multiWord: boolean
lastMatchPosition: number | null
}
const boundary = /\s|\(|\[/
// Extracts a keyword from the source text, backtracking from the cursor position.
export default function query(
text: string,
key: string,
cursor: number,
{multiWord, lookBackIndex, lastMatchPosition}: QueryOptions = {
multiWord: false,
lookBackIndex: 0,
lastMatchPosition: null
}
): Query | void {
// Activation key not found in front of the cursor.
let keyIndex = text.lastIndexOf(key, cursor - 1)
if (keyIndex === -1) return
// Stop matching at the lookBackIndex
if (keyIndex < lookBackIndex) return
if (multiWord) {
if (lastMatchPosition != null) {
// If the current activation key is the same as last match
// i.e. consecutive activation keys, then return.
if (lastMatchPosition === keyIndex) return
keyIndex = lastMatchPosition - key.length
}
// Space immediately after activation key followed by the cursor
const charAfterKey = text[keyIndex + 1]
if (charAfterKey === ' ' && cursor >= keyIndex + key.length + 1) return
// New line the cursor and previous activation key.
const newLineIndex = text.lastIndexOf('\n', cursor - 1)
if (newLineIndex > keyIndex) return
// Dot between the cursor and previous activation key.
const dotIndex = text.lastIndexOf('.', cursor - 1)
if (dotIndex > keyIndex) return
} else {
// Space between the cursor and previous activation key.
const spaceIndex = text.lastIndexOf(' ', cursor - 1)
if (spaceIndex > keyIndex) return
}
// Activation key must occur at word boundary.
const pre = text[keyIndex - 1]
if (pre && !boundary.test(pre)) return
// Extract matched keyword.
const queryString = text.substring(keyIndex + key.length, cursor)
return {
text: queryString,
position: keyIndex + key.length
}
}