Skip to content

Commit 5397dc8

Browse files
committed
fix: address code review issues in autocomplete refactor
1 parent 7ad19a6 commit 5397dc8

File tree

4 files changed

+48
-34
lines changed

4 files changed

+48
-34
lines changed

LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/CodeSuggestion/View/CodeSuggestionLabelView.swift

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,36 +33,34 @@ struct CodeSuggestionLabelView: View {
3333

3434
// swiftlint:disable shorthand_operator
3535
private func highlightedLabel() -> Text {
36-
let label = suggestion.label
36+
let nsLabel = suggestion.label as NSString
3737
let ranges = suggestion.matchedRanges
3838
let color = effectiveLabelColor
3939

4040
guard !ranges.isEmpty else {
41-
return Text(label).foregroundColor(color)
41+
return Text(suggestion.label).foregroundColor(color)
4242
}
4343

4444
var result = Text("")
4545
var currentIndex = 0
4646

4747
for range in ranges {
48-
let clampedUpper = min(range.upperBound, label.count)
48+
let clampedUpper = min(range.upperBound, nsLabel.length)
4949
guard range.lowerBound < clampedUpper else { continue }
5050

5151
if currentIndex < range.lowerBound {
52-
let start = label.index(label.startIndex, offsetBy: currentIndex)
53-
let end = label.index(label.startIndex, offsetBy: range.lowerBound)
54-
result = result + Text(label[start..<end]).foregroundColor(color)
52+
let segment = nsLabel.substring(with: NSRange(location: currentIndex, length: range.lowerBound - currentIndex))
53+
result = result + Text(segment).foregroundColor(color)
5554
}
5655

57-
let start = label.index(label.startIndex, offsetBy: range.lowerBound)
58-
let end = label.index(label.startIndex, offsetBy: clampedUpper)
59-
result = result + Text(label[start..<end]).foregroundColor(color).bold()
56+
let segment = nsLabel.substring(with: NSRange(location: range.lowerBound, length: clampedUpper - range.lowerBound))
57+
result = result + Text(segment).foregroundColor(color).bold()
6058
currentIndex = clampedUpper
6159
}
6260

63-
if currentIndex < label.count {
64-
let start = label.index(label.startIndex, offsetBy: currentIndex)
65-
result = result + Text(label[start...]).foregroundColor(color)
61+
if currentIndex < nsLabel.length {
62+
let segment = nsLabel.substring(from: currentIndex)
63+
result = result + Text(segment).foregroundColor(color)
6664
}
6765

6866
return result

LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/CodeSuggestion/View/SuggestionContentView.swift

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ struct SuggestionContentView: View {
4848
.lineLimit(1)
4949
.truncationMode(.tail)
5050
.contentShape(Rectangle())
51+
.onTapGesture(count: 1) {
52+
model.selectedIndex = index
53+
}
5154
.onTapGesture(count: 2) {
5255
model.selectedIndex = index
5356
if let selectedItem = model.selectedItem {
@@ -57,9 +60,6 @@ struct SuggestionContentView: View {
5760
)
5861
}
5962
}
60-
.onTapGesture(count: 1) {
61-
model.selectedIndex = index
62-
}
6363
.listRowInsets(EdgeInsets())
6464
.listRowBackground(
6565
RoundedRectangle(cornerRadius: 5)
@@ -86,10 +86,13 @@ struct SuggestionContentView: View {
8686

8787
private var contentWidth: CGFloat {
8888
let font = model.activeTextView?.font ?? NSFont.systemFont(ofSize: 12)
89-
// Icon (pointSize + 2) + spacing(2) + label padding (13*2) + extra buffer
9089
let iconWidth = font.pointSize + 6
9190
let maxLabelLength = min(
92-
(model.items.reduce(0) { max($0, $1.label.count + ($1.detail?.count ?? 0)) }) + 2,
91+
model.items.reduce(0) { current, item in
92+
let labelLen = (item.label as NSString).length
93+
let detailLen = ((item.detail ?? "") as NSString).length
94+
return max(current, labelLen + detailLen)
95+
} + 2,
9396
64
9497
)
9598
let textWidth = CGFloat(maxLabelLength) * font.charWidth

LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/CodeSuggestion/Window/SuggestionController.swift

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,21 +51,26 @@ public final class SuggestionController: NSWindowController {
5151
let hostingView = NSHostingView(rootView: contentView)
5252
window.contentView = hostingView
5353

54+
// Resize window when items change
5455
model.$items
5556
.receive(on: DispatchQueue.main)
5657
.sink { [weak self] _ in
57-
DispatchQueue.main.async {
58-
self?.updateWindowSizeFromContent()
59-
}
58+
self?.updateWindowSizeFromContent()
6059
}
6160
.store(in: &sizeObservers)
6261

62+
// Resize window only when preview visibility changes (not every arrow key)
6363
model.$selectedIndex
6464
.receive(on: DispatchQueue.main)
65+
.map { [weak self] index -> Bool in
66+
guard let self, index >= 0, index < self.model.items.count else { return false }
67+
let item = self.model.items[index]
68+
return item.documentation != nil || item.sourcePreview != nil
69+
|| !(item.pathComponents?.isEmpty ?? true)
70+
}
71+
.removeDuplicates()
6572
.sink { [weak self] _ in
66-
DispatchQueue.main.async {
67-
self?.updateWindowSizeFromContent()
68-
}
73+
self?.updateWindowSizeFromContent()
6974
}
7075
.store(in: &sizeObservers)
7176

@@ -154,6 +159,11 @@ public final class SuggestionController: NSWindowController {
154159
model.willClose()
155160
removeEventMonitors()
156161

162+
if let observer = windowResignObserver {
163+
NotificationCenter.default.removeObserver(observer)
164+
windowResignObserver = nil
165+
}
166+
157167
if let observer = firstResponderObserver {
158168
NotificationCenter.default.removeObserver(observer)
159169
firstResponderObserver = nil

TablePro/Core/Autocomplete/SQLCompletionProvider.swift

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,8 @@ final class SQLCompletionProvider {
2828
/// Context-aware suggestion limit: schema-heavy clauses get more results
2929
private func maxSuggestions(for clauseType: SQLClauseType) -> Int {
3030
switch clauseType {
31-
case .from, .join, .into, .dropObject, .createIndex:
32-
return 40
33-
case .select, .where_, .and, .on, .having, .groupBy, .orderBy,
31+
case .from, .join, .into, .dropObject, .createIndex,
32+
.select, .where_, .and, .on, .having, .groupBy, .orderBy,
3433
.set, .insertColumns, .returning, .using:
3534
return 40
3635
default:
@@ -624,16 +623,20 @@ final class SQLCompletionProvider {
624623
private func populateMatchRanges(_ items: inout [SQLCompletionItem], prefix: String) {
625624
guard !prefix.isEmpty else { return }
626625
let lowerPrefix = prefix.lowercased()
626+
let nsPrefix = lowerPrefix as NSString
627627

628628
for i in items.indices {
629-
let filterText = items[i].filterText
630-
if filterText.hasPrefix(lowerPrefix) {
631-
items[i].matchedRanges = [0..<lowerPrefix.count]
632-
} else if let range = filterText.range(of: lowerPrefix) {
633-
let start = filterText.distance(from: filterText.startIndex, to: range.lowerBound)
634-
items[i].matchedRanges = [start..<(start + lowerPrefix.count)]
635-
} else if let result = fuzzyMatchWithIndices(pattern: lowerPrefix, target: filterText) {
636-
items[i].matchedRanges = indicesToRanges(result.indices)
629+
let nsFilterText = items[i].filterText as NSString
630+
let prefixRange = nsFilterText.range(of: lowerPrefix, options: .anchored)
631+
if prefixRange.location != NSNotFound {
632+
items[i].matchedRanges = [0..<nsPrefix.length]
633+
} else {
634+
let containsRange = nsFilterText.range(of: lowerPrefix)
635+
if containsRange.location != NSNotFound {
636+
items[i].matchedRanges = [containsRange.location..<(containsRange.location + containsRange.length)]
637+
} else if let result = fuzzyMatchWithIndices(pattern: lowerPrefix, target: items[i].filterText) {
638+
items[i].matchedRanges = indicesToRanges(result.indices)
639+
}
637640
}
638641
}
639642
}

0 commit comments

Comments
 (0)