* Anchor textbox completions to cursor * Reposition textbox completions on window changes * Improve textbox mention search indexing * Show root mentions while file index warms * Open textbox mention popover while loading * Address textbox mention review feedback * Ignore textbox completion panel in close shortcut lint * Address textbox mention review feedback * Move textbox mention tests to Swift Testing * Fix textbox mention completion races * Use shared ripgrep resolver for textbox mentions * Fix textbox mention stale refresh paths * Address textbox mention review edge cases * Fix textbox mention markdown and scanner waiters * Normalize textbox mention control navigation * Prioritize local textbox mention skills * Fix textbox mention key routing edge cases * Stamp textbox mention cache on completion * Update textbox mention stale return test * Fix mention index warning * Address textbox mention review feedback
55 lines
1.7 KiB
Swift
55 lines
1.7 KiB
Swift
import Foundation
|
|
|
|
struct TextBoxMentionCompletionDetector {
|
|
static func query(in text: String, selectedRange: NSRange) -> TextBoxMentionQuery? {
|
|
guard selectedRange.length == 0,
|
|
selectedRange.location != NSNotFound else {
|
|
return nil
|
|
}
|
|
|
|
let nsText = text as NSString
|
|
let cursor = min(max(0, selectedRange.location), nsText.length)
|
|
guard cursor > 0 else { return nil }
|
|
|
|
var tokenStart = cursor
|
|
while tokenStart > 0 {
|
|
let previous = nsText.substring(with: NSRange(location: tokenStart - 1, length: 1))
|
|
if previous.rangeOfCharacter(from: .whitespacesAndNewlines) != nil {
|
|
break
|
|
}
|
|
tokenStart -= 1
|
|
}
|
|
|
|
guard tokenStart < cursor else { return nil }
|
|
let tokenRange = NSRange(location: tokenStart, length: cursor - tokenStart)
|
|
let token = nsText.substring(with: tokenRange)
|
|
guard let trigger = token.first else { return nil }
|
|
|
|
let kind: TextBoxMentionKind
|
|
switch trigger {
|
|
case "@":
|
|
kind = .file
|
|
case "/":
|
|
kind = .skill
|
|
case "$":
|
|
kind = .skill
|
|
default:
|
|
return nil
|
|
}
|
|
|
|
guard token.allSatisfy({ character in
|
|
character != "[" &&
|
|
character != "]" &&
|
|
character != "(" &&
|
|
character != ")" &&
|
|
character != "<" &&
|
|
character != ">"
|
|
}) else {
|
|
return nil
|
|
}
|
|
|
|
let query = String(token.dropFirst())
|
|
return TextBoxMentionQuery(kind: kind, range: tokenRange, query: query, trigger: trigger)
|
|
}
|
|
}
|