✨ feat(vscode): 代码阅读的名字高亮更显眼(当前那处描框、别处画细线),⌘↓ / ⌘↑ 在各处之间跳,跳到折叠处自动展开,筛选栏写第几处

This commit is contained in:
cruldra committed 2026-09-26 23:47:43 +08:00
1 parent c5c5d2b517
commit 49f253b80f
18 files changed
+731 -53

No files matched your search

+27 -3
View File
@@ -7,7 +7,7 @@ import type { CodeReaderRegistry } from '../registry'
import type { TreeSitterRuntime } from '../runtime'
import type { BlockFilter } from './blockFilter'
import type { Definition, FoundLocation } from './definitions'
import type { ExtensionToWebview, Reveal, WebviewToExtension } from './messages'
import type { ExtensionToWebview, KeyCombo, Reveal, WebviewToExtension } from './messages'
import { commands, Range, window, workspace, WorkspaceEdit } from 'vscode'
import { logger } from '../../logging/logger'
import { webviewHtml, webviewUiRoot } from '../../webview/html'
@@ -18,6 +18,7 @@ import { definitionAction } from './definitionAction'
import { findDefinitions, languageDefinitions, pickDefinition, ruleDefinitions } from './definitions'
import { DefinitionSources } from './definitionSources'
import { documentMessage } from './documentMessage'
import { NavigationContext, OCCURRENCES_CONTEXT } from './occurrenceNavigation'
import { occurrencesOf } from './occurrences'
export const PREVIEW_VIEW_TYPE = 'superpowers.codeReader.preview'
@@ -33,6 +34,8 @@ export class PreviewEditorProvider implements CustomTextEditorProvider {
private readonly previews = new Set<Preview>()
/** 按文档 uri:等着交给马上要打开的新预览的位置(从文本编辑器切过来时它顶部那一行,或跳到的定义) */
private readonly reveals = new Map<string, Reveal>()
/** 哪个预览眼下能用键盘在高亮的各处出现之间跳,跟着它设快捷键 when 子句用的上下文键 */
readonly navigation = new NavigationContext<Preview>(value => void commands.executeCommand('setContext', OCCURRENCES_CONTEXT, value))
constructor(
private readonly extensionUri: Uri,
@@ -43,6 +46,8 @@ export class PreviewEditorProvider implements CustomTextEditorProvider {
readonly resolveReference: (reference: RuleReference) => Promise<RuleLocation[]>,
/** 问 AI:各预览共用,同一份文件开在几处时问答、正在答的问题都一样 */
readonly qa: CodeQa,
/** 「跳到下一处 / 上一处高亮」默认绑的键:页面在这些键上拦下浏览器自己的滚动 */
readonly occurrenceKeys: readonly KeyCombo[],
) {}
resolveCustomTextEditor(document: TextDocument, panel: WebviewPanel): void {
@@ -56,10 +61,16 @@ export class PreviewEditorProvider implements CustomTextEditorProvider {
this.previews.add(preview)
panel.onDidDispose(() => {
this.previews.delete(preview)
this.navigation.update(preview, false)
preview.dispose()
})
}
/** 「跳到下一处 / 上一处高亮」:发给能跳的那个预览,从命令面板运行时发给活动的预览。 */
moveOccurrence(step: 1 | -1): void {
this.navigation.target(this.previews, preview => preview.active)?.moveOccurrence(step)
}
/** 让已打开的预览按当前注册表重发;给了 languageId 就只刷这种语言的。 */
refresh(languageId?: string): void {
for (const preview of this.previews) {
@@ -130,8 +141,11 @@ class Preview {
this.disposables = [
panel.webview.onDidReceiveMessage((msg: WebviewToExtension) => this.handleMessage(msg)),
panel.onDidChangeViewState(() => {
if (!panel.visible)
this.ready = false
if (panel.visible)
return
// 页面被销毁了,高亮跟着没了
this.ready = false
owner.navigation.update(this, false)
}),
workspace.onDidChangeTextDocument((e) => {
if (e.document === document && e.contentChanges.length > 0)
@@ -202,6 +216,12 @@ class Preview {
this.post(reveal === undefined ? message : { ...message, reveal })
}
/** 跳到高亮着的名字的下一处 / 上一处出现;页面不在就算了(页面重新加载时高亮已经没了)。 */
moveOccurrence(step: 1 | -1): void {
if (this.ready)
this.post({ type: 'moveOccurrence', step })
}
/** 滚到 reveal:页面在就直接发,正在重新加载就等它发 ready 后随文档带过去。 */
reveal(reveal: Reveal): void {
if (this.ready)
@@ -262,6 +282,7 @@ class Preview {
this.ready = true
// 先于文档发:第一份文档按筛选画,不会先整份露出来再藏
this.post({ type: 'filter', excluded: this.filter.excluded })
this.post({ type: 'occurrenceKeys', keys: [...this.owner.occurrenceKeys] })
this.postQa()
void this.postProfiles()
await this.push()
@@ -299,6 +320,9 @@ class Preview {
return
case 'findOccurrences':
await this.findOccurrences(msg.id, msg.version, msg.offset)
return
case 'occurrenceNavigation':
this.owner.navigation.update(this, msg.available)
}
}