CodeEditSourceEditor 智能代码补全实战:用 CodeSuggestionDelegate 打造提示窗口
【免费下载链接】CodeEditSourceEditorA code editor view written in Swift powered by tree-sitter.项目地址: https://gitcode.com/gh_mirrors/co/CodeEditSourceEditor
CodeEditSourceEditor 是一款基于 Swift 与 tree-sitter 构建的现代代码编辑器视图组件,它的代码补全提示窗口设计得非常克制而优雅——编辑器本身不内置任何词库,所有补全数据都通过CodeSuggestionDelegate协议交给开发者自由发挥。无论你是想在 macOS 应用里接入 AI 补全、基于符号表做索引补全,还是只想先跑一个随机词条演示,掌握这个协议就掌握了整个智能补全的入口。本文用最小代码量带你从零实战,打造一个属于你自己的补全提示窗口。
智能代码补全从哪里触发?先读懂三条主线
在动手之前,先梳理 CodeEditSourceEditor 代码补全的运行链路,它由三个模块协同工作:
- 入口层:SourceEditor.swift 是 SwiftUI 包装视图,构造时传入
completionDelegate即可注册你的补全代理。 - 协议层:CodeSuggestionDelegate.swift 定义补全数据的获取、筛选与应用约定,是本文的主角。
- 展示层:SuggestionController.swift 负责提示窗口的弹出、跟随光标与关闭。
认识 CodeSuggestionDelegate:6 个方法看懂全流程
先看协议全貌(CodeSuggestionDelegate.swift):
| 方法 | 作用 | 是否必选 |
|---|---|---|
completionTriggerCharacters() | 返回触发补全的字符集合 | 可选,默认空 |
completionSuggestionsRequested(...) | 异步请求补全建议列表 | 必选 |
completionOnCursorMove(...) | 光标移动时同步刷新/筛选列表 | 必选 |
completionWindowApplyCompletion(...) | 用户选中建议后执行插入 | 必选 |
completionWindowDidClose() | 窗口关闭回调 | 可选 |
completionWindowDidSelect(item:) | 选中建议(未确认)回调 | 可选 |
其中最核心的是中间三个方法:一个异步"拉取",一个同步"刷新",一个"落盘"执行,理解了它们,其余都是锦上添花。
快速接入:三步让补全提示窗口跑起来
第 1 步:创建补全条目模型
提示窗口里每一条建议都遵循 CodeSuggestionEntry.swift 协议。它要求的字段非常直观:label(主标题)、detail(副标题)、documentation(文档说明)、sourcePreview(源码预览,会在窗口里做语法高亮)、image与imageColor(图标)。官方示例 MockCompletionDelegate.swift 里的Suggestion类就是最精简的实现范本。
第 2 步:实现委托类
新建一个类遵循CodeSuggestionDelegate,先实现两个必选方法:
final class MyCompletionDelegate: CodeSuggestionDelegate { // 异步获取建议,返回窗口锚点位置 + 条目数组 func completionSuggestionsRequested( textView: TextViewController, cursorPosition: CursorPosition ) async -> (windowPosition: CursorPosition, items: [CodeSuggestionEntry])? { let items = await fetchFromYourIndex(cursorPosition: cursorPosition) return (cursorPosition, items) } // 光标移动时的同步刷新,只做轻量筛选 func completionOnCursorMove( textView: TextViewController, cursorPosition: CursorPosition ) -> [CodeSuggestionEntry]? { return currentItems.filter { $0.label.hasPrefix(currentPrefix) } } // 用户回车确认后,把文本真正插入编辑器 func completionWindowApplyCompletion( item: CodeSuggestionEntry, textView: TextViewController, cursorPosition: CursorPosition? ) { textView.textView.insertText(item.label) } }注意completionOnCursorMove必须是同步方法——协议注释明确要求它"要快",因为每次击键都会调用,重活请全部放进异步方法里。
第 3 步:注册进编辑器
在 SwiftUI 中构造 SourceEditor 时传入委托即可,或像 TextViewController.swift 那样直接赋值给completionDelegate属性:
SourceEditor( $text, language: .swift, configuration: config, state: $state, completionDelegate: MyCompletionDelegate() )到这一步,你的智能代码补全提示窗口已经能弹出、跟随光标、响应回车了。🎉
定制触发时机:让补全出现在对的地方
默认情况下,每输入一个字母或数字都会触发completionSuggestionsRequested(见 SuggestionTriggerCharacterModel.swift)。如果只想在特定符号后弹出,重写completionTriggerCharacters():
func completionTriggerCharacters() -> Set<String> { [".", "(", "<"] }这样只有输入.、(、<时才请求补全,可以显著减少无效请求——对走网络请求的 AI 补全尤其重要,能帮你省下大量 token 开销。
深入提示窗口内部:数据如何流动
了解数据流能帮你排查问题。看 SuggestionViewModel.swift:调用showCompletions后会启动一个异步 Task 请求建议,拿到结果后解析光标矩形、定位窗口位置,最终交给SuggestionController展示。窗口默认最多显示 8.5 行(SuggestionController.swift),超出会滚动,贴到屏幕边缘时还会自动向上或向下翻转(SuggestionController+Window.swift),这些细节都不需要你操心。
一个值得留意的细节:窗口内的源码预览会复用 tree-sitter 做快速高亮(SuggestionViewModel.swift),所以只要给条目填好sourcePreview,提示窗口里的代码片段就会自动带上语法颜色,观感直接拉满。
进阶玩法:把 AI 补全接进来
掌握了这套机制,把 AI 接进来只需两步:在completionSuggestionsRequested里请求你的大模型接口,把返回内容包装成CodeSuggestionEntry;在completionOnCursorMove里做本地前缀过滤,保证打字体验不卡顿。异步 + 同步的职责划分,恰好就是为"远端取词 + 本地筛选"这种混合场景设计的。
小结
智能代码补全的核心其实就一句话:注册一个CodeSuggestionDelegate,实现"异步拉取、同步筛选、确认插入"三个方法。CodeEditSourceEditor 已经帮你处理好了窗口定位、光标跟随、屏幕边界这些繁琐的 UI 细节,你只需要专注补全数据本身。从官方示例 MockCompletionDelegate.swift 出发,替换成你自己的词库或 AI 服务,一个专业的代码补全提示窗口就诞生了。
【免费下载链接】CodeEditSourceEditorA code editor view written in Swift powered by tree-sitter.项目地址: https://gitcode.com/gh_mirrors/co/CodeEditSourceEditor
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考