()
| 241 | } |
| 242 | |
| 243 | private findNext() { |
| 244 | const query = this.getQuery(); |
| 245 | if (!query.search) return; |
| 246 | |
| 247 | const { to } = this.view.state.selection.main; |
| 248 | const searchString = this.view.state.doc.toString(); |
| 249 | |
| 250 | try { |
| 251 | let searchPos = to; |
| 252 | let match: { from: number; to: number } | null = null; |
| 253 | |
| 254 | // 创建正则表达式用于搜索 |
| 255 | let regex: RegExp; |
| 256 | const flags = query.caseSensitive ? "g" : "gi"; |
| 257 | const pattern = query.regexp ? query.search : this.escapeRegex(query.search); |
| 258 | |
| 259 | if (query.wholeWord) { |
| 260 | regex = new RegExp(`\\b${pattern}\\b`, flags); |
| 261 | } else { |
| 262 | regex = new RegExp(pattern, flags); |
| 263 | } |
| 264 | |
| 265 | // 从当前位置开始查找 |
| 266 | regex.lastIndex = searchPos; |
| 267 | let execResult = regex.exec(searchString); |
| 268 | |
| 269 | if (execResult) { |
| 270 | match = { from: execResult.index, to: execResult.index + execResult[0].length }; |
| 271 | } else { |
| 272 | // 如果没找到,从头开始搜索 |
| 273 | regex.lastIndex = 0; |
| 274 | execResult = regex.exec(searchString); |
| 275 | if (execResult) { |
| 276 | match = { from: execResult.index, to: execResult.index + execResult[0].length }; |
| 277 | } |
| 278 | } |
| 279 | |
| 280 | if (match) { |
| 281 | this.view.dispatch({ |
| 282 | selection: { anchor: match.from, head: match.to }, |
| 283 | effects: [EditorView.scrollIntoView(match.from, { x: "nearest", y: "center" })] |
| 284 | }); |
| 285 | } |
| 286 | } catch (error) { |
| 287 | console.error("Search error:", error); |
| 288 | } |
| 289 | } |
| 290 | |
| 291 | private findPrevious() { |
| 292 | const query = this.getQuery(); |
no test coverage detected