2) VS Code 插件项目结构与配置文件

VS Code Extension 项目结构

打开 yo code 创建的项目,我们能看到下面的目录结构。 yo code output

展开之后得到的是下面的层级结构(我省略了大部分用于测试的 node_modules)。

├─.vscode
│      launch.json
│      settings.json
│      tasks.json
│          
├─src
│      extension.ts
│      
├─test
│       extension.test.ts
│       index.ts
│      
├─node_modules
│  ├─@types
│  │  ├─mocha
│  │  │      index.d.ts
│  │  │      
│  │  └─node
│  │          index.d.ts
│  │          
│  ├─typescript
│  │                  
│  └─vscode
│     │  thenable.d.ts
│     │  tslint.json
│     └─ vscode.d.ts     
│          
├─out
│  └─src
│     └─  extension.js
│  
│  .gitignore
│  .vscodeignore
│  package.json
│  README.md
│  tsconfig.json
└─ vsc-extension-quickstart.md

大体了解了整个项目的结构,让我们来看一下实际运行的效果。在 VS Code 中直接按 F5 即可启动调试。VS Code 会 启动一个新的 VS Code 窗口,在这个窗口中会额外加载我们的插件项目以便我们进行测试。

debug host

我们按 F1 或者 ctrl+shift+p 输入 hello 就能发现我们刚刚注册的 command。

debug host

执行这个 command 可以看到此时,我们项目调试控制台输出 Congratulations, your extension "vscode-extension" is now active! 插件的 activate 方法被调用。 VS Code 显示一个 Hello World 信息。

debug host

你可能会问,为什么我们的代码在我们真正执行了 command 的时候才会被激活,这是 VS Code 的一个优化。 vscode 可以直接根据 package.json 来展示插件定义的 command,而不必执行插件的代码, 保证 vscode 的启动速度。在这个插件模板中,我们注册了一个 title 为 Hello World 的 command。 activationEventsonCommand:extension.sayHello, 仅当我们执行这个 command 的时候,插件才被激活。 VS Code 才会真正开始执行我们的代码。

package.json

字段定义

名称 必需 类型 描述
name string 插件扩展的名称, 全部是小写字母,并且不能有空格.
version string 参考Semver. 例如: 1.0.0
publisher string 发布者名称
engines object 包含vscode字段的对象, 定义所需环境的版本。例如 ^1.5.0 表示需要1.5.0或者更高版本.
displayName   string 插件显示的名称.
description   string 插件的描述文本.
icon   string 插件使用的图标,大小为 128*128.
main   string 插件入口的相对路径,当插件启动时将调用入口文件的activate方法.
categories   string[] 插件的分类,常用分类有: [Languages, Snippets, Linters, Themes, Debuggers, Other].
contributes   object 插件扩展点的描述对象,详见 contributions.
activationEvents   string[] 插件激活事件的描述数组,详见 activation events.
keywords   string[] 插件的关键词,准确的关键词有助于更好的找到插件.
dependencies   object 插件依赖的 Node.js 库. 参见 npm dependencies.
devDependencies   object 插件开发环境下依赖的 Node.js 库. 例如,如果插件使用TypeScript编写,则开发环境需要依赖 typescript. 参见 npm devDependencies.
extensionDependencies   string[] 插件依赖的其他插件的id. 插件id为 ${publisher}.${name}. 例如: egret.text-tools.
scripts   object 详见 npm scripts

contributes(扩展点)

扩展点允许开发者在 vscode 中自定义一些扩展功能。

contributes.commands

自定义命令 command 。定义的命令可以在命令面板(Command Palette)中找到并执行。

Note: 当命令通过快捷键或者命令面板被执行时, 将派发 activationEvent onCommand:${command}.

可使用下列字段:

名称 必需 类型 描述
command string 表示命令的唯一id.
title string 表示命令的名称,此属性将显示在命令面板中.
例子
...
"contributes": {
	"commands": [{
		"command": "extension.sayHello",
		"title": "Hello World"
	}]
}
...

contributes.keybindings

自定义快捷键 keybinding。可以自定义命令执行的按键绑定。

Note: 可以定义不同操作系统平台的快捷键。

Note: 当命令通过快捷键或者命令面板被执行时, 将派发 activationEvent onCommand:${command}.

可使用下列字段:

名称 必需 类型 描述
command string 快捷键绑定的命令的id
key string 快捷键的按键组合,可以的按键的组合字符串参见 附录1 .
win   string 在windows平台下的按键组合,如果用户在windows下,此属性将覆盖key字段指定的按键组合.
mac   string 在mac平台下的按键组合,如果用户在mac下,此属性将覆盖key字段指定的按键组合.
when   string 快捷键何时被触发的表达式,可用的属性值参见 附录2 .
附录1 key字段可用的按键组合字符串规则

按键规则一般由组合键 + 其他按键组成。

组合按键表示如下:

操作系统 组合键
MACOS X ctrl+, shift+, alt+, cmd+
Windows ctrl+, shift+, alt+, win+

Note: 特殊的可以使用 ctrlcmd 表示windows下的ctrl, mac下的cmd

其他按键表示如下:

