✨ feat(vscode): 代码阅读侧栏加「未提交的更改」筛选

- 标题栏新按钮「未提交的更改」:树里只剩工作区各 git 仓库里没提交的文件(暂存、没暂存、未跟踪、合并冲突),每个有改动的仓库一个根,跟着 git 状态自动重摆;上色和徽标交给 VS Code 自带的 git 装饰
- 两种筛选互斥,由 TreeFilters 统一管,上下文键合并成 superpowers.codeReader.filter(review / uncommitted)
- 改动文件树改成多根,buildChangedTree 挪到 explorer/changedTree 并改吃 {path, change}
- 内置 git 扩展 API 的类型和加载抽到 src/git/gitApi、gitExtension,提交按钮的监听也改用它
- 文件注释按文件所在的工作区文件夹记,不看树从哪个根摆下来
This commit is contained in:
cruldra committed 2026-09-29 23:42:10 +08:00
1 parent 61c4728dce
commit 7f460d1257
18 files changed
+847 -240

No files matched your search

+74
View File
@@ -0,0 +1,74 @@
import type { Event, Uri } from 'vscode'
/**
* 内置 git 扩展(vscode.git)API 里用到的那一小部分,照 microsoft/vscode 的 extensions/git/src/api/git.d.ts 写的结构类型。
* 这里只有类型和状态值,运行时不依赖 vscode,纯函数和单测可以直接用;取 API 见 gitExtension.ts。
*/
/** 文件在 git 里的状态,数值照 git.d.ts 的 Status 枚举。 */
export const GIT_STATUS = {
INDEX_MODIFIED: 0,
INDEX_ADDED: 1,
INDEX_DELETED: 2,
INDEX_RENAMED: 3,
INDEX_COPIED: 4,
MODIFIED: 5,
DELETED: 6,
UNTRACKED: 7,
IGNORED: 8,
INTENT_TO_ADD: 9,
INTENT_TO_RENAME: 10,
TYPE_CHANGED: 11,
ADDED_BY_US: 12,
ADDED_BY_THEM: 13,
DELETED_BY_US: 14,
DELETED_BY_THEM: 15,
BOTH_ADDED: 16,
BOTH_DELETED: 17,
BOTH_MODIFIED: 18,
} as const
export type GitStatus = (typeof GIT_STATUS)[keyof typeof GIT_STATUS]
/** 一个文件的改动;改名的 uri 是新路径。 */
export interface GitChange {
readonly uri: Uri
readonly status: GitStatus
}
export interface GitRepositoryState {
/** 合并冲突的 */
readonly mergeChanges: readonly GitChange[]
/** 暂存的 */
readonly indexChanges: readonly GitChange[]
/** 没暂存的;设置 git.untrackedChanges 是 mixed(默认)时也含未跟踪的 */
readonly workingTreeChanges: readonly GitChange[]
/** 未跟踪的;设置 git.untrackedChanges 是 separate 时才有 */
readonly untrackedChanges: readonly GitChange[]
readonly onDidChange: Event<void>
}
export interface GitRepository {
readonly rootUri: Uri
readonly state: GitRepositoryState
/** 重读这个仓库的 git 状态 */
status: () => Promise<void>
}
/** initialized 之前 git 扩展还在找工作区里的仓库,repositories 可能不全。 */
export type GitApiState = 'uninitialized' | 'initialized'
export interface GitApi {
readonly state: GitApiState
readonly onDidChangeState: Event<GitApiState>
readonly repositories: readonly GitRepository[]
readonly onDidOpenRepository: Event<GitRepository>
readonly onDidCloseRepository: Event<GitRepository>
}
/** vscode.git 扩展激活后导出的东西。 */
export interface GitExtension {
/** 设置 git.enabled 关掉时是 false,这时 getAPI 会抛错 */
readonly enabled: boolean
getAPI: (version: 1) => GitApi
}
+11
View File
@@ -0,0 +1,11 @@
import type { GitApi, GitExtension } from './gitApi'
import { extensions } from 'vscode'
/** 取内置 git 扩展的 API(还没激活就先激活);没装、被禁用(设置 git.enabled 关了)时是 undefined,激活失败时抛错。 */
export async function loadGitApi(): Promise<GitApi | undefined> {
const extension = extensions.getExtension<GitExtension>('vscode.git')
if (!extension)
return undefined
const git = extension.isActive ? extension.exports : await extension.activate()
return git.enabled ? git.getAPI(1) : undefined
}