@@ -9,28 +9,34 @@ import { EditorPosition } from "obsidian";
9
9
* Under the hood, to avoid repeated loops of the document: we get all matches at once, order them
10
10
* according to `direction` and `cursorPosition`, and use modulo arithmetic to return the
11
11
* appropriate match.
12
+ *
13
+ * @param cm The CodeMirror editor instance.
14
+ * @param cursorPosition The current cursor position.
15
+ * @param repeat The number of times to repeat the jump (e.g. 1 to jump to the very next match). Is
16
+ * modulo-ed for efficiency.
17
+ * @param regex The regex pattern to jump to.
18
+ * @param filterMatch Optional filter function to run on the regex matches. Return false to ignore
19
+ * a given match.
20
+ * @param direction The direction to jump in.
12
21
*/
13
22
export function jumpToPattern ( {
14
23
cm,
15
24
cursorPosition,
16
25
repeat,
17
26
regex,
27
+ filterMatch = ( ) => true ,
18
28
direction,
19
29
} : {
20
30
cm : CodeMirrorEditor ;
21
31
cursorPosition : EditorPosition ;
22
32
repeat : number ;
23
33
regex : RegExp ;
34
+ filterMatch ?: ( match : RegExpExecArray ) => boolean ;
24
35
direction : "next" | "previous" ;
25
36
} ) : EditorPosition {
26
37
const content = cm . getValue ( ) ;
27
38
const cursorIdx = cm . indexFromPos ( cursorPosition ) ;
28
- const orderedMatches = getOrderedMatches ( {
29
- content,
30
- regex,
31
- cursorIdx,
32
- direction,
33
- } ) ;
39
+ const orderedMatches = getOrderedMatches ( { content, regex, cursorIdx, filterMatch, direction } ) ;
34
40
const effectiveRepeat = ( repeat % orderedMatches . length ) || orderedMatches . length ;
35
41
const matchIdx = orderedMatches [ effectiveRepeat - 1 ] ?. index ;
36
42
if ( matchIdx === undefined ) {
@@ -48,17 +54,20 @@ function getOrderedMatches({
48
54
content,
49
55
regex,
50
56
cursorIdx,
57
+ filterMatch,
51
58
direction,
52
59
} : {
53
60
content : string ;
54
61
regex : RegExp ;
55
62
cursorIdx : number ;
63
+ filterMatch : ( match : RegExpExecArray ) => boolean ;
56
64
direction : "next" | "previous" ;
57
65
} ) : RegExpExecArray [ ] {
58
66
const { previousMatches, currentMatches, nextMatches } = getAndGroupMatches (
59
67
content ,
60
68
regex ,
61
- cursorIdx
69
+ cursorIdx ,
70
+ filterMatch
62
71
) ;
63
72
if ( direction === "next" ) {
64
73
return [ ...nextMatches , ...previousMatches , ...currentMatches ] ;
@@ -77,20 +86,19 @@ function getOrderedMatches({
77
86
function getAndGroupMatches (
78
87
content : string ,
79
88
regex : RegExp ,
80
- cursorIdx : number
89
+ cursorIdx : number ,
90
+ filterMatch : ( match : RegExpExecArray ) => boolean
81
91
) : {
82
92
previousMatches : RegExpExecArray [ ] ;
83
93
currentMatches : RegExpExecArray [ ] ;
84
94
nextMatches : RegExpExecArray [ ] ;
85
95
} {
86
96
const globalRegex = makeGlobalRegex ( regex ) ;
87
- const allMatches = [ ...content . matchAll ( globalRegex ) ] ;
97
+ const allMatches = [ ...content . matchAll ( globalRegex ) ] . filter ( filterMatch ) ;
88
98
const previousMatches = allMatches . filter (
89
- ( match ) => match . index < cursorIdx && ! isCursorOnMatch ( match , cursorIdx )
90
- ) ;
91
- const currentMatches = allMatches . filter ( ( match ) =>
92
- isCursorOnMatch ( match , cursorIdx )
99
+ ( match ) => match . index < cursorIdx && ! isWithinMatch ( match , cursorIdx )
93
100
) ;
101
+ const currentMatches = allMatches . filter ( ( match ) => isWithinMatch ( match , cursorIdx ) ) ;
94
102
const nextMatches = allMatches . filter ( ( match ) => match . index > cursorIdx ) ;
95
103
return { previousMatches, currentMatches, nextMatches } ;
96
104
}
@@ -105,6 +113,6 @@ function getGlobalFlags(regex: RegExp): string {
105
113
return flags . includes ( "g" ) ? flags : `${ flags } g` ;
106
114
}
107
115
108
- function isCursorOnMatch ( match : RegExpExecArray , cursorIdx : number ) : boolean {
109
- return match . index <= cursorIdx && cursorIdx < match . index + match [ 0 ] . length ;
116
+ export function isWithinMatch ( match : RegExpExecArray , index : number ) : boolean {
117
+ return match . index <= index && index < match . index + match [ 0 ] . length ;
110
118
}
0 commit comments