generated from obsidianmd/obsidian-sample-plugin
-
-
Notifications
You must be signed in to change notification settings - Fork 220
/
BooleanDelimiters.ts
60 lines (49 loc) · 2.44 KB
/
BooleanDelimiters.ts
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
export function anyOfTheseChars(allowedChars: string): string {
return new RegExp('[' + allowedChars + ']').source;
}
/**
* A class to try to identify the type of delimiter used between Boolean operators.
*
* Note that this only checks the first and last non-operator characters on the line,
* so where there is more than one binary operator, it is still possible for the user
* to mix delimiters, and for the error to not be detected until later in the parsing process.
*/
export class BooleanDelimiters {
public readonly openFilterChars;
public readonly openFilter;
public readonly closeFilterChars;
public readonly closeFilter;
public readonly openAndCloseFilterChars;
private constructor(openFilterChars: string, closeFilterChars: string, openAndCloseFilterChars: string) {
this.openFilterChars = openFilterChars;
this.closeFilterChars = closeFilterChars;
this.openAndCloseFilterChars = openAndCloseFilterChars;
this.openFilter = anyOfTheseChars(this.openFilterChars);
this.closeFilter = anyOfTheseChars(this.closeFilterChars);
}
public static allSupportedDelimiters(): BooleanDelimiters {
return new BooleanDelimiters('("', ')"', '()"');
}
public static fromInstructionLine(instruction: string) {
const trimmedInstruction = instruction.trim();
// We use a set of capitals and spaces as a short-cut to match AND, OR, NOT, AND NOT etc.
// The only valid initial operator is NOT, so this may be worth tightening up, if
// further tests show that it would be worthwhile.
const findAnyInitialUnaryOperator = /^[A-Z ]*\s*(.*)/;
const matches = findAnyInitialUnaryOperator.exec(trimmedInstruction);
if (matches) {
const instructionWithoutAnyLeadingOperators = matches[1];
const firstChar = instructionWithoutAnyLeadingOperators[0];
const lastChar = instructionWithoutAnyLeadingOperators.slice(-1);
if (firstChar === '(' && lastChar === ')') {
return new BooleanDelimiters('(', ')', '()');
}
if (firstChar === '"' && lastChar === '"') {
return new BooleanDelimiters('"', '"', '"');
}
}
throw new Error(
'All filters in a Boolean instruction must be inside one of these pairs of delimiter characters: (...) or "...". Combinations of those delimiters are no longer supported.',
);
}
}