使用空格分割的按键序列,例如(ctrl+k ctrl+c),表示先按ctrl+k,再按ctrl+c 才能触发该快捷键。

如果要使某一命令既可以按ctrl+k触发,又可以按ctrl+c触发,请定义两组keybinding,command相同,但是key字段不同。

附录2 when字段可用的字符串

when字段可以使用 !, &&, ==, != 等表达式限定条件。如

!inDebugMode , editorTextFocus && editorLangId == 'ts' 都是可用的表达式。

例子

定义命令 "extension.sayHello" 的windows下快捷键为 Ctrl+F1,mac下快捷键为 Cmd+Shift+F1 :

...
"contributes": {
	"keybindings": [{
		"command": "extension.sayHello",
		"key": "ctrl+f1",
		"mac": "cmd+shift+f1",
		"when": "editorTextFocus"
	}]
}
...

contributes.configuration

提供可设置的选项,用户可以在全局或者工作空间的设置中修改这些设置信息。

插件的开发者需要提供一套 JSON schema 来描述这些可以配置的选项,这样用户在修改时,能够得到编辑器的智能提示。

你可以通过下面的方法来读取用户自定义的配置信息 vscode.workspace.getConfiguration('myExtension').

例子
...
"contributes": {
	"configuration": {
		"type": "object",
		"title": "TypeScript configuration",
		"properties": {
			"typescript.useCodeSnippetsOnMethodSuggest": {
				"type": "boolean",
				"default": false,
				"description": "Complete functions with their parameter signature."
			},
			"typescript.tsdk": {
				"type": "string",
				"default": null,
				"description": "Specifies the folder path containing the tsserver and lib*.d.ts files to use."
			}
		}
	}
}

contributes.languages

提供一种新语言的信息,以便 VS Code 能够支持它的开发.

这这一节中, language 一般是指一个跟文件名相关的id (See TextDocument.getLanguageId()).

VS Code 有三种方式确定一个文件使用的开发语言,这三种方式可以独立使用

  1. 文件的扩展名 (下面说的 extensions)
  2. 文件名 ( 下面说的 filenames)
  3. 文件的第一行中的文本 (下面说的 firstLine)

最后一项 VS Code 需要的信息就是 aliases:语言的别名,这个属性值列表的第一个会作为语言的显示名称,显示在编辑器的右下角和语言选择列表中。

当用户打开了一个文件,VS Code会用这三个规则匹配文件,来确认文件所使用的语言,同时,VS Code会抛出一个 activationEvent onLanguage:${language}(例如下面例子的 onLanguage:python),来激活对应的插件。

例子
...
"contributes": {
	"languages": [{
		"id": "python",
		"extensions": [ ".py" ],
		"aliases": [ "Python", "py" ],
		"filenames": [ ... ]
		"firstLine": "^#!/.*\\bpython[0-9.-]*\\b"
	}]
}

contributes.debuggers

为 VS Code 提供一个 debug 适配器,帮助 VS Code 连接到一个外部的 debug 服务,扩展 VS Code 的调试功能。

debug 适配器运行在一个单独的进程中,与 VS Code 之间采用特定的协议来通信。你需要提供至少一个可执行的脚本来实现这个 debug 适配器。

例子
...
"contributes": {
	"debuggers": [{
        	"type": "node",
        	"program": "./debugger/out/node/nodeDebug.js",
        	"runtime": "node",
        	"enableBreakpointsFor": { "languageIds": ["javascript", "typescript", "coffeescript"] }
        }]
}
...

contributes.grammars

提供一套 TextMate grammar 来为 VS Code 添加语言支持。你需要提供,这组语法需要适配的语言 language,语法的 TextMate scopeName 值,和 语法定义文件的路径

注意: 语法定义文件的格式可以是 JSON (扩展名 .json) 或 XML plist 格式 (如果扩展名不是 json 就认为是这种格式).

例子
...
"contributes": {
	"grammars": [{
		"language": "shellscript",
		"scopeName": "source.shell",
		"path": "./syntaxes/Shell-Unix-Bash.tmLanguage"
	}]
}
...

contributes.themes

为 VS Code 提供一个 TextMate theme 代码配色主题。你需要指定一个 label 表明这个主题是暗色主题还是浅色主题,还有主题文件的路径(XML plist 格式)

例子
"contributes": {
	"themes": [{
		"label": "Monokai",
		"uiTheme": "vs-dark",
		"path": "./themes/Monokai.tmTheme"
	}]
}

contributes.snippets

"contributes": {
	"snippets": [{
			"language": "go",
			"path": "./snippets/go.json"
	}]
}

contributes.jsonValidation

提供特定 json 文件的 JSON schema, url可以是插件中内置的文件,或者一个远程的url,例如 json schema store

"contributes": {
    "jsonValidation": [{ 
 		"fileMatch": ".jshintrc",
 		"url": "http://json.schemastore.org/jshintrc"
	}]
} 

更多信息可以参考 Extension Manifest File - package.json

下面,让我们来写一个 即时预览 TypeScript 执行的插件。VS Code 插件示例,一个 TypeScript 即时预览插件