()
| 289 | } |
| 290 | |
| 291 | private findPrevious() { |
| 292 | const query = this.getQuery(); |
| 293 | if (!query.search) return; |
| 294 | |
| 295 | const { from } = this.view.state.selection.main; |
| 296 | const searchString = this.view.state.doc.toString(); |
| 297 | |
| 298 | try { |
| 299 | let searchPos = from; |
| 300 | |
| 301 | // 创建正则表达式用于搜索 |
| 302 | let regex: RegExp; |
| 303 | const flags = query.caseSensitive ? "g" : "gi"; |
| 304 | const pattern = query.regexp ? query.search : this.escapeRegex(query.search); |
| 305 | |
| 306 | if (query.wholeWord) { |
| 307 | regex = new RegExp(`\\b${pattern}\\b`, flags); |
| 308 | } else { |
| 309 | regex = new RegExp(pattern, flags); |
| 310 | } |
| 311 | |
| 312 | // 从当前位置向后查找 |
| 313 | let lastMatch: { from: number; to: number } | null = null; |
| 314 | let execResult: RegExpExecArray | null; |
| 315 | |
| 316 | while ((execResult = regex.exec(searchString)) !== null) { |
| 317 | if (execResult.index < searchPos) { |
| 318 | lastMatch = { from: execResult.index, to: execResult.index + execResult[0].length }; |
| 319 | } else { |
| 320 | break; |
| 321 | } |
| 322 | } |
| 323 | |
| 324 | if (lastMatch) { |
| 325 | this.view.dispatch({ |
| 326 | selection: { anchor: lastMatch.from, head: lastMatch.to }, |
| 327 | effects: [EditorView.scrollIntoView(lastMatch.from, { x: "nearest", y: "center" })] |
| 328 | }); |
| 329 | } else { |
| 330 | // 循环搜索:如果前面没有匹配项,找到文档中的最后一个匹配项 |
| 331 | regex.lastIndex = 0; |
| 332 | let finalMatch: { from: number; to: number } | null = null; |
| 333 | while ((execResult = regex.exec(searchString)) !== null) { |
| 334 | finalMatch = { from: execResult.index, to: execResult.index + execResult[0].length }; |
| 335 | } |
| 336 | |
| 337 | if (finalMatch) { |
| 338 | this.view.dispatch({ |
| 339 | selection: { anchor: finalMatch.from, head: finalMatch.to }, |
| 340 | effects: [EditorView.scrollIntoView(finalMatch.from, { x: "nearest", y: "center" })] |
| 341 | }); |
| 342 | } |
| 343 | } |
| 344 | } catch (error) { |
| 345 | console.error("Search error:", error); |
| 346 | } |
| 347 | } |
| 348 |
no test coverage detected