@@ -177,7 +177,7 @@ extension FindViewController: FindPanelDelegate {
177177 let range = emphasizeAPI. emphasizedRanges [ activeIndex] . range
178178 textViewController. textView. scrollToRange ( range)
179179 textViewController. setCursorPositions ( [ CursorPosition ( range: range) ] )
180-
180+
181181 // Show bezel notification if we cycled from last to first match
182182 if previousIndex == emphasizeAPI. emphasizedRanges. count - 1 && activeIndex == 0 {
183183 BezelNotification . show (
@@ -324,10 +324,8 @@ extension FindViewController: FindPanelDelegate {
324324 let searchResults = matches. map { $0. range }
325325 findPanel. searchDelegate? . findPanelUpdateMatchCount ( searchResults. count)
326326
327- // If we have an active highlight and the same number of matches, try to preserve the active index
328- let currentActiveIndex = target. emphasizeAPI? . emphasizedRangeIndex ?? 0
329- let activeIndex = ( target. emphasizeAPI? . emphasizedRanges. count == searchResults. count) ?
330- currentActiveIndex : 0
327+ // Get the nearest match to either the cursor or visible area
328+ let activeIndex = getNearestHighlightIndex ( matchRanges: searchResults) ?? 0
331329
332330 emphasizeAPI. emphasizeRanges ( ranges: searchResults, activeIndex: activeIndex)
333331
@@ -338,49 +336,46 @@ extension FindViewController: FindPanelDelegate {
338336 }
339337 }
340338
341- private func getNearestHighlightIndex( matchRanges: [ NSRange ] ) -> Int ? {
342- // order the array as follows
343- // Found: 1 -> 2 -> 3 -> 4
344- // Cursor: |
345- // Result: 3 -> 4 -> 1 -> 2
346- guard let cursorPosition = target? . cursorPositions. first else { return nil }
347- let start = cursorPosition. range. location
339+ private func getNearestHighlightIndex( matchRanges: borrowing [ NSRange ] ) -> Int ? {
340+ guard !matchRanges. isEmpty,
341+ let textViewController = target as? TextViewController ,
342+ let textView = textViewController. textView,
343+ let visibleRange = textView. visibleTextRange else { return nil }
344+
345+ // Determine target position based on cursor visibility
346+ let targetPosition : Int
347+ if let cursorPosition = textViewController. cursorPositions. first? . range. location,
348+ visibleRange. contains ( cursorPosition) {
349+ targetPosition = cursorPosition
350+ } else {
351+ targetPosition = visibleRange. location
352+ }
348353
349- var left = 0
350- var right = matchRanges. count - 1
351- var bestIndex = - 1
352- var bestDiff = Int . max // Stores the closest difference
354+ // Binary search for the nearest match
355+ var left = 0 , right = matchRanges. count - 1
356+ var bestIndex : Int ? = nil
357+ var bestDiff = Int . max
353358
354359 while left <= right {
355360 let mid = left + ( right - left) / 2
356361 let midStart = matchRanges [ mid] . location
357- let diff = abs ( midStart - start )
362+ let diff = abs ( midStart - targetPosition )
358363
359- // If it's an exact match, return immediately
360- if diff == 0 {
361- return mid
362- }
363-
364- // If this is the closest so far, update the best index
365364 if diff < bestDiff {
366365 bestDiff = diff
367366 bestIndex = mid
368367 }
369368
370- // Move left or right based on the cursor position
371- if midStart < start {
369+ if midStart < targetPosition {
372370 left = mid + 1
373371 } else {
374372 right = mid - 1
375373 }
376374 }
377375
378- return bestIndex >= 0 ? bestIndex : nil
376+ return bestIndex
379377 }
380378
381- // Only re-serach the part of the file that changed upwards
382- private func reSearch( ) { }
383-
384379 // Returns true if string contains uppercase letter
385380 // used for: ignores letter case if the search query is all lowercase
386381 private func smartCase( str: String ) -> Bool {
0 commit comments