# 源控制API
VS Code 允许插件创作者通过扩展API去定义源控制管理特性(Source Control Management,SCM),VS Code整合了各式各样的SCM体系,而只给用户展现了一组小巧、强大的API接口,还是带用户界面的那种。
VS Code自带一个源控制器:Git,它是源控制API的最佳实践。如果你想构建你自己的SCM供应器,那么这是一个很好的起点。
VS Code插件市场还有很多类似的超赞的插件,比如SVN。
如果你需要帮助,请查看vscode命名空间API。
# 源控制模型
SourceControl
负责生产源控制模型的实体,它里面有SourceControlResourceState
实例的资源状态,而资源状态又是SourceControlResourceGroup
实例整理成组的。
通过vscode.scm.createSourceControl
创建一个新的源控制器。
为了更好地理解这几种实体的交互,让我们拿Git来做例子,考虑下列git status
输出:
vsce master* → git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: README.md
renamed: src/api.ts -> src/test/api.ts
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
deleted: .travis.yml
modified: README.md
2
3
4
5
6
7
8
9
10
11
12
13
14
15
这个工作区里面发生了很多事,首先,README.md
文件已经被修改了但还没有提交,然后立刻又被修改了。 其次,src/api.ts
文件被移动到了src/test/api.ts
,这个修改已经存备(staged), 最后,.travis.yml
文件被删除。
对于这个工作区而言,Git定义了两个资源组:工作中(Working tree)和已索引(Index),对于单个组而言,每次文件修改就会产生一些资源状态:
- 已索引 - 资源组
- 修改
README.md
- 资源状态 - 移动
src/api.ts
到src/test/api.ts
- 资源状态
- 修改
- 工作中 - 资源组
- 删除
.travis.yml
- 资源状态 - 修改
README.md
- 资源状态
- 删除
同一个README.md
是怎么成为两组截然不同的资源状态呢?
下面揭秘Git是如何创建这个模型的:
function createResourceUri(relativePath: string): vscode.Uri {
const absolutePath = path.join(vscode.workspace.rootPath, relativePath);
return vscode.Uri.file(absolutePath);
}
const gitSCM = vscode.scm.createSourceControl('git', "Git");
const index = gitSCM.createResourceGroup('index', "Index");
index.resourceStates = [
{ resourceUri: createResourceUri('README.md') },
{ resourceUri: createResourceUri('src/test/api.ts') }
];
const workingTree = gitSCM.createResourceGroup('workingTree', "Changes");
workingTree.resourceStates = [
{ resourceUri: createResourceUri('.travis.yml') },
{ resourceUri: createResourceUri('README.md') }
];
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
源变动和最终产生的资源组会传递到源控制视图上。
# 源控制视图
当源变动时,VS Code会生成源控制视图。源状态可通过SourceControlResourceDecorations
自定义:
export interface SourceControlResourceState {
readonly decorations?: SourceControlResourceDecorations;
}
2
3
上述例子已经足以让源控制视图生成一个简单的列表,不过用户可能想要在不同的资源状态上进行不同的操作。比如,当用户点击资源状态时,会发生什么呢?资源状态提供了一个可选命令去处理这类场景:
export interface SourceControlResourceState {
readonly command?: Command;
}
2
3
# 菜单
要想提供更加丰富的交互效果,我们提供了5个源控制菜单项供你使用。
scm/title
菜单在源控制视图的顶部右上方,菜单项水平排列在标题栏
中,另外一些会在...
下拉菜单中。
scm/resourceGroup/context
和scm/resourceState/context
是类似的,你可以通过前者自定义资源组,后者则是定义资源状态。将菜单项放在inline
组里,可以水平在视图中展示它们。而其他的菜单项可以通过鼠标右击的形式展示在菜单中。菜单中调用的命令会传入资源状态作为参数。注意SCM视图提供多选,因此命令函数可能一次性会接收一个或多个参数。
例如,Git支持往scm/resourceState/context
菜单中添加git.stage
命令和使用下列方法,提供多个文件的存备(staged):
stage(...resourceStates: SourceControlResourceState[]): Promise<void>;
创建它们的时候,SourceControl
和SourceControlResourceGroup
实例会需要你提供一个string类型的id
,这些值最终会在scmProvider
和scmResourceGroup
以上下文键值的形式出现。在菜单项的when
语法中使用这些上下文键值。看个Git如何通过git.stage
命令显示菜单项的:
{
"command": "git.stage",
"when": "scmProvider == git && scmResourceGroup == merge",
"group": "inline"
}
2
3
4
5
scm/change/title
可以对行内变动配置标题栏的命令(contribute commands to the title bar of an inline change)。命令中的参数有文档的URI,变动数组,当前行内变动所在索引。例如下面是一个可以配置菜单的GitstageChange
命令声明:
async stageChange(uri: Uri, changes: LineChange[], index: number): Promise<void>;
scm/sourceControl
菜单根据环境出现在源控制实例的边上。
最后,scm/change/title
菜单是和快速Diff功能相关联的,越新的文件越靠前,你可以针对特定的代码变动调用命令。
# SCM 输入框
源控制输入框位于每个源控制视图的顶部,接收用户输入的信息。你可以获取(或设置)这个信息供后续使用。在Git中,比如说,这可以作为一个commit框,用户输入了提交信息后,触发git commit
命令:
export interface SourceControlInputBox {
value: string;
}
export interface SourceControl {
readonly inputBox: SourceControlInputBox;
}
2
3
4
5
6
7
用户可以通过Ctrl+Enter(Mac上是Cmd+Enter)接收任意信息,在SourceControl
中的acceptInputCommand
处理这类事件。
export interface SourceControl {
readonly acceptInputCommand?: Command;
}
2
3
# 快速Diff
VS Code支持显示快速Diff编辑器的高亮槽,点击这些槽会出现一个内部diff交互器,你可以在这里为上下文配置命令。
这些高亮槽是VS Code自己计算出来的,你要做的就是根据给定的文件提供原始文件内容
export interface SourceControl {
quickDiffProvider?: QuickDiffProvider;
}
2
3
使用QuickDiffProvider
,你的实现需要告诉VS Code——参数传入的给定资源Uri
所对应的原始资源Uri
。
TIP
如果你想在给定Uri
的情况下,为任意资源提供内容,那么你可以把源控制API和**工作区命名空间的registerTextDocumentContentProvider
方法**结合起来使用。
# 下一步
想要学习更多关于VS Code扩展性模型,请参考:
- SCM API 参考 - 查看完整的SCM API文档
- Git 插件 - 学习Git插件实现
- 插件API概览 - 学习全部的VS Code扩展性模型
- 插件配置清单 - VS Code package.json插件配置清单参考
- 发布内容配置点 - VS Code发布内容配置点参考