Skip to content

Commit a952872

Browse files
authored
Node Search (#8)
1 parent 6f7b86e commit a952872

File tree

6 files changed

+124
-122
lines changed

6 files changed

+124
-122
lines changed

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ let package = Package(
1717
),
1818
],
1919
dependencies: [
20-
.package(url: "https://github.com/codefiesta/VimKit", from: .init(0, 4, 8))
20+
.package(url: "https://github.com/codefiesta/VimKit", from: .init(0, 4, 9))
2121
],
2222
targets: [
2323
.target(

Sources/VimAssistant/Extensions/Array+Extensions.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,9 @@ extension Array where Element: Comparable {
2020
return indices
2121
}
2222
}
23+
24+
extension Array where Element == String {
25+
func containsIgnoringCase(_ element: Element) -> Bool {
26+
contains { $0.caseInsensitiveCompare(element) == .orderedSame }
27+
}
28+
}

Sources/VimAssistant/Model/VimAssistant+Handler.swift

Lines changed: 0 additions & 114 deletions
This file was deleted.

Sources/VimAssistant/Model/VimAssistant.swift

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,4 +111,61 @@ public class VimAssistant: ObservableObject, @unchecked Sendable {
111111

112112
return try? JSONDecoder().decode(VimPrediction.self, from: data)
113113
}
114+
115+
/// Handles the specified prediction.
116+
/// - Parameters:
117+
/// - vim: the vim object to update based on the given prediction.
118+
/// - prediction: the prediction to handle
119+
func handle(vim: Vim, prediction: VimPrediction?) async {
120+
guard let prediction, let bestPrediction = prediction.bestPrediction else { return }
121+
let action = bestPrediction.action
122+
switch action {
123+
case .isolate:
124+
let ids = search(vim: vim, in: prediction)
125+
guard ids.isNotEmpty else { return }
126+
await vim.isolate(ids: ids)
127+
case .hide:
128+
let ids = search(vim: vim, in: prediction)
129+
guard ids.isNotEmpty else { return }
130+
await vim.hide(ids: ids)
131+
case .quantify:
132+
break
133+
case .zoomIn:
134+
await vim.zoom()
135+
case .zoomOut:
136+
await vim.zoom(out: true)
137+
case .lookLeft:
138+
await vim.look(.left)
139+
case .lookRight:
140+
await vim.look(.right)
141+
case .lookUp:
142+
await vim.look(.up)
143+
case .lookDown:
144+
await vim.look(.down)
145+
case .panLeft:
146+
await vim.pan(.left)
147+
case .panRight:
148+
await vim.pan(.right)
149+
case .panUp:
150+
await vim.pan(.up)
151+
case .panDown:
152+
await vim.pan(.down)
153+
}
154+
}
155+
156+
/// Performs a fuzzy search using the levenshtein distance algorithm across the node tree to find the best results.
157+
/// - Parameters:
158+
/// - vim: the vim object to search
159+
/// - prediction: the prediction to extract entity names from
160+
/// - Returns: a set of node ids that match the prediction
161+
private func search(vim: Vim, in prediction: VimPrediction) -> Set<Int> {
162+
guard let tree = vim.tree else { return [] }
163+
var ids: Set<Int> = .init()
164+
for entity in prediction.entities {
165+
let searchResults = tree.search(entity.value)
166+
guard let bestResult = searchResults.first else { continue }
167+
ids.formUnion(bestResult.item.ids)
168+
}
169+
return ids
170+
}
114171
}

Sources/VimAssistant/Views/VimAssistantView.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ public struct VimAssistantView: View {
1515
@State
1616
var assistant: VimAssistant = .init()
1717

18-
/// The handler to pass prediction information to.
19-
var handler: VimAssistant.Handler = .init()
18+
// /// The handler to pass prediction information to.
19+
// var handler: VimAssistant.Handler = .init()
2020

2121
@State
2222
var inputText: String = .empty
@@ -48,7 +48,10 @@ public struct VimAssistantView: View {
4848
predictionView
4949
}
5050
.onChange(of: assistant.prediction) { _, prediction in
51-
handler.handle(vim: vim, prediction: prediction)
51+
Task {
52+
await assistant.handle(vim: vim, prediction: prediction)
53+
}
54+
// handler.handle(vim: vim, prediction: prediction)
5255
}
5356
}
5457

Sources/VimAssistant/Views/VimPredictionView.swift

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ struct VimPredictionView: View {
7171
for entity in prediction.entities {
7272
let entityText = text[entity.range]
7373
var attributedEntityString = AttributedString(entityText)
74-
attributedEntityString.foregroundColor = .cyan
74+
attributedEntityString.foregroundColor = entity.label.color
7575
attributedEntityString.underlineStyle = .single
7676
attributedEntityString.link = URL(string: "/\(entity.label)/\(entity.value)")!
7777
result.replaceSubrange(bounds: entity.range, with: attributedEntityString)
@@ -95,15 +95,17 @@ struct VimPredictionView: View {
9595
Divider()
9696
.fixedSize()
9797

98-
Text("Recognized entities:")
99-
.font(.subheadline).bold()
98+
if prediction.entities.isNotEmpty {
99+
Text("Recognized entities:")
100+
.font(.subheadline).bold()
101+
}
100102
ForEach(prediction.entities) { entity in
101103
HStack {
102104
Text(text[entity.range])
103105
.bold()
104106
Text(entity.label.rawValue)
105107
.padding(1)
106-
.background(Color.cyan)
108+
.background(entity.label.color)
107109
.foregroundStyle(Color.black)
108110
.cornerRadius(2)
109111
}
@@ -133,3 +135,51 @@ struct VimPredictionView: View {
133135
let prediction = try! JSONDecoder().decode(VimPrediction.self, from: json.data(using: .utf8)!)
134136
VimPredictionView(prediction: prediction, explain: .constant(true))
135137
}
138+
139+
extension VimPrediction.NerLabel {
140+
141+
var color: Color {
142+
switch self {
143+
case .person:
144+
.purple
145+
case .organization:
146+
.blue
147+
case .location:
148+
.black
149+
case .date:
150+
.mint
151+
case .time:
152+
.cyan
153+
case .event:
154+
.cyan
155+
case .workOfArt:
156+
.cyan
157+
case .fac:
158+
.cyan
159+
case .gpe:
160+
.cyan
161+
case .language:
162+
.cyan
163+
case .law:
164+
.cyan
165+
case .norp:
166+
.cyan
167+
case .product:
168+
.cyan
169+
case .cardinal:
170+
.blue
171+
case .bimCategory:
172+
.cyan
173+
case .bimFamily:
174+
.orange
175+
case .bimType:
176+
.cyan
177+
case .bimInstance:
178+
.cyan
179+
case .bimLevel:
180+
.yellow
181+
case .bimView:
182+
.cyan
183+
}
184+
}
185+
}

0 commit comments

Comments
 (0)