Skip to content

Commit e22ec05

Browse files
committed
Merge branch 'feature/chat-instruction-on-scopes-and-plugins' into develop
2 parents 96a6a0a + 99f6a63 commit e22ec05

3 files changed

Lines changed: 49 additions & 6 deletions

File tree

Core/Sources/ChatService/ChatPluginController.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ final class ChatPluginController {
1212
self.chatGPTService = chatGPTService
1313
var all = [String: ChatPlugin.Type]()
1414
for plugin in plugins {
15-
all[plugin.command] = plugin
15+
all[plugin.command.lowercased()] = plugin
1616
}
1717
self.plugins = all
1818
}
@@ -29,7 +29,7 @@ final class ChatPluginController {
2929
let regex = try NSRegularExpression(pattern: #"^\/([a-zA-Z0-9]+)"#)
3030
let matches = regex.matches(in: content, range: NSRange(content.startIndex..., in: content))
3131
if let match = matches.first {
32-
let command = String(content[Range(match.range(at: 1), in: content)!])
32+
let command = String(content[Range(match.range(at: 1), in: content)!]).lowercased()
3333
// handle exit plugin
3434
if command == "exit" {
3535
if let plugin = runningPlugin {

Core/Sources/SuggestionWidget/CustomTextEditor.swift

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,25 @@ struct CustomTextEditor: NSViewRepresentable {
88
@Binding var text: String
99
let font: NSFont
1010
let onSubmit: () -> Void
11+
var completions: (_ text: String, _ words: [String], _ range: NSRange)
12+
-> [String] = { _, _, _ in
13+
[]
14+
}
1115

1216
func makeNSView(context: Context) -> NSScrollView {
17+
context.coordinator.completions = completions
1318
let textView = (context.coordinator.theTextView.documentView as! NSTextView)
1419
textView.delegate = context.coordinator
1520
textView.string = text
1621
textView.font = font
1722
textView.allowsUndo = true
1823
textView.drawsBackground = false
19-
24+
2025
return context.coordinator.theTextView
2126
}
2227

2328
func updateNSView(_ nsView: NSScrollView, context: Context) {
29+
context.coordinator.completions = completions
2430
let textView = (context.coordinator.theTextView.documentView as! NSTextView)
2531
guard textView.string != text else { return }
2632
textView.string = text
@@ -32,6 +38,7 @@ extension CustomTextEditor {
3238
var view: CustomTextEditor
3339
var theTextView = NSTextView.scrollableTextView()
3440
var affectedCharRange: NSRange?
41+
var completions: (String, [String], _ range: NSRange) -> [String] = { _, _, _ in [] }
3542

3643
init(_ view: CustomTextEditor) {
3744
self.view = view
@@ -43,13 +50,14 @@ extension CustomTextEditor {
4350
}
4451

4552
view.text = textView.string
53+
textView.complete(nil)
4654
}
4755

4856
func textView(_ textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
4957
if commandSelector == #selector(NSTextView.insertNewline(_:)) {
5058
if let event = NSApplication.shared.currentEvent,
5159
!event.modifierFlags.contains(.shift),
52-
event.keyCode == 36
60+
event.keyCode == 36 // enter
5361
{
5462
view.onSubmit()
5563
return true
@@ -66,6 +74,16 @@ extension CustomTextEditor {
6674
) -> Bool {
6775
return true
6876
}
77+
78+
func textView(
79+
_ textView: NSTextView,
80+
completions words: [String],
81+
forPartialWordRange charRange: NSRange,
82+
indexOfSelectedItem index: UnsafeMutablePointer<Int>?
83+
) -> [String] {
84+
index?.pointee = -1
85+
return completions(textView.textStorage?.string ?? "", words, charRange)
86+
}
6987
}
7088
}
7189

Core/Sources/SuggestionWidget/SuggestionPanelContent/ChatPanel.swift

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ struct ChatPanelMessages: View {
8888
}
8989
}
9090
.listItemTint(.clear)
91-
91+
9292
Instruction()
9393

9494
Spacer()
@@ -147,6 +147,8 @@ private struct Instruction: View {
147147
- The text cursor location.
148148
149149
If you'd like me to examine the entire file, simply add `@file` to the beginning of your message.
150+
151+
To use plugins, you can start a message with `/pluginName`.
150152
"""
151153
)
152154
} else {
@@ -160,6 +162,8 @@ private struct Instruction: View {
160162
- The text cursor location.
161163
162164
If you would like me to examine the selected code, please prefix your message with `@selection`. If you would like me to examine the entire file, please prefix your message with `@file`.
165+
166+
To use plugins, you can start a message with `/pluginName`.
163167
"""
164168
)
165169
}
@@ -350,7 +354,28 @@ struct ChatPanelInputArea: View {
350354
CustomTextEditor(
351355
text: $typedMessage,
352356
font: .systemFont(ofSize: 14),
353-
onSubmit: { submitText() }
357+
onSubmit: { submitText() },
358+
completions: { text, _, range in
359+
if text.isEmpty { return [] }
360+
let availableFeatures = [
361+
"/run",
362+
"/airun",
363+
"/math",
364+
"/search",
365+
"@selection",
366+
"@file",
367+
]
368+
return availableFeatures
369+
.filter { $0.hasPrefix(text) && $0 != text }
370+
.compactMap {
371+
guard let index = $0.index(
372+
$0.startIndex,
373+
offsetBy: range.location,
374+
limitedBy: $0.endIndex
375+
) else { return nil }
376+
return String($0[index...])
377+
}
378+
}
354379
)
355380
.padding(.top, 1)
356381
.padding(.bottom, -1)

0 commit comments

Comments
 (0)