├── .nojekyll ├── docs ├── .nojekyll ├── extensibility-reference │ ├── vscode-api.md │ ├── overview.md │ ├── api-markdown.md │ ├── document-selectors.md │ ├── activation-events.md │ ├── principles-patterns.md │ ├── api-scm.md │ └── api-debugging.md ├── advanced-topics │ ├── extension-host.md │ └── using-proposed-api.md ├── references │ ├── icons-in-labels.md │ ├── vscode-api.md │ ├── document-selector.md │ ├── activation-events.md │ ├── commands.md │ └── extension-guidelines.md ├── extension-guides │ ├── custom-data-extension.md │ ├── markdown-extension.md │ ├── task-provider.md │ ├── product-icon-theme.md │ ├── color-theme.md │ ├── virtual-documents.md │ ├── file-icon-theme.md │ ├── tree-view.md │ ├── command.md │ └── scm-provider.md ├── get-started │ ├── wrapping-up.md │ ├── your-first-extension.md │ └── extension-anatomy.md ├── extension-capabilities │ ├── theming.md │ ├── extending-workbench.md │ ├── README.md │ └── common-capabilities.md ├── preknowledge │ ├── first-step.md │ ├── declaration-files.md │ ├── class.md │ └── generics.md ├── language-extensions │ ├── snippet-guide.md │ ├── README.md │ └── language-configuration-guide.md ├── README.md ├── extension-authoring │ ├── overview.md │ ├── extension-generator.md │ ├── samples.md │ ├── example-tasks.md │ ├── testing-extensions.md │ ├── developing-extensions.md │ ├── publish-extension.md │ ├── example-hello-world.md │ └── example-word-count.md ├── api │ └── README.md ├── _sidebar.md ├── working-with-extensions │ ├── continuous-integration.md │ ├── bundling-extension.md │ └── publish-extension.md └── _navbar.md ├── .prettierignore ├── resources └── favicon.ico ├── LICENSE ├── README.md └── Progress.md /.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | docsify.js -------------------------------------------------------------------------------- /resources/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Liiked/VS-Code-Extension-Doc-ZH/HEAD/resources/favicon.ico -------------------------------------------------------------------------------- /docs/extensibility-reference/vscode-api.md: -------------------------------------------------------------------------------- 1 | ## vscode 命名空间 API 2 | 3 | 由于本节内容平实,冗杂,且更新较快,日后若时间充裕再做翻译,目前请读者自行参阅官方原文档[vscode namespace API](https://code.visualstudio.com/docs/extensionAPI/vscode-api) -------------------------------------------------------------------------------- /docs/advanced-topics/extension-host.md: -------------------------------------------------------------------------------- 1 | # 插件主机 2 | 3 | 你已经在[插件诊断](/get-started/extension-anatomy)中学习了插件会将`active`和`deactive`声明周期函数暴露给VS Code,在本节我们来看看**插件主机/插件宿主(Extension Host)**是怎么管理所有运行中的插件的。 4 | 5 | **插件主机**是VS Code中负责加载和运行插件的Node.js进程,虽然你在写插件时不必关心这件事,但是掌握插件主机的运行原理对你创作插件还是非常有用的。 6 | 7 | ## 稳定性和性能 8 | --- 9 | 10 | VS Code致力于为用户提供一个稳定且高性能的编辑环境,因此出错的插件不应该影响到用户的体验。所以**插件主机**可以预防这些事情: 11 | 12 | - 启动性能影响 13 | - 阻塞的UI操作 14 | - 修改UI 15 | 16 | 另外,VS Code提供的[激活事件机制](/references/activation-events)也让插件只在用到时才懒加载它们,比如,Markdown插件应该只在用户打开了Markdown文件时才启动,因此避免了不必要CPU和内存消耗。 -------------------------------------------------------------------------------- /docs/references/icons-in-labels.md: -------------------------------------------------------------------------------- 1 | # 标签中的图标 2 | 3 | 你可以在插件中使用github提供的开源图标[Octicons](https://octicons.github.com/),你甚至可以在[`StatusBarItem`](https://code.visualstudio.com/api/references/vscode-api#StatusBarItem)文本和[`QuickPickItem`](https://code.visualstudio.com/api/references/vscode-api#QuickPickItem)标签中使用。添加图标的语法如下: 4 | 5 | ```typescript 6 | $(alert); 7 | ``` 8 | 9 | 你还可以像这样使用多个标签 10 | 11 | ```typescript 12 | $(eye) $(heart) $(mark-github) GitHub 13 | ``` 14 | 15 | #### 图标列表 16 | 17 | **图标列表**请参考[官方文档](https://code.visualstudio.com/api/references/icons-in-labels) -------------------------------------------------------------------------------- /docs/advanced-topics/using-proposed-api.md: -------------------------------------------------------------------------------- 1 | # 使用不稳定的API 2 | 3 | 在VS Code中,插件API的兼容性非常重要,我们尽最大努力避免API变动以便插件开发人员已经发布的插件可以按预期工作。但是,这对使得我们束手束脚,一旦新的API发布后,就不可能再轻易改动。 4 | 5 | 不稳定的API(Proposed API)则解决了这个问题,不稳定的API是VS Code已经实现但是还未公开的API。它们只在Insider版的VS Code中可用,而且很有可能再次产生变动,你也不能在想要发布的插件中使用。不管怎样,插件开发者开始可以在本地开发时测试这些API,然后给VS Code团队提供建议的,经过不断修改之后最终可能出现在稳定版中。 6 | 7 | ## 使用不稳定的API 8 | 9 | 下面是在本地开发中测试未稳定API的步骤: 10 | 11 | - 使用 VS Code的[Insider](https://code.visualstudio.com/insiders)版本 12 | - 在`package.json`中添加`"enableProposedApi": true` 13 | - 把最新的[`vscode.proposed.d.ts`](https://github.com/Microsoft/vscode/blob/master/src/vs/vscode.proposed.d.ts)复制到你的项目中 -------------------------------------------------------------------------------- /docs/extension-guides/custom-data-extension.md: -------------------------------------------------------------------------------- 1 | # 自定义数据插件 2 | 3 | [自定义数据格式](https://github.com/microsoft/vscode-custom-data) 可帮助插件作者轻松地扩展 VS Code 的 HTML / CSS 语言支持能力,且不用多写一行代码。 4 | 5 | 通过以下两个[配置点](/references/contribution-points) 可以使用自定义数据: 6 | - `contributes.html.customData` 7 | - `contributes.css.customData` 8 | 9 | 比如,在插件的`package.json`中配置这两行之后: 10 | ```json 11 | { 12 | "contributes": { 13 | "html": { 14 | "customData": ["./html.html-data.json"] 15 | }, 16 | "css": { 17 | "customData": ["./css.css-data.json"] 18 | } 19 | } 20 | } 21 | ``` 22 | 23 | VS Code 会根据这两个文件中定义的 HTML/CSS 实体,提供对应的语言支持能力,比如自动完成、悬停提示等。 24 | 25 | 你可以在 [自定义数据示例](https://github.com/microsoft/vscode-extension-samples/tree/master/custom-data-sample) 中查看。 -------------------------------------------------------------------------------- /docs/get-started/wrapping-up.md: -------------------------------------------------------------------------------- 1 | # 小结 2 | 3 | 在[你的第一个插件](/get-started/your-first-extension.md)中,你学会了如何创建,运行和调试插件。在[解析插件结构](/get-started/extension-anatomy.md)中,你学习了有关VS Code插件开发的基本概念。但是我们现在还只看到了冰山一角,下面我们提供了进一步打磨你开发插件能力的章节索引。 4 | 5 | ## 开发插件 6 | 这一章内容将教你如何开发高质量VS Code插件。你将会学到: 7 | 8 | - 如何为你的插件提供[集成测试](/working-with-extensions/testing-extension) 9 | - 如何将你的插件发布到[插件市场](https://marketplace.visualstudio.com/) 10 | - 如何为你的插件建立[持续集成](/working-with-extensions/continuous-integration) 11 | 12 | ## 插件功能 13 | 14 | 在这一章中,我们把[VS Code API](/references/vscode-api)和[发布内容配置](/references/contribution-points)分成了不同类别,每个分类都是某一功能的简明教程。在这个章节你可以验证自己的插件灵感是否可行,或者从中找到新的创作想法。 15 | 16 | ## 指南和示例 17 | 18 | 我们提供了大量示例插件,一些插件源码还包含了详细的指南,你可以在[插件指南列表](/extension-guides/README.md)找到全部的指南和示例,或者查看[vscode-extension-samples](https://github.com/Microsoft/vscode-extension-samples)仓库。 -------------------------------------------------------------------------------- /docs/extension-capabilities/theming.md: -------------------------------------------------------------------------------- 1 | # 主题 2 | 3 | VS Code中的主题分为两类: 4 | - **色彩主题**:UI组件ID和文本符号ID到色彩间的映射。通过色彩主题你可以修改VS Code UI组和编辑器中的文本。 5 | - **图标主题**:文件类型/名称到图片之间的映射。文件图标显示于VS Code的资源管理侧边栏、快速打开列表和编辑器Tab等UI中。 6 | 7 | ## 色彩主题 8 | --- 9 | 10 | ![color-theme](https://media.githubusercontent.com/media/Microsoft/vscode-docs/master/api/extension-capabilities/images/theming/color-theme.png) 11 | 12 | 如上图所示,色彩主题定义了2种映射: 13 | - `colors`控制UI组件的颜色 14 | - `tokenColors`控制了每个代码标记单元(你的代码会根据[语法](/language-extensions/syntax-highlight-guide)分割成一个个标记单元)的颜色。 15 | 16 | 创建主题详见[色彩主题指南](/extension-guides/color-theme)和[色彩主题 示例](https://github.com/Microsoft/vscode-extension-samples/tree/master/theme-sample) 17 | 18 | ## 图标主题 19 | --- 20 | 图标主题允许你: 21 | - 将图标ID映射至图片或者字体图标上。 22 | - 根据文件名或这个文件的语言类型关联上图标ID 23 | 24 | [图标主题指南](/extension-guides/icon-theme)会详细探讨其中的细节。 25 | ![file-icon-theme](https://media.githubusercontent.com/media/Microsoft/vscode-docs/master/api/extension-capabilities/images/theming/file-icon-theme.png) 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Square Coin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/preknowledge/first-step.md: -------------------------------------------------------------------------------- 1 | # 非JS开发者的第一步 2 | 3 | 本章节并不是官方教程的一部分,作为读者的你可能擅长于C++,Python,Java等其他主流语言,而并不了解基于现代前端技术构建的VS Code和他的插件开发语言和模式。本章参考了官方文档模式,循序渐进地带你了解制作插件的一些编程基础,以免你在阅读文档时晕头转向,本章结束之后,你应该能比较顺利地阅读文档中出现的所有TypeScript代码,没有障碍地学习VS Code插件基础,但是如果你希望达到一定程度的TypeScript编程水平,请参考[汉化版文档](https://www.tslang.cn/)。当然,**本章并不是所有读者必须阅读的,你可以按照自己的喜好或者需要,查询对应的小节,如果你有足够的经验也完全可以跳过本章**。 4 | 5 | ## 前端和客户端技术 6 | --- 7 | 8 | 众所周知,客户端界面技术已是一门非常“老古董”的技术了,从图形系统诞生至今,各类客户端开发技术和模式你方唱罢我登场,淘汰了一批又一批。而Web前端技术,在浏览器和网络技术的依托之下还在不断发展,在这期间浏览器对编译器孜孜不倦的优化,终于将JavaScript语言提升到了一个新的高度,使JavaScript语言进入了传统客户端领域,但是作为开发者必须意识到,即使是在TypeScript的加持下,JavaScript也并没有变成一门真正的静态类型语言,**因此你在使用TypeScript的时候依旧需要谨慎行事并遵守社区的最佳实践**。 9 | 10 | 我们教程学习的对象VS Code,便是建立在浏览器开源项目Chromium演化而来——名为Electron的客户端技术之上,它使用了性能极高的JS编译器和浏览器界面技术,**将前端的三大编程基础JavaScript,HTML,CSS无缝地衔接进来,并融合了系统层级的编程接口**。而VS Code在此之上进一步封装和优化,将编辑器进程和插件进程独立开来,同时高度封装DOM(文档对象模型)接口,禁止用户直接修改界面,我们只能通过VS Code提供的模式去开发符合规范的插件,虽然这些规定限制了开发者的手脚,但是更带来了安全、稳健、性能上的优势。 11 | 12 | ## TypeScript和VS Code 13 | --- 14 | 15 | TypeScript起初是微软开发的以JavaScript为基础的编程语言,他兼容JavaScript的所有特性,并扩展了JS的类型系统,使得用户在大型系统开发中更加游刃有余,VS Code天然支持TypeScript,帮助开发者写出更加稳定、安全的代码。因此所有文档的示例,包括插件本身,绝大部分都是使用TypeScript开发的,俗话说“不积跬步无以至千里”,当你足够了插件的基础之后,阅读文档才会更加顺利。 16 | 17 | 由于VS Code已经禁用了CSS和HTML,因此本章不会介绍这些内容,有兴趣的读者可参阅[MDN文档](https://developer.mozilla.org/zh-CN/docs/Web) 18 | -------------------------------------------------------------------------------- /docs/extensibility-reference/overview.md: -------------------------------------------------------------------------------- 1 | # 扩展性参考 2 | 3 | 本章内容将深入到VS Code扩展性细节中一窥究竟。在我们着手深入之前,你最好能重新看一下[插件介绍](extension-authoring/overview.md)和[Hello World](/extension-authoring/example-hello-world.md)示例,以免你接触本章内容后感到脑壳疼。 4 | 5 | 查看VS Code插件最简单的方法就是上[插件市场](https://code.visualstudio.com/docs/editor/extension-gallery),如果你构建好了你的第一个应用,就可以[发布](/extension-authoring/publish-extension.md)上去给其他人使用了。 6 | 7 | ## 扩展性文档索引 8 | 9 | 本章文档将着重介绍下列主题: 10 | 11 | 12 | | 主题 | 描述 | 13 | | ---- | ---- | 14 | | [package.json 插件配置清单](/extensibility-reference/extension-manifest.md) | 每个VS Code 插件根目录都配有一个`package.json`清单文件,这个文件提供插件概览和一些必须的字段 | 15 | | [发布内容配置点](/extensibility-reference/contribution-points.md) | 基于`package.json`的配置内容,你可以添加诸如:commands, themes, debuggers……的插件配置 | 16 | | [激活事件](/extensibility-reference/activation-events.md) | VS Code对插件执行懒加载机制。这篇文档提供了`package.json`中可用于激活的配置点,比如在特定文档打开时激活,命令触发时激活等等 | 17 | | [API vscode 命名空间](/extensibility-reference/vscode-api.md) | 查看完整的vscode命名空间API | 18 | | [API 复杂命令](/extensibility-reference/vscode-api-commands.md) | 查看VS Code中的复杂命令API | 19 | | [用于调试的API](/extensibility-reference/api-debugging.md) | 学习将调试器和VS Code配合使用的细节 | 20 | | [API 示例](/extension-authoring/samples.md) | 学习VS Code插件API的有关示例 | 21 | | [Markdown插件API](/extensibility-reference/api-markdown.md) | 学习VS Code插件API的有关示例 | 22 | 23 | ## 语言插件指引 24 | 25 | 如果你正在实现编程语言支持,可以参考[语言插件指引](extensibility-reference/language-extension-guidelines)主题,这节内容提供了VS Code可以使用的各种各样的语言特性(比如:代码建议、代码行为、格式化、重命名等)和教你如何实现它们。 -------------------------------------------------------------------------------- /docs/language-extensions/snippet-guide.md: -------------------------------------------------------------------------------- 1 | # 代码片段 2 | 3 | [`contributes.snippets`](/extensibility-reference/contribution-points#contributessnippets)配置允许你将*代码片段*打包进VS Code插件中。 4 | 5 | [创建代码片段](https://code.visualstudio.com/docs/editor/userdefinedsnippets#_creating-your-own-snippets)主题详细介绍了新建代码片段的全部内容。本篇指南只是告诉你关于打包*代码片段*的大体思路。比较推荐的做法是: 6 | 7 | - 用`Preferences: Configure User Snippets`命令创建和调试代码片段。 8 | - 如果你觉得满意了,将整个JSON文件复制到插件目录下,起个名字比如说`snippets.json`文件。 9 | - 将下列配置添加到你的`package.json`中 10 | 11 | ```json 12 | { 13 | "contributes": { 14 | "snippets": [ 15 | { 16 | "language": "javascript", 17 | "path": "./snippets.json" 18 | } 19 | ] 20 | } 21 | } 22 | ``` 23 | 24 | 本篇的源代码在[https://github.com/Microsoft/vscode-extension-samples/tree/master/snippet-sample](https://github.com/Microsoft/vscode-extension-samples/tree/master/snippet-sample) 25 | 26 | ?> 提示:在`package.json`中添加如下分类,用户才能轻松找到你的插件。 27 | 28 | ```json 29 | { 30 | "categories": ["Snippets"] 31 | } 32 | ``` 33 | 34 | ## 使用TextMate代码片段 35 | --- 36 | 37 | 你也可以用[yo code](/get-started/your-first-extension)将TextMate代码片段(.tmSnippets)直接添加到插件里去。生成器中的可选项`New Code Snippets`会帮你指向.tmSnippets的目录,它们最后都会一起打包到VS Code 插件里。生成器甚至还支持Sublime代码片段(.sublime-snippets)。 38 | 39 | 生成器最终输出的文件有两个:一份插件清单`package.json`,和一份转换为VS Code代码片段的`snippets.json`。 40 | 41 | ```bash 42 | . 43 | ├── snippets // VS Code integration 44 | │ └── snippets.json // The JSON file w/ the snippets 45 | └── package.json // extension's manifest 46 | ``` 47 | 48 | 把生成的代码片段文件夹复制到你的`.vscode/extensions`下的新文件夹中,然后重启VS Code。 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VS Code 插件开发文档 2 | 3 | ![Maintenance](https://img.shields.io/maintenance/yes/2021?style=for-the-badge) 4 | ![GitHub last commit](https://img.shields.io/github/last-commit/liiked/VS-Code-Extension-Doc-ZH?style=for-the-badge) 5 | 6 | 7 | 欢迎来到为巨硬填坑的中文文档😆 8 | [📚 中文文档(github 版)](https://liiked.github.io/VS-Code-Extension-Doc-ZH/) 9 | 10 | [📚 原文档](https://code.visualstudio.com/docs/extensions/overview) 11 | 12 | ## 提问、纠错和参与 13 | 14 | - **提问**:欢迎大家在[issue区](https://github.com/Liiked/VS-Code-Extension-Doc-ZH/issues/104)对插件开发进行提问,虽然这里不是官方答疑平台,不过你可以在[讨论区](https://github.com/Liiked/VS-Code-Extension-Doc-ZH/discussions)和国内的插件开发者进行交流。具体的开发问题,可以参考 VS Code 官方提供的 [`Stack Overflow` 中 VS Code 相关问题标签](https://stackoverflow.com/questions/tagged/visual-studio-code)、[Gitter 频道](https://gitter.im/Microsoft/vscode) 和 [VS Code Dev Slack 讨论区](https://join.slack.com/t/vscode-dev-community/shared_invite/enQtMjIxOTgxNDE3NzM0LWU5M2ZiZDU1YjBlMzdlZjA2YjBjYzRhYTM5NTgzMTAxMjdiNWU0ZmQzYWI3MWU5N2Q1YjBiYmQ4MzY0NDE1MzY)。 15 | 16 | - **纠错和润饰**:在翻译过程中难免会出现笔误、翻译不到位、存在优化空间等情况,当然最严重的应属于翻译的章节或者片段难以理解,请在[issue](https://github.com/Liiked/VS-Code-Extension-Doc-ZH/issues/104)中不吝赐教,我们会优先处理这类问题。 17 | 18 | - **参与**:由于国内已经有过一版VS Code文档的社区翻译版本,但是质量,emmmmm……,所以本项目会采取较为严格的翻译审查,若你有热情一同学习和贡献自己的力量,请参考我们的翻译指南。 19 | 20 | ## 翻译计划 21 | 22 | 翻译计划见[项目计划](https://github.com/Liiked/VS-Code-Extension-Doc-ZH/projects/2) 23 | 24 | 如果你有兴趣、能力和时间,欢迎[贡献代码](https://github.com/Liiked/VS-Code-Extension-Doc-ZH/issues/104) 25 | 26 | ## 特别感谢 27 | 28 | [//]: contributor-faces 29 | 30 | 31 | 32 | [//]: contributor-faces -------------------------------------------------------------------------------- /docs/extension-capabilities/extending-workbench.md: -------------------------------------------------------------------------------- 1 | # 扩展工作台 2 | “工作台”是指整个VS Code UI和其中包含的下列UI 组件: 3 | - 标题栏 4 | - 活动栏 5 | - 侧边栏 6 | - 面板 7 | - 编辑器群 8 | - 状态栏 9 | 10 | VS Code提供了各式各样的API让在工作台你添加自己的组件。比如下图: 11 | 12 | ![workbench-contribution](https://code.visualstudio.com/assets/api/extension-capabilities/extending-workbench/workbench-contribution.png) 13 | 14 | - 活动栏:[Azure App Service extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azureappservice)添加了一个[视图容器](#视图容器) 15 | - 侧边栏:内置的[NPM 插件](https://github.com/Microsoft/vscode/tree/master/extensions/npm) 添加了一个 [Tree View](#树视图) 到资源管理器视图 16 | - 编辑器群:内置的[Markdown 插件](https://github.com/Microsoft/vscode/tree/master/extensions/markdown-language-features) 添加了一个[Webview](#webview) 到编辑器的旁边 17 | - 状态栏:[VSCodeVim 插件](https://marketplace.visualstudio.com/items?itemName=vscodevim.vim) 添加了一个[状态栏项目](#状态栏项) 18 | 19 | ## 视图容器 20 | --- 21 | 22 | 在[`contributes.viewsContainers`](/extensibility-reference/contribution-points?id=contributesviewscontainers)发布内容配置中,你可以添加新的视图容器在5个内置的视图容器中。学习更多[树视图](/extension-guides/tree-view)。 23 | 24 | ## 树视图 25 | --- 26 | 27 | 在[`contributes.views`](/extensibility-reference/contribution-points?#contributesviews)发布内容配置中,你可以添加在任何视图容器岁添加新的视图。学习更多[树视图](/extension-guides/tree-view)。 28 | 29 | ## Webview 30 | --- 31 | 32 | Webview是使用HTML/CSS/JS高度定制的视图。它们显示在编辑器区域中。详见[Webview指南](/extension-guides/webview)。 33 | 34 | ## 状态栏项 35 | --- 36 | 37 | 插件可以创建自定义的[`StatusBarItem`](https://code.visualstudio.com/api/references/vscode-api#StatusBarItem)显示在状态栏中。状态栏项可以显示文本和图标,还可以在点击事件触发时运行命令。 38 | 39 | - 显示文本和图标 40 | - 点击时运行命令 41 | 42 | 状态栏插件的例子可以[戳这里](https://github.com/Microsoft/vscode-extension-samples/tree/master/statusbar-sample) 43 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # 术语表和说明 2 | 3 | !> **注意:**本项目不支持低版本浏览器和IE浏览器 4 | 5 | ## 提问、纠错和参与 6 | --- 7 | - **提问**:欢迎大家在issue区对插件开发进行提问,虽然这里不是官方答疑平台,不过你可以在这里和国内的插件开发者进行交流。 8 | 9 | - **纠错和润饰**:在翻译过程中难免会出现笔误、翻译不到位、存在优化空间等情况,当然最严重的应属于翻译的章节或者片段难以理解,请在issue中不吝赐教,我们会优先处理这类问题。 10 | 11 | - **参与**:由于国内已经有过一版VS Code文档的社区翻译版本,但是质量,emmmmm……,所以本项目会采取较为严格的翻译审查,若你有热情一同学习和贡献自己的力量,请参考我们的[开发和翻译指南](https://github.com/Liiked/VS-Code-Extension-Doc-ZH)。 12 | 13 | ## 术语表 14 | --- 15 | 术语表收录出现在VS Code中独有的或是易引起歧义的词汇,不包含常见词汇,如Extension。该表按首字母排序。 16 | 该表格式: 17 | - 普通词汇 `英文名称 术语名称` 18 | - 单义词 `[出处或参考解释链接]() 术语名称:解释` 19 | - 多义词 `[出处或参考解释链接]() 术语名称1/术语名称2:解释` 20 | 21 | [terms]: 该术语表是术语表插件的源数据,激活术语表插件的关键字即下述链接后的文字请用逗号分隔,术语描述则是冒号后面的内容 22 | 23 | - [Activation Events](https://code.visualstudio.com/docs/extensionAPI/overview) 激活事件:用于激活插件的VS Code事件钩子。 24 | - [Contribution Points](https://code.visualstudio.com/docs/extensionAPI/overview) 发布内容配置点:package.json的一部分,用于配置插件启动命令、用户可更改的插件配置,可以理解为插件的主要配置文件。 25 | - [Debug Adapter](https://code.visualstudio.com/docs/extensions/overview#_language-servers) 调试适配器:连接真正的调试程序(或运行时)和调试界面的插件称之为调试适配器。VS Code没有原生调试程序,而是依赖【调试器插件】调用通信协议(调试适配器协议)和VS Code的调试器界面实现。 26 | - [Extension Manifest](https://code.visualstudio.com/docs/extensionAPI/overview) 插件清单:VS Code自定义的pacakge.json文件,其中包含着插件的入口、配置等重要信息。 27 | - Extensibility 扩展性 28 | - [Extension Host](https://code.visualstudio.com/docs/extensionAPI/patterns-and-principles) 扩展主机:与VS Code主进程隔离的插件进程,插件运行的地方,开发者可在这个进程中调用VS Code提供的各类API。 29 | - [Language Servers](https://code.visualstudio.com/docs/extensions/overview#_language-servers) 语言服务器:插件模式中使用C/S结构的的服务器端,用于高消耗的特殊插件场景,如语言解析、智能提示等。与之相对,客户端则是普通的插件,两者通过VS Code 的API进行通信。 30 | - [Language Identifier](https://code.visualstudio.com/docs/languages/identifiers) 语言标识符:定义在发布内容配置的特定标识/名称,便于后续引用该语言配置。通常为某种编程语言的通俗名称,如JavaScript的语言标识符是【javascript】,Python的语言标识符是【python】。 -------------------------------------------------------------------------------- /docs/references/vscode-api.md: -------------------------------------------------------------------------------- 1 | # VS Code API 2 | 3 | **VS Code API**是VS Code提供给插件使用的一系列Javascript API。 4 | 5 | !> 注意:VS Code API 变动较快,翻译版本的参与人员和精力有限无法保证实时跟进,有需要的小伙伴请自行参考[官方文档](https://code.visualstudio.com/api/references/vscode-api),其中包含了完整而且是最新的VS Code API列表。 6 | 7 | ## API模式 8 | --- 9 | 10 | 以下将介绍我们在VS Code中经常使用的API模式。 11 | 12 | #### Promises(异步) 13 | 14 | VS Code API完全采用了promise的实现。对于插件来说允许任何promise形式的返回格式,如ES6,WinJS,A+等。 15 | 16 | 一个promise库需要它的API使用`Thenable`类型来表达,`Thenable`类型代表了一种通用特性的实现——then方法。 17 | 18 | 大多数时候promise是一个可选项,VS Code调用插件之后,它能直接处理正常的返回结果也能处理`Thenable`的结果类型。当promise是可选的API返回结果时,API会在返回类型中用`Thenable`表示。 19 | 20 | ```typescript 21 | provideNumber(): number | Thenable 22 | ``` 23 | 24 | #### Cancellation Tokens(取消式令牌) 25 | 26 | 有些事件可能从不稳定的变化状态开始,而随着状态变化这一事件最后肯能被取消了。比如:IntelliSense(智能补全)被触发后,用户持续输入的行为使得这一操作最终被取消了。 27 | 28 | API也为这种行为提供了解决方案,你可以通过`CancellationToken`检查取消的状态(`isCancellationRequested`)或者当*取消*发生时得到通知(`onCancellationRequested`)。取消式令牌通常是API函数的最后一个(可选)参数。 29 | 30 | #### Disposables(释放器) 31 | 32 | VS Code API使用了[释放器模式](https://en.wikipedia.org/wiki/Dispose_pattern),这个模式被用于事件侦听,命令,UI交互和各类语言配置上。 33 | 34 | 例如:`setStatusBarMessage(value: string)`事件返回一个`Disposable`对象,这个对象最终调用`dispose`方法移除message。 35 | 36 | #### Events(事件) 37 | 38 | 事件在API中被暴露为函数,当你订阅一个事件侦听器时绑定。事件侦听器调用后会返回一个`Disposable`,它会在dispose触发后,移除事件侦听器。 39 | 40 | ```typescript 41 | var listener = function(event) { 42 | console.log("It happened", event); 43 | }; 44 | 45 | // 开始侦听 46 | var subscription = fsWatcher.onDidDelete(listener); 47 | 48 | // 你的代码 49 | 50 | subscription.dispose(); // 停止侦听 51 | ``` 52 | 53 | 事件的命名规则遵循`on[Will | Did] 动词 + 名词`的形式。通过`onWill`表示将要发生,`onDid`表示已经发生,`动词`表示行为,`名词`指代上下文或目标。 54 | 55 | 举个栗子:`window.onDidChangeActiveTextEditor`中,激活的编辑器(ActiveTextEditor:`名词`)变动(change:`动词`)后(`onDid`)会触发事件。 56 | 57 | #### 严格null检查 58 | 59 | VS CodeAPI使用`undefined`和`null`的Typescript类型,同样也支持[严格null检查](https://github.com/Microsoft/TypeScript/pull/7140)。 60 | -------------------------------------------------------------------------------- /docs/extension-authoring/overview.md: -------------------------------------------------------------------------------- 1 | # 扩展Visual Studio Code 2 | 所有的VS Code插件都共享一套注册、加载和连接`VS Code extensibility API`的通用模型,但其中有两大插件类型与通用插件模型有些许出入——`语言服务器`和`调试器`。他们有一些专属的调用协议,我们会在后面的章节里单独介绍这两个插件类型。 3 | 4 | - 插件类型 5 | - [普通插件](#插件) - 基本的插件类型 6 | - [语言服务器](#语言服务器) - 高IO/CPU密集型任务的插件 7 | - [调试器](#调试适配器debug-adapter) - 通过`调试适配器`连接外部调试器的插件 8 | 9 | ![调用示意图](https://raw.githubusercontent.com/Microsoft/vscode-docs/master/api/language-extensions/images/language-server-extension-guide/extensibility-architecture.png) 10 | 11 | ## 插件 12 | --- 13 | 14 | 插件激活后会运行在我们的共享插件主机环境(shared extension host process)中,这种插件进程分离的设计确保VS Code能在繁杂的任务中不会宕机。 15 | 16 | 插件能够的运行的时机包括: 17 | - `激活`:当检测到某类文件/存在某类文件/使用命令面板/使用组合键时,加载插件 18 | - `工作区`:打开编辑器、状态栏、信息提示 19 | - `事件`:编辑器的生命周期事件,如:`open, close, change`等等 20 | - `编辑器`:读取文件,操作和选择文本 21 | - `编辑器加强`:加强诸如IntelliSense,Peek,Hover,Diagnostics等富文本编辑支持功能 22 | 23 | 我们提供了两个端到端的基础教程,供你快速入门: 24 | 1. [Hello World](/extension-authoring/example-hello-world) - 生成一个本地运行的基础插件,了解插件的目录结构、配置文件,理解`激活`的触发机制。 25 | 2. [Word Count](docs/extension-authoring/example-word-count) - 根据特定的文件类型更新状态栏,响应编辑器的文本操作,学习文件被删除时该如何处理。 26 | 27 | 另外,首先建议你阅读一下[扩展性原则和模式](/extensibility-reference/principles-patterns)部分,能帮助你了解贯穿整个`extensibility API`的编程模式。 28 | 29 | ## 语言服务器 30 | 31 | 语言服务器是一种特殊的插件,它能加强VS Code中各种语言的编辑体验。有了语言服务器后,你可以实现诸如“转跳到定义”、“错误检查”和其他[语言功能](/extensibility-reference/language-extension-guidelines)了。 32 | 33 | ## 调试适配器(Debug Adapter) 34 | 35 | VS Code实现了一套原生的调试器UI,并通过`调试适配器`连接到`调试器插件`上。调试适配器专属进程控制VS Code和`VS Code debug protcol`的通信,它能通过任何语言来实现。 36 | 37 | 详情查看创建[调试器插件](/extension-authoring/example-debug-adapter) 38 | 39 | --- 40 | 41 | 尝试VS Code插件最简单的方式就是去[插件市场](https://code.visualstudio.com/docs/editor/extension-gallery),里面有非常多有用的插件,安装然后试试这些插件,你说不定会有所启发。 42 | 43 | ## 语言插件指南 44 | 45 | 通过`extensibility API`学习如何使用语言服务器协议——[语言插件指南](/extensibility-reference/language-extension-guidelines)。 46 | 47 | ## 主题,代码片段和高亮 48 | 49 | 在VS Code中你可以自定义主题、代码片段和语法高亮。通过TextMate配置文件,你可以很轻松地重用你原来的主题,或者你也可以在你的插件中直接使用`.tmTheme .tmSnippets .tmLanguage`文件。 50 | 51 | ## 写插件吧! 52 | 53 | 使用Yeoman[插件生成器](/extension-authoring/extension-generator)轻松创建插件项目。 54 | 55 | ## 测试你的插件 56 | 57 | 我们还提供了强力的[测试支持](/extension-authoring/testing-extensions),通过VS Code API轻松测试你的VS Code实例。 58 | 59 | ## 获取插件灵感 60 | 61 | 大量的社区灵感应该转化为插件而不是产品本身的功能,这样用户才有更广的选择余地,VS Code团队将潜在的插件打上了`*extension-candidate`标签,你可以通过[VS Code repository](https://github.com/Microsoft/vscode)的issue列表找到还在开发中的插件,为喜欢的插件贡献一份力量吧。 -------------------------------------------------------------------------------- /docs/api/README.md: -------------------------------------------------------------------------------- 1 | # 插件 API 2 | VS Code内置了扩展能力,在插件API加持之下,VS Code几乎每一个部分都可以自定义或者加强。而且,VS Code中的很多核心功能已编译为[插件](https://github.com/Microsoft/vscode/tree/master/extensions),它们都共用了一套插件API。 3 | 4 | 本文档将介绍: 5 | - 如何构建、运行、调试、测试和发布插件 6 | - 如何利用好VS Code丰富的插件API 7 | - 代码示例和各个指南的位置,方便你快速入门。如果你只是想看看已经发布的插件,可移步至[VS Code插件市场](https://marketplace.visualstudio.com/vscode) 8 | 9 | ## 插件能做什么? 10 | --- 11 | 12 | 下面我们看看使用插件API能做到些什么: 13 | - 改变VS Code的颜色和图标主题——[主题](/extension-capabilities/theming.md) 14 | - 在UI中添加自定义组件和视图——[扩展工作台](/extension-capabilities/extending-workbench.md) 15 | - 创建Webview,使用HTML/CSS/JS显示自定义网页——[Webview指南](/extension-guides/webview.md) 16 | - 支持新的编程语言——[语言插件概览](/language-extensions/README.md) 17 | - 支持特定运行时的调试——[调试插件指南](/extension-guides/debugger-extension.md) 18 | 19 | 如果你想大概浏览一下所有的插件API,请参阅[插件功能概述](/extension-capabilities/README.md)。[插件指南](/extension-guides/README.md)列出了各种插件API使用的示例代码和指南。 20 | 21 | ## 如何构建插件? 22 | --- 23 | 24 | 想要做出一个好插件需要花费不少精力,我们来看看这个教程的每个章节能为你做点什么: 25 | 26 | - **第一步** [Hello World示例]()会教你贯穿于制作插件时的基本概念 27 | - **开发插件** 包含了各类插件开发更深的主题,比如[发布]()和[测试]()插件 28 | - **插件功能** 将VS Code庞杂的API拆解成了几个小分类,帮你掌握到每个主题下的开发细节 29 | - **插件指南** 包括指南和代码实例,详细介绍特定API的使用场景 30 | - **语言插件** 通过代码和指南阐述如何添加编程语言支持 31 | - **进阶主题** 解释了[插件主机](/advanced-topics/extension-host.md)和[使用不稳定的API](/advanced-topics/using-proposed-api.md)等更深层级的概念 32 | 33 | ## 最新进度 34 | 35 | VS Code 每个月更新一次,插件 API 也随着每个版本的发布而更新。新功能和新的 API会在每个迭代中扩展 VS Code 插件的能力。 36 | 37 | 要想跟上潮流,你可以看看 **每月发布报告**,其中的以下部分是你需要关注的: 38 | - [Extension authoring](https://code.visualstudio.com/updates#_extension-authoring) - 学习新版中的插件 API 39 | - [Proposed extension APIs](https://code.visualstudio.com/updates#_proposed-extension-apis) - 给即将到来的实验性 API 提供反馈 40 | 41 | ## 寻求帮助 42 | --- 43 | 44 | 如果你在开发中遇到了问题,请尝试: 45 | - [ Stack Overflow](https://stackoverflow.com/questions/tagged/visual-studio-code):其中有将近[12k](https://stackoverflow.com/questions/tagged/visual-studio-code)个打了`visual-studio-code`标签的问题,而且半数以上都已经有了答案,搜索你遇到的问题,提问,或者帮助其他人解决VS Code中遇到的问题。 46 | 47 | - [Gitter频道](https://gitter.im/Microsoft/vscode)和[VS Code Dev Slack](https://join.slack.com/t/vscode-dev-community/shared_invite/enQtMjIxOTgxNDE3NzM0LWU5M2ZiZDU1YjBlMzdlZjA2YjBjYzRhYTM5NTgzMTAxMjdiNWU0ZmQzYWI3MWU5N2Q1YjBiYmQ4MzY0NDE1MzY):插件开发人员的公共聊天室,VS Code项目组成员偶尔也会出现。 48 | 49 | 你若对本文档有任何建议,请在[Microsoft/vscode-docs](https://github.com/Microsoft/vscode-docs/issues)中创建issue。如果你的插件问题无法解决,或者对VS Code插件API有任何建议,请在[Microsoft/vscode](https://github.com/Microsoft/vscode/issues)中新建issue。 -------------------------------------------------------------------------------- /docs/extension-authoring/extension-generator.md: -------------------------------------------------------------------------------- 1 | # 插件生成器 2 | 3 | ## 预先准备 4 | 你需要安装Node.js,并配置好`$PATH`。Node.js安装好之后通常会包含npm——Node.js的包管理器,也就是我们马上要用来安装插件生成器的东西。 5 | 6 | ## 安装生成器 7 | --- 8 | 在终端(windows环境下为cmd, powershell)输入 9 | ```bash 10 | npm install -g yo generator-code 11 | ``` 12 | 13 | #### 运行Yo Code😎 14 | 15 | 听起来好像有点啰嗦?我们马上就开始了,将下列命令输入到终端: 16 | ```bash 17 | yo code 18 | ``` 19 | ![run yo code](https://raw.githubusercontent.com/Microsoft/vscode-docs/master/docs/extensions/images/yocode/yocode.png) 20 | 21 | !> 注意:yo code会根据最新的vscode版本生成发开目录,如果遇到运行失败的问题,请检查`package.json`中`engines.vscode`的版本号是否与您当前的vscode一致 22 | 23 | ## 生成器选项 24 | --- 25 | > Yeoman生成器能帮你创建一个新插件的骨架,也可以基于已有的TetMate配置文件创建一个开箱即用的语言、主题或者片段。 26 | 27 | #### 新插件(TypeScript) 28 | 我们接下来要创建一个"hello world"项目作为本节示例,请: 29 | - 输入插件名称,在当前目录下生成同名文件夹 30 | - 新建几个基础文件夹,source,test,output 31 | - 模板生成器会创建`package.json`和一些基本文件 32 | - 新建`launch.json`和`tasks.json`,以便到时候按F5能debugger代码 33 | - (可选)生成Git仓库 34 | 35 | 创建好之后,用vscode打开这个文件夹,查看`vsc-extension-quickstart.md`,你就知道接下来要干什么了。 36 | 37 | #### 新插件(JavaScript) 38 | 和上面的过程一样,不过是用JavaScript语言。 39 | 40 | #### 新主题 41 | 基于已有的TextMate文件生成主题插件,或者直接来个全新的。 42 | - 推荐你使用已有的基础样式生成新的主题。 43 | - 根据`.tmTheme`文件生成一个新主题。 44 | 45 | 接下来: 46 | - 输入主题名称,同时会生成对应的色彩主题名称(light/dark)。 47 | - 输入插件名称,创建同名的项目文件夹。 48 | 49 | 同样,一旦你都做完了这些事情,去查看目录下的`vsc-extension-quickstart.md`吧。 50 | #### 新的语法高亮 51 | 生成一个色彩高亮插件 52 | - 输入已有的TextMate文件(.tmLanguage,.plist,.json),文件会自动导入到新插件中。如果你需要用新的语法创建高亮,把名字留空就行了。 53 | - 输入插件名称,你就能得到一个同名文件夹。 54 | 55 | #### 新的代码片段 56 | - 输入包含TextMate snippets (.tmSnippet) 或者 Sublime snippets (.sublime-snippet)的文件夹目录,这些文件待会会自动转为vscode代码片段。 57 | - 选择需要激活的编程语言 58 | - 输入插件名称,得到同名项目文件夹 59 | 60 | 然后继续去看`vsc-extension-quickstart.md`咯 61 | 62 | #### 新的插件包 63 | 用你喜欢的插件创建一个插件包 64 | - 输入已经安装的插件名称,加入到你的插件包里 65 | - 输入插件名称,得到同名项目文件夹 66 | 67 | ## 我的插件目录在哪? 68 | --- 69 | 每个操作系统的插件目录都不一样,你可能会用到的。 70 | 71 | ``` bash 72 | Windows %USERPROFILE%\.vscode\extensions 73 | macOS ~/.vscode/extensions 74 | Linux ~/.vscode/extensions 75 | ``` 76 | 如果你需要在每次vscode运行时加载插件,把你的项目复制到`.vscode/extensions`目录下。如:`~/.vscode/extensions/myextension` 77 | 78 | 79 | ## FAQ 80 | --- 81 | **问: 为什么`yo code`在我的windows 10上无法识别键盘方向键?** 82 | 83 | ![yo-workaround](https://raw.githubusercontent.com/Microsoft/vscode-docs/master/docs/extensions/images/yocode/yo-workaround.png) 84 | 85 | 答: 如果方向键没有任何反应,可以试试在管理员权限下运行终端。 86 | 87 | ## 下一步 88 | - [发布工具](/extension-authoring/publish-extension) 89 | - [Hello World](/extension-authoring/example-hello-world) 90 | - [其他例子](/extension-authoring/samples) -------------------------------------------------------------------------------- /docs/extension-authoring/samples.md: -------------------------------------------------------------------------------- 1 | # VS Code 插件示例 2 | 我们已经在一开始尝试了2个示例,也了解了不少核心概念: 3 | - [你的第一个插件](/extension-authoring/example-hello-world.md) - 阐释了扩展性的一些核心观念。 4 | - [计数器插件](/extension-authoring/example-word-count.md) - 在上面示例的基础上的另一个示例。 5 | 6 | ## 示例插件 7 | 8 | | 示例 | 描述 | 类型 | 已发布到市场 | 9 | | :----|:---- |:---- |:---- | 10 | | [字数计数器](https://github.com/Microsoft/vscode-wordcount) | 在状态栏展示Markdown文件的字数计数,我们提供了这个示例的[引导章节](/extension-authoring/example-hello-world.md) | 插件 | Y | 11 | | [MD工具](https://github.com/Microsoft/vscode-MDTools) | 为选中的文本提供诸如:转换大写,转换为HTML等功能 | 插件 | Y | 12 | | [装饰器](https://github.com/Microsoft/vscode-extension-samples/tree/master/decorator-sample) | 如何为编辑器中的文本添加入边框、颜色、鼠标指针,还有给miniMap添加高亮的示例 | 插件 | N | 13 | | [文本内容提供器](https://github.com/Microsoft/vscode-extension-samples/tree/master/contentprovider-sample) | 教你如何使用API命令,怎么用`TextDocumentContentProvider`API创建虚拟文档的例子 | 插件 | Y | 14 | | [TSLint](https://github.com/Microsoft/vscode-tslint) | 用这个插件校验Typescript文件语法 | 语言服务器 | Y | 15 | | [模拟调试器](https://github.com/Microsoft/vscode-mock-debug) | 帮你生成和测试调试器 | 调试器 | Y | 16 | | [GO语言支持](https://github.com/microsoft/vscode-go) | 为[Go Lang]提供丰富的语言支持——如:智能补全,调试,转跳,重命名变量,语法插件…… | 插件 | Y | 17 | | [树形数据提供器](https://github.com/Microsoft/vscode-extension-samples/tree/master/tree-view-sample) | 学习使用`TreeDataProvider`API,给VS Code加上自定义视图 | 插件 | N | 18 | 19 | ## 示例仓库 20 | 21 | 在[VS Code Extension Samples](https://github.com/Microsoft/vscode-extension-samples)里面有更多的VS Code 示例插件,你会发现示例基本上采用了最佳实践和最新的API。 22 | 23 | ## 文档 24 | --- 25 | 26 | 想要了解VS Code扩展性模型,请参阅: 27 | - [原则和模式](/extensibility-reference/principles-patterns.md) - 包含扩展性的核心观念和模式 28 | - [语言插件指引](/extensibility-reference/language-extension-guidelines.md) - 学习声明式的、程序式的语言集合。 29 | 30 | ## 构建插件的工具 31 | 32 | | 工具 | 目的 | 33 | | :----- | :----- | 34 | | [插件生成器](/extension-authoring/extension-generator.md) | 为了帮你实现一个基本的插件,我们提供了[Yeoman](http://yeoman.io/)生成器。这个插件能帮你初始化插件开发环境、API类型文件、相关的模块。这个插件的源码[在这](https://github.com/Microsoft/vscode-generator-code) | 35 | | [开发插件](http://yeoman.io/) | 我们努力为大家提供了一条简单的插件开发、调试之路 | 36 | | [发布工具](docs/extension-authoring/publish-extension.md) | 如果你的插件一切顺利,那就是时候把它分享到[插件市场](https://code.visualstudio.com/docs/editor/extension-gallery)上了,只需要一个非常简单的命令行工具。源码在[这里](https://github.com/Microsoft/vsce)哦 | 37 | 38 | ## 下一步 39 | 40 | - [插件市场](https://code.visualstudio.com/docs/editor/extension-gallery) - 学习更多关于VS Code公共插件市场的内容。 41 | - ['code'Yeoman 生成器](/extension-authoring/extension-generator.md) - 快速创建你的第一个VS Code插件。 42 | - [扩展性参阅](/extensibility-reference/overview.md) - 关于API的更多细节。 43 | -------------------------------------------------------------------------------- /docs/extensibility-reference/api-markdown.md: -------------------------------------------------------------------------------- 1 | # Markdown插件 2 | 3 | Markdown插件可以帮你扩展和加强VS Code内置的Markdown预览,包括改变预览的样式、添加新的Markdown语法。 4 | 5 | ## 用CSS改变Mark预览样式 6 | --- 7 | 配置CSS可以改变mark预览的布局和样式,在你的插件`pacakge.json`中注册`markdown.previewStyles`即可: 8 | 9 | ```json 10 | "contributes": { 11 | "markdown.previewStyles": [ 12 | "./style.css" 13 | ] 14 | } 15 | ``` 16 | `markdown.previewStyles`类型是插件根目录下的文件列表。 17 | 18 | 配置的样式会在用户的`"markdown.styles"`之前,内置Markdown预览样式之后加载。 19 | 20 | [Markdown Preview GitHub Styling](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-preview-github-styles)是一个如何将Markdown预览变成像GitHub渲染风格的好例子,在GitHub上去查看[源码](https://github.com/mjbvz/vscode-github-markdown-preview-style)吧 21 | 22 | ## 使用markdown-it插件添加新语法 23 | --- 24 | VS Code Markdown预览支持[CommonMark规格](https://spec.commonmark.org/),插件可以通过一个[markdown-it插件](https://github.com/markdown-it/markdown-it#syntax-extensions)添加新的Markdown语法。 25 | 26 | 首先,在你的插件`package.json`中配置`"markdown.markdownItPlugins"`: 27 | ```json 28 | "contributes": { 29 | "markdown.markdownItPlugins": true 30 | } 31 | ``` 32 | 然后在插件的主`activation`函数中,返回一个包含名`extendMarkdownIt`函数的对象。这个函数接收一个markdown-it实例,然后必须返回出新的markdown-it实例: 33 | ```typescript 34 | import * as vscode from 'vscode' 35 | 36 | export function activate(context: vscode.ExtensionContext) { 37 | return { 38 | extendMarkdownIt(md: any) { 39 | return md.use(require('markdown-it-emoji')); 40 | } 41 | } 42 | } 43 | ``` 44 | 若想配置多个markdown-it插件,只需多次链式调用`use`声明即可。 45 | ```typescript 46 | return md.use(require('markdown-it-emoji')).use(require('markdown-it-hashtag')); 47 | ``` 48 | Markdown预览第一次显示时,配置了markdown-it的插件会变成懒加载激活。 49 | 50 | [markdown-emoji](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-emoji)插件展示了如何使用markdown-it添加emoji支持,你可以在GitHub上查看Emoji插件的[源码](https://github.com/mjbvz/vscode-markdown-emoji)。 51 | 52 | 你可能还想了解: 53 | - markdown-it插件开发者[指南](https://github.com/markdown-it/markdown-it/blob/master/docs/development.md) 54 | - [现成的markdown-it插件](https://www.npmjs.com/browse/keyword/markdown-it-plugin) 55 | 56 | ## 用脚本添加进阶功能 57 | --- 58 | 对于进阶特性,在插件中配置可运行的脚本: 59 | ```json 60 | "contributes": { 61 | "markdown.previewScripts": [ 62 | "./main.js" 63 | ] 64 | } 65 | ``` 66 | 配置的脚本是异步加载的,每次内容变动还会重载。 67 | 68 | [Markdown Preview Mermaid Support](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid)插件展示了如何使用脚本添加[鱼骨图](https://knsv.github.io/mermaid/index.html)和流程图预览。在[这里](https://github.com/mjbvz/vscode-markdown-mermaid)查看插件源码。 69 | 70 | 71 | -------------------------------------------------------------------------------- /docs/extension-guides/markdown-extension.md: -------------------------------------------------------------------------------- 1 | # Markdown插件 2 | 3 | Markdown插件可以帮你扩展和加强VS Code内置的Markdown预览,包括改变预览的样式、添加新的Markdown语法。 4 | 5 | ## 用CSS改变Markdown预览样式 6 | --- 7 | 8 | 配置CSS可以改变markdown预览的布局和样式,在你的插件`pacakge.json`中注册`markdown.previewStyles`[发布内容配置](/references/contribution-points)即可: 9 | 10 | ```json 11 | "contributes": { 12 | "markdown.previewStyles": [ 13 | "./style.css" 14 | ] 15 | } 16 | ``` 17 | 18 | `markdown.previewStyles`类型是插件根目录下的文件列表。 19 | 20 | 配置的样式会在用户的`"markdown.styles"`之前,内置Markdown预览样式之后加载。 21 | 22 | [Markdown Preview GitHub Styling](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-preview-github-styles)是一个如何将Markdown预览变成像GitHub渲染风格的好例子,在GitHub上去查看[源码](https://github.com/mjbvz/vscode-github-markdown-preview-style)吧 23 | 24 | ## 使用markdown-it插件添加新语法 25 | --- 26 | 27 | VS Code Markdown预览支持[CommonMark规格](https://spec.commonmark.org/),插件可以通过一个[markdown-it插件](https://github.com/markdown-it/markdown-it#syntax-extensions)添加新的Markdown语法。 28 | 29 | 首先,在你的插件`package.json`中配置`"markdown.markdownItPlugins"`: 30 | 31 | ```json 32 | "contributes": { 33 | "markdown.markdownItPlugins": true 34 | } 35 | ``` 36 | 37 | 然后在插件的主`activation`函数中,返回一个包含名`extendMarkdownIt`函数的对象。这个函数接收一个markdown-it实例,然后必须返回出新的markdown-it实例: 38 | 39 | ```typescript 40 | import * as vscode from 'vscode' 41 | 42 | export function activate(context: vscode.ExtensionContext) { 43 | return { 44 | extendMarkdownIt(md: any) { 45 | return md.use(require('markdown-it-emoji')); 46 | } 47 | } 48 | } 49 | ``` 50 | 51 | 若想配置多个markdown-it插件,只需多次链式调用`use`声明即可。 52 | 53 | ```typescript 54 | return md.use(require('markdown-it-emoji')).use(require('markdown-it-hashtag')); 55 | ``` 56 | 57 | Markdown预览第一次显示时,配置了markdown-it的插件会变成懒加载激活。 58 | 59 | [markdown-emoji](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-emoji)插件展示了如何使用markdown-it添加emoji支持,你可以在GitHub上查看Emoji插件的[源码](https://github.com/mjbvz/vscode-markdown-emoji)。 60 | 61 | 你可能还想了解: 62 | 63 | - markdown-it插件开发者[指南](https://github.com/markdown-it/markdown-it/blob/master/docs/development.md) 64 | - [现成的markdown-it插件](https://www.npmjs.com/browse/keyword/markdown-it-plugin) 65 | 66 | ## 用脚本添加进阶功能 67 | --- 68 | 69 | 对于进阶特性,在插件中配置可运行的脚本: 70 | 71 | ```json 72 | "contributes": { 73 | "markdown.previewScripts": [ 74 | "./main.js" 75 | ] 76 | } 77 | ``` 78 | 79 | 配置的脚本是异步加载的,每次内容变动还会重载。 80 | 81 | [Markdown Preview Mermaid Support](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid)插件展示了如何使用脚本添加[鱼骨图](https://knsv.github.io/mermaid/index.html)和流程图预览。在[这里](https://github.com/mjbvz/vscode-markdown-mermaid)查看插件源码。 -------------------------------------------------------------------------------- /docs/extension-authoring/example-tasks.md: -------------------------------------------------------------------------------- 1 | # 示例-任务 2 | 3 | 通常,在VS Code中,用户可以通过`task.json`定义一个[任务](https://code.visualstudio.com/docs/editor/tasks)。不过在软件开发中,VS Code会自动检测某些任务。本节介绍了插件应该怎样自动检测任务,为最终用户提供任务。 4 | 5 | ## 定义任务 6 | --- 7 | 8 | 想要定义一个系统级别的任务,插件需要通过properties定义任务,在下面叫做Rake的例子中,任务是这样定义的: 9 | 10 | ?>**译者注:**rake是ruby实现的任务管理和自动构建工具,详细请参考[rake](https://rubygems.org/gems/rake/) 11 | 12 | ```json 13 | "taskDefinitions": [ 14 | { 15 | "type": "rake", 16 | "required": [ 17 | "task" 18 | ], 19 | "properties": { 20 | "task": { 21 | "type": "string", 22 | "description": "The Rake task to customize" 23 | }, 24 | "file": { 25 | "type": "string", 26 | "description": "The Rake file that provides the task. Can be omitted." 27 | } 28 | } 29 | } 30 | ] 31 | ``` 32 | 33 | 上面代码里面,我们为`rake`*任务集*配置了一个**任务定义**。任务定义有两个属性`task`和`file`,`task`是Rake任务的名字,file指向了包含任务的文件。`task`属性是必须的,`file`则为可选。如果省略了`file`属性,则会使用工作区根目录下名为rake的文件。 34 | 35 | ## 任务供应器函数 36 | --- 37 | 38 | 和语言供应器函数相同,任务供应器使插件支持代码补全,一个插件可以只注册一个任务供应器函数然后执行所有可用的任务集合。使用`vscode.tasks`命名空间达成这一目标: 39 | ```typescript 40 | import * as vscode from 'vscode'; 41 | 42 | let rakePromise: Thenable | undefined = undefined; 43 | const taskProvider = vscode.tasks.registerTaskProvider('rake', { 44 | provideTasks: () => { 45 | if (!rakePromise) { 46 | rakePromise = getRakeTasks(); 47 | } 48 | return rakePromise; 49 | }, 50 | resolveTask(_task: vscode.Task): vscode.Task | undefined { 51 | return undefined; 52 | } 53 | }); 54 | ``` 55 | 56 | 目前`resolveTask`只返回了`undefined`,而将来VS Code会通过这个方法优化任务的加载。 57 | 58 | `getRakeTasks`的实现做了下面的事情: 59 | - 使用`rake -AT -f Rakefile`命令列出rake文件中的所有rake任务 60 | - 转换为stdio输出 61 | - 对每个任务创建一个`vscode.task`实现 62 | 63 | 因为一个rake任务初始化需要`package.json`中有对应的任务定义,VS Code会用TypeScript接口定义出结构,像这样: 64 | 65 | ```typescript 66 | interface RakeTaskDefinition extends vscode.TaskDefinition { 67 | 68 | /** 69 | * The task name 70 | */ 71 | task: string; 72 | 73 | /** 74 | * The rake file containing the task 75 | */ 76 | file?: string; 77 | } 78 | ``` 79 | 80 | 假设我们的输出最终来自于一个叫`compile`的任务,那么对应的任务创建过程如下所示: 81 | ```typescript 82 | let task = new vscode.Task({ type: 'rake', task: 'compile' }, 'compile', 'rake', new vscode.ShellExecution('rake compile')); 83 | ``` 84 | 85 | 每个输出任务都对应着上述过程,最后通过调用`getRakeTasks`会返回一个任务数组。 86 | 87 | `ShellExecution`会针对不同的系统在shell中执行`rake compile`命令(如:在Windows下会在PowerShell中执行,Ubuntu则是bash)。如果某个任务需要直接执行进程(不通过shell生成),则可以使用`vscode.ProcessExecution`。`ProcessExecution`的优势在于插件可以完全控制传入进程的参数,`ShellExecution`则会使用shell命令转义(比如:bash中的*展开)。如果`ShellExecution`是通过单个命令创建的,那么插件需要在命令内部确保引号和转义符的正确使用(比如,如何处理空格)。 -------------------------------------------------------------------------------- /docs/extensibility-reference/document-selectors.md: -------------------------------------------------------------------------------- 1 | # 文档选择器 2 | 3 | 插件的特性可以通过语言、类型、位置等文档选择器类型加以筛选,本节将深入文档选择器、文档协议等插件创作者应该了解的内容。 4 | 5 | ### 不在磁盘上的文件 6 | 7 | 并不是所有文件都是储存在磁盘上的,比如一份刚刚创建的文件。除非特别指明,文档选择器通常会**应用**于所有文档类型。用[DocumentFilter](https://code.visualstudio.com/docs/extensionAPI/vscode-api#DocumentFilter)的`scheme`属性将协议范围缩小,比如说,`{ scheme: 'file', language: 'typescript' }`是特用于储存在磁盘上的TypeScript文件的。 8 | 9 | ## 文档选择器 10 | --- 11 | VS Code插件 API结合了特定的语言特性,通过文档选择器的[DocumentSelector](https://code.visualstudio.com/docs/extensionAPI/vscode-api#DocumentSelector)类型,可以支持如智能感知(IntelliSense)的特性,这是实现特定语言所支持特性的最为简单的机制。 12 | 13 | 下面的片段注册了一个TypeScript文件的[HoverProvider](https://code.visualstudio.com/docs/extensionAPI/vscode-api#HoverProvider),文档选择器以`typescript`作为语言标识符。 14 | 15 | ```typescript 16 | vscode.languages.registerHoverProvider('typescript', { 17 | provideHover(doc: vscode.TextDocument) { 18 | return new vscode.Hover('For *all* TypeScript documents.'); 19 | } 20 | }) 21 | ``` 22 | 23 | 文档选择器可以不只是语言标识符,还可以是[DocumentFilter](https://code.visualstudio.com/docs/extensionAPI/vscode-api#DocumentFilter)中`scheme`实现的复杂选择器,文件路径支持`pattern`参数和glob模式。 24 | 25 | ```typescript 26 | vscode.languages.registerHoverProvider({ pattern: '**/test/**' }, { 27 | provideHover(doc: vscode.TextDocument) { 28 | return new vscode.Hover('For documents inside `test`-folders only'); 29 | } 30 | }) 31 | ``` 32 | 33 | 下面这个代码片段使用了`scheme`过滤器和语言标识符。`untitled`协议正是为未存到本地磁盘的文件准备的。 34 | 35 | ```typescript 36 | vscode.languages.registerHoverProvider({ scheme: 'untitled', language: 'typescript' }, { 37 | provideHover(doc: vscode.TextDocument) { 38 | return new vscode.Hover('For new, unsaved TypeScript documents only'); 39 | } 40 | }) 41 | ``` 42 | 43 | ## 文档协议 44 | --- 45 | 文档的`scheme`常常不受人待见,但是它实际上提供了非常重要的信息。大部分文件都是储存在磁盘上的,插件创作者也常假设自己正在处理的文档也是存在磁盘上的。用一个简单的`typescript`选择器做个例子,其中的假设就是**Typescript在磁盘上**,不过大部分开发场景都过于宽松了,使用了诸如`{ scheme: 'file', language: 'typescript' }`显式的选择器。 46 | 47 | 当插件特定依赖于从磁盘上读写时,这个问题显得尤为重要。请看下面的代码: 48 | 49 | ```typescript 50 | vscode.languages.registerHoverProvider('typescript', { // 👎 过于宽松 51 | provideHover(doc: vscode.TextDocument) { 52 | const { size } = fs.statSync(doc.uri.fsPath); // ⚠️ 'untitled:/Untitled1.ts' 或者其他情况会则么样? 53 | return new vscode.Hover(`Size in bytes is ${size}`); 54 | } 55 | }) 56 | ``` 57 | 58 | 上面的例子里,悬浮提示器想要展示该文档在磁盘上的大小,但是它没有检测文档是不是真的储存在磁盘上,比如一个新创建但还没有保存的文档。正确的方法是告诉VS Code这个功能只在文件储存在磁盘上时才工作: 59 | 60 | ```typescript 61 | vscode.languages.registerHoverProvider({ scheme: 'file', language: 'typescript' }, { // 👍 文件储存在磁盘上时才工作 62 | provideHover(doc: vscode.TextDocument) { 63 | const { size } = fs.statSync(doc.uri.fsPath); 64 | return new vscode.Hover(`Size in bytes is ${size}`); 65 | } 66 | }) 67 | ``` 68 | 69 | ## 总结 70 | --- 71 | 文档通常都储存在文件系统中,但也有例外:未保存的新文件、Git使用的缓存文件、FTP上的远程文件等等。如果你的插件特性依赖于磁盘读取,那么你就要用文档选择器时应带上`file`协议。 -------------------------------------------------------------------------------- /docs/get-started/your-first-extension.md: -------------------------------------------------------------------------------- 1 | # 你的第一个插件 2 | 3 | 在本小节中,我们会教你一些基础概念,请先安装好[Node.js](https://nodejs.org/en/)和[Git](https://git-scm.com/),然后安装[Yeoman](http://yeoman.io/)和[VS Code Extension Generator](https://www.npmjs.com/package/generator-code): 4 | 5 | ```bash 6 | npm install -g yo generator-code 7 | ``` 8 | 9 | 这个脚手架会生成一个可以立马开发的项目。运行生成器,然后填好下列字段: 10 | 11 | ```bash 12 | yo code 13 | 14 | # ? What type of extension do you want to create? New Extension (TypeScript) 15 | # ? What's the name of your extension? HelloWorld 16 | ### Press to choose default for all options below ### 17 | 18 | # ? What's the identifier of your extension? helloworld 19 | # ? What's the description of your extension? LEAVE BLANK 20 | # ? Enable stricter TypeScript checking in 'tsconfig.json'? Yes 21 | # ? Setup linting using 'tslint'? Yes 22 | # ? Initialize a git repository? Yes 23 | # ? Which package manager to use? npm 24 | 25 | code ./helloworld 26 | ``` 27 | 28 | 完成后进入 VS Code,按下`F5`,你会立即看到一个**插件发开主机**窗口,其中就运行着插件。 29 | 30 | 在命令面板(`Ctrl+Shift+P`)中输入`Hello World`命令。 31 | 32 | 35 | 36 | 如果你看到了`Hello World`提示弹窗,恭喜你成功了! 37 | 38 | ## 开发插件 39 | 40 | --- 41 | 42 | 现在让我们稍稍改动一下弹窗显示的内容: 43 | 44 | - 将项目文件`extension.ts`中的`Hello World`改为`Hello VS Code` 45 | - 重新加载开发窗口 46 | - 再次运行`Hello World`命令 47 | 48 | 你应该就能看到显示的消息更新了: 49 | 50 | 53 | 54 | 请浏览你的项目目录和代码,然后进行下面的小练习: 55 | 56 | - 为命令面板中的`Hello World`换一个名字 57 | - [配置](/references/contribution-points.md)一个新的命令:打开一个提示弹窗,显示当前时间 58 | - 用显示警告信息的[VS Code API](/references/vscode-api.md)替换原本的`vscode.window.showInformationMessage` 59 | 60 | ## 调试插件 61 | 62 | --- 63 | 64 | VS Code 内置的调试功能已经非常方便了,在代码序号的左侧空白处点击一下,VS Code 就会设下断点,进入调试模式后将鼠标悬停于变量上显示变量值,或是在调试侧边栏中检查变量值,此时,你还可以用**调试控制台**直接对表达式求值。 65 | 66 | 69 | 70 | 有关 Node.js 调试的部分,请参考[Node.js 调试](https://code.visualstudio.com/docs/nodejs/nodejs-debugging)部分。 71 | 72 | ## 下一步 73 | 74 | 在下个主题[解析插件结构](/get-started/extension-anatomy.md)中,我们会大致看一下`Hello World`示例的源码,然后解释一些关键的概念。 75 | 76 | 本节教程的源码可参考[https://github.com/Microsoft/vscode-extension-samples/tree/master/helloworld-sample](https://github.com/Microsoft/vscode-extension-samples/tree/master/helloworld-sample)。 77 | 此外,[插件指引](/extension-guides/README.md)章节还包含其他示例代码,每个例子都对应着不同的 VS Code Api 和发布内容配置。 78 | 79 | #### 使用 Javascript 80 | 81 | 在本指南中,我们主要使用 TypeScript 开发 VS Code 插件,因为我们认为 TS 是开发插件的最佳实践。如果你想使用 JS,我们也同样提供了源码[helloworld-minimal-sample](https://github.com/Microsoft/vscode-extension-samples/tree/master/helloworld-minimal-sample) 82 | -------------------------------------------------------------------------------- /docs/extension-guides/task-provider.md: -------------------------------------------------------------------------------- 1 | # 任务 2 | 3 | 通常,在VS Code中,用户可以通过`task.json`定义一个[任务](https://code.visualstudio.com/docs/editor/tasks)。不过在软件开发中,VS Code会自动检测某些任务。 4 | 5 | 本节介绍了插件应该怎样使用[Rakefiles](https://ruby.github.io/rake/)中的**自动检测任务**配置项,为最终用户提供任务。完整的源代码请参阅[这里](https://github.com/Microsoft/vscode-extension-samples/tree/master/task-provider-sample)。 6 | 7 | ## 定义任务 8 | --- 9 | 10 | 想要定义一个系统级别的任务,插件需要通过properties定义任务,在下面叫做Rake的例子中,任务是这样定义的: 11 | 12 | ?>**译者注:**rake是ruby实现的任务管理和自动构建工具,详细请参考[rake](https://rubygems.org/gems/rake/) 13 | 14 | ```json 15 | "taskDefinitions": [ 16 | { 17 | "type": "rake", 18 | "required": [ 19 | "task" 20 | ], 21 | "properties": { 22 | "task": { 23 | "type": "string", 24 | "description": "The Rake task to customize" 25 | }, 26 | "file": { 27 | "type": "string", 28 | "description": "The Rake file that provides the task. Can be omitted." 29 | } 30 | } 31 | } 32 | ] 33 | ``` 34 | 35 | 上面代码里面,我们为`rake`*任务集*配置了一个**任务定义**。任务定义有两个属性`task`和`file`,`task`是Rake任务的名字,file指向了包含任务的文件。`task`属性是必须的,`file`则为可选。如果省略了`file`属性,则会使用工作区根目录下名为`RakeFile`的文件。 36 | 37 | ## 任务供应器函数 38 | --- 39 | 40 | 和语言供应器函数相同,任务供应器使插件支持代码补全,一个插件可以只注册一个任务供应器函数然后执行所有可用的任务集合。使用`vscode.tasks`命名空间达成这一目标: 41 | ```typescript 42 | import * as vscode from 'vscode'; 43 | 44 | let rakePromise: Thenable | undefined = undefined; 45 | const taskProvider = vscode.tasks.registerTaskProvider('rake', { 46 | provideTasks: () => { 47 | if (!rakePromise) { 48 | rakePromise = getRakeTasks(); 49 | } 50 | return rakePromise; 51 | }, 52 | resolveTask(_task: vscode.Task): vscode.Task | undefined { 53 | return undefined; 54 | } 55 | }); 56 | ``` 57 | 58 | 目前`resolveTask`只返回了`undefined`,而将来VS Code会通过这个方法优化任务的加载。 59 | 60 | `getRakeTasks`的实现做了下面的事情: 61 | - 使用`rake -AT -f Rakefile`命令列出rake文件中的所有rake任务 62 | - 转换为stdio输出 63 | - 对每个任务创建一个`vscode.task`实现 64 | 65 | 因为一个rake任务初始化需要`package.json`中有对应的任务定义,VS Code会用TypeScript接口定义出结构,像这样: 66 | 67 | ```typescript 68 | interface RakeTaskDefinition extends vscode.TaskDefinition { 69 | 70 | /** 71 | * The task name 72 | */ 73 | task: string; 74 | 75 | /** 76 | * The rake file containing the task 77 | */ 78 | file?: string; 79 | } 80 | ``` 81 | 82 | 假设我们的输出最终来自于一个叫`compile`的任务,那么对应的任务创建过程如下所示: 83 | ```typescript 84 | let task = new vscode.Task( 85 | { type: 'rake', task: 'compile' }, 86 | 'compile', 87 | 'rake', 88 | new vscode.ShellExecution('rake compile') 89 | ); 90 | ``` 91 | 92 | 每个输出任务都对应着上述过程,最后通过调用`getRakeTasks`会返回一个任务数组。 93 | 94 | `ShellExecution`会针对不同的系统在shell中执行`rake compile`命令(如:在Windows下会在PowerShell中执行,Ubuntu则是bash)。如果某个任务需要直接执行进程(不通过shell生成),则可以使用`vscode.ProcessExecution`。`ProcessExecution`的优势在于插件可以完全控制传入进程的参数,`ShellExecution`则会使用shell命令转义(比如:bash中的*展开)。如果`ShellExecution`是通过单个命令创建的,那么插件需要在命令内部确保引号和转义符的正确使用(比如,如何处理空格)。 -------------------------------------------------------------------------------- /docs/_sidebar.md: -------------------------------------------------------------------------------- 1 | * [◼️术语表和说明](/) 2 | * [◼️预备知识](/) 3 | * [非JS开发者的第一步](/preknowledge/first-step.md) 4 | * [认识Typescript-变量和类型](/preknowledge/variable-and-type.md) 5 | * [认识Typescript-类](/preknowledge/class.md) 6 | * [认识Typescript-接口和命名空间](/preknowledge/interface-and-namespace.md) 7 | * [认识Typescript-泛型](/preknowledge/generics.md) 8 | * [认识Typescript-声明文件](/preknowledge/declaration-files.md) 9 | * [◼️概述](/api/README) 10 | * ◼️第一步 11 | * [你的第一个插件](/get-started/your-first-extension.md) 12 | * [解析插件结构](/get-started/extension-anatomy.md) 13 | * [小结](/get-started/wrapping-up.md) 14 | * ◼️开发插件 15 | * [测试插件](/working-with-extensions/testing-extension.md) 16 | * [发布插件](/working-with-extensions/publish-extension.md) 17 | * [打包插件](/working-with-extensions/bundling-extension.md) 18 | * [持续集成](/working-with-extensions/continuous-integration.md) 19 | * ◼️插件功能 20 | * [概述](/extension-capabilities/README.md) 21 | * [常用功能](/extension-capabilities/common-capabilities.md) 22 | * [主题](/extension-capabilities/theming.md) 23 | * [扩展工作台](/extension-capabilities/extending-workbench.md) 24 | * ◼️插件指南 25 | * [概述](/extension-guides/README.md) 26 | * [命令](/extension-guides/command.md) 27 | * [色彩主题](/extension-guides/color-theme.md) 28 | * [文件图标主题](/extension-guides/file-icon-theme.md) 29 | * [产品图标主题](/extension-guides/product-icon-theme.md) 30 | * [树视图](/extension-guides/tree-view.md) 31 | * [Webview](/extension-guides/webview.md) 32 | * [笔记本](/extension-guides/notebook.md) 33 | * [虚拟文档](/extension-guides/virtual-documents.md) 34 | * [任务](/extension-guides/task-provider.md) 35 | * [源控制](/extension-guides/scm-provider.md) 36 | * [调试器插件](/extension-guides/debugger-extension.md) 37 | * [Markdown插件](/extension-guides/markdown-extension.md) 38 | * [自定义编辑器](/extension-guides/custom-editors.md) 39 | * [自定义数据插件](/extension-guides/custom-data-extension.md) 40 | * ◼️语言插件 41 | * [概述](/language-extensions/) 42 | * [语法高亮](/language-extensions/syntax-highlight-guide.md) 43 | * [语义高亮](/language-extensions/semantic-highlight-guide.md) 44 | * [代码片段](/language-extensions/snippet-guide.md) 45 | * [语言配置](/language-extensions/language-configuration-guide.md) 46 | * [程序性语言特性](/language-extensions/programmatic-language-features.md) 47 | * [语言服务器](/language-extensions/language-server-extension-guide.md) 48 | * [嵌入语言](/language-extensions/embedded-languages.md) 49 | * ◼️进阶主题 50 | * [插件主机](/advanced-topics/extension-host.md) 51 | * [远程开发](/advanced-topics/remote-extensions.md) 52 | * [使用不稳定的API](/advanced-topics/using-proposed-api.md) 53 | * ️️◼️参考 54 | * [VS Code API](/references/vscode-api.md) 55 | * [发布内容配置](/references/contribution-points.md) 56 | * [激活事件](/references/activation-events.md) 57 | * [插件清单](/references/extension-manifest.md) 58 | * [命令](/references/commands.md) 59 | * [when 子句上下文](/references/when-clause-contexts.md) 60 | * [主题色彩](/references/theme-color.md) 61 | * [标签中的图标](/references/icons-in-labels.md) 62 | * [文档选择器](/references/document-selector.md) 63 | * [插件开发准则](/references/extension-guidelines.md) 64 | -------------------------------------------------------------------------------- /docs/references/document-selector.md: -------------------------------------------------------------------------------- 1 | # 文档选择器 2 | 3 | 插件的特性可以通过语言、类型、位置等文档选择器类型加以筛选,本节将深入文档选择器、文档协议等插件创作者应该了解的内容。 4 | 5 | ## 不在磁盘上的文件 6 | --- 7 | 8 | 并不是所有文件都是储存在磁盘上的,比如一份刚刚创建的文件。除非特别指明,文档选择器通常会应用于**所有**文档类型。使用[DocumentFilter](https://code.visualstudio.com/api/references/vscode-api#DocumentFilter)的`scheme`属性将协议范围缩小,比如说,`{ scheme: 'file', language: 'typescript' }`是特定的用于储存在磁盘上的TypeScript文件。 9 | 10 | ## 文档选择器 11 | --- 12 | 13 | VS Code插件API结合了特定的语言特性, 通过文档选择器的[DocumentSelector](https://code.visualstudio.com/api/references/vscode-api#DocumentSelector)类型, 可以支持例如智能感知(IntelliSense)等特性. 这是实现特定语言所支持特性的最为简单的机制. 14 | 15 | 下面的片段注册了一个Typescript文件的[HoverProvider](https://code.visualstudio.com/api/references/vscode-api#HoverProvider), 此时的文档选择器是`typescript`语言标识符. 16 | 17 | ```typescript 18 | vscode.languages.registerHoverProvider('typescript', { 19 | provideHover(doc: vscode.TextDocument) { 20 | return new vscode.Hover('For *all* TypeScript documents.'); 21 | } 22 | }); 23 | ``` 24 | 25 | 文档选择器可以不只是一个语言标识符, 还可以是复杂选择器——比如基于`协议(scheme)`和文件路径的[DocumentFilter](https://code.visualstudio.com/api/references/vscode-api#DocumentFilter), 文件路径支持`pattern`参数和glob模式: 26 | 27 | ```typescript 28 | vscode.languages.registerHoverProvider( 29 | { pattern: '**/test/**' }, 30 | { 31 | provideHover(doc: vscode.TextDocument) { 32 | return new vscode.Hover('For documents inside `test`-folders only'); 33 | } 34 | } 35 | ); 36 | ``` 37 | 38 | 下面这个片段, 使用合并后的`协议(scheme)`过滤器和语言标识符作为参数. `未命名的(untitled)`协议正是为暂未保存到本地磁盘的文件准备的. 39 | 40 | ```typescript 41 | vscode.languages.registerHoverProvider( 42 | { scheme: 'untitled', language: 'typescript' }, 43 | { 44 | provideHover(doc: vscode.TextDocument) { 45 | return new vscode.Hover('For new, unsaved TypeScript documents only'); 46 | } 47 | } 48 | ); 49 | ``` 50 | 51 | ## 文档协议 52 | --- 53 | 54 | `文档协议`经常会被忽视, 但是它提供了很重要的信息. 插件开发者经常假设自己正在处理的文档也是存在磁盘上的. 用一个简单的`typescript`选择器做个例子, 假设**Typescript文件在磁盘上**, 不过大部分开发场景都过于宽松了,使用了诸如`{ scheme: 'file', language: 'typescript' }`显式的选择器。 55 | 56 | 当某项功能依赖于从磁盘上读/写文件时, 这个问题显得尤为重要. 请看下面的代码: 57 | 58 | ```typescript 59 | // 👎 too lax 60 | vscode.languages.registerHoverProvider('typescript', { 61 | provideHover(doc: vscode.TextDocument) { 62 | const { size } = fs.statSync(doc.uri.fsPath); // ⚠️ what about 'untitled:/Untitled1.ts' or others? 63 | return new vscode.Hover(`Size in bytes is ${size}`); 64 | } 65 | }); 66 | ``` 67 | 68 | 上面的例子中, 悬浮提示器想展示文件占用的磁盘大小, 但是它不会检查文档是不是真的存储在磁盘上. 比如, 一个新创建但是未保存的文件. 正确的做法是告诉VS Code只在文件存储在磁盘上时才开始工作. 69 | 70 | ```typescript 71 | // 👍 only works with files on disk 72 | vscode.languages.registerHoverProvider( 73 | { scheme: 'file', language: 'typescript' }, 74 | { 75 | provideHover(doc: vscode.TextDocument) { 76 | const { size } = fs.statSync(doc.uri.fsPath); 77 | return new vscode.Hover(`Size in bytes is ${size}`); 78 | } 79 | } 80 | ); 81 | ``` 82 | 83 | ## 总结 84 | --- 85 | 文档通常都储存在文件系统中,但也有例外:未保存的新文件、Git使用的缓存文件、FTP上的远程文件等等。如果你的插件特性依赖于磁盘读取,那么你就要用文档选择器时应带上file协议。 86 | 87 | ## 下一步 88 | 89 | 阅读下列文章来了解更多有关于VS Code可拓展模型的知识. 90 | 91 | - [插件清单](/references/extension-manifest) - VS Code的package.json(插件清单)文件配置相关 92 | - [发布内容配置](/references/contribution-points) - VS Code发布内容相关 93 | -------------------------------------------------------------------------------- /docs/language-extensions/README.md: -------------------------------------------------------------------------------- 1 | # 概述 2 | 3 | VS Code通过语言插件可以为各式各样的编程语言提供智能的编辑体验。VS Code并不含内置语言支持,不过提供了一整套支持富文本特性的API。 4 | 比如,[HTML](https://github.com/Microsoft/vscode/tree/master/extensions/html)插件是一个可以为VS Code中的HTML文件提供语法高亮的插件。 5 | 类似的,当你输入`console.`时,智能补全会提示`log`,这是[Typescript Language Features](https://github.com/Microsoft/vscode/tree/master/extensions/typescript-language-features)插件提供的。 6 | 7 | 语言特性大致可以分为下面两种: 8 | 9 | ## 声明式语言特性 10 | --- 11 | 12 | 定义在配置文件的语言功能称之为*编程式语言特性*,比如,[html](https://github.com/Microsoft/vscode/tree/master/extensions/html),[css](https://github.com/Microsoft/vscode/tree/master/extensions/css)和[typescript-基础支持](https://github.com/Microsoft/vscode/tree/master/extensions/typescript-basics)插件都打包在了VS Code中,所以提供了下列声明式语言特性: 13 | 14 | - 语法高亮 15 | - 代码片段补全 16 | - 括号匹配 17 | - 自动闭合括号 18 | - 括号识别 19 | - 启动、关闭注释 20 | - 自动缩进 21 | - 代码折叠 22 | 23 | 我们提供了3个指南供你开发语言插件的声明式特性: 24 | 25 | - [语法高亮指南](/language-extensions/syntax-highlight-guide):VS Code 使用TextMate语法来高亮代码。这个指南将教你用简单的TextMate语法开发一个VS Code插件。 26 | - [代码片段补全指南](/language-extensions/snippet-guide): 这个指南教你怎么把代码片段打包进插件中。 27 | - [语言配置指南](/language-extensions/language-configuration-guide):VS Code允许插件为任何编程语言定义 **语言配置**。这个文件控制着基本的编辑功能,如开闭注释、括号匹配/识别,和(基础)代码折叠。 28 | 29 | 30 | ## 编程式语言特性 31 | --- 32 | 33 | 编程式语言特性包括自动补全、错误检查和跳转到定义。这些功能一般通过*语言服务器*驱动,这个服务器会分析你的项目,然后提供对应的功能。最好的例子就是打包在VS Code中的[`typescript-language-features`](https://github.com/Microsoft/vscode/tree/master/extensions/typescript-language-features)插件,它利用[TypeScript Language Service](https://github.com/Microsoft/TypeScript/wiki/Using-the-Language-Service-API)提供了诸如下面罗列的编程式语言特性: 34 | 35 | - 悬停信息([vscode.languages.registerHoverProvider](https://code.visualstudio.com/api/references/vscode-api#languages.registerHoverProvider)) 36 | - 自动补全([vscode.languages.registerCompletionItemProvider](https://code.visualstudio.com/api/references/vscode-api#languages.registerDefinitionProvider)) 37 | - 转跳到定义([vscode.languages.registerDefinitionProvider](https://code.visualstudio.com/api/references/vscode-api#languages.registerDefinitionProvider)) 38 | - 错误检查 39 | - 格式化 40 | - 重构 41 | - 代码折叠 42 | 43 | 下面是[编程式语言特性](/language-extensions/programmatic-language-features)的完整列表。 44 | 45 | ![multi-ls](https://media.githubusercontent.com/media/Microsoft/vscode-docs/master/api/language-extensions/images/overview/multi-ls.png) 46 | 47 | ## 语言服务器协议(Language Server Protocol) 48 | --- 49 | 50 | [语言服务器协议](https://microsoft.github.io/language-server-protocol/)将语言服务器(一个静态代码分析工具)和语言客户端(一般就是源代码)之间的通信进行了标准化,这样一来插件开发者就可以只写一次代码分析程序,然后在多个编辑器中重用了。 51 | 52 | 在[编程式语言特性](/language-extensions/programmatic-language-features)列表中,你可以找到所有VS Code的语言特性,以及它和[语言服务器协议规格](https://microsoft.github.io/language-server-protocol/specification)之间的映射关系。 53 | 54 | 我们提供了一个非常详尽的指南,里面会告诉你怎么实现一个语言服务器插件: 55 | 56 | - [语言服务器插件指南](/language-extensions/language-server-extension-guide) 57 | 58 | ![multi-editor](https://media.githubusercontent.com/media/Microsoft/vscode-docs/master/api/language-extensions/images/overview/multi-editor.png) 59 | 60 | ## 特殊功能 61 | --- 62 | 63 | #### 多目录工作区支持 64 | 65 | 当用户打开了一个[多目录工作区](https://code.visualstudio.com/docs/editor/multi-root-workspaces),你可能需要将你的语言服务器插件做相应的调整。这个主题探讨了几种多目录工作区的语言服务器的实现方法。 66 | (译者注:官方可能尚未完成这个部分的文档) 67 | 68 | #### 嵌入式语言 69 | 70 | 嵌入式语言在web开发中是非常常见的,比如HTML中的CSS/JS,JS/TS中的GraphQL。这个主题探讨了针对嵌入语言实现VS Code语言特性的各种方法。 71 | (译者注:官方可能尚未完成这个部分的文档) -------------------------------------------------------------------------------- /docs/extension-guides/product-icon-theme.md: -------------------------------------------------------------------------------- 1 | # 产品图标主题(预览) 2 | 3 | VS Code 包含了大量内置图标,他们可以用在视图、编辑器、悬浮栏、状态栏,甚至插件中。文末的示例中演示了在过滤器按钮、视图按钮、状态栏、断点、树视图折叠按钮、编辑器中使用图标。 4 | 5 | 产品图标主题让插件可以自定义 VS Code 的整体外观。但是 *产品主题图标* 不包含文件图标(会被文件图标主题覆盖)和插件配置的图标。 6 | 7 | VS Code 要求图标一定是图标字体定义的字形,用于限制(当前)产品图标统一为一种颜色。图标的颜色可以在使用时,可被当前激活的主题色所修改。 8 | 9 | !> 注意:产品图标主题仍在预览阶段,其配置格式还会有所修改。在正式发布之前,如果插件需要定义产品图标主题,需要打开`enableProposedApi`设置。你需要注意开发中的插件只能在 [Insider release](https://code.visualstudio.com/insiders/) 版本中运行。同时,你无法将这类插件发布到市场上。 10 | 11 | ## 添加一个新的产品图标主题 12 | 13 | 在 `package.json` 中的 `productIconTheme` 配置产品图标主题 14 | 15 | ```json 16 | { 17 | "contributes": { 18 | "productIconTheme": [ 19 | { 20 | "id": "aliensAreBack", 21 | "label": "Aliens Are Back", 22 | "path": "./producticons/aliens-product-icon-theme.json" 23 | } 24 | ] 25 | } 26 | } 27 | ``` 28 | 29 | 其中 `id` 是这个产品图标主题的唯一标识。它会显示在设置中,所以你定义 `id` 时注意要有唯一性和可读性。 30 | `label` 则会展示在产品图标主题选择下拉框中。`path` 则指向了插件定义图标系列的地方。如果你的文件名遵循 `*product-icon-theme.json` 的格式,那么你在编辑图标主题文件时,你就会获得代码补全和悬浮提示。 31 | 32 | 当你完成图标主题之后,你还得在`package.json`中加上下面的配置 33 | 34 | ```json 35 | "enableProposedApi": true 36 | ``` 37 | 38 | ## 产品图标定义文件 39 | 40 | 产品图标定义文件由一个或多个图标字体组成的图标定义集合的 JSON 文件。 41 | 42 | ### 字体定义 43 | 44 | `font`部分可以声明一个以上的字形字体。 45 | 这些字体稍后会在图标定义文件中可以引用。如果图标定义不指定字体 ID,那么默认会使用第一个声明的字体。 46 | 47 | 将字体文件复制到你的插件里,然后设置好相应的路径。 48 | 49 | 我们建议你使用 [WOFF](https://developer.mozilla.org/docs/Web/Guide/WOFF) 字体 50 | 51 | - 设置字体格式为'woff' 52 | - weight 属性值定义[在这](https://developer.mozilla.org/docs/Web/CSS/font-weight#Values) 53 | - style 属性值定义[在这](https://developer.mozilla.org/docs/Web/CSS/@font-face/font-style#Values) 54 | 55 | ```json 56 | { 57 | "fonts": [ 58 | { 59 | "id": "alien-font", 60 | "src": [ 61 | { 62 | "path": "./alien.woff", 63 | "format": "woff" 64 | } 65 | ], 66 | "weight": "normal", 67 | "style": "normal" 68 | } 69 | ] 70 | } 71 | ``` 72 | 73 | ### 图标定义 74 | 75 | VS Code 维护了一个被视图引用的图标ID列表,产品图标的 `iconDefinitions` 可以将新的图标设置到这些 ID 上。 76 | 77 | 每个定义都要使用 `fontId` 引用定义在 `fonts` 部分的字体,如果遗漏了 `fontId`,则会取字体定义中的首个字体。 78 | 79 | ```json 80 | { 81 | "iconDefinitions": { 82 | "dialog-close": { 83 | "fontCharacter": "\\43", 84 | "fontId": "alien-font" 85 | } 86 | } 87 | } 88 | ``` 89 | 90 | 所有图标的 ID 可以在 [图标参考](https://code.visualstudio.com/api/references/icons-in-labels#icon-listing) 中查看 91 | 92 | 93 | ## 开发和测试 94 | 95 | VS Code 为 `package.json` 内置了多种编辑特性。想在产品图标主题文件中启动这个功能,你的主题文件需要以 `product-icon-theme.json` 结尾。然后你就获得了所有属性的代码补全、悬浮提示和校验。 96 | 97 | 现在试一下产品图标主题,在 VS Code 中打开你的产品图标主题插件目录,然后按下`F5`,接着 VS Code 会启动插件开发主机并运行你的插件。这个窗口启用了你的插件,并且自动使用了第一个产品图标主题。 98 | 99 | 并且 VS Code 会监测主题文件的变动,任何图标的更新都会自动应用到 VS Code 界面上。只要你修改了产品图标定义文件,你就可以在界面上看到实时变化。 100 | 101 | 使用**Preferences: Product Icon Theme**切换产品图标主题。 102 | 103 | 想要知道 VS Code UI的某个图标到底用的是什么,打开**Help > Toggle Developer Tools**然后: 104 | - 点击开发者工具左上角的检查工具 105 | - 将鼠标移动到你想要检查的图标上 106 | - 如果图标的类名是`codicon.codicon-remote`,那么这个图标的 ID 就是`remote` 107 | 108 | ![dev-tool-select-tool](https://code.visualstudio.com/assets/api/extension-guides/product-icon-theme/dev-tool-select-tool.png) 109 | 110 | ## 示例 111 | 112 | [产品颜色主题示例](https://github.com/microsoft/vscode-extension-samples/tree/master/product-icon-theme-sample) 可以供你体验和使用。 -------------------------------------------------------------------------------- /docs/extension-capabilities/README.md: -------------------------------------------------------------------------------- 1 | # 插件功能 2 | 3 | VS Code 提供了非常多的方法,供插件扩展VS Code本身的能力。但是有的时候也很难找到对的[发布内容配置](/references/contribution-points.md)和[VS Code API](/references/vscode-api.md)。这章内容将插件的功能分成了几个部分,每个部分都将告诉你: 4 | - 插件可以使用的功能 5 | - 这些功能点的细节索引 6 | - 一些插件灵感 7 | 8 | 不过,我们也会告诉你一些[限制](#限制),为了避免插件影响到VS Code的性能和稳定性。比如:插件不可以修改VS Code UI底层的DOM。 9 | 10 | ## 常用功能 11 | --- 12 | 13 | [常用功能](/extension-capabilities/common-capabilities)是你在任何插件中都可能用到的核心功能。 14 | 15 | 这些功能包括: 16 | 17 | - 注册命令、配置、快捷键绑定、菜单等。 18 | - 保存工作区或全局数据。 19 | - 显示通知信息。 20 | - 使用快速选择获得用户输入。 21 | - 打开系统的文件选择工具,以便用户选择文件或文件夹。 22 | - 使用进度API提示耗时较长的操作。 23 | 24 | ## 主题 25 | --- 26 | 27 | [主题](/extension-capabilities/theming)控制着VS Code的外观——编辑器中的源代码的颜色和VS Code UI颜色。如果你曾经想要把VS Code搞成绿色,想象自己在黑客帝国里写代码,或者想要追求极简性冷淡灰色风格,那么主题章节就是为你而来。 28 | 29 | ##### 插件灵感 30 | 31 | - 改变你的代码颜色 32 | - 改变VS Code UI颜色 33 | - 将现有的TextMate主题应用到VS Code中 34 | - 添加自定义图标 35 | 36 | ## 声明式添加语言特性 37 | --- 38 | 39 | [声明式语言特性](/language-extensions/README#声明式语言特性)添加了基础的编程语言编辑支持,如括号匹配、自动缩进和语法高亮。这些功能都可以通过声明配置而不用写任何代码就可以获得,更高级的语言特性如IntelliSense或调试,请看[编程式添加语言特性](#编程式添加语言特性) 40 | 41 | ##### 插件灵感 42 | 43 | - 将常用的JS代码片段打包到插件中 44 | - 为VS Code添加新的语言支持 45 | - 为一门语言添加或替换语法 46 | - 通过注入的方式,扩展一门语法 47 | - 将现有的 TextMate 语法迁移到VS Code中 48 | 49 | ## 编程式添加语言特性 50 | --- 51 | 52 | [编程式添加语言特性](/language-extensions/README#编程式语言特性)可以为编程语言添加更为丰富的特性,如:悬停提示、转跳定义、错误诊断、IntelliSense和CodeLens。这些语言特性暴露于[`vscode.languages.*`](https://code.visualstudio.com/api/references/vscode-api#languages)API。语言插件可以直接使用这些API,或是自己写一个语言服务器,通过[语言服务器库](https://github.com/Microsoft/vscode-languageserver-node)将它适配到VS Code。 53 | 54 | 虽然我们提供了一个[语言特性](/language-extensions/programmatic-language-features)列表,但是并不阻碍你发挥想象,自由使用这些API。比方说,在行内显示额外信息,使用CodeLens和代码悬停是非常好的方式,而错误诊断可以高亮拼写或代码风格错误。 55 | 56 | ##### 插件灵感 57 | 58 | - 鼠标悬停于API上时, 出现用法示例 59 | - 使用诊断,报告代码风格错误 60 | - 注册新的HTML代码格式化 61 | - 提供丰富的IntelliSense中间件 62 | - 为一门语言添加代码折叠、面包屑、轮廓支持 63 | 64 | ## 扩展工作台 65 | --- 66 | 67 | [扩展工作台](/extension-capabilities/extending-workbench)加强了 VS Code 工作台的UI,为资源管理侧边栏添加了新的右击行为,你甚至可以用 [TreeView](/extension-guides/tree-view)API构建自定义的资源管理侧边栏。如果你的插件需要完全自定义用户界面,那就使用[Webview API](/extension-guides/webview)和HTML,CSS,Javascript构建你自己的UI。 68 | 69 | ##### 插件灵感 70 | 71 | - 自定义资源管理侧边栏的菜单行为 72 | - 在侧边栏中创建新的、交互式的TreeView 73 | - 定义新的活动栏视图 74 | - 在状态栏显示新的信息 75 | - 使用`WebView` API显示自定义内容 76 | - 配置*源控制(git/svn等)*来源 77 | 78 | ## 调试 79 | --- 80 | 81 | 你可以利用[调试](https://code.visualstudio.com/docs/editor/debugging)来制作[调试器插件](/extension-guides/debugger-extension),这个插件需要将VS Code的调试UI连接到真实的调试器或者运行时上。 82 | 83 | ##### 插件灵感 84 | 85 | - 通过[调试适配器](https://microsoft.github.io/debug-adapter-protocol/implementors/adapters/)将VS Code的调试UI连接到真实的调试器或者运行时上 86 | - 通过调试器插件添加语言支持 87 | - 为调试配置文件添加丰富的智能提示或者悬停信息 88 | - 为调试配置文件添加代码片段 89 | 90 | 另一方面,VS Code也提供了非常多的[调试器插件API](https://code.visualstudio.com/api/references/vscode-api#debug),你可以用来实现任何VS Code调试器相关的功能,加强用户的调试体验。 91 | 92 | ##### 插件灵感 93 | 94 | - 动态生成调试器配置文件,启动调试器会话 95 | - 跟踪调试会话的声明周期 96 | - 编程式管理断点 97 | 98 | ## 限制 99 | --- 100 | 101 | 最后,我还对插件也提出了一些限制。 102 | 103 | #### 不可访问DOM 104 | 105 | 插件没有权限访问VS Code UI的底层DOM,**禁止**添加自定义的CSS 和 HTML片段到VS Code UI上。 106 | 107 | 我们在一直努力优化VS Code底层的web技术,为用户创造高可用、持续响应的编辑器,而我们也会继续调整这些技术中使用到的DOM。为了确保不会干扰到VS Code的性能和稳定性,同时不阻断其他插件的运行,所以我们的插件都跑在[插件主机](/advanced-topics/extension-host)进程中,而且阻止了插件直接访问DOM的途径。 -------------------------------------------------------------------------------- /docs/working-with-extensions/continuous-integration.md: -------------------------------------------------------------------------------- 1 | # 持续集成 2 | 3 | 插件测试也可以用诸如[Travis CI](https://travis-ci.org/)自动运行测试。[`vscode-test`](https://github.com/Microsoft/vscode-test)库可以基于 CI 设置插件测试,而且里面还包含了一个 Azure Pipelines 的[示例插件](https://github.com/microsoft/vscode-test/tree/master/sample)。你可以先看看[构建管线](https://dev.azure.com/vscode/vscode-test/_build?definitionId=15)是什么样子的,或者直接查看[`azure-pipelines.yml`file](https://github.com/microsoft/vscode-test/blob/master/sample/azure-pipelines.yml)。 4 | 5 | ## Azure Pipelines 6 | 7 | --- 8 | 9 | ![pipelines-logo](https://media.githubusercontent.com/media/Microsoft/vscode-docs/master/api/working-with-extensions/images/continuous-integration/pipelines-logo.png) 10 | 11 | 你可以在[Azure DevOps](https://azure.microsoft.com/services/devops/)上创建免费的项目,它为你提供了代码托管、看板、构建和测试基础设施等等。最重要的是,你可以获得[10 个免费的并行任务](https://azure.microsoft.com/services/devops/pipelines/)容量,用于你构建项目,不论是在 Windows, macOS 还是 Linux 上。 12 | 13 | 首先,你需要创建一个免费的[Azure DevOps](https://azure.microsoft.com/services/devops/)账号,然后给你的插件创建一个[Azure DevOps 项目](https://azure.microsoft.com/en-us/features/devops-projects/)。 14 | 15 | 然后,把`azure-pipelines.yml`文件添加到插件仓库的根目录下,不同于 Linux 中的`xvfb`配置脚本,需要 VS Code 运行在 Linux 的无头 CI 机器上,我们的配置文件非常简单: 16 | 17 | ```yaml 18 | trigger: 19 | - master 20 | 21 | strategy: 22 | matrix: 23 | linux: 24 | imageName: "ubuntu-16.04" 25 | mac: 26 | imageName: "macos-10.13" 27 | windows: 28 | imageName: "vs2017-win2016" 29 | 30 | pool: 31 | vmImage: $(imageName) 32 | 33 | steps: 34 | - task: NodeTool@0 35 | inputs: 36 | versionSpec: "8.x" 37 | displayName: "Install Node.js" 38 | 39 | - bash: | 40 | /usr/bin/Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & 41 | echo ">>> Started xvfb" 42 | displayName: Start xvfb 43 | condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux')) 44 | 45 | - bash: | 46 | echo ">>> Compile vscode-test" 47 | yarn && yarn compile 48 | echo ">>> Compiled vscode-test" 49 | cd sample 50 | echo ">>> Run sample integration test" 51 | yarn && yarn compile && yarn test 52 | displayName: Run Tests 53 | env: 54 | DISPLAY: ":99.0" 55 | ``` 56 | 57 | 最后,在你的 DveOps 项目里[创建一个新的管线](https://docs.microsoft.com/azure/devops/pipelines/get-started-yaml?view=vsts#get-your-first-build),然后指向`azure-pipelines.yml`文件,启动 build,然后……真香~ 58 | 59 | ![pipelines](https://media.githubusercontent.com/media/Microsoft/vscode-docs/master/api/working-with-extensions/images/continuous-integration/pipelines.png) 60 | 61 | 你可以启用持续构建——每当有 pull requests 进入特定分支的时候自动进行构建。相关内容请查看[构建管线触发器](https://docs.microsoft.com/azure/devops/pipelines/build/triggers)。 62 | 63 | ## Travis CI 64 | 65 | --- 66 | 67 | [vscode-test](https://github.com/microsoft/vscode-test)还包含了一份[Travis CI 构建文件](https://github.com/microsoft/vscode-test/blob/master/.travis.yml),因为 Travis 上的环境变量定义和 Azure 所有不同,`xvfb`脚本也有些许不一样: 68 | 69 | ```yaml 70 | language: node_js 71 | os: 72 | - osx 73 | - linux 74 | node_js: 8 75 | 76 | install: 77 | - | 78 | if [ $TRAVIS_OS_NAME == "linux" ]; then 79 | export DISPLAY=':99.0' 80 | /usr/bin/Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & 81 | fi 82 | script: 83 | - | 84 | echo ">>> Compile vscode-test" 85 | yarn && yarn compile 86 | echo ">>> Compiled vscode-test" 87 | cd sample 88 | echo ">>> Run sample integration test" 89 | yarn && yarn compile && yarn test 90 | cache: yarn 91 | ``` 92 | -------------------------------------------------------------------------------- /docs/extension-capabilities/common-capabilities.md: -------------------------------------------------------------------------------- 1 | # 常用功能 2 | 3 | 常用功能对你的插件来说非常重要,几乎所有的都会或多或少地用到这些功能,下面我们为你简单地介绍一下它们。 4 | 5 | ## 命令 6 | --- 7 | 8 | 命令是VS Code 运作的核心。你可以打开*命令面板*执行,用快捷键执行,还可以在菜单中鼠标右键执行。 9 | 10 | 一个插件应该: 11 | - 使用[`vscode.commands`](https://code.visualstudio.com/api/references/vscode-api#commands)注册和执行命令 12 | - 配置[`contributes.commands`](/references/contribution-points#contributescommands),确保命令面板中可以顺利执行你注册的命令 13 | 14 | 在[插件指南/命令](/extension-guides/command)中学习更多相关内容。 15 | 16 | 17 | ## 配置 18 | --- 19 | 20 | 插件需要在[`contributes.configuration`](/references/contribution-points#contributesconfiguration)发布内容配置点中填写有关的配置,你可以[`workspace.getConfiguration`](https://code.visualstudio.com/api/references/vscode-api#workspace.getConfiguration)API中阅读有关内容。 21 | 22 | 23 | ## 键位绑定 24 | --- 25 | 26 | 插件可以添加自定义键位映射,在[`contributes.keybindings`](/references/contribution-points?id=contributeskeybindings)和[键位绑定](https://code.visualstudio.com/docs/getstarted/keybindings)中了解更多有关内容。 27 | 28 | ## 菜单 29 | --- 30 | 31 | 插件可以自定义上下文菜单项,菜单会根据用户右击VS Code UI的不同位置而各不相同。查看更多[`contributes.menus`](/extensibility-reference/contribution-points#contributesmenus)发布内容配置。 32 | 33 | ## 数据储存 34 | --- 35 | 36 | VS Code中有三种数据储存方式: 37 | 38 | - [`ExtensionContext.workspaceState`](https://code.visualstudio.com/api/references/vscode-api#ExtensionContext.workspaceState):键值对组成的工作区数据。当同一个工作区再次打开时会重新取出数据。 39 | - [`ExtensionContext.globalState`](https://code.visualstudio.com/api/references/vscode-api#ExtensionContext.globalState):键值对组成的全局数据。当插件激活时会再次取出这些数据。 40 | - [`ExtensionContext.storagePath`](https://code.visualstudio.com/api/references/vscode-api#ExtensionContext.storagePath):指向你的插件可以读写的本地文件夹的路径。如果你要储存比较大的数据,这是一个非常好的选择。 41 | - [`ExtensionContext.globalStoragePath`](https://code.visualstudio.com/api/references/vscode-api#ExtensionContext.globalStoragePath):指向你的插件可以读写的本地存储的路径。如果你要存储所有工作区内的大文件,这时一个非常好的选择。 42 | 43 | 插件的执行上下文在`activate`函数中,详见[插件入口文件](/get-started/extension-anatomy#插件入口文件)。 44 | 45 | ## 显示通知 46 | --- 47 | 48 | 几乎所有的插件都需要在某些时候为用户提示信息。VS Code提供了3个API来展示不同重要程度的信息: 49 | 50 | - [`window.showInformationMessage`](https://code.visualstudio.com/api/references/vscode-api#window.showInformationMessage) 51 | - [`window.showWarningMessage`](https://code.visualstudio.com/api/references/vscode-api#window.showWarningMessage) 52 | - [`window.showErrorMessage`](https://code.visualstudio.com/api/references/vscode-api#window.showErrorMessage) 53 | 54 | ## 快速选择 55 | --- 56 | 57 | 使用[`vscode.QuickPick`](https://code.visualstudio.com/api/references/vscode-api#QuickPick)API,你可以轻松地收集用户输入或者为用户显示选择列表。[快速输入 示例](https://github.com/Microsoft/vscode-extension-samples/tree/master/quickinput-sample)将详细解释这个API。 58 | 59 | ## 文件选择 60 | --- 61 | 62 | 插件可以使用[`vscode.window.showOpenDialog`](https://code.visualstudio.com/api/references/vscode-api#vscode.window.showOpenDialog)API打开系统文件选择器,然后选择文件或是文件夹。 63 | 64 | ## 输出渠道 65 | --- 66 | 67 | *输出面板*显示了一组[`输出渠道`](https://code.visualstudio.com/api/references/vscode-api#OutputChannel),以便于你查看日志。你可以使用[`window.createOutputChannel`](https://code.visualstudio.com/api/references/vscode-api#window.createOutputChannel)创建一个新的输出渠道。 68 | 69 | ## 进度API 70 | --- 71 | 72 | 使用[`vscode.Progress`](https://code.visualstudio.com/api/references/vscode-api#Progress)将处理进度报告给用户。 73 | 74 | 通过[`ProgressLocation`](https://code.visualstudio.com/api/references/vscode-api#ProgressLocation)选项,进度可以显示在不同的区域: 75 | - 显示在通知区 76 | - 显示在源控制视图 77 | - VS Code窗口中的通用进度条位置 78 | 79 | 详见[进度 示例](https://github.com/Microsoft/vscode-extension-samples/tree/master/progress-sample)。 -------------------------------------------------------------------------------- /docs/_navbar.md: -------------------------------------------------------------------------------- 1 | 2 | * 内容导航 3 | * **预备知识** 4 | * [非JS开发者的第一步](/preknowledge/first-step.md) 5 | * [Typescript-变量和类型](/preknowledge/variable-and-type.md) 6 | * [Typescript-类](/preknowledge/class.md) 7 | * [Typescript-接口和命名空间](/preknowledge/interface-and-namespace.md) 8 | * [Typescript-泛型](/preknowledge/generics.md) 9 | * [Typescript-声明文件](/preknowledge/declaration-files.md) 10 | * **第一步** 11 | * [你的第一个插件](/get-started/your-first-extension.md) 12 | * [解析插件结构](/get-started/extension-anatomy.md) 13 | * [小结](/get-started/wrapping-up.md) 14 | * **开发插件** 15 | * [测试插件](/working-with-extensions/testing-extension.md) 16 | * [发布插件](/working-with-extensions/publish-extension.md) 17 | * [打包插件](/working-with-extensions/bundling-extension.md) 18 | * [持续集成](/working-with-extensions/continuous-integration.md) 19 | * **插件功能** 20 | * [概述](/extension-capabilities/readme.md) 21 | * [常用功能](/extension-capabilities/common-capabilities.md) 22 | * [主题](/extension-capabilities/theming.md) 23 | * [扩展工作台](/extension-capabilities/extending-workbench.md) 24 | * **插件指南** 25 | * [概述](/extension-guides/readme.md) 26 | * [命令](/extension-guides/command.md) 27 | * [色彩主题](/extension-guides/color-theme.md) 28 | * [文件图标主题](/extension-guides/file-icon-theme.md) 29 | * [产品图标主题](/extension-guides/product-icon-theme.md) 30 | * [树视图](/extension-guides/tree-view.md) 31 | * [Webview](/extension-guides/webview.md) 32 | * [笔记本](/extension-guides/notebook.md) 33 | * [虚拟文档](/extension-guides/virtual-documents.md) 34 | * [任务](/extension-guides/task-provider.md) 35 | * [源控制](/extension-guides/scm-provider.md) 36 | * [调试器插件](/extension-guides/debugger-extension.md) 37 | * [Markdown插件](/extension-guides/markdown-extension.md) 38 | * [自定义编辑器](/extension-guides/custom-editors.md) 39 | * [自定义数据插件](/extension-guides/custom-data-extension.md) 40 | * **语言插件** 41 | * [概述](/language-extensions/) 42 | * [语法高亮](/language-extensions/syntax-highlight-guide.md) 43 | * [语义高亮](/language-extensions/semantic-highlight-guide.md) 44 | * [代码片段](/language-extensions/snippet-guide.md) 45 | * [语言配置](/language-extensions/language-configuration-guide.md) 46 | * [程序性语言特性](/language-extensions/programmatic-language-features.md) 47 | * [语言服务器](/language-extensions/language-server-extension-guide.md) 48 | * [嵌入语言](/language-extensions/embedded-languages.md) 49 | * **进阶主题** 50 | * [插件主机](/advanced-topics/extension-host.md) 51 | * [远程开发](/advanced-topics/remote-extensions.md) 52 | * [使用不稳定的API](/advanced-topics/using-proposed-api.md) 53 | * ️️**参考** 54 | * [VS Code API](/references/vscode-api.md) 55 | * [发布内容配置](/references/contribution-points.md) 56 | * [激活事件](/references/activation-events.md) 57 | * [插件清单](/references/extension-manifest.md) 58 | * [命令](/references/commands.md) 59 | * [when 子句上下文](/references/when-clause-contexts.md) 60 | * [主题色彩](/references/theme-color.md) 61 | * [标签中的图标](/references/icons-in-labels.md) 62 | * [文档选择器](/references/document-selector.md) 63 | * [插件开发准则](/references/extension-guidelines.md) 64 | * ️️参考 65 | * [VS Code API](/references/vscode-api.md) 66 | * [发布内容配置](/references/contribution-points.md) 67 | * [激活事件](/references/activation-events.md) 68 | * [插件清单](/references/extension-manifest.md) 69 | * [命令](/references/commands.md) 70 | * [when 子句上下文](/references/when-clause-contexts.md) 71 | * [主题色彩](/references/theme-color.md) 72 | * [标签中的图标](/references/icons-in-labels.md) 73 | * [文档选择器](/references/document-selector.md) 74 | * [插件开发准则](/references/extension-guidelines.md) 75 | -------------------------------------------------------------------------------- /Progress.md: -------------------------------------------------------------------------------- 1 | ## 翻译计划 2 | 3 | - **第一期计划** - 翻译*插件创作*内的所有章节 4 | - ✅ [示例:语言服务器](https://code.visualstudio.com/docs/extensions/example-language-server) 5 | - ✅ [调试适配器](https://code.visualstudio.com/docs/extensions/example-debuggers) 6 | - ✅ [Webview API](https://code.visualstudio.com/docs/extensions/webview) 7 | - ✅ [更多例子](https://code.visualstudio.com/docs/extensions/samples) 8 | - ✅ [开发插件](https://code.visualstudio.com/docs/extensions/developing-extensions) 9 | - ✅ [发布插件](https://code.visualstudio.com/docs/extensions/publish-extension) 10 | - ✅ [测试插件](https://code.visualstudio.com/docs/extensions/testing-extensions) 11 | 12 | - **第二期计划** - 翻译*扩展性参阅*内的所有章节 13 | - ✅ [扩展性参阅](https://code.visualstudio.com/docs/extensionAPI/overview) 14 | - ✅ [扩展性原则和模式](https://code.visualstudio.com/docs/extensionAPI/patterns-and-principles) 15 | - ✅ [语言插件指引](https://code.visualstudio.com/docs/extensionAPI/language-support) 16 | - ✅ [插件清单](https://code.visualstudio.com/docs/extensionAPI/extension-manifest) 17 | - ✅ [发布内容配置](https://code.visualstudio.com/docs/extensionAPI/extension-points) 18 | - ✅ [激活事件](https://code.visualstudio.com/docs/extensionAPI/activation-events) 19 | - ✅ [文档选择器](https://code.visualstudio.com/docs/extensionAPI/document-selectors) 20 | - ✅ [vscode 命名空间API](https://code.visualstudio.com/docs/extensionAPI/vscode-api) 21 | - ✅ [复杂命令](https://code.visualstudio.com/docs/extensionAPI/vscode-api-commands) 22 | - ✅ [调试器API](https://code.visualstudio.com/docs/extensionAPI/api-debugging) 23 | - ✅ [源控制](https://code.visualstudio.com/docs/extensionAPI/api-scm) 24 | - ✅ [Markdown插件](https://code.visualstudio.com/docs/extensionAPI/api-markdown) 25 | 26 | - **第三期计划** - 审阅文档中的链接和内容 27 | - ✅ 审阅插件创作和Readme 28 | - ✅ 介绍部分 29 | - ✅ 从示例开始 30 | - ✅ 开发步骤 + 进阶 31 | - ✅ 审阅扩展性参考 32 | - ✅ 1-4节 33 | - ✅ 5-7节 34 | - ✅ 8-10节 35 | - ✅ 添加navbar和原始页面 36 | 37 | - **第四期计划** 38 | - ✅ 添加[示例-任务](https://code.visualstudio.com/docs/extensions/example-tasks)章节 39 | - ✅ 添加术语速查小插件 40 | 41 | - **第五期计划** - 对应官方文档改版升级 42 | 这一版不检查链接,注意大部分链接都可能是空的、错误的 43 | 44 | - ✅ 第一步 45 | - ✅ 你的第一个插件 46 | - ✅ 解析插件结构 47 | - ✅ 小结 48 | - ✅ 开发插件 49 | - ✅ 测试插件 50 | - ✅ 打包插件 51 | - ✅ 发布插件 52 | - ✅ 持续集成 53 | - ✅ 插件功能 54 | - ✅ 概述 55 | - ✅ 常用功能 56 | - ✅ 主题 57 | - ✅ 扩展工作台 58 | - ✅ 插件指南 59 | - ✅ 概述 60 | - ✅ 命令 61 | - ✅ 色彩主题 62 | - ✅ 图标主题 63 | - ✅ 树视图 64 | - ✅ Webview 65 | - ✅ 虚拟文档 66 | - ✅ 任务 67 | - ✅ 源控制 68 | - ✅ 调试器插件 69 | - ✅ Markdown插件 70 | - ✅ 语言插件 71 | - ✅ 概述 72 | - ✅ 语法高亮 73 | - ✅ 代码片段 74 | - ✅ 语言配置 75 | - ✅ 程序性语言特性 76 | - ✅ 语言服务器 77 | - ✅ 进阶主题 78 | - ✅ 插件主机 79 | - ✅ 使用不稳定的API 80 | - ✅ 参考 81 | - ✅ VS Code API 82 | - ✅ 发布内容配置 83 | - ✅ 激活事件 84 | - ✅ 插件清单 85 | - ✅ 命令 86 | - ✅ 主题色彩 87 | - ✅ 标签中的图标 88 | - ✅ 文档选择器 89 | 90 | 91 | - **第六期计划** - 审阅和链接补充 92 | - ✅ 第一步 93 | - ✅ 开发插件 94 | - ✅ 插件功能 95 | - ✅ 插件指南 96 | - ✅ 语言插件 97 | - ✅ 进阶主题 98 | - ✅ 参考 99 | 100 | - **第七期计划** 101 | - ✅ 更新docsify依赖 102 | - ⬜ 修改"_sidebar","_navbar"的请求依赖 103 | - ✅ 更好的navbar 104 | - ✅ 添加评论插件 105 | - ✅ 添加复制代码插件 106 | - ⬜ 预备知识 - Javascript部分 107 | - ✅ 预备知识 - Typescript部分 108 | - **第八期计划** 109 | - ✅ 更新 概述 110 | - ✅ 更新 插件指南-文件图标主题 111 | - ✅ 新增 插件指南-产品图标主题 112 | - ✅ 新增 插件指南-记事本 113 | - ✅ 新增 插件指南-自定义编辑器 114 | - ✅ 新增 插件指南-自定义数据插件 115 | - ✅ 更新 语言插件-语法高亮指南 116 | - ✅ 新增 语言插件-语义高亮指南 117 | - ✅ 更新 语言插件-语言服务器 118 | - ✅ 新增 语言插件-嵌入语言 119 | - ✅ 更新 进阶主题-远程开发与代码空间 120 | - ✅ 恢复 查看原文档功能 121 | - ✅ 去除 导航栏“第一版”入口 122 | -------------------------------------------------------------------------------- /docs/extension-guides/color-theme.md: -------------------------------------------------------------------------------- 1 | # 色彩主题 2 | 3 | 色彩可视化工作在VS Code可以分成两种类型: 4 | - 工作台(Workbench)色彩:在视图和编辑器中使用的工作台(Workbench)色彩,包括视图、编辑器、活动栏、状态栏等。整个色彩列表[查看这里](/references/theme-color)。 5 | - 语法色彩:语法色彩就是编辑器中代码的颜色,它基于TextMate语法和TextMate主题规则进行着色。 6 | 7 | 下面将分别介绍这两种类型。 8 | 9 | ## 工作台色彩 10 | --- 11 | 12 | 创建工作台色彩最简单的方式就是使用现成的主题,然后开始定制。 13 | 14 | - 在VS Code中切换到你想要编辑的色彩主题。 15 | - 打开[设置](https://code.visualstudio.com/docs/getstarted/settings),用`workbench.colorCustomizations`修改视图和编辑器色彩。一般来说会即时生效,如果没有生效你需要自己重启VS Code。 16 | 17 | 下面是一个改变了标题栏颜色的配置 18 | ```json 19 | { 20 | "workbench.colorCustomizations": { 21 | "titleBar.activeBackground": "#ff0000" 22 | } 23 | } 24 | ``` 25 | 26 | - [完整的主题色彩列表](/references/theme-color) 27 | 28 | ## 语法色彩 29 | --- 30 | 31 | 新建语法高亮色彩有两种方式: 32 | - 直接使用社区现成的TextMate主题(`.tmTheme`文件) 33 | - 自己想一个主题规则出来 34 | 35 | 当然,还有更简单的方式: 36 | 37 | - 切换到色彩主题,用[设置](https://code.visualstudio.com/docs/getstarted/settings)中的`editor.tokenColorCustomizations`进行自定义,就像上面修改工作台色彩一样,修改会立即呈现,你不需要重启VS Code。 38 | 39 | 下面的例子修改了编辑器中注释的颜色: 40 | 41 | ```json 42 | { 43 | "editor.tokenColorCustomizations": { 44 | "comments": "#FF0000" 45 | } 46 | } 47 | ``` 48 | 49 | 设置支持一些简单的语法标识模型,比如“comments”,“strings”,“numbers”等等。如果你想定制更多颜色,那么直接应用TextMate语法规则就可以了,详见[语法高亮指南](/language-extensions/syntax-highlight-guide)。 50 | 51 | 52 | ## 创建新的色彩主题 53 | --- 54 | 55 | 既然你已经用过`workbench.colorCustomizations`和`editor.tokenColorCustomizations`笨拙地修改过颜色,那么接下来我们可以见识见识大杀器了。 56 | 57 | - 打开**命令面板**输入**Developer: Generate Color Theme from Current Settings** 58 | - 使用VS Code的 [Yeoman](http://yeoman.io/) 插件生成器,生成新的主题: 59 | ```bash 60 | npm install -g yo generator-code 61 | yo code 62 | ``` 63 | - 如果你像下图这样选择了自定义主题,则选择'Start fresh' 64 | 65 | ![生成新主题](https://media.githubusercontent.com/media/Microsoft/vscode-docs/master/api/extension-guides/images/color-theme/yocode-colortheme.png) 66 | 67 | - 把从设置中生成的主题文件复制到新的插件中 68 | - 如果你想使用现成的TextMate主题,那你就需要在插件生成的时候选择导入TextMate主题并打包。另外,如果你下载了一个主题,那么只要用`.tmTheme`链接替换`tokenColors`部分就可以了。 69 | 70 | ```json 71 | { 72 | "type": "dark", 73 | "colors": { 74 | "editor.background": "#1e1e1e", 75 | "editor.foreground": "#d4d4d4", 76 | "editorIndentGuide.background": "#404040", 77 | "editorRuler.foreground": "#333333", 78 | "activityBarBadge.background": "#007acc", 79 | "sideBarTitle.foreground": "#bbbbbb" 80 | }, 81 | "tokenColors": "./Diner.tmTheme" 82 | } 83 | ``` 84 | ?> 为你的色彩文件添加`.color-theme.json`前缀,那么你在编辑这个文件时就能自动获得悬浮提示、代码补全、色彩装饰器和色彩选择器等功能了。 85 | 86 | ?> [ColorSublime](https://colorsublime.github.io/)有成百上千个现成的TextMate主题。你可以选择一个你喜欢的主题,复制下载链接,然后用Yeoman选择这个主题生成你的插件。格式如:`"https://raw.githubusercontent.com/Colorsublime/Colorsublime-Themes/master/themes/(name).tmTheme"` 87 | 88 | 89 | ## 测试新的主题 90 | --- 91 | 92 | 通过按F5打开一个插件主机开发窗口,来测试主题。 93 | 94 | 通过**文件 > 首选项 > 颜色主题**,在下拉菜单里找到你的主题。然后通过移动上下箭头,预览你自己的主题。 95 | 96 | ![选择我的主题](https://media.githubusercontent.com/media/Microsoft/vscode-docs/master/api/extension-guides/images/color-theme/mytheme.png) 97 | 98 | 主题文件的改动,会实时同步到`插件开发主机`窗口。 99 | 100 | ## 将主题发布到插件市场 101 | --- 102 | 103 | 如果你想把主题分享给社区,通过[插件市场](https://code.visualstudio.com/docs/editor/extension-gallery)去发布它吧。用[vsce publishing tool](/working-with-extensions/publish-extension)打包你的主题然后发布到VS Code市场。 104 | 105 | ?> 小贴士:想要用户轻松地找到你的主题,最好修改一下`package.json`,把关键字"theme"写到插件描述(extension description)中,然后把`Category`设置为`Theme` 106 | 107 | 要想让你的插件在插件市场上看起来更好一点,我们建议你参考一下[插件市场展示小贴士](/references/extension-manifest#插件市场展示小贴士)。 108 | 109 | ## 添加新的色彩id 110 | --- 111 | 112 | [色彩配置点](/references/contribution-points#contributescolors)可以配置插件的*色彩id*,当在`workbench.colorCustomizations`和主题文件中使用代码补全时,这些色彩也会出现。用户可以在[插件配置](https://code.visualstudio.com/docs/editor/extension-gallery#_extension-details)选项卡中看到插件定义了什么颜色。 113 | 114 | ## 更多 115 | 116 | - [CSS Tricks - 新建一个VS Code主题](https://css-tricks.com/creating-a-vs-code-theme/) -------------------------------------------------------------------------------- /docs/extensibility-reference/activation-events.md: -------------------------------------------------------------------------------- 1 | # 激活事件 - package.json 2 | 3 | 在VS Code中,插件都是懒加载的,所以你得为VS Code提供插件激活的时机。 我们提供了下列激活时机: 4 | 5 | * [`onLanguage:${language}`](extensibility-reference/activation-events#activationeventsonlanguage) 6 | * [`onCommand:${command}`](extensibility-reference/activation-events#activationeventsoncommand) 7 | * [`onDebug`](extensibility-reference/activation-events#activationeventsondebug) 8 | * [`workspaceContains:${toplevelfilename}`](extensibility-reference/activation-events#activationeventsworkspacecontains) 9 | * [`onFileSystem:${scheme}`](extensibility-reference/activation-events#activationeventsonfilesystem) 10 | * [`onView:${viewId}`](extensibility-reference/activation-events#activationeventsonview) 11 | * [`onUri`](extensibility-reference/activation-events#activationeventsonuri) 12 | * [`*`](extensibility-reference/activation-events#activationevents) 13 | 14 | 我们在[`package.json` 插件清单](extensibility-reference/extension-manifest.md)中提供了一个插件最少所需的激活事件。 15 | 16 | ## activationEvents.onLanguage 17 | 18 | 特定语言文件打开时激活: 19 | 20 | ```json 21 | ... 22 | "activationEvents": [ 23 | "onLanguage:python" 24 | ] 25 | ... 26 | ``` 27 | 28 | `onLanguage`只支持[语言标识符](/docs/languages/identifiers.md)中的值。 29 | 30 | 在`activationEvents`数组中声明多个`onLanguage`入口实现多语言支持 31 | 32 | ```json 33 | "activationEvents": [ 34 | "onLanguage:json", 35 | "onLanguage:markdown", 36 | "onLanguage:typescript" 37 | ] 38 | ... 39 | ``` 40 | 41 | ## activationEvents.onCommand 42 | 43 | 当调用命令时激活事件: 44 | 45 | ```json 46 | ... 47 | "activationEvents": [ 48 | "onCommand:extension.sayHello" 49 | ] 50 | ... 51 | ``` 52 | 53 | ## activationEvents.onDebug 54 | 55 | 调试会话(debug session)启动前激活: 56 | 57 | ```json 58 | ... 59 | "activationEvents": [ 60 | "onDebug" 61 | ] 62 | ... 63 | ``` 64 | 65 | ### onDebugInitialConfigurations and onDebugResolve 66 | 67 | 这是两个粒度更细的激活事件: 68 | 69 | * `onDebugInitialConfigurations` 在`DebugConfigurationProvider`中的 `provideDebugConfigurations`方法之前触发。 70 | * `onDebugResolve:type` 在`DebugConfigurationProvider`的`resolveDebugConfiguration`方法之前触发。 71 | 72 | **首要原则:** 如果调试插件的激活事件比较轻量,那么就用`onDebug`。相反,根据`DebugConfigurationProvider`实现的对应方法( `provideDebugConfigurations`或`resolveDebugConfiguration`),使用`onDebugInitialConfigurations`或`onDebugResolve` 。参见 [Debug Type specific Hooks](/docs/extensionAPI/api-debugging.md#debug-type-specific-hooks)。 73 | 74 | ## activationEvents.workspaceContains 75 | 76 | 文件夹打开后,且文件夹中至少包含一个符合glob模式的文件时触发。 77 | 78 | ```json 79 | ... 80 | "activationEvents": [ 81 | "workspaceContains:**/.editorconfig" 82 | ] 83 | ... 84 | ``` 85 | 86 | ## activationEvents.onFileSystem 87 | 88 | 从*协议(scheme)*打开的文件或文件夹打开时触发。通常是`file`-协议,也可以用自定义的文件供应器函数替换掉,比如`ftp`、`ssh`。 89 | 90 | ```json 91 | ... 92 | "activationEvents": [ 93 | "onFileSystem:sftp" 94 | ] 95 | ... 96 | ``` 97 | 98 | ## activationEvents.onView 99 | 100 | 指定的视图id展开时触发: 101 | 102 | ```json 103 | ... 104 | "activationEvents": [ 105 | "onView:nodeDependencies" 106 | ] 107 | ... 108 | ``` 109 | 110 | ## activationEvents.onUri 111 | 112 | 插件的系统级URI打开时触发。这个URI协议需要带上`vscode` 或者 `vscode-insiders`协议。URI授权必须是插件的唯一标识,剩余的URI是可选的。 113 | 114 | ```json 115 | ... 116 | "activationEvents": [ 117 | "onUri" 118 | ] 119 | ... 120 | ``` 121 | 122 | 如果 `vscode.git`插件定义了`onUri`激活事件,那么下列任意URI打开时就会触发: 123 | 124 | - `vscode://vscode.git/init` 125 | - `vscode://vscode.git/clone?url=https%3A%2F%2Fgithub.com%2FMicrosoft%2Fvscode-vsce.git` 126 | - `vscode-insiders://vscode.git/init` (for VS Code Insiders) 127 | 128 | ## activationEvents.* 129 | 130 | 当VS Code启动时触发。为了保证良好的用户体验,只在你的插件没有其他任何激活事件的前提下,添加这个激活事件。 131 | 132 | ```json 133 | ... 134 | "activationEvents": [ 135 | "*" 136 | ] 137 | ... 138 | ``` 139 | 140 | !> **注意:** 一个插件如果侦听了多个激活事件,那么最好用`"*"`替换掉。 141 | 142 | !> **注意:** 插件**必须**从它的主模块中输出一个`activate()`函数,当任意的激活事件触发时,VS Code会**仅仅调用一次这个函数**。此外,插件也**应该** 导出一个`deactivate()`函数,当VS Code关闭时执行清理的任务。如果清理进程是异步的,插件的`deactivate()`**必须**返回一个Promise。如果这个清理任务是同步的,那么`deactivate()`可以返回`undefined`。 143 | 144 | ## 下一步 145 | 146 | 学习更多VS Code扩展性模型,看看下列主题: 147 | 148 | * [插件清单](/docs/extensionAPI/extension-manifest.md) - VS Code package.json 插件清单文件参考 149 | * [发布内容配置点](/docs/extensionAPI/extension-points.md) - VS Code 发布内容配置点参考 -------------------------------------------------------------------------------- /docs/extension-guides/virtual-documents.md: -------------------------------------------------------------------------------- 1 | # 虚拟文档 2 | 3 | 通过VS Code的文本内容供应器API(text document content provider API),你可以为任意来源的文件创建只读文档。本示例源码请查看[https://github.com/Microsoft/vscode-extension-samples/blob/master/virtual-document-sample/README.md](https://github.com/Microsoft/vscode-extension-samples/blob/master/virtual-document-sample/README.md) 4 | 5 | ## TextDocumentContentProvider 6 | --- 7 | 8 | 这个API工作于uri协议之上,你需要声明一个*供应器函数(provider)*,然后这个函数还需要返回文本内容。供应器函数必须提供*协议(scheme)*,而且函数注册之后不可改变这个协议。一个供应器函数可以对应多个协议,而多个供应器函数也可以只注册一个协议。 9 | 10 | ```typescript 11 | vscode.workspace.registerTextDocumentContentProvider(myScheme, myProvider); 12 | ``` 13 | 14 | 调用`registerTextDocumentContentProvider`函数会返回一个用于释放资源的*释放器*。供应器函数还必须实现`provideTextDocumentContent`函数,这个函数需要传入uri参数和取消式令牌(cancellation token)调用。 15 | 16 | ```typescript 17 | const myProvider = class implements vscode.TextDocumentContentProvider { 18 | provideTextDocumentContent(uri: vscode.Uri): string { 19 | // 简单调用cowsay, 直接把uri-path当做文本内容 20 | return cowsay.say({ text: uri.path }); 21 | } 22 | }; 23 | ``` 24 | 25 | !> **注意**:我们的供应器函数不为虚拟文档创建uri——他的角色仅仅只是**根据uri返回对应的文本内容**。 26 | 27 | 下面我们简单使用一个'cowsay'命令创建一个uri,然后编辑器就能显示了: 28 | 29 | ```typescript 30 | vscode.commands.registerCommand('cowsay.say', async () => { 31 | let what = await vscode.window.showInputBox({ placeHolder: 'cow say?' }); 32 | if (what) { 33 | let uri = vscode.Uri.parse('cowsay:' + what); 34 | let doc = await vscode.workspace.openTextDocument(uri); // 调用供应器函数 35 | await vscode.window.showTextDocument(doc, { preview: false }); 36 | } 37 | }); 38 | ``` 39 | 40 | 这个命令首先弹出了一个输入框,然后创建了一个*`cowsay`协议*的uri,再然后根据这个uri读取了文档,最后为这个文档内容打开了一个编辑器(这里的“编辑器”不是指VS Code本身,而是VS Code中打开的单个编辑区tab)。在第三步中,*供应器函数*需要为这个uri提供对应的内容。 41 | 42 | 经过这整个流程,我们才算完整地实现了一个*文本内容供应器*,接下来的部分我们继续学习怎么更新虚拟文档,怎么注册虚拟文档的 UI命令。 43 | 44 | ### 更新虚拟文档 45 | 46 | 为了支持跟踪虚拟文档发生的变化,供应器实现了`onDidChange`事件。如果文档正在被使用,那么必须为其提供一个uri来调用它,同时编辑器会请求新的内容。 47 | 48 | `vscode.Event`定义了VS Code的事件规范。实现事件的最好方式就是使用`vscode.EventEmitter`,比如: 49 | 50 | ```typescript 51 | const myProvider = class implements vscode.TextDocumentContentProvider { 52 | // 事件发射器和事件 53 | onDidChangeEmitter = new vscode.EventEmitter(); 54 | onDidChange = this.onDidChangeEmitter.event; 55 | 56 | //... 57 | }; 58 | ``` 59 | 60 | 上述就是VS Code监听虚拟文档变化所必须的内容。下面将使用事件发射器来添加*编辑器行为*。 61 | 62 | ### 添加编辑器命令 63 | 64 | 为了阐述事件变动和获取更多cowsay,我们需要倒叙cow刚刚说的东西。首先我们需要一个命令: 65 | 66 | ```typescript 67 | // 注册一个可以更新当前cow的命令 68 | subscriptions.push( 69 | vscode.commands.registerCommand('cowsay.backwards', async () => { 70 | if (!vscode.window.activeTextEditor) { 71 | return; // 不打开编辑器 72 | } 73 | let { document } = vscode.window.activeTextEditor; 74 | if (document.uri.scheme !== myScheme) { 75 | return; // 不是我的协议时直接返回 76 | } 77 | // 获取path的内容, 对这个内容倒序处理, 然后创建一个新的uri 78 | let say = document.uri.path; 79 | let newSay = say 80 | .split('') 81 | .reverse() 82 | .join(''); 83 | let newUri = document.uri.with({ path: newSay }); 84 | await vscode.window.showTextDocument(newUri, { preview: false }); 85 | }) 86 | ); 87 | ``` 88 | 89 | 上面的代码片段检查了我们当前是不是激活了一个编辑器(用户当前选中的编辑器tab),对应的文档是不是符合我们的协议。因为命令是对任何人生效的,所以我们有必要去做这些检查。然后uri的path对象被翻转,再重新创建出一个新的uri,最后则打开了一个编辑器。 90 | 91 | 92 | 注册命令最重要事就是在`package.json`中声明配置。我们在`contributes`部分添加下列配置: 93 | ```json 94 | "menus": { 95 | "editor/title": [ 96 | { 97 | "command": "cowsay.backwards", 98 | "group": "navigation", 99 | "when": "resourceScheme == cowsay" 100 | } 101 | ] 102 | } 103 | ``` 104 | `contributes/commands`中的`cowsay.backwards`命令告诉编辑器*操作*出现在编辑器的标题菜单中(工具栏右上角),但如果只是这样简单的配置,每个编辑器就都会显示这个命令。然后我们的`when`语句就出场了,它描述了何时才显示这个操作。在这个例子中,文档的资源协议必须是`cowsay`,我们的命令才会生效。这个配置对默认显示全部命令的`commandPalette`菜单同样生效。 105 | 106 | ![cowsay-bwd](https://media.githubusercontent.com/media/Microsoft/vscode-docs/master/api/extension-guides/images/virtual-documents/cowsay-bwd.png) 107 | 108 | ### 事件的可见性 109 | 110 | *文档供应器函数*是VS Code中的一等公民,它们的内容以常规的文本文档格式呈现,它们共用一套基础实现方式——如:使用了文件系统的实现。这也就意味着“你的”文档无法被隐藏,它们必定会出现在`onDidOpenTextDocument`和`onDidCloseTextDocument`事件中,它们是`vscode.workspace.textDocuments`中的一部分。通用的准则就是根据文档的`协议`决定你是否需要对文档进行什么操作。 111 | 112 | ### 文件系统API 113 | 114 | 如果你需要更强的灵活性和掌控力,请查看[`FileSystemProvider`](https://code.visualstudio.com/api/references/vscode-api#FileSystemProvider)API,它可以实现整套完整的文件系统,获取文件、文件夹、二进制数据,删除文件,创建文件等等。 -------------------------------------------------------------------------------- /docs/extension-authoring/testing-extensions.md: -------------------------------------------------------------------------------- 1 | # 测试你的插件 2 | 3 | VS Code可以运行和调试支持VS Code API的插件。这些测试会运行在VS Code的特殊实例`扩展开发环境`中,这个环境有权访问全部的API。我们将这样的测试称为集成测试,因为它远远超越了单独运行在VS Code中的单元测试。本篇侧重于VS Code的集成测试,至于单元测试,你可以使用任何流行的测试框架,如[Mocha](https://mochajs.org/)或者[Jasmine](https://jasmine.github.io/)。 4 | 5 | ## Yo Code测试脚手架 6 | --- 7 | [yo code 生成器](/extension-authoring/extension-generator.md)基础插件项目包含了一些示例测试和必要的基础设施。 8 | 9 | !> **注意:**本篇假设你已经创建了一个Typescript插件(或Javascript插件),不然先参考[基础部分](extension-authoring/extension-generator) 10 | 11 | 打开一个插件项目目录,打开**调试**侧边栏选择`Extension Tests`配置。 12 | 13 | ![launch-tests](https://raw.githubusercontent.com/Microsoft/vscode-docs/master/docs/extensions/images/testing-extensions/launch-tests.png) 14 | 15 | 选中配置之后,点击绿色的小角标,启动调试。VS Code会在`扩展开发环境`实例中加载插件,然后运行调试。测试的输出会进入*调试控制台*: 16 | 17 | ![test-output](https://raw.githubusercontent.com/Microsoft/vscode-docs/master/docs/extensions/images/testing-extensions/test-output.png) 18 | 19 | 生成的测试使用了[Mocha 测试框架](https://mochajs.org/)的测试运行器和库。 20 | 21 | 插件项目文件夹中的附带了`src/test`,其中有一个`index.ts`文件,定义了Mocha测试运行器的配置,`extension.test.ts`中包含着测试示例`Something 1`。通常来说你可以不管`index.ts`,不过你也可以调整Mocha的配置。 22 | 23 | ``` 24 | ├── src 25 | │ └── test 26 | │ ├── extension.test.ts 27 | │ └── index.ts 28 | ``` 29 | 30 | 你可以在`test`目录下创建更多的`test.ts`文件,它们会被自动构建(到`out/test`)然后运行。测试运行器只会匹配`*.test.ts`模式的文件。 31 | 32 | ## 加载测试配置 33 | --- 34 | 35 | `Extension Tests`的配置文件在项目的`.vscode\launch.json`的文件中。就像`Extension`配置一样,通过`--extensionTestsPath`参数,指定编译的测试文件位置(假设是Typescript项目)。 36 | ```json 37 | { 38 | "name": "Extension Tests", 39 | "type": "extensionHost", 40 | "request": "launch", 41 | "runtimeExecutable": "${execPath}", 42 | "args": [ 43 | "--extensionDevelopmentPath=${workspaceFolder}", 44 | "--extensionTestsPath=${workspaceFolder}/out/test" 45 | ], 46 | "outFiles": [ 47 | "${workspaceFolder}/out/test/**/*.js" 48 | ] 49 | } 50 | ``` 51 | 52 | ## 将参数传递到扩展开发环境中 53 | --- 54 | 在加载配置中添加参数列表,然后测试示例就能在你指定的目录或文件中启动测试了。 55 | ```json 56 | "args": [ 57 | "file or folder name", 58 | "--extensionDevelopmentPath=${workspaceFolder}", 59 | "--extensionTestsPath=${workspaceFolder}/out/test" 60 | ] 61 | ``` 62 | 用这个方式,你的测试就可以运行在可预测的文件结构中运行了。 63 | 64 | ## 从项目中排除测试文件 65 | --- 66 | 当你想要分享插件的时候,你可能就不需要测试文件出现在*插件包*里了。[.vscodeignore](https://github.com/Microsoft/vscode-docs/blob/master/docs/extensions/publish-extension.md#advance-usage)文件可以让你在使用[vsce构建工具](https://github.com/Microsoft/vscode-docs/blob/master/docs/extensions/publish-extension.md)的时候排除测试文件。默认情况下,`yo code`生成的项目会排除`test`和`out/test`文件夹。 67 | ``` 68 | out/test/** 69 | ``` 70 | 71 | ## 使用Travis CI自动测试 72 | --- 73 | 你也可以用诸如[Travis CI](https://travis-ci.org/)自动构建机器来自动运行测试。 74 | 75 | 为了启动自动插件测试,`vscode`包需要提供一个可以运行下列任务的测试命令: 76 | - 下载和解压VS Code 77 | - 在VS Code内加载插件测试任务 78 | - 将测试结果输出到控制台中,或在异常中退出 79 | 80 | 为了完成这项命令,打开你的`package.json`然后将下列代码添加到`scripts`中: 81 | ```json 82 | "test": "node ./node_modules/vscode/bin/test" 83 | ``` 84 | 85 | 你可以在顶层配置一个`.travis.yml`文件,就可以轻松地启用Travis CI了: 86 | ```yml 87 | sudo: false 88 | 89 | os: 90 | - osx 91 | - linux 92 | 93 | before_install: 94 | - if [ $TRAVIS_OS_NAME == "linux" ]; then 95 | export CXX="g++-4.9" CC="gcc-4.9" DISPLAY=:99.0; 96 | sh -e /etc/init.d/xvfb start; 97 | sleep 3; 98 | fi 99 | 100 | install: 101 | - npm install 102 | - npm run vscode:prepublish 103 | 104 | script: 105 | - npm test --silent 106 | ``` 107 | 108 | 上述脚本可以运行在Linux和macOS上,值得注意的一点是为了在Linux上运行测试,你需要配置一个`before_install`告诉Linux在构建中启动VS Code。 109 | 110 | 下面是一些用于测试运行器的可选的环境变量: 111 | 112 | | 名称 | 描述 | 113 | | --- | --- | 114 | | CODE_VERSION | 运行测试的VS Code版本(如:0.10.10)| 115 | | CODE_DOWNLOAD_URL | 下载VS Code的完整URL | 116 | | CODE_TESTS_PATH | 执行测试的位置(默认是process.cwd()/out/test or process.cwd()/test) | 117 | | CODE_EXTENSIONS_PATH | 加载插件的位置(默认是process.cwd()) | 118 | | CODE_TESTS_WORKSPACE | test实例打开的工作区位置(默认是CODE_TESTS_PATH) | 119 | 120 | ## 在Windows中使用AppVeyor测试 121 | --- 122 | 你也可以在Windows中用[AppVeyor](https://www.appveyor.com/)进行测试 123 | 124 | ## 下一步 125 | 126 | - [发开插件](/extension-authoring/developing-extensions.md) - 学习更多调试插件的内容。 127 | - [vsce](https://github.com/Microsoft/vscode-docs/blob/master/docs/extensions/publish-extension.md) - 使用VSCE命令行工具发布插件。 128 | - [插件配置清单](/extensibility-reference/extension-manifest.md) - VS Code插件配置清单参阅。 129 | - [扩展API](/extensibility-reference/vscode-api.md) - 学习更多VS Code扩展性API。 -------------------------------------------------------------------------------- /docs/extension-guides/file-icon-theme.md: -------------------------------------------------------------------------------- 1 | # 图标主题 2 | 3 | VS Code的UI在文件名称左边显示图标,插件配置的图标系列可以让用户自由选择他们喜爱的图标。 4 | 5 | ## 添加新的图标主题 6 | --- 7 | 8 | 你能使用图标文件(最好是SVG)和字体图标创建自己的图标主题。作为示例,你可以参考一下2个内置主题:[Minimal](https://github.com/Microsoft/vscode/tree/master/extensions/theme-defaults),[Seti](https://github.com/Microsoft/vscode/tree/master/extensions/theme-seti) 9 | 10 | 首先,创建一个VS Code插件,然后把`iconTheme`配置点(contribution point)添加进去 11 | 12 | ```json 13 | "contributes": { 14 | "iconThemes": [ 15 | { 16 | "id": "turtles", 17 | "label": "Turtles", 18 | "path": "./fileicons/turtles-icon-theme.json" 19 | } 20 | ] 21 | } 22 | ``` 23 | 24 | - `id`作为这个图标主题的标识,目前只做内部使用,未来可能会用在设置里面,所以最好设置一个可读性强的唯一值。 25 | - `label`会显示在*主题选择*下拉框中。 26 | - `path`指示了图标集所在的位置。如果你的图标系列名称遵循`*icon-theme.json`命名规范,那么VS Code就能提供完整的支持。 27 | 28 | ### 图标文件集(Icon set file) 29 | 图标文件集是一个JSON文件,包含了所有的**关联图标**和图标定义。 30 | 31 | 一个**关联图标**将**图标定义**映射到一个文件上(类型如:文件,文件夹,json文件...)。**图标定义**指示了图标的所在位置:可以是一个图片文件,或者glyph字体。 32 | 33 | ### 图标定义 34 | 35 | `iconDefinitions`部分包含了所有定义。每个定义有一个id,用于指向定义。一个定义能供多个文件关联引用。 36 | 37 | ```json 38 | "iconDefinitions": { 39 | "_folder_dark": { 40 | "iconPath": "./images/Folder_16x_inverse.svg" 41 | } 42 | } 43 | ``` 44 | 45 | 这里,**图标定义**包含了一个标识符`_folder_dark`。除此之外还支持以下属性: 46 | 47 | - `iconPath`:当使用svg/png文件时:指向图片的路径。 48 | - `fontCharacter`:当使用glyph字体时:字体中使用的字符。 49 | - `fontColor`:当使用glyph字体时:设置glyph的颜色。 50 | - `fontSize`:当使用字体时:设置字体大小。默认情况下会使用字体本身定义的字体大小。这个值应为父级字号的相对值(如 150%)。 51 | - `fontId`:当使用字体时: 字体的ID。如果没有指定,则会采用`font specification`部分的第一个字体。 52 | 53 | ### 关联文件 54 | 55 | 图标能关联到文件夹,文件夹名称,文件,文件名称,文件插件,和[语言Id](/references/contribution-points#contributeslanguages)。 56 | 57 | 这些关联都能被提炼为诸如'light'和'highContrast'色彩主题。 58 | 59 | 每个文件关联指向一个**图标定义** 60 | 61 | ```json 62 | "file": "_file_dark", 63 | "folder": "_folder_dark", 64 | "folderExpanded": "_folder_open_dark", 65 | "folderNames": { 66 | ".vscode": "_vscode_folder", 67 | }, 68 | "fileExtensions": { 69 | "ini": "_ini_file", 70 | }, 71 | "fileNames": { 72 | "win.ini": "_win_ini_file", 73 | }, 74 | "languageIds": { 75 | "ini": "_ini_file" 76 | }, 77 | "light": { 78 | "folderExpanded": "_folder_open_light", 79 | "folder": "_folder_light", 80 | "file": "_file_light", 81 | "fileExtensions": { 82 | "ini": "_ini_file_light", 83 | } 84 | }, 85 | "highContrast": { 86 | } 87 | ``` 88 | 89 | - `file`是一个默认文件图标,为那些没有匹配到任何插件、文件名、语言类型的文件所准备的。目前所有文件图标属性都会被继承(只适用于:glyphs字体、字体大小(fontSize))。 90 | - `folder`收起的文件夹图标,如果`folderExpanded`没有设置,那么展开的文件夹也会使用这个图标。使用`folderNames`关联特殊名称的文件夹。文件夹图标是可选的,如果不设置,那文件夹就不会显示任何图标。 91 | - `folderExpanded`展开的文件夹图标。这个图标是可选的,如果不设置就会使用`folder`定义好的图标。 92 | - `folderNames`特殊名称文件夹图标。这个键是用于文件夹名称的,不支持包含路径的名称,不支持匹配模式和通配符。大小写不敏感。 93 | - `folderNamesExpanded`展开的特殊名称文件夹图标。 94 | - `rootFolder` 收起的工作区根文件夹图标,如果`rootFolderExpanded`没有设置,那么展开的工作区根文件夹也会使用这个图标。如果不设置,则会使用`folder`定义的文件夹图标。 95 | - `rootFolderExpanded` 展开的工作区根文件夹图标。如果没有设置,则会使用`rootFolder`定义的文件夹图标。 96 | - `languageIds`语言类型图标。这个键将匹配在*语言配置点(contribution point)*配置的[语言id](/references/contribution-points#contributeslanguages)。注意语言配置的'第一行'是不考虑在内的。 97 | - `fileExtensions`文件插件图标。根据文件插件的名称匹配。插件名称是文件名点号后面(不包含点号)。拥有多重点号的文件名称,如`lib.d.ts`会匹配多个模式——`d.ts`和`ts`。大小写敏感。 98 | - `fileNames`文件图标。这个键需要文件的全称进行匹配,不支持包含路径的名称,不支持模式和通配符。大小写敏感。`fileNames`是最高优先匹配。 99 | 100 | 匹配优先级:`fileNames` > `fileExtensions` > `languageIds` 101 | 102 | `light`和`highContrast`部分的属性表和上面相同,只是会在对应的主题下覆盖原有图标配置。 103 | 104 | ### 字体定义 105 | 106 | 在'font'部分添加任意你喜欢的字形和字体。定义好之后,你就可以在图标定义中使用它们了。如果没有指定字体id,那么默认使用第一个定义的字体。 107 | 108 | 将字体文件移动到你的插件中,设置好对应的路径。推荐使用[WOFF](https://developer.mozilla.org/zh-CN/docs/WOFF)字体。 109 | 110 | - 设置格式为'woff' 111 | - 字重键值的定义参考[这里](https://developer.mozilla.org/docs/Web/CSS/font-weight#Values) 112 | - 样式键值对的定义参考在[这里](https://developer.mozilla.org/docs/Web/CSS/@font-face/font-style#Values) 113 | - 使用图标引用该字体时的字号。因此字体字号总是以百分比表示。 114 | 115 | ```json 116 | "fonts": [ 117 | { 118 | "id": "turtles-font", 119 | "src": [ 120 | { 121 | "path": "./turtles.woff", 122 | "format": "woff" 123 | } 124 | ], 125 | "weight": "normal", 126 | "style": "normal", 127 | "size": "150%" 128 | } 129 | ], 130 | "iconDefinitions": { 131 | "_file": { 132 | "fontCharacter": "\\E002", 133 | "fontColor": "#5f8b3b", 134 | "fontId": "turtles-font" 135 | } 136 | } 137 | ``` 138 | 139 | ### 图标主题中的文件夹图标 140 | 141 | 文件图标主题会告诉文件浏览器不要显示默认文件夹图标(倒三角或者横杠),这个模式可在配置中加入`"hidesExplorerArrows":true`覆盖默认VS Code的设置。 -------------------------------------------------------------------------------- /docs/preknowledge/declaration-files.md: -------------------------------------------------------------------------------- 1 | # 声明文件 2 | 3 | 当你在使用VS Code编写TypeScript文件时,你不太可能在每个文件上都标明`interface`字样的接口,一旦某个文件的方法或者变量比较多,你的代码可能就会被非常多的类型注解占据,在大型项目或者是你生成的库文件中为了保持代码的整洁,你就可能需要**声明文件**的帮助。 4 | 5 | ## 创建一个声明文件 6 | --- 7 | 8 | 声明文件以`.d.ts`结尾,与TypeScript文件`.ts`稍有区别。当你的项目目录中出现了`.d.ts`结尾的文件时,所有与之关联的规则都会自动应用。声明文件支持我们前面介绍的各类语法,但是你得在语法前面加上`declare`。 9 | 10 | ## 例子 11 | --- 12 | 13 | ### 全局变量 14 | 15 | **文档** 16 | 17 | > 全局变量foo包含了存在组件总数。 18 | 19 | **代码** 20 | 21 | ```typescript 22 | console.log("Half the number of widgets is " + (foo / 2)); 23 | ``` 24 | 25 | **声明** 26 | 27 | 使用declare var声明变量。 如果变量是只读的,那么可以使用 declare const。 你还可以使用 declare let如果变量拥有块级作用域。 28 | 29 | ```typescript 30 | /** 组件总数 */ 31 | declare var foo: number; 32 | ``` 33 | 34 | ### 全局函数 35 | **文档** 36 | 37 | > 用一个字符串参数调用greet函数向用户显示一条欢迎信息。 38 | 39 | **代码** 40 | ```typescript 41 | greet("hello, world"); 42 | ``` 43 | **声明** 44 | 45 | 使用declare function声明函数。 46 | ```typescript 47 | declare function greet(greeting: string): void; 48 | ``` 49 | 50 | ### 带属性的对象 51 | **文档** 52 | 53 | > 全局变量myLib包含一个makeGreeting函数, 还有一个属性 numberOfGreetings指示目前为止欢迎数量。 54 | 55 | **代码** 56 | 57 | ```typescript 58 | let result = myLib.makeGreeting("hello, world"); 59 | console.log("The computed greeting is:" + result); 60 | 61 | let count = myLib.numberOfGreetings; 62 | ``` 63 | 64 | **声明** 65 | 66 | 使用declare namespace描述用点表示法访问的类型或值。 67 | ```typescript 68 | declare namespace myLib { 69 | function makeGreeting(s: string): string; 70 | let numberOfGreetings: number; 71 | } 72 | ``` 73 | ### 函数重载 74 | **文档** 75 | 76 | getWidget函数接收一个数字,返回一个组件,或接收一个字符串并返回一个组件数组。 77 | 78 | **代码** 79 | ```typescript 80 | let x: Widget = getWidget(43); 81 | 82 | let arr: Widget[] = getWidget("all of them"); 83 | ``` 84 | **声明** 85 | ```typescript 86 | declare function getWidget(n: number): Widget; 87 | declare function getWidget(s: string): Widget[]; 88 | ``` 89 | ### 可重用类型(接口) 90 | **文档** 91 | 92 | > 当指定一个欢迎词时,你必须传入一个GreetingSettings对象。 这个对象具有以下几个属性: 93 | > 94 | > 1- greeting:必需的字符串 95 | > 96 | > 2- duration: 可选的时长(毫秒表示) 97 | > 98 | > 3- color: 可选字符串,比如‘#ff00ff’ 99 | 100 | **代码** 101 | ```typescript 102 | greet({ 103 | greeting: "hello world", 104 | duration: 4000 105 | }); 106 | ``` 107 | **声明** 108 | 109 | 使用interface定义一个带有属性的类型。 110 | ```typescript 111 | interface GreetingSettings { 112 | greeting: string; 113 | duration?: number; 114 | color?: string; 115 | } 116 | 117 | declare function greet(setting: GreetingSettings): void; 118 | ``` 119 | 120 | ### 可重用类型(类型别名) 121 | **文档** 122 | 123 | > 在任何需要欢迎词的地方,你可以提供一个string,一个返回string的函数或一个Greeter实例。 124 | 125 | **代码** 126 | 127 | ```typescript 128 | function getGreeting() { 129 | return "howdy"; 130 | } 131 | class MyGreeter extends Greeter { } 132 | 133 | greet("hello"); 134 | greet(getGreeting); 135 | greet(new MyGreeter()); 136 | ``` 137 | 138 | **声明** 139 | 140 | 你可以使用类型别名来定义类型的短名: 141 | 142 | ```typescript 143 | type GreetingLike = string | (() => string) | MyGreeter; 144 | 145 | declare function greet(g: GreetingLike): void; 146 | ``` 147 | ### 组织类型 148 | **文档** 149 | 150 | > greeter对象能够记录到文件或显示一个警告。 你可以为 .log(...)提供LogOptions和为.alert(...)提供选项。 151 | 152 | **代码** 153 | ```typescript 154 | const g = new Greeter("Hello"); 155 | g.log({ verbose: true }); 156 | g.alert({ modal: false, title: "Current Greeting" }); 157 | ``` 158 | **声明** 159 | 160 | 使用命名空间组织类型。 161 | ```typescript 162 | declare namespace GreetingLib { 163 | interface LogOptions { 164 | verbose?: boolean; 165 | } 166 | interface AlertOptions { 167 | modal: boolean; 168 | title?: string; 169 | color?: string; 170 | } 171 | } 172 | ``` 173 | 你也可以在一个声明中创建嵌套的命名空间: 174 | ```typescript 175 | declare namespace GreetingLib.Options { 176 | // Refer to via GreetingLib.Options.Log 177 | interface Log { 178 | verbose?: boolean; 179 | } 180 | interface Alert { 181 | modal: boolean; 182 | title?: string; 183 | color?: string; 184 | } 185 | } 186 | ``` 187 | ### 类 188 | **文档** 189 | 190 | > 你可以通过实例化Greeter对象来创建欢迎词,或者继承Greeter对象来自定义欢迎词。 191 | 192 | **代码** 193 | ```typescript 194 | const myGreeter = new Greeter("hello, world"); 195 | myGreeter.greeting = "howdy"; 196 | myGreeter.showGreeting(); 197 | 198 | class SpecialGreeter extends Greeter { 199 | constructor() { 200 | super("Very special greetings"); 201 | } 202 | } 203 | ``` 204 | **声明** 205 | 206 | 使用declare class描述一个类或像类一样的对象。 类可以有属性和方法,就和构造函数一样。 207 | ```typescript 208 | declare class Greeter { 209 | constructor(greeting: string); 210 | 211 | greeting: string; 212 | showGreeting(): void; 213 | } 214 | ``` 215 | -------------------------------------------------------------------------------- /docs/extensibility-reference/principles-patterns.md: -------------------------------------------------------------------------------- 1 | # 扩展性原则和模式 2 | 3 | ## 扩展性实现 4 | --- 5 | 6 | VS Code有着非常丰富的扩展性模型和生产插件的方法。不过我们没有给插件作者提供直接操作底层UI DOM的方法。在VS Code开发中,我们会不断优化底层web技术的使用使其达到高可用、高响应的状态,我们会随着这些技术和产品的演进继续调整DOM的使用方式。为了维持其性能和兼容性,插件在独立的进程中运行同时阻止插件作者直接操作DOM,这样有助于保持不同编程语言实现的插件一致性,VS Code还为很多场景提供了一整套内置的UI组件,如IntelliSense,这样一来,插件开发者也就不需要重复造轮子了。 7 | 8 | 这些规定乍看可能比较严格,我们也一直在寻找更好的方法改进我们的扩展性,增加插件的能力,期待聆听你的反馈和意见。 9 | 10 | ## 核心 11 | --- 12 | 13 | #### 插件独立 - 稳定性 14 | 15 | 插件虽好但是它会影响到VS Code的启动性能和整体稳定性,所以VS Code为插件的加载和执行单独开辟了一条进程,`extension host process`,这样一来出错的插件就不会影响到VS Code,尤其是在VS Code刚启动的时候。 16 | 17 | 这样的架构确保了终端用户能控制住VS Code:不论什么时候,用户都可以打开、输入、保存文件,不管插件在做什么VS Code都需要保证UI的及时响应。 18 | 19 | `extension host`是一个Node.js进程,并将VS Code API暴露给了插件开发者。VS Code在`extension host`下为插件提供了debug支持。 20 | 21 | #### 插件激活时机 - 性能 22 | 23 | VS Code会尽可能晚地加载插件,为了达到控制内存的目的,如果插件在会话期间没有用到就不会加载。为了帮助开发者理解插件的懒加载机制,VS Code提供了称之为`activation events`的事件表。激活事件定义了特定的触发时机,比如:一个Markdown辅助插件只需要在用户打开Markdown文件的时候启动。 24 | 25 | #### Extension Manifest(插件配置清单) 26 | 27 | 为了激活一个懒加载插件,VS Code需要一份插件的描述文件,`插件清单(extension manifest)`是一份添加了[VS Code特定字段](/extensibility-reference/extension-manifest.md)的`package.json`文件,其中包含了激活事件的配置位置。VS Code提供了一系列插件可以使用的`发布内容配置(contribution points)`。例如,想给VS Code添加一个指令,则需要你在名为`commands`的配置点中定义指令。一旦你在`package.json`中定义好了配置。VS Code 在启动时会读取、解析这个清单然后准备相应的UI界面。 28 | 29 | ?> **译者注**:定义在发布内容配置中的有些东西会暴露在用户的**配置**中,用户可以通过setting.json等文件修改你的插件行为,因此叫做这个略拗口的名字——发布内容配置。**配置点**则是构成发布内容配置的一个个键值对。 30 | 31 | 查看更多的[package.json 发布内容配置](/extensibility-reference/contribution-points.md) 32 | 33 | #### 扩展性API 34 | 35 | 查看[扩展性API](/extensibility-reference/vscode-api.md)取得更多细节。 36 | 37 | 为了修改和自定义UI,VS Code采用了强有力的Web技术(HTML,CSS)。你可以很轻松地给DOM添加节点,然后使用CSS定义它的样式。不过,这个技术也并非没有缺陷,尤其是在实现像VS Code这样复杂的应用时。 38 | 39 | 易变的界面结构和紧密绑定到UI上的插件一起工作时可能会导致崩溃,因此VS Code采用了预防性的措施避免这种问题——不提供操作DOM的API。 40 | 41 | #### 基于协议的插件 42 | 43 | 在VS Code中比较常见的场景是插件在各自独立的进程中运行,然后通过特定协议与VS Code进行通信,比如:语言服务器和调试适配器。 44 | 45 | 一般来说,这个通信协议使用 stdin/stdout 标准和JSON载荷进行消息传输。 46 | 47 | 使用分离的进程有助于插件建立独立的边界,维持VS Code核心编辑器进程的稳定性,同时也有助于插件开发人员为特定的插件实现选择合适的编程语言。 48 | 49 | ## 扩展性模式 50 | --- 51 | 52 | 扩展性API遵循下列模式。 53 | 54 | #### Promises(异步) 55 | 56 | VS Code API完全采用了promise的实现。对于插件来说允许任何promise形式的返回格式,如ES6,WinJS,A+等。 57 | 58 | 一个promise库需要它的API使用`Thenable`类型来表达,`Thenable`类型代表了一种通用特性的实现——then方法。 59 | 60 | 大多数时候promise是一个可选项,VS Code调用插件之后,它能直接处理正常的返回结果也能处理`Thenable`的结果类型。当promise是可选的API返回结果时,API会在返回类型中用`Thenable`表示。 61 | 62 | ```typescript 63 | provideNumber(): number | Thenable 64 | ``` 65 | 66 | #### Cancellation Tokens(取消式令牌) 67 | 68 | 有些事件可能从不稳定的变化状态开始,而随着状态变化这一事件最后肯能被取消了。比如:IntelliSense(智能补全)被触发后,用户持续输入的行为使得这一操作最终被取消了。 69 | 70 | API也为这种行为提供了解决方案,你可以通过`CancellationToken`检查取消的状态(`isCancellationRequested`)或者当*取消*发生时得到通知(`onCancellationRequested`)。取消式令牌通常是API函数的最后一个(可选)参数。 71 | 72 | #### Disposables(释放器) 73 | 74 | VS Code API使用了[释放器模式](https://en.wikipedia.org/wiki/Dispose_pattern),这个模式被用于事件侦听,命令,UI交互和各类语言配置上。 75 | 76 | 例如:`setStatusBarMessage(value: string)`事件返回一个`Disposable`对象,这个对象最终调用`dispose`方法移除message。 77 | 78 | #### Events(事件) 79 | 80 | 事件在API中被暴露为函数,当你订阅一个事件侦听器时绑定。事件侦听器调用后会返回一个`Disposable`,它会在dispose触发后,移除事件侦听器。 81 | 82 | ```typescript 83 | var listener = function(event) { 84 | console.log("It happened", event); 85 | }; 86 | 87 | // 开始侦听 88 | var subscription = fsWatcher.onDidDelete(listener); 89 | 90 | // 你的代码 91 | 92 | subscription.dispose(); // 停止侦听 93 | ``` 94 | 95 | 事件的命名规则遵循`on[Will | Did] 动词 + 名词`的形式。通过`onWill`表示将要发生,`onDid`表示已经发生,`动词`表示行为,`名词`指代上下文或目标。 96 | 97 | 举个栗子:`window.onDidChangeActiveTextEditor`中,激活的编辑器(ActiveTextEditor:`名词`)变动(change:`动词`)后(`onDid`)会触发事件。 98 | 99 | ## 严格null检查 100 | --- 101 | 102 | VS CodeAPI使用`undefined`和`null`的Typescript类型,同样也支持[严格null检查](https://github.com/Microsoft/TypeScript/pull/7140)。 103 | 104 | ## 在插件中使用Node.js模块 105 | --- 106 | 107 | 就像一个node模块,你可以把依赖添加到`pacakge.json`中的`dependencies`字段中去,甚至把VS Code[专用的node模块包](https://code.visualstudio.com/docs/extensionAPI/extension-manifest#_useful-node-modules)加进去。 108 | 109 | 安装和打包 110 | 111 | VS Code不会在用户安装插件时,把你的依赖安装起来,所以你需要在发布之前使用`npm install`。插件的发布包中包含着所有的依赖。使用`vsce ls`命令列出`vsce`之后会包含的依赖包。 112 | 113 | 使用`.vscodeignore`文件排除掉已经在你插件依赖中的包。查看`vsce`发布工具,查看更多[相关细节](https://code.visualstudio.com/docs/extensions/publish-extension#_vscodeignore)。 114 | 115 | ## FAQ 116 | --- 117 | **问:我能在插件中使用原生Node.js模块吗?** 118 | 119 | 答:如果你在Windows平台上开发了一个原生模块插件,当你发布插件时,Windows上的编译器会将原生依赖编译进去,这样一来,macOS或者Linux的用户就用不了插件了。 120 | 121 | 目前这个问题的唯一方案是,将4个平台(Windows x86和x64,Linux,macOS)的所有二进制文件包含进来,并让这些代码在不同平台上动态加载。 122 | 123 | 我们不建议插件使用原生npm模块,因为原生模块会和插件打包,每当VS Code更新,这个包会随VS Code内置的node.js版本重新编译。你能在开发者工具(帮助 > 打开开发者工具)中运行`process.versions`找到Node.js和模块版本。 124 | 125 | ## 下一步 126 | 127 | [插件配置清单](/extensibility-reference/extension-manifest.md) - VS Code的专有package.json文件参考 128 | 129 | [发布内容配置点](/extensibility-reference/contribution-points.md) - VS Code属性表参考 130 | 131 | [激活事件](/extensibility-reference/activation-events.md) - VS Code激活事件参考 -------------------------------------------------------------------------------- /docs/get-started/extension-anatomy.md: -------------------------------------------------------------------------------- 1 | # 解析插件结构 2 | 3 | 上一节中,你已经能够自己创建一个基础的插件了,但是在面纱之下,它究竟是怎么运作的呢? 4 | 5 | `Hello World`插件包含了3个部分: 6 | - 注册[`onCommand`](/references/activation-events.md#onCommand) [**激活事件**](/references/activation-events.md): `onCommand:extension.helloWorld`,所以用户可以在输入`Hello World`命令后激活插件。 7 | - 使用[`contributes.commands`](/references/contribution-points.md#contributescommands) [**发布内容配置**](/references/contribution-points.md),绑定一个命令ID `extension.helloWorld`,然后 `Hello World`命令就可以在命令面板中使用了。 8 | - 使用[`commands.registerCommand`](/references/vscode-api#commandsregisterCommand) [**VS Code API**](/references/vscode-api.md) 将一个函数绑定到你注册的命令ID`extension.helloWorld`上。 9 | 10 | 理解下面三个关键概念你才能作出一个基本的插件: 11 | - [**激活事件**](references/activation-events.md): 插件激活的时机。 12 | - [**发布内容配置**](references/contribution-points.md): VS Code扩展了 `package.json` [插件清单](/get-started/extension-anatomy?id=插件清单)的字段以便于开发插件。 13 | - [**VS Code API**](references/vscode-api.md): 你的插件代码中需要调用的一系列JavaScript API。 14 | 15 | 大体上,你的插件就是通过组合发布内容配置和VS Code API扩展VS Code的功能。你能在[插件功能概述](/extension-capabilities/README.md)主题中找到合适你插件的配置点和VS Code API。 16 | 17 | 好了,现在让我们自己瞧一瞧`Hello World`示例的源码部分,以及我们上面提到的3个概念是如何应用其中的。 18 | 19 | ## 插件目录结构 20 | --- 21 | 22 | ``` 23 | . 24 | ├── .vscode 25 | │ ├── launch.json // 插件加载和调试的配置 26 | │ └── tasks.json // 配置TypeScript编译任务 27 | ├── .gitignore // 忽略构建输出和node_modules文件 28 | ├── README.md // 一个友好的插件文档 29 | ├── src 30 | │ └── extension.ts // 插件源代码 31 | ├── package.json // 插件配置清单 32 | ├── tsconfig.json // TypeScript配置 33 | ``` 34 | 35 | 下面的几个文件超出了本节讨论的范围,你可以自行前往相应的章节挖掘详细内容: 36 | - `launch.json` 用于配置VS Code [调试](https://code.visualstudio.com/docs/editor/debugging) 37 | - `tasks.json` 用于定义VS Code [任务](https://code.visualstudio.com/docs/editor/tasks) 38 | - `tsconfig.json` 参阅TypeScript [Handbook](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) 39 | 40 | 现在,让我们把精力集中在这个插件的关键部分——`package.json`和`extensions.ts`。 41 | 42 | #### 插件清单 43 | 44 | 每个VS Code插件都必须包含一个`package.json`,它就是插件的[配置清单](/references/extension-manifest.md)。`package.json`混合了Node.js字段,如:`scripts`、`dependencies`,还加入了一些VS Code独有的字段,如:`publisher`、`activationEvents`、`contributes`等。关于这些VS Code字段说明都在[插件清单参考]()中可以找到。我们在本节介绍一些非常重要的字段: 45 | 46 | - `name` 和 `publisher`: VS Code 使用`.`作为一个插件的ID。你可以这么理解,Hello World 例子的 ID 就是`vscode-samples.helloworld-sample`。VS Code 使用 ID 来区分各个不同的插件。 47 | - `main`: 插件的主入口。 48 | - `activationEvents` 和 `contributes`: [激活事件](/references/activation-events.md) and [发布内容配置](/references/contribution-points.md)。 49 | - `engines.vscode`: 描述了这个插件依赖的最低VS Code API版本。 50 | - `postinstall` 脚本: 如果你的`engines.vscode`声明的是1.25版的VS Code API,那它就会按照这个声明去安装目标版本。一旦`vscode.d.ts`文件存在于`node_modules/vscode/vscode.d.ts`,IntelliSense就会开始运作,你就可以对所有VS Code API进行定义跳转或者语法检查了。 51 | 52 | ```json 53 | { 54 | "name": "helloworld-sample", 55 | "displayName": "helloworld-sample", 56 | "description": "HelloWorld example for VS Code", 57 | "version": "0.0.1", 58 | "publisher": "vscode-samples", 59 | "repository": "https://github.com/Microsoft/vscode-extension-samples/helloworld-sample", 60 | "engines": { 61 | "vscode": "^1.25.0" 62 | }, 63 | "categories": ["Other"], 64 | "activationEvents": ["onCommand:extension.helloWorld"], 65 | "main": "./out/extension.js", 66 | "contributes": { 67 | "commands": [ 68 | { 69 | "command": "extension.helloWorld", 70 | "title": "Hello World" 71 | } 72 | ] 73 | }, 74 | "scripts": { 75 | "vscode:prepublish": "npm run compile", 76 | "compile": "tsc -p ./", 77 | "watch": "tsc -watch -p ./", 78 | "postinstall": "node ./node_modules/vscode/bin/install" 79 | }, 80 | "devDependencies": { 81 | "@types/node": "^8.10.25", 82 | "tslint": "^5.11.0", 83 | "typescript": "^2.6.1", 84 | "vscode": "^1.1.22" 85 | } 86 | } 87 | ``` 88 | 89 | ## 插件入口文件 90 | --- 91 | 92 | 插件入口文件会导出两个函数,`activate` 和 `deactivate`,你注册的**激活事件**被触发之时执行`activate`,`deactivate`则提供了插件关闭前执行清理工作的机会。 93 | 94 | [`vscode`](https://www.npmjs.com/package/vscode)模块包含了一个位于`node ./node_modules/vscode/bin/install`的脚本,这个脚本会拉取`package.json`中`engines.vscode`字段定义的VS Code API。这个脚本执行过后,你就得到了智能代码提示,定义跳转等TS特性了。 95 | 96 | ```typescript 97 | // 'vscode'模块包含了VS Code extensibility API 98 | // 按下述方式导入这个模块 99 | import * as vscode from 'vscode'; 100 | 101 | // 一旦你的插件激活,vscode会立刻调用下述方法 102 | export function activate(context: vscode.ExtensionContext) { 103 | 104 | // 用console输出诊断信息(console.log)和错误(console.error) 105 | // 下面的代码只会在你的插件激活时执行一次 106 | console.log('Congratulations, your extension "my-first-extension" is now active!'); 107 | 108 | // 入口命令已经在package.json文件中定义好了,现在调用registerCommand方法 109 | // registerCommand中的参数必须与package.json中的command保持一致 110 | let disposable = vscode.commands.registerCommand('extension.helloWorld', () => { 111 | // 把你的代码写在这里,每次命令执行时都会调用这里的代码 112 | // ... 113 | // 给用户显示一个消息提示 114 | vscode.window.showInformationMessage('Hello World!'); 115 | }); 116 | 117 | context.subscriptions.push(disposable); 118 | } 119 | ``` 120 | -------------------------------------------------------------------------------- /docs/extension-guides/tree-view.md: -------------------------------------------------------------------------------- 1 | # 树视图 2 | 3 | 本节将教你如何为VS Code添加*视图容器*和*树视图*的插件,示例插件的源代码请查看[https://github.com/Microsoft/vscode-extension-samples/tree/master/tree-view-sample](https://github.com/Microsoft/vscode-extension-samples/tree/master/tree-view-sample)。 4 | 5 | ## 视图容器 6 | --- 7 | 8 | *视图容器*包含了一列*视图(views)*,这些*视图*又包含在内置的*视图容器*中。 9 | 10 | ![view-container](https://media.githubusercontent.com/media/Microsoft/vscode-docs/master/api/extension-guides/images/tree-view/view-container.png) 11 | 12 | 要想配置一个视图容器,你首先得注册`package.json`中的[`contributes.viewsContainers`](/references/contribution-points#contributesviewscontainers)。你还必须配置以下字段: 13 | 14 | - `id`: 新视图容器的名称 15 | - `title`: 展示给用户的视图容器名称,它会显示在视图容器上方 16 | - `icon`: 在活动栏中展示的图标 17 | 18 | ```json 19 | "contributes": { 20 | "viewsContainers": { 21 | "activitybar": [ 22 | { 23 | "id": "package-explorer", 24 | "title": "Package Explorer", 25 | "icon": "media/dep.svg" 26 | } 27 | ] 28 | } 29 | } 30 | ``` 31 | 32 | ## 树视图 33 | --- 34 | 35 | *视图*是显示在视图容器中的UI片段。使用[`contributes.views`](/references/contribution-points#contributesviews)进行配置,你就可以将新的*视图*添加到内置或者你配置好的视图容器中了。 36 | 37 | ![view](https://media.githubusercontent.com/media/Microsoft/vscode-docs/master/api/extension-guides/images/tree-view/view.png) 38 | 39 | 要想配置一个*视图*,你首先得注册`package.json`中的[`contributes.views`](/references/vscode-api)。你必须给*视图*配置一个ID外加一个名称,你还可以配置*视图*出现的位置: 40 | 41 | - `explorer`: 显示在资源管理器侧边栏 42 | - `debug`: 显示在调试侧边栏 43 | - `scm`: 显示在源代码侧边栏 44 | - `test`: 测试侧边栏中的资源管理器视图 45 | - 显示在你定义好的*视图容器*中 46 | 47 | ```json 48 | "contributes": { 49 | "views": { 50 | "package-explorer": [ 51 | { 52 | "id": "nodeDependencies", 53 | "name": "Node Dependencies", 54 | "when": "explorer" 55 | } 56 | ] 57 | } 58 | } 59 | ``` 60 | 61 | 当用户打开了对应的视图,VS Code会触发[`onView:${viewId}`](/references/activation-events?id=onview)事件(如上面例子中,这个事件写为`onView:nodeDependencies`)。你也可以通过配置`when`字段控制视图的展示。 62 | 63 | ## 视图的操作 64 | --- 65 | 66 | 你可以配置*视图*下述位置的操作: 67 | 68 | - `view/title`: *视图*标题位置显示的操作。这里可以配置主要的操作,使用`"group": "navigation"`进行配置,剩余的二级操作则出现在`...`菜单中。 69 | - `view/item/context`: 每个*视图项*的操作。这里可以配置主要的操作,使用`"group": "inline"`,剩余的二级操作则出现在`...`菜单中。 70 | 71 | 使用`when`属性控制这些操作的展示。 72 | 73 | ![view-actions](https://media.githubusercontent.com/media/Microsoft/vscode-docs/master/api/extension-guides/images/tree-view/view-actions.png) 74 | 75 | 例如: 76 | ```json 77 | "contributes": { 78 | "commands": [ 79 | { 80 | "command": "nodeDependencies.refreshEntry", 81 | "title": "Refresh", 82 | "icon": { 83 | "light": "resources/light/refresh.svg", 84 | "dark": "resources/dark/refresh.svg" 85 | } 86 | }, 87 | { 88 | "command": "nodeDependencies.addEntry", 89 | "title": "Add" 90 | }, 91 | { 92 | "command": "nodeDependencies.editEntry", 93 | "title": "Edit", 94 | "icon": { 95 | "light": "resources/light/edit.svg", 96 | "dark": "resources/dark/edit.svg" 97 | } 98 | }, 99 | { 100 | "command": "nodeDependencies.deleteEntry", 101 | "title": "Delete" 102 | } 103 | ], 104 | "menus": { 105 | "view/title": [ 106 | { 107 | "command": "nodeDependencies.refreshEntry", 108 | "when": "view == nodeDependencies", 109 | "group": "navigation" 110 | }, 111 | { 112 | "command": "nodeDependencies.addEntry", 113 | "when": "view == nodeDependencies" 114 | } 115 | ], 116 | "view/item/context": [ 117 | { 118 | "command": "nodeDependencies.editEntry", 119 | "when": "view == nodeDependencies && viewItem == dependency", 120 | "group": "inline" 121 | }, 122 | { 123 | "command": "nodeDependencies.deleteEntry", 124 | "when": "view == nodeDependencies && viewItem == dependency" 125 | } 126 | ] 127 | } 128 | } 129 | ``` 130 | 131 | !> **注意**:如果你需要针对特定的条目显示特殊的操作,定义树视图项的`TreeItem.contextValue`,并且在`when`中使用表达式,视图项的值储存在表达式的`viewItem`中。 132 | 133 | 如: 134 | 135 | ```json 136 | "contributes": { 137 | "menus": { 138 | "view/item/context": [ 139 | { 140 | "command": "nodeDependencies.deleteEntry", 141 | "when": "view == nodeDependencies && viewItem == dependency" 142 | } 143 | ] 144 | } 145 | } 146 | ``` 147 | 148 | ## 为树视图提供数据 149 | --- 150 | 151 | 插件创作者需要注册[`TreeDataProvider`](https://code.visualstudio.com/api/references/vscode-api#TreeDataProvider),以便动态生成*视图*中的数据。 152 | 153 | ```typescript 154 | vscode.window.registerTreeDataProvider('nodeDependencies', new DepNodeProvider()); 155 | ``` 156 | 157 | 更多实现请参考[nodeDependencies.ts](https://github.com/Microsoft/vscode-extension-samples/tree/master/tree-view-sample/src/nodeDependencies.ts) 158 | 159 | ## 动态创建树视图 160 | --- 161 | 162 | 如果你想在*视图*中通过编程手段创建一些操作,你就不能再注册`window.registerTreeDataProvider`了,而是`window.createTreeView`,这样一来你就有权限提供你喜欢的视图操作了: 163 | 164 | ```typescript 165 | vscode.window.createTreeView('ftpExplorer', { 166 | treeDataProvider: new FtpTreeDataProvider() 167 | }); 168 | ``` 169 | 170 | 更多实现请参考[ftpExplorer.ts](https://github.com/Microsoft/vscode-extension-samples/tree/master/tree-view-sample/src/ftpExplorer.ts) -------------------------------------------------------------------------------- /docs/references/activation-events.md: -------------------------------------------------------------------------------- 1 | # 激活事件 2 | 3 | **激活事件**是`package.json`中`activationEvents`字段声明的一个JSON对象, 参考[插件清单](/references/extension-manifest). 当**激活事件**触发时, 插件就会被激活. 下面是可用的**激活事件**列表: 4 | 5 | - [激活事件](#激活事件) 6 | - [onLanguage](#onlanguage) 7 | - [onCommand](#oncommand) 8 | - [onDebug](#ondebug) 9 | - [onDebugInitialConfigurations](#ondebuginitialconfigurations) 10 | - [onDebugResolve](#ondebugresolve) 11 | - [workspaceContains](#workspacecontains) 12 | - [onFileSystem](#onfilesystem) 13 | - [onView](#onview) 14 | - [onUri](#onuri) 15 | - [onWebviewPanel](#onwebviewpanel) 16 | - [onCustomEditor](#oncustomeditor) 17 | - [onAuthenticationRequest](#onauthenticationrequest) 18 | - [onStartupFinished](#onstartupfinished) 19 | - [*](#start-up) 20 | 21 | `package.json`的配置项都可以在[插件清单](/references/extension-manifest)中找到. 22 | 23 | ## onLanguage 24 | --- 25 | 26 | 打开特定语言文件时激活事件和相关插件 27 | 28 | ```json 29 | ... 30 | "activationEvents": [ 31 | "onLanguage:python" 32 | ] 33 | ... 34 | ``` 35 | 36 | `onLanguage`事件需要指定特定的[语言标识符](https://code.visualstudio.com/docs/languages/identifiers) 37 | 38 | 也可以添加多种语言: 39 | 40 | ```json 41 | "activationEvents": [ 42 | "onLanguage:json", 43 | "onLanguage:markdown", 44 | "onLanguage:typescript" 45 | ] 46 | ``` 47 | 48 | ## onCommand 49 | --- 50 | 51 | 调用命令时激活 52 | 53 | ```json 54 | ... 55 | "activationEvents": [ 56 | "onCommand:extension.sayHello" 57 | ] 58 | ... 59 | ``` 60 | 61 | ## onDebug 62 | --- 63 | 64 | 调试会话(debug session)启动前激活 65 | 66 | ```json 67 | ... 68 | "activationEvents": [ 69 | "onDebug" 70 | ] 71 | ... 72 | ``` 73 | 74 | ### onDebugInitialConfigurations 75 | 76 | ### onDebugResolve 77 | 78 | 这是两个粒度更细的`onDebug`激活事件: 79 | 80 | - `DebugConfigurationProvider`中的`provideDebugConfigurations`在`onDebugInitialConfigurations`之后触发 81 | - `onDebugResolve:type`在`DebugConfigurationProvider`的`resolveDebugConfiguration`方法之前触发. 82 | 83 | **友情提示**: 如果调试插件比较轻量, 使用`onDebug`. 相反, 根据`DebugConfigurationProvider`实现的对应方法(`provideDebugConfigurations`或`resolveDebugConfiguration`),使用`onDebugInitialConfigurations`或`onDebugResolve`. 参阅[使用调试器插件](/extension-guides/debugger-extension#using-a-debugconfigurationprovider). 84 | 85 | ## workspaceContains 86 | --- 87 | 88 | 文件夹打开后,且文件夹中至少包含一个符合glob模式的文件时触发. 89 | 90 | ```json 91 | "activationEvents": [ 92 | "workspaceContains:**/.editorconfig" 93 | ] 94 | ``` 95 | 96 | ## onFileSystem 97 | --- 98 | 99 | 以协议(scheme)打开文件或文件夹时触发. 通常是`file`-协议,也可以用自定义的文件供应器函数替换掉,比如`ftp`、`ssh`. 100 | 101 | ```json 102 | ... 103 | "activationEvents": [ 104 | "onFileSystem:sftp" 105 | ] 106 | ... 107 | ``` 108 | 109 | ## onView 110 | --- 111 | 112 | 指定id的视图展开时触发: 113 | 114 | ```json 115 | ... 116 | "activationEvents": [ 117 | "onView:nodeDependencies" 118 | ] 119 | ... 120 | ``` 121 | 122 | ## onUri 123 | --- 124 | 125 | 插件的系统级URI打开时触发. 这个URI协议需要带上`vscode`或者 `vscode-insiders`协议. URI主机名必须是插件的唯一标识,剩余的URI是可选的. 126 | 127 | ```json 128 | ... 129 | "activationEvents": [ 130 | "onUri" 131 | ] 132 | ... 133 | ``` 134 | 135 | 如果`vscode.git`插件定义了`onUri`激活事件,那么下列任意URI打开时就会触发: 136 | 137 | - `vscode://vscode.git/init` 138 | - `vscode://vscode.git/clone?url=https%3A%2F%2Fgithub.com%2FMicrosoft%2Fvscode-vsce.git` 139 | - `vscode-insiders://vscode.git/init`(for VS Code Insiders) 140 | 141 | ## onWebviewPanel 142 | --- 143 | 144 | 当相应`viewType`的`webview`恢复时触发. 145 | 146 | 下面是一个例子: 147 | 148 | ```json 149 | "activationEvents": [ 150 | ..., 151 | "onWebviewPanel:catCoding" 152 | ] 153 | ``` 154 | 155 | VS Code 恢复 (restore) `viewType` 为 `catCoding` 的 webview 时会激活插件. 调用 `window.createWebviewPanel` 可以设置 `viewType`, 你可能会需要其它的激活事件(比如: `onCommand`)初始化你的插件,然后再创建`webview`视图. 156 | 157 | ## onCustomEditor 158 | --- 159 | 160 | 当相应 `viewType` 的 [自定义编辑器](../extension-guides/custom-editors.md) 被创建时触发. 161 | 162 | 163 | 下面是一个例子: 164 | ```json 165 | "activationEvents": [ 166 | "onCustomEditor:catCustoms.pawDraw" 167 | ] 168 | ``` 169 | 170 | VS Code 恢复 (restore) `viewType` 为 `catCustoms.pawDraw` 的自定义编辑器时会激活插件. 171 | 首先通过 [`自定义编辑器` 的发布内容配置](../extension-guides/custom-editors.md#发布内容配置) 设置 `viewType` ,然后为 `registerCustomEditorProvider` 提供一个 供应器函数. 172 | 173 | !> **注意**: 从VS Code 1.74.0开始,包含自定义编辑器的插件,不再需要单独配置 `onCustomEditor` 事件来激活. 174 | 175 | ## onAuthenticationRequest 176 | --- 177 | 178 | 当插件通过 `authentication.getSession()` API和相应的 `providerId` 请求认证会话时会激活插件. 179 | 180 | 下面是一个例子: 181 | 182 | ```json 183 | "activationEvents": [ 184 | "onAuthenticationRequest:github" 185 | ] 186 | ``` 187 | 188 | 当 VS Code 需要获取类型为 `github` 的 `AuthenticationSession` 将激活插件. 189 | 190 | !> **注意**: 从VS Code 1.74.0开始,包含认证程序的插件,不再需要单独配置 `onAuthenticationRequest` 事件来激活. 191 | 192 | ## onStartupFinished 193 | --- 194 | 195 | VS Code启动一段时间后才会激活插件. 它类似于 `*` 类激活事件,但它不会减慢VS Code启动. 目前,该事件在所有 `*` 类插件激活完成后触发. 196 | 197 | ```json 198 | ... 199 | "activationEvents": [ 200 | "onStartupFinished" 201 | ] 202 | ... 203 | ``` 204 | 205 | ## Start up 206 | --- 207 | 208 | 当VS Code启动时触发. 为了保证良好的用户体验,只在你的插件没有其他任何激活事件的前提下,添加这个激活事件. 209 | 210 | ```json 211 | ... 212 | "activationEvents": [ 213 | "*" 214 | ] 215 | ... 216 | ``` 217 | 218 | !> **注意**: 一个插件如果侦听了多个激活事件, 那么最好用`"*"`替换掉. 219 | 220 | !> **注意**: 插件**必须**从它的主模块中输出一个`activate()`函数,当任意的激活事件触发时,VS Code会**仅仅调用一次这个函数**. 此外,插件也**应该** 导出一个`deactivate()`函数,当VS Code关闭时执行清理的任务. 如果清理进程是异步的,插件的`deactivate()`**必须**返回一个Promise. 如果这个清理任务是同步的,那么`deactivate()`可以返回`undefined`. 221 | -------------------------------------------------------------------------------- /docs/language-extensions/language-configuration-guide.md: -------------------------------------------------------------------------------- 1 | # 语言配置 2 | 3 | 通过[`contributes.languages`](/extensibility-reference/contribution-points#contributeslanguages)发布内容配置,你可以配置以下*声明式语言特性*: 4 | 5 | - 启用/关闭注释 6 | - 定义括号 7 | - 自动闭合符号 8 | - 自动环绕符号 9 | - 代码折叠 10 | - 单词匹配 11 | - 缩进规则 12 | 13 | [语言配置示例](https://github.com/Microsoft/vscode-extension-samples/tree/master/language-configuration-sample)中配置JavaScript文件中的编辑功能。本篇指南会详细解释`language-configuration.json`中的内容: 14 | 15 | !> **注意**:如果你的语言配置文件以**`language-configuration.json`**结尾,那么VS Code会帮你添加代码补全和校验功能。 16 | 17 | ```json 18 | { 19 | "comments": { 20 | "lineComment": "//", 21 | "blockComment": ["/*", "*/"] 22 | }, 23 | "brackets": [["{", "}"], ["[", "]"], ["(", ")"]], 24 | "autoClosingPairs": [ 25 | { "open": "{", "close": "}" }, 26 | { "open": "[", "close": "]" }, 27 | { "open": "(", "close": ")" }, 28 | { "open": "'", "close": "'", "notIn": ["string", "comment"] }, 29 | { "open": "\"", "close": "\"", "notIn": ["string"] }, 30 | { "open": "`", "close": "`", "notIn": ["string", "comment"] }, 31 | { "open": "/**", "close": " */", "notIn": ["string"] } 32 | ], 33 | "autoCloseBefore": ";:.,=}])>` \n\t", 34 | "surroundingPairs": [ 35 | ["{", "}"], 36 | ["[", "]"], 37 | ["(", ")"], 38 | ["'", "'"], 39 | ["\"", "\""], 40 | ["`", "`"] 41 | ], 42 | "folding": { 43 | "markers": { 44 | "start": "^\\s*//\\s*#?region\\b", 45 | "end": "^\\s*//\\s*#?endregion\\b" 46 | } 47 | }, 48 | "wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)", 49 | "indentationRules": { 50 | "increaseIndentPattern": "^((?!\\/\\/).)*(\\{[^}\"'`]*|\\([^)\"'`]*|\\[[^\\]\"'`]*)$", 51 | "decreaseIndentPattern": "^((?!.*?\\/\\*).*\\*/)?\\s*[\\}\\]].*$" 52 | } 53 | } 54 | ``` 55 | 56 | ## 启用/关闭注释 57 | --- 58 | 59 | VS Code提供了切换注释开关的命令: 60 | 61 | - **Toggle Line Comment** 62 | - **Toggle Block Comment** 63 | 64 | 分别来配置`comments.lineComment`控制块注释和`comments.blockComment`控制行注释。 65 | 66 | ```json 67 | { 68 | "comments": { 69 | "lineComment": "//", 70 | "blockComment": ["/*", "*/"] 71 | } 72 | } 73 | ``` 74 | 75 | ## 定义括号 76 | --- 77 | 78 | 你在VS Code中将鼠标移动到一个括号边上时,VS Code会自动高亮对应的括号。 79 | 80 | ```json 81 | { 82 | "brackets": [["{", "}"], ["[", "]"], ["(", ")"]] 83 | } 84 | ``` 85 | 86 | 另外,当你运行**Go to Bracket**或**Select to Bracket**时,VS Code会自动使用你的定义找到最近、最匹配的括号。 87 | 88 | ## 自动闭合符号 89 | --- 90 | 91 | 当你输入`'`时,VS Code会自动帮你补全另一个单引号然后将光标放在引号中间,我们来看看是怎么做的: 92 | 93 | ```json 94 | { 95 | "autoClosingPairs": [ 96 | { "open": "{", "close": "}" }, 97 | { "open": "[", "close": "]" }, 98 | { "open": "(", "close": ")" }, 99 | { "open": "'", "close": "'", "notIn": ["string", "comment"] }, 100 | { "open": "\"", "close": "\"", "notIn": ["string"] }, 101 | { "open": "`", "close": "`", "notIn": ["string", "comment"] }, 102 | { "open": "/**", "close": " */", "notIn": ["string"] } 103 | ] 104 | } 105 | ``` 106 | 107 | 配置`notIn`键(key)可以在你需要的时候关闭这个功能。比如你在写下面的代码: 108 | 109 | ```javascript 110 | // ES6's Template String 111 | `ES6's Template String`; 112 | ``` 113 | 114 | 此时单引号就不会闭合。 115 | 116 | 用户可以使用`editor.autoClosingQuotes`和`editor.autoClosingBrackets`设置*自动闭合符号*的行为。 117 | 118 | #### 在XXX前闭合符号 119 | 120 | 如果符号的右边有空白,那么VS Code默认会启用符号闭合,所以当你在JSX代码中输入`{`时,符号并不会闭合: 121 | 122 | ```javascript 123 | const Component = () => 124 |
125 | ^ VS Code默认不会闭合此处的括号 126 |
127 | ``` 128 | 129 | 但是你可以用下面的定义覆盖默认行为: 130 | 131 | ```json 132 | { 133 | "autoCloseBefore": ";:.,=}])>` \n\t" 134 | } 135 | ``` 136 | 137 | 现在如果你在`>`前面输入`{`,VS Code会自动补全`}`。 138 | 139 | ## 自动环绕符号 140 | --- 141 | 142 | 当你选择了一堆文本然后输入左括号时,VS Code会对选中内容外围加上对应的括号。这个功能叫做*自动环绕符号*,你可以参考下面的代码指定这项功能: 143 | 144 | ```json 145 | { 146 | "surroundingPairs": [ 147 | ["{", "}"], 148 | ["[", "]"], 149 | ["(", ")"], 150 | ["'", "'"], 151 | ["\"", "\""], 152 | ["`", "`"] 153 | ] 154 | } 155 | ``` 156 | 157 | 注意用户可以通过`editor.autoSurround`设置*自动环绕符号*的行为。 158 | 159 | ## 代码折叠 160 | --- 161 | 162 | 在VS Code中有三种代码折叠类型: 163 | 164 | - 缩进折叠:这是VS Code中默认的缩进行为,当两行内容有着相同的缩进级别时,你就可以看到折叠标记了。 165 | - 语言配置折叠:当VS Code发现`folding.markers`同时定义了`start`和`end`时,对应区域内就会出现折叠标记。下述配置会对`//#region`和`//#endregionJSON`区域创建代码折叠标记: 166 | 167 | ```json 168 | { 169 | "folding": { 170 | "markers": { 171 | "start": "^\\s*//\\s*#?region\\b", 172 | "end": "^\\s*//\\s*#?endregion\\b" 173 | } 174 | } 175 | } 176 | ``` 177 | 178 | - 语言服务器折叠:语言服务器获取到[textDocument/foldingRange](https://microsoft.github.io/language-server-protocol/specification#textDocument_foldingRange)请求中的代码折叠列表数据,VS Code之后根据这份列表创建折叠标记。通过语言服务器协议学习更多关于[程序性语言特性](/language-extensions/programmatic-language-features)。 179 | 180 | ## 单词匹配 181 | --- 182 | 183 | `wordPattern`定义了程序语言中*单词*单位。因此当你使用词语相关的命令,如:**Move cursor to word start**(Ctrl+Left)或者**Move cursor to word end**(Ctrl+Right)时,编辑器会根据正则寻找单词边界。 184 | 185 | ```json 186 | { 187 | "wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)" 188 | } 189 | ``` 190 | 191 | ## 缩进规则 192 | --- 193 | 194 | `indentationRules`定义了编辑器应该如何调整当前行或你粘贴、输入、移动的下一行缩进。 195 | 196 | ```json 197 | { 198 | "indentationRules": { 199 | "increaseIndentPattern": "^((?!\\/\\/).)*(\\{[^}\"'`]*|\\([^)\"'`]*|\\[[^\\]\"'`]*)$", 200 | "decreaseIndentPattern": "^((?!.*?\\/\\*).*\\*/)?\\s*[\\)\\}\\]].*$" 201 | } 202 | } 203 | ``` 204 | 205 | 比如,`if (true) {`匹配`increasedIndentPattern`,然后如果你在`{`后面按下Enter后,编辑器会自动缩进一次,你如代码看起来会像这样: 206 | 207 | ```javascript 208 | if (true) { 209 | console.log(); 210 | ``` 211 | 212 | 如果没有设置缩进规则,当行尾以开符号结尾时编辑器会左缩进,以闭合符号结尾时右缩进。这里的*开闭符号*由`brackets`定义。 213 | 214 | 注意`editor.formatOnPaste`是由[DocumentRangeFormattingEditProvider](https://code.visualstudio.com/api/references/vscode-api#DocumentRangeFormattingEditProvider)控制,而不由自动缩进控制。 -------------------------------------------------------------------------------- /docs/extension-authoring/developing-extensions.md: -------------------------------------------------------------------------------- 1 | # 开发插件 2 | 3 | 这个章节会详细地讲解如何插件的运行,调试和故障排除。这些技巧也同样适用于调试你从市场安装的问题应用。 4 | 5 | ## 创建你自己的插件 6 | --- 7 | 为了开发VS Code插件,VS Code本身提供了以下几个工具,帮你快速开发: 8 | - Yeoman生成器,用脚手脚创建一个插件 9 | - 智能补全——悬停和找到你需要的插件API 10 | - 编译Typescript(如果用Typescript实现的话) 11 | - 运行和调试插件 12 | - 发布插件 13 | 14 | 我们建议你用脚手架生成基础文件,Yeoman的`yo code`命令可以完成这个工作,生成器能极大地提升你的开发体验,我们在[插件生成器](/extension-authoring/extension-generator.md)里面有详细的步骤。 15 | 16 | !> **注意**:以下部分假设你已经掌握了`yo code`Yeoman 插件生成器,和创建`launch.json`、`task.json`的基础知识。 17 | 18 | ## 运行和调试插件 19 | --- 20 | 按下`F5`,你就可以很轻松地调试插件了。这个命令会打开一个加载了你的插件的新窗口,插件输出的信息能在`调试控制台`里找到,在这个模式下你可以打断点、一步步地调试代码,在`调试`侧边栏或者`调试控制台`(用console方法输出才可以)检查变量。 21 | 22 | ![](https://github.com/Microsoft/vscode-docs/raw/master/docs/extensions/images/developing-extensions/debug.png) 23 | 24 | 根据插件的不同,你可能需要更多关于调试适配器或者语言服务器插件的相关教程: 25 | 26 | - [示例:语言服务器](/extension-authoring/example-language-server.md) - 学习如何实现一个语言服务器插件 27 | - [示例:调试器](/extension-authoring/developing-extensions.md) - 通过VS Code Debug Protocol接入调试器 28 | 29 | ## 编译Typescript 30 | 如果你的插件是Typescript实现的,那你首先就要把代码编译成Javascript。 31 | 编译过程的配置如下所示: 32 | - `tsconfig.json`定义了Typescript的编译选项。了解更多[Typescript wiki](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html)或者[Typescript语言章节](https://code.visualstudio.com/docs/languages/typescript#_tsconfigjson) 33 | - 当前Typescript编译器的版本在`node_modules`文件夹里面 34 | - API定义在`node_modules/vscode`中 35 | 36 | 运行插件前,Typescript编译器会被触发。`.vscode/launch.json`中的`preLaunchTask`属性定义了这项工作,在调试会话启动前会先启动这个配置好的任务。 37 | 38 | 如果你的插件在很久之前就编译好了,比如依赖于`0.1.0`ts版本,而`2.0.0`已经老早就出来了,那么通过下列步骤来升级你的插件: 39 | 40 | ```json 41 | // 访问 https://go.microsoft.com/fwlink/?LinkId=733558 42 | // 查看更多关于tasks.json格式的内容 43 | { 44 | "version": "2.0.0", 45 | "tasks": [ 46 | { 47 | "type": "npm", 48 | "script": "watch", 49 | "problemMatcher": "$tsc-watch", 50 | "isBackground": true, 51 | "presentation": { 52 | "reveal": "never" 53 | }, 54 | "group": { 55 | "kind": "build", 56 | "isDefault": true 57 | } 58 | } 59 | ] 60 | } 61 | ``` 62 | 63 | 将下列设置添加到*settings.json*中 64 | 65 | 66 | ```json 67 | // 关边tsc的自动检测任务,因为我们在添加了npm脚本 68 | "typescript.tsc.autoDetect": "off" 69 | ``` 70 | 71 | 确保*launch.json.*中引用了正确的*预运行任务*: 72 | ```json 73 | "preLaunchTask": "npm: watch" 74 | ``` 75 | ?> **注意:**Typescript编译器运行在watch模式下,所以任何文件变动都会自动编译 76 | 77 | ## 加载你的插件 78 | 你的插件会加载在`插件开发环境`的新窗口中。用`extensionDevelopmentPath`命令行也可以达到同样的效果,这个选项告诉VS Code去哪里查找新的插件: 79 | 80 | ```bash 81 | code --extensionDevelopmentPath=_my_extension_folder 82 | ``` 83 | 84 | 一旦插件环境加载完毕,VS Code就会把调试器附加上去,然后启动调试会话。 85 | 86 | 下面是按下`F5`之后的会发生的事情: 87 | 88 | 1. `.vscode/launch.json`指示VS Code先运行一个叫做`npm`的任务 89 | 2. `.vscode/tasks.json`定义了`npm`任务,其实就是`npm run compile`的脚本命令 90 | 3. `package.json`定义`compile`为`tsc -watch -p ./` 91 | 4. 然后会调用node_modules文件夹下的Typescript编译器,然后生成`out/extension.js`和`out/extension.js.map` 92 | 5. Typescript编译成功之后,生成`code --extensionDevelopmentPath=${workspaceFolder}`进程 93 | 6. 加载运行在**扩展环境**下的第二个VS Code实例,它会搜寻`${workspaceFolder}`下的插件 94 | 95 | ## 修改你的插件 96 | 97 | 你可以在VS Code状态栏的左侧观察Typscript编译器的进度,在状态栏中你也可以找到编译的错误和警告。当编译通过之后,你必须重启**扩展开发环境**才能查看到你的修改。重启扩展开发环境有两种可选的方式: 98 | 99 | - 在调试面板中按下`重启` 100 | - 在插件开发环境中按`Ctrl+R`(macOS:Cmd+R) 101 | 102 | ## 分析你的插件 103 | 104 | 你可以用Chrome DevTool内存和CUP分析工具分析你的插件。 105 | 106 | 跟我做: 107 | 1. 在命令行中带上`--inspect-extensions=`标识,启动你的VS Code,比如:`code --inspect-extensions=9333` 108 | 2. 在VS Code的**命令面板(`Shfit + Cttl+ P`)**中选择并打开**Developer: Toggle Developer Tools** 109 | 3. 在打开的DevTool中查看`Console`标签,找到`Debugger listening on port 9333`开头的`chrome-devtools`链接信息 110 | 4. 打开你自己的Chrome浏览器,输入该链接,然后会进入DevTool提供的专用调试环境 111 | 5. 使用内存和CPU分析器,了解内存和计算资源的使用情况 112 | 113 | ![chrome-devtools](https://raw.githubusercontent.com/Microsoft/vscode-docs/master/docs/extensions/images/developing-extensions/chrome-devtools.png) 114 | 115 | ## 问题追踪 116 | 117 | 当你自己的的插件或者市场上的插件出现问题时,你可以参考这些建议进行问题追踪: 118 | 119 | #### 禁用插件,启动VS Code 120 | 121 | 通过`--disable-extensions`命令行,禁用VS Code会话中的所有插件。这个方式可以帮你逐步缩小问题范围——到底是插件问题,还是VS Code本身的问题。 122 | 123 | ```bash 124 | code --disable-extensions 125 | ``` 126 | #### 使用开发工具控制台 127 | 128 | 如果你安装的插件不能正常工作,第一步工作最好是先检查一下VS Code**开发者工具**的Console面板。插件作者可能在开发插件的时候已经添加了一些日志——VS Code 运行于Electron之上,所以你可以通过Chrome**开发者工具**获得有力的支持。 129 | 130 | 通过**帮助**>**切换开发人员工具**(Windows/Linux:`Ctrl + Shift + I`,macOS:`Cmd + Shift + I`)打开**开发工具**然后选择**Console**标签。试着运行插件的功能,检查Console的输出。你可以使用`console.log`输出各类信息以及VS Code扩展环境抛出的详细异常。 131 | 132 | ?> **开发者小贴士:**当你制作插件的时候,请为用户提供有用的日志信息,你给用户的信息越多,用户越能够独立地解决问题。好的日志也同样能帮你快速地找到真正的问题所在。 133 | 134 | #### 重装插件 135 | 136 | 有时候安装插件会失败或者报错,所以任何插件不能正常工作的时候,你都可以尝试卸载然后重装插件的方式来解决。VS Code提供了一个非常方便的命令**Developer: Reinstall Extension**,输入这串命令之后,你可以在下拉框里选择你要重装的插件,最后按照指示重载VS Code就好了。 137 | 138 | #### 查看插件的README 139 | 140 | 为了正常运行,有些插件会有一些其他的依赖,比如独立的语法检查器、编译器、自定义的配置文件等。因此在侧边栏**插件**中点击某个插件后显示的**插件详情**页面会非常有用,它就是插件的**README**,其中可能包含了插件的配置和使用方式。 141 | 142 | ## FAQ 143 | 144 | **问:我怎么在插件里使用VS Code新版本引入的API?** 145 | 146 | 答:如果你想用最新的VS Code API,你可以在插件的`package.json`中的`engines`声明你想要用的引擎版本。 147 | 148 | 步骤如下: 149 | 150 | - 在`package.json`中的`engines`字段设置你的插件所需要的最低VS Code版本 151 | - 在`package.json`中添加`postinstall`脚本: 152 | ```json 153 | "scripts": { 154 | "postinstall": "node ./node_modules/vscode/bin/install" 155 | } 156 | ``` 157 | - 在你的插件根目录下输入`npm install` 158 | - `vscode`模块根据`engine`中声明的版本下载对应的`vscode.d.ts` 159 | - 回到VS Code,用代码补全验证是否出现了你想要的API提示 160 | 161 | ## 下一步 162 | 163 | - [测试你的插件](/extension-authoring/testing-extensions.md) - 学习如何写单元测试和集成测试。 164 | - [发布工具](/extension-authoring/publish-extension.md) - 用vsce命令行工具发布你的插件。 165 | - [插件配置清单](/extensibility-reference/extension-manifest.md) - VS Code插件清单文件参阅。 166 | - [插件API](/extensibility-reference/vscode-api.md) - 学习更多VS Code扩展性API。 -------------------------------------------------------------------------------- /docs/extensibility-reference/api-scm.md: -------------------------------------------------------------------------------- 1 | # VS Code中的源控制 2 | --- 3 | 4 | VS Code 允许插件创作者通过扩展API去定义*源控制管理*特性(Source Control Management,SCM),VS Code整合了各式各样的SCM体系,而只给用户展现了一组小巧、强大的API接口,还是带用户界面的那种。 5 | 6 | ![main.png](https://raw.githubusercontent.com/Microsoft/vscode-docs/master/docs/extensionAPI/images/api-scm/main.png) 7 | 8 | 9 | VS Code自带一个源控制器:Git,本篇能帮你在VS Code中加入你自己的SCM系统。 10 | 11 | 如果你需要帮助,请查看[vscode命名空间API](https://github.com/Microsoft/vscode-docs/blob/master/docs/extensionAPI/vscode-api.md#scm)。 12 | 13 | ## 源控制模型 14 | --- 15 | `SourceControl`负责生产源控制模型的实体,它里面有`SourceControlResourceState`实例的**资源状态**,而资源状态又是`SourceControlResourceGroup`实例整理成**组**的。 16 | 17 | 通过`vscode.scm.createSourceControl`创建一个新的*源控制器*。 18 | 19 | 为了更好地理解这几种实体的交互,让我们拿Git来做例子,考虑下列`git status`输出: 20 | ```bash 21 | vsce master* → git status 22 | On branch master 23 | Your branch is up-to-date with 'origin/master'. 24 | Changes to be committed: 25 | (use "git reset HEAD ..." to unstage) 26 | 27 | modified: README.md 28 | renamed: src/api.ts -> src/test/api.ts 29 | 30 | Changes not staged for commit: 31 | (use "git add/rm ..." to update what will be committed) 32 | (use "git checkout -- ..." to discard changes in working directory) 33 | 34 | deleted: .travis.yml 35 | modified: README.md 36 | ``` 37 | 这个工作区里面发生了很多事,首先,`README.md`文件已经被修改了但还没有提交,然后立刻又被修改了。 其次,`src/api.ts`文件被移动到了`src/test/api.ts`,这个修改已经存备(staged), 最后,`.travis.yml`文件被删除。 38 | 39 | 对于这个工作区而言,Git定义了两个资源组:**工作中(Working tree)**和**已索引(Index)**,对于单个组而言,每次**文件修改**就会产生一些资源状态: 40 | - **已索引** - 资源组 41 | - 修改`README.md` - 资源状态 42 | - 移动`src/api.ts`到`src/test/api.ts` - 资源状态 43 | - **工作中** - 资源组 44 | - 删除`.travis.yml` - 资源状态 45 | - 修改`README.md` - 资源状态 46 | 47 | 同一个`README.md`是怎么成为两组截然不同的资源状态呢? 48 | 49 | 下面揭秘Git是如何创建这个模型的: 50 | 51 | ```typescript 52 | function createResourceUri(relativePath: string): vscode.Uri { 53 | const absolutePath = path.join(vscode.workspace.rootPath, relativePath); 54 | return vscode.Uri.file(absolutePath); 55 | } 56 | 57 | const gitSCM = vscode.scm.createSourceControl('git', "Git"); 58 | 59 | const index = gitSCM.createResourceGroup('index', "Index"); 60 | index.resourceStates = [ 61 | { resourceUri: createResourceUri('README.md') }, 62 | { resourceUri: createResourceUri('src/test/api.ts') } 63 | ]; 64 | 65 | const workingTree = gitSCM.createResourceGroup('workingTree', "Changes"); 66 | workingTree.resourceStates = [ 67 | { resourceUri: createResourceUri('.travis.yml') }, 68 | { resourceUri: createResourceUri('README.md') } 69 | ]; 70 | ``` 71 | 72 | 源变动和最终产生的资源组会传递到源控制视图上。 73 | 74 | ## 源控制视图 75 | --- 76 | 当源变动时,VS Code会生成源控制视图。源状态可通过`SourceControlResourceDecorations`自定义: 77 | 78 | ```typescript 79 | export interface SourceControlResourceState { 80 | readonly decorations?: SourceControlResourceDecorations; 81 | } 82 | ``` 83 | 84 | 上述例子已经足以让源控制视图生成一个简单的列表,不过用户可能想要在不同的资源状态上进行不同的操作。比如,当用户点击资源状态时,会发生什么呢?资源状态提供了一个可选命令去处理这类场景: 85 | ```typescript 86 | export interface SourceControlResourceState { 87 | readonly command?: Command; 88 | } 89 | ``` 90 | 91 | ### 菜单 92 | 93 | 要想提供更加丰富的交互效果,我们提供了5个源控制菜单项供你使用。 94 | 95 | `scm/title`菜单在源控制视图的顶部右上方,菜单项水平排列在标题栏中,另外一些会在`...`下拉菜单中。`scm/resourceGroup/context`和`scm/resourceState/context`是类似的,你可以通过前者自定义资源组,后者则是定义资源状态。将菜单项放在`inline`组里,可以水平在视图中展示它们。而其他的菜单项可以通过鼠标右击的形式展示在菜单中。菜单中调用的命令会传入资源状态作为参数。注意SCM视图提供多选,因此命令函数可能一次性会接收一个或多个参数。 96 | 97 | 例如,Git支持往`scm/resourceState/context`菜单中添加`git.stage`命令和使用下列方法,提供多个文件的存备(staged): 98 | ```typescript 99 | stage(...resourceStates: SourceControlResourceState[]): Promise; 100 | ``` 101 | 创建它们的时候,`SourceControl`和`SourceControlResourceGroup`实例会需要你提供一个string类型的`id`,这些值最终会在`scmProvider`和`scmResourceGroup`以上下文键值的形式出现。在菜单项的`when`语法中使用这些[上下文键值](https://code.visualstudio.com/docs/getstarted/keybindings#_when-clause-contexts)。看个Git如何通过`git.stage`命令显示菜单项的: 102 | ``` 103 | { 104 | "command": "git.stage", 105 | "when": "scmProvider == git && scmResourceGroup == merge", 106 | "group": "inline" 107 | } 108 | ``` 109 | 110 | `scm/change/title`可以对*行内变动*配置标题栏的命令(contribute commands to the title bar of an inline change)。命令中的参数有文档的URI,变动数组,当前行内变动所在索引。例如下面是一个可以配置菜单的Git`stageChange`命令声明: 111 | 112 | ```typescript 113 | async stageChange(uri: Uri, changes: LineChange[], index: number): Promise; 114 | ``` 115 | 116 | `scm/sourceControl`菜单根据环境出现在源控制实例的边上。 117 | 118 | ![](https://raw.githubusercontent.com/Microsoft/vscode-docs/master/docs/extensionAPI/images/api-scm/sourcecontrol-menu.png) 119 | 120 | 最后,`scm/change/title`菜单是和快速Diff功能相关联的,越新的文件越靠前,你可以针对特定的代码变动调用命令。 121 | 122 | ### SCM 输入框 123 | 源控制输入框位于每个源控制视图的顶部,接收用户输入的信息。你可以获取(或设置)这个信息供后续使用。在Git中,比如说,这可以作为一个commit框,用户输入了提交信息后,触发`git commit`命令: 124 | 125 | ```typescript 126 | export interface SourceControlInputBox { 127 | value: string; 128 | } 129 | 130 | export interface SourceControl { 131 | readonly inputBox: SourceControlInputBox; 132 | } 133 | ``` 134 | 135 | 用户可以通过Ctrl+Enter(Mac上是Cmd+Enter)接收任意信息,在`SourceControl`中的`acceptInputCommand`处理这类事件。 136 | ```typescript 137 | export interface SourceControl { 138 | readonly acceptInputCommand?: Command; 139 | } 140 | ``` 141 | ## 快速Diff 142 | --- 143 | VS Code支持显示快速Diff编辑器的高亮槽,点击这些槽会出现一个内部diff交互器,你可以在这里为上下文配置命令。 144 | 145 | ![](https://raw.githubusercontent.com/Microsoft/vscode-docs/master/docs/extensionAPI/images/api-scm/quickdiff.png) 146 | 147 | 这些高亮槽是VS Code自己计算出来的,你要做的就是根据给定的文件提供原始文件内容 148 | 149 | ```typescript 150 | export interface SourceControl { 151 | quickDiffProvider?: QuickDiffProvider; 152 | } 153 | ``` 154 | 155 | 使用`QuickDiffProvider`,你的实现需要告诉VS Code——参数传入的给定资源URI所对应的原始资源URI。 156 | 157 | ## 下一步 158 | 159 | 想要学习更多关于VS Code扩展性模型,请参考: 160 | 161 | * [SCM API 参考](https://code.visualstudio.com/docs/extensionAPI/vscode-api#_scm) - 查看完整的SCM API文档 162 | * [Git 插件](https://github.com/Microsoft/vscode/tree/master/extensions/git) - 学习Git插件实现 163 | * [插件API概览](/extensibility-reference/overview.md) - 学习全部的VS Code扩展性模型 164 | * [插件配置清单](/extensibility-reference/extension-manifest.md) - VS Code package.json插件配置清单参考 165 | * [发布内容配置点](/extensibility-reference/contribution-points.md) - VS Code发布内容配置点参考 166 | -------------------------------------------------------------------------------- /docs/extension-guides/command.md: -------------------------------------------------------------------------------- 1 | # 命令 2 | 3 | 命令会触发VS Code中注册的行为,如果你[配置过键位](https://code.visualstudio.com/docs/getstarted/keybindings),那么你就处理过了命令。命令也是插件将功能暴露给用户的地方,它绑定了VS Code UI中的行为,并在内部处理了相关逻辑。 4 | 5 | ## 使用命令 6 | --- 7 | 8 | VS Code内部含有大量和编辑器交互、控制UI、后台操作的[内置命令](/references/commands)。许多插件将它们的核心功能暴露为*命令*的形式供用户或者其他插件使用。 9 | 10 | ### 程序性执行一个命令 11 | 12 | [`vscode.commands.executeCommand`](https://code.visualstudio.com/api/references/vscode-api#commands.executeCommand)API可以程序性调用一个命令,你可以通过它将VS Code的内置函数构建在你的插件中,比如VS Code内置的Git和Markdown插件中的东西。 13 | 14 | 我们看个例子🌰:`editor.action.addCommentLine`命令可以将当前选中行变成注释(你可以偷偷把这个功能地集成到你自己的插件中哦): 15 | ```typescript 16 | import * as vscode from 'vscode'; 17 | 18 | function commentLine() { 19 | vscode.commands.executeCommand('editor.action.addCommentLine'); 20 | } 21 | ``` 22 | 23 | 有些命令可以接收改变行为的参数,有些会有返回结果。形如`vscode.executeDefinitionProvider`的API,它要求传入一个document的URI地址和position作为参数,并返回一个包含定义列表的promise: 24 | 25 | ```typescript 26 | import * as vscode from 'vscode'; 27 | 28 | async function printDefinitionsForActiveEditor() { 29 | const activeEditor = vscode.window.activeTextEditor; 30 | if (!activeEditor) { 31 | return; 32 | } 33 | 34 | const definitions = await vscode.commands.executeCommand( 35 | 'vscode.executeDefinitionProvider', 36 | activeEditor.document.uri, 37 | activeEditor.selection.active 38 | ); 39 | 40 | for (const definition of definitions) { 41 | console.log(definition); 42 | } 43 | } 44 | ``` 45 | 46 | 更多命令详见: 47 | - [浏览键盘快捷键](https://code.visualstudio.com/docs/getstarted/keybindings) 48 | - [VS Code内置高级命令API](/references/commands) 49 | 50 | ### 命令的URLs 51 | 52 | 命令URI是执行注册命令的链接。它们可被用于悬停文本上的可点击链接,代码补全提示中的细节信息,甚至可以出现在webview中。 53 | 54 | 命令URI使用`command`作为协议头,然后紧跟着命令名称。比如:`editor.action.addCommentLine`的命令URI是:`command:editor.action.addCommentLine`。下面是一个显示在当前行注释中显示链接的悬停函数。 55 | 56 | ```typescript 57 | import * as vscode from 'vscode'; 58 | 59 | export function activate(context: vscode.ExtensionContext) { 60 | vscode.languages.registerHoverProvider( 61 | 'javascript', 62 | new class implements vscode.HoverProvider { 63 | provideHover( 64 | _document: vscode.TextDocument, 65 | _position: vscode.Position, 66 | _token: vscode.CancellationToken 67 | ): vscode.ProviderResult { 68 | const commentCommandUri = vscode.Uri.parse(`command:editor.action.addCommentLine`); 69 | const contents = new vscode.MarkdownString(`[Add comment](${commentCommandUri})`); 70 | 71 | // command URIs如果想在Markdown 内容中生效, 你必须设置`isTrusted`。 72 | // 当创建可信的Markdown 字符, 请合理地清理所有的输入内容 73 | // 以便你期望的命令command URIs生效 74 | contents.isTrusted = true; 75 | 76 | return new vscode.Hover(contents); 77 | } 78 | }() 79 | ); 80 | } 81 | ``` 82 | 83 | 命令上的参数列表会从JSON数组变成URI格式:下面的例子使用了`git.stage`命令创建一个悬停操作——将当前文件进行git暂存: 84 | 85 | ```typescript 86 | import * as vscode from 'vscode'; 87 | 88 | export function activate(context: vscode.ExtensionContext) { 89 | vscode.languages.registerHoverProvider( 90 | 'javascript', 91 | new class implements vscode.HoverProvider { 92 | provideHover( 93 | document: vscode.TextDocument, 94 | _position: vscode.Position, 95 | _token: vscode.CancellationToken 96 | ): vscode.ProviderResult { 97 | const args = [{ resourceUri: document.uri }]; 98 | const commentCommandUri = vscode.Uri.parse( 99 | `command:git.stage?${encodeURIComponent(JSON.stringify(args))}` 100 | ); 101 | const contents = new vscode.MarkdownString(`[Stage file](${commentCommandUri})`); 102 | contents.isTrusted = true; 103 | return new vscode.Hover(contents); 104 | } 105 | }() 106 | ); 107 | } 108 | ``` 109 | 110 | ## 新建命令 111 | --- 112 | 113 | ### 注册一个命令 114 | 115 | [`vscode.commands.registerCommand`](https://code.visualstudio.com/api/references/vscode-api#commands.registerCommand)会把命令ID绑定到你插件的函数上: 116 | ```typescript 117 | import * as vscode from 'vscode'; 118 | 119 | export function activate(context: vscode.ExtensionContext) { 120 | const command = 'myExtension.sayHello'; 121 | 122 | const commandHandler = (name?: string = 'world') => { 123 | console.log(`Hello ${name}!!!`); 124 | }; 125 | 126 | context.subscriptions.push(vscode.commands.registerCommand(command, commandHandler)); 127 | } 128 | ``` 129 | 130 | 只要`myExtension.sayHello`命令执行,就会调用对应的处理函数,你也可以通过`executeCommand`程序性调用它,或者从VS Code UI中,抑或快捷键的方式调用。 131 | 132 | ### 创建面向用户的命令 133 | `vscode.commands.registerCommand`仅仅是将命令id绑定到了处理函数上,如果想让用户从*命令面板*中找到你的命令,你还需要在`package.json`中配置对应的命令`配置项(contribution)`: 134 | ```json 135 | { 136 | "contributes": { 137 | "commands": [ 138 | { 139 | "command": "myExtension.sayHello", 140 | "title": "Say Hello" 141 | } 142 | ] 143 | } 144 | } 145 | ``` 146 | 147 | `commands`配置告诉VS Code你的插件提供了一个命令,而且允许你控制命令在UI中的显示。现在,我们的命令终于出现在*命令面板*中了: 148 | 149 | ![命令面板](https://media.githubusercontent.com/media/Microsoft/vscode-docs/master/api/extension-guides/images/commands/palette.png) 150 | 151 | 我们依旧需要使用`registerCommand`将真实的命令id绑定到函数上。也就是说,如果我们的插件没有激活,那么用户从*命令面板*中选择`myExtension.sayHello`也不会有任何效果。为了避免这种事,插件必须注册一个面向全部用户场景的命令`onCommand` `activiationEvent`: 152 | ```json 153 | { 154 | "activationEvents": ["onCommand:myExtension.sayHello"] 155 | } 156 | ``` 157 | 现在当用户第一次调用`myExtension.sayHello`时,插件就会自动激活,`registerCommand`会将`myExtension.sayHello`绑定到正确的处理函数上。 158 | 159 | 对于内部命令你不需要使用`onCommand`,但是下面的场景中你必须定义好激活事件: 160 | - 需要使用*命令面板*调用 161 | - 需要快捷键调用 162 | - 需要通过VS Code UI调用,比如在编辑器标题栏上触发 163 | - 意在供其他插件使用时 164 | 165 | ### 控制命令出现在*命令面板*的时机 166 | 167 | 默认情况下,所有*命令面板*中出现的命令都可以在`package.json`的`commands`部分中配置。不过,有些命令是场景相关的,比如在特定的语言的编辑器中,或者只有用户设置了某些选项时才展示。 168 | 169 | [`menus.commandPalette`](/references/contribution-points#contributesmenus)发布内容配置运行你限制命令出现在*命令面板*的时机。你需要配置命令ID和一条[when语句](https://code.visualstudio.com/docs/getstarted/keybindings#_when-clause-contexts): 170 | ```json 171 | { 172 | "contributes": { 173 | "menus": { 174 | "commandPalette": [ 175 | { 176 | "command": "myExtension.sayHello", 177 | "when": "editorLangId == markdown" 178 | } 179 | ] 180 | } 181 | } 182 | } 183 | ``` 184 | 185 | 现在`myExtension.sayHello`命令只会出现在用户的Markdown文件中了。 -------------------------------------------------------------------------------- /docs/extension-authoring/publish-extension.md: -------------------------------------------------------------------------------- 1 | # 发布插件 2 | 3 | ## vsce —— 发布工具参阅 4 | 5 | [vsce](https://github.com/Microsoft/vsce)是一个用于将插件发布到[市场](https://code.visualstudio.com/docs/editor/extension-gallery)上的命令行工具。 6 | 7 | ## 安装 8 | --- 9 | 请确认本机已经安装了[Node.js](https://nodejs.org/),然后运行: 10 | ```bash 11 | npm install -g vsce 12 | ``` 13 | 14 | ## 使用 15 | --- 16 | 然后你就可以在命令行里直接使用`vsce`了。下面是一个快速发布的示例(在你登录和打包好插件之后): 17 | 18 | ```bash 19 | $ vsce publish 20 | Publishing uuid@0.0.1... 21 | Successfully published uuid@0.0.1! 22 | ``` 23 | 24 | 更多可用的命令参数,请使用`vsce --help` 25 | 26 | ## 发布教程 27 | --- 28 | !> **注意:** 出于安全考虑,`vsce`不会发布包含用户提供SVG图片的插件。 29 | 30 | 发布工具会检查以下内容: 31 | - `pacakge.json`文件中的icon不可以是SVG。 32 | - `pacakge.json`中的标记不可以是SVG,除非来自于[可靠的图标来源](/extensibility-reference/extension-manifest.md#使用认证过的标志) 33 | - `README.md`和`CHANGELOG.md`中的图片链接需要使用`https`协议 34 | - `README.md`和`CHANGELOG.md`中的图片不可以是SVG,除非来自[可靠的图标来源](/extensibility-reference/extension-manifest.md#使用认证过的标志) 35 | 36 | --- 37 | 38 | VS Code插件市场的服务是[Visual Studio Team Services](https://visualstudio.microsoft.com/team-services)提供的,因此验证、代理、管理插件都是由这个服务提供的。 39 | 40 | `vsce`只能用[Personal Access Tokens](https://docs.microsoft.com/vsts/integrate/get-started/authentication/pats)发布插件,所以至少要创建一个Token以便发布插件。 41 | 42 | #### 获取Personal Access Token 43 | 44 | 首先,请先确保你有一个[Visual Studio Team Services](https://docs.microsoft.com/vsts/accounts/create-account-msa-or-work-student)账户。 45 | 46 | 下面的例子里,我们假设账户名为`monacotools`,从你的账户主页(例如:https://monacotools.visualstudio.com )进入**安全(Security)**页: 47 | 48 | ![publishers1](https://raw.githubusercontent.com/Microsoft/vscode-docs/master/docs/extensions/images/publish-extension/publishers1.png) 49 | 50 | 点击**添加(Add)**创建一个新的Personal Access Token: 51 | 52 | ![publishers2](https://raw.githubusercontent.com/Microsoft/vscode-docs/master/docs/extensions/images/publish-extension/publishers2.png) 53 | 54 | 给Personal Access Token添加描述,过期时间等等,给它设置**最高权限**: 55 | 56 | ![publishers3](https://raw.githubusercontent.com/Microsoft/vscode-docs/master/docs/extensions/images/publish-extension/publishers3.png) 57 | 58 | 然后会显示你刚创建好的Personal Access Token,复制好,待会我们还要用来发布插件呢。 59 | 60 | #### 创建一个发行方 61 | 62 | **发行方**是VS Code市场有权发布插件的唯一标识,每个插件的[package.json](/extensibility-reference/extension-manifest.md)文件都包含着`publisher`字段。 63 | 64 | 现在我们已经有了[Personal Access Token](#获取Personal-Access-Token),我们马上可以用`vsce`创建一个发行方: 65 | 66 | ```bash 67 | vsce create-publisher (publisher name) 68 | ``` 69 | `vsce`会记住这个Personal Access Token,日后再用这个发行方的时候会自动带上。 70 | 71 | ?> 注意:另外,你也可以在市场的发行方[管理页](https://marketplace.visualstudio.com/manage)中创建发行方,然后用这个账号登录`vsce`。 72 | 73 | #### 发行方登录 74 | 75 | 如果你已经有发行方账号了: 76 | ```bash 77 | vsce login (publisher name) 78 | ``` 79 | 和`create-publisher`命令类似地,`vsce`会要求输入你的Personal Access Token。 80 | 81 | 你也可以用命令参数`-p `直接登录发行方然后立即发布插件: 82 | 83 | ```bash 84 | vsce publish -p 85 | ``` 86 | 87 | #### 增量更新插件版本 88 | 89 | 用SemVer语义标识符:`major`,`minor`,`patch`增量更新插件版本号。 90 | 91 | 例如,你想把插件从1.0.0更新到1.1.0,那么加上`minor`: 92 | ```bash 93 | vsce publish minor 94 | ``` 95 | 96 | 插件`package.json`的version会先更新,然后才发布插件。 97 | 98 | 你也可以通过命令行指定版本号: 99 | ```bash 100 | vsce publish 2.0.1 101 | ``` 102 | 103 | #### 下架插件 104 | 105 | 通过指定插件id`publisher.extension`下架插件: 106 | ``` 107 | vsce unpublish (publisher name).(extension name) 108 | ``` 109 | !> **注意:**当你下架插件的时候,市场会移除所有插件的历史统计数据,请在下架前再三考虑,最好还是更新插件吧。 110 | 111 | #### 插件打包 112 | 你也可能只是想打包一下插件,而不是发布到商店里。用下列命令将插件打包到`.vsix`文件中: 113 | 114 | ``` 115 | vsce package 116 | ``` 117 | 118 | 这个命令会在当前目录生成一个`.vsix`文件,直接从`.vsix`安装插件是允许的,查看[从VSIX安装插件](https://github.com/Microsoft/vscode-docs/blob/master/docs/editor/extension-gallery.md#install-from-a-vsix)了解更多内容。 119 | 120 | #### VS Code版本兼容性 121 | 122 | 当你制作插件的时候,你需要描述插件对VS Code的版本兼容性——修改`package.json`中的`engines.vscode`: 123 | 124 | ```json 125 | { 126 | "engines": { 127 | "vscode": "^1.8.0" 128 | } 129 | } 130 | ``` 131 | 132 | `1.8.0`标识你的插件只与`1.8.0`的VS Code兼容,`^1.8.0`则表示你的插件向上兼容,包括`1.8.1, 1.9.0`等等。 133 | 134 | 用`engines.vscode`可以保证插件的安装环境包含了插件依赖的API。这个机制在稳定版和Insider版本都适用。 135 | 136 | 例如,最新的稳定版VS Code版本是`1.8.0`,而新的API在`1.9.0`开发版中释出,所以用`1.9.0-insider`标识插件在Insider版本中都可用。 137 | 如果你想发布一个使用这些API的插件,则设置版本依赖为`^1.9.0`,你的插件则只能安装在`>=1.9.0`的VS Code上,也就意味着所有当前的Insider版本都可以用得上,而稳定版只有在更新到`1.9.0`才能使用。 138 | 139 | ## 进阶用法 140 | --- 141 | 142 | #### 符合市场的插件 143 | 144 | 你可以自定义插件在市场中的外观,查看示例`GO 插件`。 145 | 146 | 下面是一些让你的插件在市场看起来更酷的小提示: 147 | 148 | - 插件根目录下面的`README.md`文件可以用来填充插件市场的页面内容。`vsce`会将README中的链接通过下面两种方式修改掉: 149 | - 如果你的`package.json`的`repository`字段是一个Github仓库,`vsce`会自动检测,然后相应地调整链接。 150 | - 运行`vsce package`时,加上`--baseContentUrl`和`--baseImagesUrl`标识重载上述行为。 151 | - 插件根目录下的`LICENSE`会成为插件的license。 152 | - 同样的`CHANGELOG.md`文件会成为插件的发布日志。 153 | - 通过设置`package.json`的`galleryBanner.color`hex值,修改banner的背景色。 154 | - 通过给`package.json`中的`icon`设置一个相对路径,可以将一个`128px`的PNG图标放进你的插件中。 155 | 156 | - 参见[插件市场展现小提示](https://github.com/Microsoft/vscode-docs/blob/master/docs/extensionAPI/extension-manifest.md#marketplace-presentation-tips) 157 | 158 | #### `.vscodeignore` 159 | 160 | 创建一个`.vscodeignore`文件可以排除插件目录中的内容。这个文件支持[glob](https://github.com/isaacs/minimatch)模式,每个表达式一行。 161 | 162 | 例如: 163 | ``` 164 | **/*.ts 165 | **/tsconfig.json 166 | !file.ts 167 | ``` 168 | 你应该忽略哪些不必在运行时用到的文件。例如:你的插件是用Typescript写的,那么你就应该忽略所有的`**/*.ts`文件。 169 | 170 | ?> **注意:**在`devDependencies`列出的开发依赖会被自动忽略,你不必将他们加入到`.vscodeignore`中。 171 | 172 | ##### 预发布步骤 173 | 174 | 你是可以在清单文件中添加预发布步骤的,下面的命令会在插件每次打包时执行: 175 | ```json 176 | { 177 | "name": "uuid", 178 | "version": "0.0.1", 179 | "publisher": "joaomoreno", 180 | "engines": { 181 | "vscode": "0.10.x" 182 | }, 183 | "scripts": { 184 | "vscode:prepublish": "tsc" 185 | } 186 | } 187 | ``` 188 | 上面的示例会在每次插件打包时调用Typescript编译器。 189 | 190 | ## FAQ 191 | ##### 问:当我发布插件时遇到了403 Forbidden(或 401 Unauthorized)错误? 192 | 193 | 答:很有可能是你创建PAT (Personal Access Token) 时没有选择`all accessible accounts`。你还需要将授权范围设置为`All scopes`,这样发布工具才能工作。 194 | 195 | ##### 问:我没办法用`vsce`工具下架插件? 196 | 197 | 答:你可能改变了插件ID或者发行方名称。不过你还可以在[管理页面](https://marketplace.visualstudio.com/manage)发布或者下架插件。 198 | 199 | ##### 问:为什么vsce不保留文件属性? 200 | 201 | 答:请注意,当你在Windows平台构建和发布插件的时候,所有插件包内的文件会缺失POSIX文件属性,或称之为执行位(executable bit)的东西。一些基于这些属性的`node_modules`依赖则会调整工作方式。从Linux和macOS平台构建则会如预期执行。 202 | 203 | ## 下一步 204 | - [插件市场](https://code.visualstudio.com/docs/editor/extension-gallery) - 学习更多VS Code公共插件市场。 205 | - [测试插件](/extension-authoring/testing-extensions.md) - 添加插件测试,提高插件质量。 206 | -------------------------------------------------------------------------------- /docs/extensibility-reference/api-debugging.md: -------------------------------------------------------------------------------- 1 | # 调试器API 2 | 3 | VS Code 允许插件创作者制作新的**调试器插件**,或为已有的调试功能添加**特性**。 4 | 5 | 我们提供了两个领域的API: 6 | - 通过成熟又强力的**协议**生成新的VS Code常规调试界面 7 | - 常规的**插件API**,但不包括VS Code的全部调试功能 8 | 9 | 提供这两种截然不同的API是因为VS Code的“热拔插调试器”插件架构(我们不会移除向后兼容的基于*协议*的调试器连接方法) 10 | 11 | 下列图片展示了两种API在VS Code中协作的方式: 12 | 13 | ![debug-extension-api](https://raw.githubusercontent.com/Microsoft/vscode-docs/master/docs/extensionAPI/images/api-debugging/debug-extension-api.png) 14 | 15 | **调试适配器**是一个典型的脱机程序,通过**调试适配器协议(Debug Adapter Protocol)**连接到真实的调试器和具体的调试器API上。因为调试适配器可以用任意的语言实现,因此非常适合先前*已有*的调试器或者运行时存在的场合,连接协议比实现了协议本身的客户端库提供的API更加重要。 16 | 17 | 调试适配器并不是VS Code本身的插件,而要创作者封装出一个调试器插件才行,不要担心,你并不需要写太多代码。这个插件只是一个容器,在`package.json`中只要提供必要的**配置项**即可。当调试器会话运行后,VS Code会进入调试器插件,启动调试适配器,然后用调试适配器协议通信。 18 | 19 | 下面是我们为调试器插件提供的最新的API。 20 | 21 | ## 调试器插件API 22 | --- 23 | 24 | 所有供调试使用的插件API都在`vscode.debug`下的命名空间中,你可以在[vscode 命名空间API参考](https://github.com/Microsoft/vscode-docs/blob/master/docs/extensionAPI/vscode-api.md#debug)中查看。 25 | 26 | #### 调试型钩子 27 | 28 | 所有调试型的钩子都在`DebugConfigurationProvider`中。 29 | 30 | `registerDebugConfigurationProvider`注册了`DebugConfigurationProvider`,调试器类型本身是在[发布内容配置项`debugger`](https://github.com/Microsoft/vscode-docs/blob/master/docs/extensionAPI/extension-points.md#contributesdebuggers)中配置的。 31 | 32 | 当前,你可以使用的钩子有: 33 | 34 | - 只要VS Code通过`launch.json`初始化出一个新的调试器配置就会为所有注册了`DebugConfigurationProviders`的插件调用`provideDebugConfigurations`,然后合并返回的调试器配置,注入到package.json中。 35 | - VS Code每次在启动调试会话前调用`resolveDebugConfiguration`方法,`resolveDebugConfiguration`的实现可以通过给调试配置中传入缺省值或者添加/改变/移除配置项的方式和调试配置“通信”。通过这个机制,甚至可以实时调整调试类型。 36 | 37 | - `debugAdapterExecutable`方法会在VS Code启动了调试器之后调用,这个方法会返回调试适配器执行的路径(接受可选参数)。如果没有实现这个方法,VS Code则会使用package.json中配置的静态路径。 38 | 39 | 40 | #### 调试会话生命周期API 41 | 42 | 一个调试会话在插件API中表示为`DebugSession`,它的声明周期可以通过下列方式控制和追踪: 43 | - `startDebugging `:调试启动时触发,可以接受一个命名的调试器/复合配置/内存中的配置。 44 | - `onDidStartDebugSession`:调试会话启动后触发。 45 | - 当前激活的调试会话可由变量`activeDebugSession`获得,调试会话变动反应在`onDidChangeActiveDebugSession`事件中。 46 | - `onDidTerminateDebugSession`:调试会话关闭后触发。 47 | 48 | #### 调试会话API 49 | 50 | 目前调试会话的API还比较少: 51 | 52 | - 通过`customRequest`方法将调试适配器的请求发送到受控调试方。 53 | - 自定义的调试适配器事件在`onDidReceiveDebugSessionCustomEvent`中获取。 54 | 55 | #### 断点API 56 | 57 | 所有的断点类型都是`Breakpoint`的子类,当前提供的子类有`SourceBreakpoint`和`FunctionBreakpoint` 58 | 59 | - `vscode.debug.breakpoints`提供了工作区所有的断点集合。用`instanceof`检查单个断点的具体对象类型。 60 | - `vscode.debug.onDidChangeBreakpoints`侦听断点的添加、移除、改变事件。 61 | - `SourceBreakpoints`和`FunctionBreakpoints`只能通过`addBreakpoints`和`removeBreakpoints`函数添加。 62 | 63 | !>注意:一开始获取断点可能是一个空数组,而随后则会触发`BreakpointsChangeEvent`事件并更新`vscode.debug.breakpoints`,在这个时间点你就能获得正确的集合。所以如果你需要正确的断点集合,不要忘了注册`BreakpointsChangeEvent`事件。 64 | 65 | ## 调试适配器协议(DAP - Debug Adapter Protocol) 66 | --- 67 | 你可以在[vscode-debugadapter-node](https://github.com/Microsoft/vscode-debugadapter-node)仓库中找到JSON格式或者TypeScript定义的[调试适配器协议](https://microsoft.github.io/debug-adapter-protocol)规格说明书。这两个文件都详细地列出了每个协议的请求、响应和事件结构。这个协议在NPM库[vscode-debugprotocol](https://www.npmjs.com/package/vscode-debugprotocol)中也可以找到。 68 | 69 | 我们已经实现了调试适配器协议的TypeScript和C#客户端版本,不过只有JavaScript/TypeScript的客户端库在NPM[vscode-debugadapter-node](https://github.com/Microsoft/vscode-debugadapter-node)中是可用的。C#的库可以在[Mono Debug](https://github.com/Microsoft/vscode-mono-debug/blob/master/src/DebugSession.cs)中找到。 70 | 71 | 下列调试器插件项目会教你如何实现调试适配器: 72 | 73 | GitHub项目 | 描述 | 实现语言 74 | --- | --- | --- 75 | [Mock Debug](https://github.com/Microsoft/vscode-mock-debug.git) | 一个假的调试器 | TypeScript 76 | [Node Debug2](https://github.com/Microsoft/vscode-node-debug2.git) | 内建的基于CDP-based的Node.js调试器 |TypeScript 77 | [Node Debug](https://github.com/Microsoft/vscode-node-debug.git) | 内建的传统Node.js调试器 |TypeScript 78 | [Mono Debug](https://github.com/Microsoft/vscode-mono-debug.git) | 一个供Mono使用的简单的C#调试器 | C# 79 | 80 | ## 一语道破——调试适配器协议 81 | --- 82 | 我们快速地看一下VS Code和调试器间的互动,这应该能帮你快速地实现基于调试适配器协议的调试适配器。 83 | 84 | 调试器会话启动,VS Code加载调试适配器,通过*stdin*和*stdout*进行通信。VS Code发送了一个**初始化**请求,然后用*行列值是0,1*的路径格式信息(原生或URI)配置好调试器。如果你的调试器是TypeScript或C#实现的`Debugsession`中派生出来的,你则不需要自行处理初始化请求。 85 | 86 | 根据用户创建的启动配置文件中的*请求*属性,VS Code会发送*加载(launch)*或是*附加(attch)*请求。对于**加载**类型,调试适配器需要加载一个运行时或者可以调试的程序。如果这个程序可以通过stdin/stdout和用户进行交互,那么调试适配器就会在一个可交互的终端或者控制台加载这个程序。对于**附加**类型,调试适配器则会连接或者附加到一个已经运行的程序上面。 87 | 88 | 因为这两种请求的参数都高度依赖特定的调试适配器实现,所以调试适配器协议不提供任何参数描述。而VS Code则会把所有用户启动配置传给*加载*或*附加*请求。这两种属性的智能补全和悬停信息提示可以在适配器插件中的`package.json`进行配置,以帮助用户知道何时可以创建或编辑*启动配置*。 89 | 90 | VS Code会帮调试适配器保留断点,所以必须要在调试会话启动时,对应地注册适配器中的断点。因为VS Code不知道注册断点的最佳时机,所以调试适配器会发送一个**initialize**事件给VS Code,告知它已经准备好接收断点配置请求了。 91 | 92 | 然后VS Code就会调用断点配置请求,发送所有的断点: 93 | 94 | * **setBreakpoints** 为每个源文件带上断点, 95 | * **setFunctionBreakpoints** 如果调试适配器支持函数断点, 96 | * **setExceptionBreakpoints** 如果调试适配器支持异常选项, 97 | * **configurationDoneRequest** 指示配置序列已经结束。 98 | 99 | 所以,当你准备好了的时候不要忘了发送*initialize*事件接收断点。不然已保留的断点不会再储存下来。 100 | 101 | *setBreakpoints*请求为文件设置所有已存在的断点(所以不是增量的哦)。常见的场景就是为某个文件清除所有的断点,然后再根据请求设置断点。*setFunctionBreakpoints*和*setFunctionBreakpoints*需要返回真正的断点,然后VS Code就会动态地更新UI,如果断点无法跟随请求设置然后就会在后台移除。 102 | 103 | 当程序停止(在程序入口,断点命中,抛出异常,或者用户需要暂停执行),那么调试适配器必须发出**stopped**事件,带上原因和线程id。根据这条信息,VS Code会先请求**threads**(见下),然后列出停止的线程的堆栈追踪日志(栈帧列表)。如果用户深入到栈帧(stack frame)中去,VS Code会先请求这个栈帧的**scopes**,然后是这个scope的变量。如果变量是自构建的,VS Code会通过额外的*variables*请求获取它的属性。这个过程会生成下列事件层级: 104 | 105 | ``` 106 | Threads 107 | Stackframes 108 | Scopes 109 | Variables 110 | ... 111 | Variables 112 | ``` 113 | VS Code调试界面支持多线程(如果你只用Node.js调试器的话可能还不知道这个功能)。当VS Code接收到**stopped**或**thread**事件,然后它会立刻请求当时所有的**threads**并显示到界面上。如果只检测到一个线程,VS Code则会保留在单线程模式。**Thread**事件是可选的,不过调试适配器可以强制发送这个事件,即使不在暂停状态,VS Code也会动态地更新线程界面。 114 | 115 | 成功地**加载**或**附加**了调试适配器后,VS Code会发送**threads**请求当前线程,获取线程基线,然后开始侦听**threads**事件检查是否有新的或是终止的线程。即使你的调试适配器不支持多线程,它也必须实现**threads**请求,然后返回一个(虚假的)线程。线程的id必须要在所有需要线程id的地方消费掉,比如:**stacktrace**, **pause**,**continue**,**next**,**stepIn**,和 **stepOut**。 116 | 117 | 当发送**disconnect**请求时,VS Code会终止调试会话。如果调试目标在*加载*时被断开了,那么则会终止目标程序(如果必要的话,会强制终止)。如果调试目标在*附加*初始化时断开,那么则会立刻断开目标(程序则会继续执行)。在目标正常终止或崩溃时,调试适配器必须触发一个**terminated**事件。收到断开请求后,VS Code就会关闭调试适配器。 118 | 119 | ## 下一步 120 | 学习更多VS Code扩展性模型,请参阅下列主题: 121 | 122 | * [示例:调试器](/extension-authoring/example-debug-adapter.md) - 查看一个可执行的'模拟'调试器示例。 123 | * [插件API概览](/extensibility-reference/vscode-api.md) - 学习完整的VS Code扩展性模型。 124 | * [插件配置清单](/extensibility-reference/extension-manifest.md) - VS Code的package.json插件配置清单参阅 125 | * [发布内容配置](/extensibility-reference/contribution-points.md) - VS Code发布内容配置参阅 -------------------------------------------------------------------------------- /docs/preknowledge/class.md: -------------------------------------------------------------------------------- 1 | # 类 2 | 3 | 传统的JavaScript程序使用**函数**和基于**原型**的继承来创建可重用的组件。Typescript则在此基础上加入了语法糖**类**。 4 | 5 | 了解Javascript的基础内容请参考[对象原型](https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Objects/Object_prototypes)。 6 | 7 | ## 声明类 8 | 9 | 我们首先来看一个例子 10 | 11 | ```typescript 12 | class Greeter { 13 | greeting: string; 14 | constructor(message: string) { 15 | this.greeting = message; 16 | } 17 | greet() { 18 | return "Hello, " + this.greeting; 19 | } 20 | } 21 | 22 | let greeter = new Greeter("world"); 23 | ``` 24 | 25 | 如果你使用过C#或Java,你会对这种语法非常熟悉。 我们声明一个 Greeter类。这个类有3个成员:一个叫做 greeting的属性,一个构造函数和一个 greet方法。 26 | 27 | 你会注意到,我们在引用任何一个类成员的时候都用了 this。 它表示我们访问的是类的成员。 28 | 29 | 最后一行,我们使用 new构造了 Greeter类的一个实例。 它会调用之前定义的构造函数,创建一个 Greeter类型的新对象,并执行构造函数初始化它。 30 | 31 | ## 继承 32 | 33 | 在TypeScript里,我们可以使用常用的面向对象模式。 基于类的程序设计中一种最基本的模式是允许使用继承来扩展现有的类。 34 | 35 | 看下面的例子: 36 | 37 | ```typescript 38 | class Animal { 39 | move(distance: number = 0) { 40 | console.log(`Animal moved ${distance}m.`); 41 | } 42 | } 43 | 44 | class Dog extends Animal { 45 | bark() { 46 | console.log('Woof! Woof!'); 47 | } 48 | } 49 | 50 | const dog = new Dog(); 51 | dog.bark(); 52 | dog.move(10); 53 | dog.bark(); 54 | ``` 55 | 56 | 这个例子展示了最基本的继承:类从基类中继承了属性和方法。这里,`Dog`是一个 *派生类*,通过 `extends`关键字使它从 `Animal` 基类中派生出来。 派生类通常被称作 子类,基类通常被称作 超类或父类。 57 | 58 | 因为 Dog继承了 Animal的功能,因此我们可以创建一个 Dog的实例,它能够 bark()和 move()。 59 | 60 | 下面我们来看个更加复杂的例子。 61 | 62 | ```typescript 63 | class Animal { 64 | name: string; 65 | constructor(theName: string) { this.name = theName; } 66 | 67 | move(distance: number = 0) { 68 | console.log(`${this.name} moved ${distance}m.`); 69 | } 70 | } 71 | 72 | class Snake extends Animal { 73 | constructor(name: string) { super(name); } 74 | 75 | move(distance = 5) { 76 | console.log("Slithering..."); 77 | super.move(distance); 78 | } 79 | } 80 | 81 | class Horse extends Animal { 82 | constructor(name: string) { super(name); } 83 | 84 | move(distance = 45) { 85 | console.log("Galloping..."); 86 | super.move(distance); 87 | } 88 | } 89 | 90 | let sam = new Snake("Sammy the Python"); 91 | let tom: Animal = new Horse("Tommy the Palomino"); 92 | 93 | sam.move(); 94 | tom.move(34); 95 | ``` 96 | 97 | 与前一个例子的不同点是,这次两个派生类包含了一个构造函数,它**必须调用 `super()`**,它会执行基类的构造函数。 而且,在构造函数里访问 this的属性之前,我们 **必须**要调用 super(),这个是TypeScript强制规定的。 98 | 99 | ## 修饰符 100 | 101 | 102 | #### public 103 | 104 | 如果你对其它语言中的类比较了解,就会注意到我们在之前的代码里并没有使用 `public`来做修饰;例如,C#要求必须明确地使用 `public`指定成员是可见的。 在TypeScript里,成员都默认为 `public`。在上面的例子里,我们可以自由的访问程序里定义的成员。 105 | 106 | #### private 107 | 108 | 当成员被标记成 `private`时,它就不能在声明它的类的外部访问。比如 109 | 110 | ```typescript 111 | class Animal { 112 | private name: string; 113 | constructor(theName: string) { this.name = theName; } 114 | } 115 | 116 | new Animal("Cat").name; // 错误: 'name' 是私有的. 117 | ``` 118 | 119 | #### protected 120 | protected修饰符与 private修饰符的行为很相似,但有一点不同, protected成员在派生类中仍然可以访问。 121 | ```typescript 122 | class Person { 123 | protected name: string; 124 | constructor(name: string) { this.name = name; } 125 | } 126 | 127 | class Employee extends Person { 128 | private department: string; 129 | 130 | constructor(name: string, department: string) { 131 | super(name) 132 | this.department = department; 133 | } 134 | 135 | public getElevatorPitch() { 136 | return `Hello, my name is ${this.name} and I work in ${this.department}.`; 137 | } 138 | } 139 | 140 | let howard = new Employee("Howard", "Sales"); 141 | console.log(howard.getElevatorPitch()); 142 | console.log(howard.name); // 错误 143 | ``` 144 | 145 | 注意,我们不能在 `Person`类外使用 `name`,但是我们仍然可以通过 `Employee`类的**实例方法**访问,因为 `Employee`是由 `Person`派生而来的。 146 | 147 | #### readonly 148 | 149 | 你可以使用 `readonly`关键字将属性设置为只读的。 只读属性必须在声明时或构造函数里被初始化。 150 | 151 | ```typescript 152 | class Octopus { 153 | readonly name: string; 154 | readonly numberOfLegs: number = 8; 155 | constructor (theName: string) { 156 | this.name = theName; 157 | } 158 | } 159 | let dad = new Octopus("Man with the 8 strong legs"); 160 | dad.name = "Man with the 3-piece suit"; // 错误! name 是只读的. 161 | ``` 162 | 163 | #### get/set 164 | 165 | TypeScript支持通过`getters/setters`来截取对对象成员的访问。 它能帮助你有效的控制对对象成员的访问。 166 | 167 | 下面来看如何把一个简单的类改写成使用 `get`和 `set`。 首先,我们从一个没有使用存取器的例子开始。 168 | 169 | ```typescript 170 | class Employee { 171 | fullName: string; 172 | } 173 | 174 | let employee = new Employee(); 175 | employee.fullName = "Bob Smith"; 176 | if (employee.fullName) { 177 | console.log(employee.fullName); 178 | } 179 | ``` 180 | 181 | 下面这个版本里,我们先检查用户密码是否正确,然后再允许其修改员工信息。 我们把对 `fullName`的直接访问改成了可以检查密码的 set方法。 我们也加了一个 get方法,让上面的例子仍然可以工作。 182 | ```typescript 183 | let passcode = "secret passcode"; 184 | 185 | class Employee { 186 | private _fullName: string; 187 | 188 | get fullName(): string { 189 | return this._fullName; 190 | } 191 | 192 | set fullName(newName: string) { 193 | if (passcode && passcode == "secret passcode") { 194 | this._fullName = newName; 195 | } 196 | else { 197 | console.log("Error: Unauthorized update of employee!"); 198 | } 199 | } 200 | } 201 | 202 | let employee = new Employee(); 203 | employee.fullName = "Bob Smith"; 204 | if (employee.fullName) { 205 | alert(employee.fullName); 206 | } 207 | ``` 208 | 209 | #### static 210 | 211 | 到目前为止,我们只讨论了类的实例成员,那些仅当类被实例化的时候才会被初始化的属性。 我们也可以创建类的静态成员,这些属性存在于类本身上面而不是类的实例上。 212 | 213 | ```typescript 214 | class Router { 215 | static baseRoute = '/basePath'; 216 | calculateRoute(path: string) { 217 | return Router.baseRoute + this.commonPrefix + path; 218 | } 219 | constructor (public commonPrefix: string) { } 220 | } 221 | 222 | let route1 = new Router('/api'); // 一级路径为/api 223 | let route2 = new Router('/page'); // 一级路径为/page 224 | 225 | console.log(route1.calculateRoute('/main')); // 最终路径/basePath/api/main 226 | console.log(route2.calculateRoute('/user')); // 最终路径/basePath/page/user 227 | ``` 228 | 229 | #### abstract 230 | 231 | 抽象类做为其它派生类的基类使用。 它们一般不会直接被实例化。 不同于接口,抽象类可以包含成员的实现细节。 `abstract`关键字是用于定义抽象类和在抽象类内部定义抽象方法。 232 | 233 | ```typescript 234 | abstract class Animal { 235 | abstract makeSound(): void; 236 | move(): void { 237 | console.log('roaming the earch...'); 238 | } 239 | } 240 | ``` 241 | 242 | ## 下一步 243 | 244 | - [接口和命名空间](/preknowledge/interface-and-namespace) - 进一步了解Typescript所规定的语法 245 | 246 | -------------------------------------------------------------------------------- /docs/extension-guides/scm-provider.md: -------------------------------------------------------------------------------- 1 | # 源控制API 2 | 3 | VS Code 允许插件创作者通过扩展API去定义*源控制管理*特性(Source Control Management,SCM),VS Code整合了各式各样的SCM体系,而只给用户展现了一组小巧、强大的API接口,还是带用户界面的那种。 4 | 5 | ![VS Code的SCM](https://media.githubusercontent.com/media/Microsoft/vscode-docs/master/api/extension-guides/images/scm-provider/main.png) 6 | 7 | 8 | VS Code自带一个源控制器:Git,它是源控制API的最佳实践。如果你想构建你自己的SCM供应器,那么这是[一个很好的起点](https://github.com/Microsoft/vscode/blob/master/extensions/git/src/repository.ts)。 9 | 10 | > VS Code插件市场还有很多类似的超赞的插件,比如[SVN](https://marketplace.visualstudio.com/items?itemName=johnstoncode.svn-scm)。 11 | 12 | 如果你需要帮助,请查看[vscode命名空间API](https://code.visualstudio.com/api/references/vscode-api#scm)。 13 | 14 | ## 源控制模型 15 | --- 16 | `SourceControl`负责生产源控制模型的实体,它里面有`SourceControlResourceState`实例的**资源状态**,而资源状态又是`SourceControlResourceGroup`实例整理成**组**的。 17 | 18 | 通过`vscode.scm.createSourceControl`创建一个新的*源控制器*。 19 | 20 | 为了更好地理解这几种实体的交互,让我们拿[Git](https://github.com/Microsoft/vscode/tree/master/extensions/git)来做例子,考虑下列`git status`输出: 21 | 22 | ```bash 23 | vsce master* → git status 24 | On branch master 25 | Your branch is up-to-date with 'origin/master'. 26 | Changes to be committed: 27 | (use "git reset HEAD ..." to unstage) 28 | 29 | modified: README.md 30 | renamed: src/api.ts -> src/test/api.ts 31 | 32 | Changes not staged for commit: 33 | (use "git add/rm ..." to update what will be committed) 34 | (use "git checkout -- ..." to discard changes in working directory) 35 | 36 | deleted: .travis.yml 37 | modified: README.md 38 | ``` 39 | 这个工作区里面发生了很多事,首先,`README.md`文件已经被修改了但还没有提交,然后立刻又被修改了。 其次,`src/api.ts`文件被移动到了`src/test/api.ts`,这个修改已经存备(staged), 最后,`.travis.yml`文件被删除。 40 | 41 | 对于这个工作区而言,Git定义了两个资源组:**工作中(Working tree)**和**已索引(Index)**,对于单个组而言,每次**文件修改**就会产生一些资源状态: 42 | - **已索引** - 资源组 43 | - 修改`README.md` - 资源状态 44 | - 移动`src/api.ts`到`src/test/api.ts` - 资源状态 45 | - **工作中** - 资源组 46 | - 删除`.travis.yml` - 资源状态 47 | - 修改`README.md` - 资源状态 48 | 49 | 同一个`README.md`是怎么成为两组截然不同的资源状态呢? 50 | 51 | 下面揭秘Git是如何创建这个模型的: 52 | 53 | ```typescript 54 | function createResourceUri(relativePath: string): vscode.Uri { 55 | const absolutePath = path.join(vscode.workspace.rootPath, relativePath); 56 | return vscode.Uri.file(absolutePath); 57 | } 58 | 59 | const gitSCM = vscode.scm.createSourceControl('git', "Git"); 60 | 61 | const index = gitSCM.createResourceGroup('index', "Index"); 62 | index.resourceStates = [ 63 | { resourceUri: createResourceUri('README.md') }, 64 | { resourceUri: createResourceUri('src/test/api.ts') } 65 | ]; 66 | 67 | const workingTree = gitSCM.createResourceGroup('workingTree', "Changes"); 68 | workingTree.resourceStates = [ 69 | { resourceUri: createResourceUri('.travis.yml') }, 70 | { resourceUri: createResourceUri('README.md') } 71 | ]; 72 | ``` 73 | 74 | 源变动和最终产生的资源组会传递到源控制视图上。 75 | 76 | ## 源控制视图 77 | --- 78 | 当源变动时,VS Code会生成源控制视图。源状态可通过`SourceControlResourceDecorations`自定义: 79 | 80 | ```typescript 81 | export interface SourceControlResourceState { 82 | readonly decorations?: SourceControlResourceDecorations; 83 | } 84 | ``` 85 | 86 | 上述例子已经足以让源控制视图生成一个简单的列表,不过用户可能想要在不同的资源状态上进行不同的操作。比如,当用户点击资源状态时,会发生什么呢?资源状态提供了一个可选命令去处理这类场景: 87 | ```typescript 88 | export interface SourceControlResourceState { 89 | readonly command?: Command; 90 | } 91 | ``` 92 | 93 | ### 菜单 94 | 95 | 要想提供更加丰富的交互效果,我们提供了5个源控制菜单项供你使用。 96 | 97 | `scm/title`菜单在源控制视图的顶部右上方,菜单项水平排列在`标题栏`中,另外一些会在`...`下拉菜单中。 98 | 99 | `scm/resourceGroup/context`和`scm/resourceState/context`是类似的,你可以通过前者自定义资源组,后者则是定义资源状态。将菜单项放在`inline`组里,可以水平在视图中展示它们。而其他的菜单项可以通过鼠标右击的形式展示在菜单中。菜单中调用的命令会传入资源状态作为参数。注意SCM视图提供多选,因此命令函数可能一次性会接收一个或多个参数。 100 | 101 | 例如,Git支持往`scm/resourceState/context`菜单中添加`git.stage`命令和使用下列方法,提供多个文件的存备(staged): 102 | 103 | ```typescript 104 | stage(...resourceStates: SourceControlResourceState[]): Promise; 105 | ``` 106 | 107 | 创建它们的时候,`SourceControl`和`SourceControlResourceGroup`实例会需要你提供一个string类型的`id`,这些值最终会在`scmProvider`和`scmResourceGroup`以上下文键值的形式出现。在菜单项的`when`语法中使用这些[上下文键值](https://code.visualstudio.com/docs/getstarted/keybindings#_when-clause-contexts)。看个Git如何通过`git.stage`命令显示菜单项的: 108 | 109 | ```json 110 | { 111 | "command": "git.stage", 112 | "when": "scmProvider == git && scmResourceGroup == merge", 113 | "group": "inline" 114 | } 115 | ``` 116 | 117 | `scm/change/title`可以对*行内变动*配置标题栏的命令(contribute commands to the title bar of an inline change)。命令中的参数有文档的URI,变动数组,当前行内变动所在索引。例如下面是一个可以配置菜单的Git`stageChange`命令声明: 118 | 119 | ```typescript 120 | async stageChange(uri: Uri, changes: LineChange[], index: number): Promise; 121 | ``` 122 | 123 | `scm/sourceControl`菜单根据环境出现在源控制实例的边上。 124 | 125 | ![源控制菜单](https://media.githubusercontent.com/media/Microsoft/vscode-docs/master/api/extension-guides/images/scm-provider/sourcecontrol-menu.png) 126 | 127 | 最后,`scm/change/title`菜单是和快速Diff功能相关联的,越新的文件越靠前,你可以针对特定的代码变动调用命令。 128 | 129 | ### SCM 输入框 130 | 131 | 源控制输入框位于每个源控制视图的顶部,接收用户输入的信息。你可以获取(或设置)这个信息供后续使用。在Git中,比如说,这可以作为一个commit框,用户输入了提交信息后,触发`git commit`命令: 132 | 133 | ```typescript 134 | export interface SourceControlInputBox { 135 | value: string; 136 | } 137 | 138 | export interface SourceControl { 139 | readonly inputBox: SourceControlInputBox; 140 | } 141 | ``` 142 | 143 | 用户可以通过Ctrl+Enter(Mac上是Cmd+Enter)接收任意信息,在`SourceControl`中的`acceptInputCommand`处理这类事件。 144 | 145 | ```typescript 146 | export interface SourceControl { 147 | readonly acceptInputCommand?: Command; 148 | } 149 | ``` 150 | 151 | ## 快速Diff 152 | --- 153 | 154 | VS Code支持显示**快速Diff**编辑器的高亮槽,点击这些槽会出现一个内部diff交互器,你可以在这里为上下文配置命令。 155 | 156 | ![SCM快速Diff](https://media.githubusercontent.com/media/Microsoft/vscode-docs/master/api/extension-guides/images/scm-provider/quickdiff.png) 157 | 158 | 这些高亮槽是VS Code自己计算出来的,你要做的就是根据给定的文件提供原始文件内容 159 | 160 | ```typescript 161 | export interface SourceControl { 162 | quickDiffProvider?: QuickDiffProvider; 163 | } 164 | ``` 165 | 166 | 使用`QuickDiffProvider`,你的实现需要告诉VS Code——参数传入的给定资源`Uri`所对应的原始资源`Uri`。 167 | 168 | ?> **提示**: 如果你想在给定`Uri`的情况下,为任意资源提供内容,那么你可以把**源控制API**和**[工作区命名空间的`registerTextDocumentContentProvider`方法](https://code.visualstudio.com/api/references/vscode-api#workspace)**结合起来使用。 169 | 170 | ## 下一步 171 | 172 | 想要学习更多关于VS Code扩展性模型,请参考: 173 | 174 | * [SCM API 参考](https://code.visualstudio.com/docs/extensionAPI/vscode-api#_scm) - 查看完整的SCM API文档 175 | * [Git 插件](https://github.com/Microsoft/vscode/tree/master/extensions/git) - 学习Git插件实现 176 | * [插件API概览](/) - 学习全部的VS Code扩展性模型 177 | * [插件配置清单](/references/extension-manifest) - VS Code package.json插件配置清单参考 178 | * [发布内容配置点](/references/contribution-points) - VS Code发布内容配置点参考 -------------------------------------------------------------------------------- /docs/preknowledge/generics.md: -------------------------------------------------------------------------------- 1 | # 认识Typescript-泛型 2 | 3 | 软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。 4 | 5 | 在像C#和Java这样的语言中,可以使用**泛型**来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件。 6 | 7 | ## 泛型之Hello World 8 | --- 9 | 下面来创建第一个使用泛型的例子:identity函数。 这个函数会返回任何传入它的值。 你可以把这个函数当成是 `echo`命令。 10 | 11 | 不用泛型的话,这个函数可能是下面这样: 12 | 13 | ```typescript 14 | function identity(arg: number): number { 15 | return arg; 16 | } 17 | ``` 18 | 19 | 或者,我们使用any类型来定义函数: 20 | 21 | ```typescript 22 | function identity(arg: any): any { 23 | return arg; 24 | } 25 | ``` 26 | 27 | 使用`any`类型会导致这个函数可以接收任何类型的arg参数,这样就丢失了一些信息:传入的类型与返回的类型应该是相同的。如果我们传入一个数字,我们只知道任何类型的值都有可能被返回。 28 | 29 | 因此,我们需要一种方法使返回值的类型与传入参数的类型是相同的。 这里,我们使用了**类型变量**,它是一种特殊的变量,*只用于表示类型而不是值*。 30 | 31 | ```typescript 32 | function identity(arg: T): T { 33 | return arg; 34 | } 35 | ``` 36 | 37 | 我们给identity添加了类型变量`T`。 `T`帮助我们捕获用户传入的类型(比如:`number`),之后我们就可以使用这个类型。 之后我们再次使用了`T`当做返回值类型。现在我们可以知道参数类型与返回值类型是相同的了。 这允许我们跟踪函数里使用的类型的信息。 38 | 39 | 我们把这个版本的`identity`函数叫做泛型,因为它可以适用于多个类型。 不同于使用`any`,它不会丢失信息,像第一个例子那像保持准确性,传入数值类型并返回数值类型。 40 | 41 | 我们定义了泛型函数后,可以用两种方法使用。 第一种是,传入所有的参数,包含类型参数: 42 | 43 | ```typescript 44 | let output = identity("myString"); // type of output will be 'string' 45 | ``` 46 | 47 | 这里我们明确的指定了`T`是`string`类型,并做为一个参数传给函数,使用了`<>`括起来而不是`()`。 48 | 49 | 第二种方法更普遍。利用了*类型推论* -- 即编译器会根据传入的参数自动地帮助我们确定T的类型: 50 | 51 | ```typescript 52 | let output = identity("myString"); // type of output will be 'string' 53 | ``` 54 | 55 | 注意我们没必要使用尖括号(`<>`)来明确地传入类型;编译器可以查看`myString`的值,然后把`T`设置为它的类型。 类型推论帮助我们保持代码精简和高可读性。如果编译器不能够自动地推断出类型的话,只能像上面那样明确的传入`T`的类型,在一些复杂的情况下,这是可能出现的。 56 | 57 | ## 使用泛型变量 58 | --- 59 | 60 | 使用泛型创建像`identity`这样的泛型函数时,编译器要求你在函数体必须正确的使用这个通用的类型。 换句话说,你必须把这些参数当做是任意或所有类型。 61 | 62 | 看下之前identity例子: 63 | 64 | ```typescript 65 | function identity(arg: T): T { 66 | return arg; 67 | } 68 | ``` 69 | 70 | 如果我们想同时打印出arg的长度。 我们很可能会这样做: 71 | 72 | ```typescript 73 | function loggingIdentity(arg: T): T { 74 | console.log(arg.length); // Error: T doesn't have .length 75 | return arg; 76 | } 77 | ``` 78 | 79 | 如果这么做,编译器会报错说我们使用了`arg`的`.length`属性,但是没有地方指明`arg`具有这个属性。 记住,这些类型变量代表的是任意类型,所以使用这个函数的人可能传入的是个数字,而数字是没有 `.length`属性的。 80 | 81 | 现在假设我们想操作T类型的数组而不直接是T。由于我们操作的是数组,所以`.length`属性是应该存在的。 我们可以像创建其它数组一样创建这个数组: 82 | 83 | ```typescript 84 | function loggingIdentity(arg: T[]): T[] { 85 | console.log(arg.length); // Array has a .length, so no more error 86 | return arg; 87 | } 88 | ``` 89 | 90 | 你可以这样理解`loggingIdentity`的类型:泛型函数`loggingIdentity`,接收类型参数`T`和参数`arg`,它是个元素类型是`T`的数组,并返回元素类型是`T`的数组。 如果我们传入数字数组,将返回一个数字数组,因为此时 `T`的的类型为number。 这可以让我们把泛型变量`T`当做类型的一部分使用,而不是整个类型,增加了灵活性。 91 | 92 | 我们也可以这样实现上面的例子: 93 | 94 | ```typescript 95 | function loggingIdentity(arg: Array): Array { 96 | console.log(arg.length); // Array has a .length, so no more error 97 | return arg; 98 | } 99 | ``` 100 | 使用过其它语言的话,你可能对这种语法已经很熟悉了。 在下一节,会介绍如何创建自定义泛型像 Array一样。 101 | 102 | ## 泛型类型 103 | --- 104 | 上一节,我们创建了identity通用函数,可以适用于不同的类型。 在这节,我们研究一下函数本身的类型,以及如何创建泛型接口。 105 | 106 | 泛型函数的类型与非泛型函数的类型没什么不同,只是有一个类型参数在最前面,像函数声明一样: 107 | 108 | ```typescript 109 | function identity(arg: T): T { 110 | return arg; 111 | } 112 | 113 | let myIdentity: (arg: T) => T = identity; 114 | ``` 115 | 116 | 我们也可以使用不同的泛型参数名,只要在数量上和使用方式上能对应上就可以。 117 | 118 | ```typescript 119 | function identity(arg: T): T { 120 | return arg; 121 | } 122 | 123 | let myIdentity: (arg: U) => U = identity; 124 | ``` 125 | 126 | 我们还可以使用带有调用签名的对象字面量来定义泛型函数: 127 | 128 | ```typescript 129 | function identity(arg: T): T { 130 | return arg; 131 | } 132 | 133 | let myIdentity: {(arg: T): T} = identity; 134 | ``` 135 | 136 | 这引导我们去写第一个泛型接口了。 我们把上面例子里的对象字面量拿出来做为一个接口: 137 | 138 | ```typescript 139 | interface GenericIdentityFn { 140 | (arg: T): T; 141 | } 142 | 143 | function identity(arg: T): T { 144 | return arg; 145 | } 146 | 147 | let myIdentity: GenericIdentityFn = identity; 148 | ``` 149 | 150 | 一个相似的例子,我们可能想把泛型参数当作整个接口的一个参数。 这样我们就能清楚的知道使用的具体是哪个泛型类型(比如: `Dictionary而不只是Dictionary`)。 这样接口里的其它成员也能知道这个参数的类型了。 151 | 152 | ```typescript 153 | interface GenericIdentityFn { 154 | (arg: T): T; 155 | } 156 | 157 | function identity(arg: T): T { 158 | return arg; 159 | } 160 | 161 | let myIdentity: GenericIdentityFn = identity; 162 | ``` 163 | 164 | 注意,我们的示例做了少许改动。 不再描述泛型函数,而是把非泛型函数签名作为泛型类型一部分。 当我们使用 `GenericIdentityFn` 的时候,还得传入一个类型参数来指定泛型类型(这里是:`number`),锁定了之后代码里使用的类型。 对于描述哪部分类型属于泛型部分来说,理解何时把参数放在调用签名里和何时放在接口上是很有帮助的。 165 | 166 | 除了泛型接口,我们还可以创建泛型类。 注意,无法创建泛型枚举和泛型命名空间。 167 | 168 | ## 泛型类 169 | --- 170 | 171 | ```typescript 172 | class GenericNumber { 173 | zeroValue: T; 174 | add: (x: T, y: T) => T; 175 | } 176 | 177 | let myGenericNumber = new GenericNumber(); 178 | myGenericNumber.zeroValue = 0; 179 | myGenericNumber.add = function(x, y) { return x + y; }; 180 | ``` 181 | 182 | GenericNumber类的使用是十分直观的,并且你可能已经注意到了,没有什么去限制它只能使用number类型。 也可以使用字符串或其它更复杂的类型。 183 | 184 | ```typescript 185 | let stringNumeric = new GenericNumber(); 186 | stringNumeric.zeroValue = ""; 187 | stringNumeric.add = function(x, y) { return x + y; }; 188 | 189 | console.log(stringNumeric.add(stringNumeric.zeroValue, "test")); 190 | ``` 191 | 192 | 与接口一样,直接把泛型类型放在类后面,可以帮助我们确认类的所有属性都在使用相同的类型。 193 | 194 | ## 泛型约束 195 | --- 196 | 197 | 你应该会记得之前的一个例子,我们有时候想操作某类型的一组值,并且我们知道这组值具有什么样的属性。 在 `loggingIdentity` 例子中,我们想访问`arg`的`length`属性,但是编译器并不能证明每种类型都有`length`属性,所以就报错了。 198 | 199 | ```typescript 200 | function loggingIdentity(arg: T): T { 201 | console.log(arg.length); // Error: T doesn't have .length 202 | return arg; 203 | } 204 | ``` 205 | 206 | 相比于操作any所有类型,我们想要限制函数去处理任意带有`.length`属性的所有类型。 只要传入的类型有这个属性,我们就允许,就是说至少包含这一属性。 为此,我们需要列出对于T的约束要求。 207 | 208 | 为此,我们定义一个接口来描述约束条件。 创建一个包含 `.length`属性的接口,使用这个接口和extends关键字来实现约束: 209 | 210 | ```typescript 211 | interface Lengthwise { 212 | length: number; 213 | } 214 | 215 | function loggingIdentity(arg: T): T { 216 | console.log(arg.length); // Now we know it has a .length property, so no more error 217 | return arg; 218 | } 219 | ``` 220 | 221 | 现在这个泛型函数被定义了约束,因此它不再是适用于任意类型: 222 | 223 | ```typescript 224 | loggingIdentity(3); // Error, number doesn't have a .length property 225 | ``` 226 | 227 | 我们需要传入符合约束类型的值,必须包含必须的属性: 228 | 229 | ```typescript 230 | loggingIdentity({length: 10, value: 3}); 231 | ``` 232 | 233 | ### 在泛型约束中使用类型参数 234 | 235 | 你可以声明一个类型参数,且它被另一个类型参数所约束。 比如,现在我们想要用属性名从对象里获取这个属性。 并且我们想要确保这个属性存在于对象 obj上,因此我们需要在这两个类型之间使用约束。 236 | 237 | ```typescript 238 | function getProperty(obj: T, key: K) { 239 | return obj[key]; 240 | } 241 | 242 | let x = { a: 1, b: 2, c: 3, d: 4 }; 243 | 244 | getProperty(x, "a"); // okay 245 | getProperty(x, "m"); // error: Argument of type 'm' isn't assignable to 'a' | 'b' | 'c' | 'd'. 246 | ``` -------------------------------------------------------------------------------- /docs/working-with-extensions/bundling-extension.md: -------------------------------------------------------------------------------- 1 | # 打包插件 2 | 3 | VS Code 插件体积常常随着更新越来越大,它会产生很多文件,而且还依赖各种[npm](https://www.npmjs.com/)包。 4 | 程序开发的最佳实践是抽象和重用,但过度拆分和庞大的代码结构产生的代价就是更大的插件体积和更慢的运行效率。加载 100 个小文件远比加载一个大文件来的慢,这就是我们更推荐打包插件的原因。 5 | *打包*是将多个小的源文件打包成单个入口文件的过程。 6 | 7 | 对于 Javascript 而言,可选的构建工具非常多,比较流行的如[rollup.js](https://rollupjs.org/),[parcel](https://parceljs.org/)和[webpack](https://webpack.js.org/)。大部分构建工具的概念和功能都是相似的,本节主要使用**webpack**打包。 8 | 9 | ## 使用 webpack 10 | 11 | --- 12 | 13 | webpack 这个开发工具可以在[npm](https://www.npmjs.com/)里找到,为了获取 webpack 和它的命令行界面,打开终端然后输入: 14 | 15 | ```bash 16 | npm i --save-dev webpack webpack-cli 17 | ``` 18 | 19 | 这行命令会先安装 webpack,然后更新你插件里的`package.json`中的`devDependencies`字段。Webpack 是一个 Javascrip 打包工具,但是大部分 VS Code 插件是用 Typescript 写的,所以你需要在 webpack 中配置`ts-loader`,它才能正确编译 Typescript。安装`ts-loader`: 20 | 21 | ```bash 22 | npm i --save-dev ts-loader 23 | ``` 24 | 25 | ## 配置 webpack 26 | 27 | --- 28 | 29 | 既然所有的工具都安装好了,我们现在可以开始配置 webpack 了。通常来说,你的项目目录中需要创建一个`webpack.config.js`文件,webpack 才能知道按什么规则打包你的插件。下面的配置示例是 VS Code 插件专用的,让我们来开这个头吧: 30 | 31 | ```javascript 32 | /*--------------------------------------------------------------------------------------------- 33 | * Copyright (c) Microsoft Corporation. All rights reserved. 34 | * Licensed under the MIT License. See License.txt in the project root for license information. 35 | *--------------------------------------------------------------------------------------------*/ 36 | 37 | //@ts-check 38 | 39 | "use strict"; 40 | 41 | const path = require("path"); 42 | 43 | /**@type {import('webpack').Configuration}*/ 44 | const config = { 45 | target: "node", // vscode插件运行在Node.js环境中 📖 -> https://webpack.js.org/configuration/node/ 46 | 47 | entry: "./src/extension.ts", // 插件的入口文件 📖 -> https://webpack.js.org/configuration/entry-context/ 48 | output: { 49 | // 打包好的文件储存在'dist'文件夹中 (请参考package.json), 📖 -> https://webpack.js.org/configuration/output/ 50 | path: path.resolve(__dirname, "dist"), 51 | filename: "extension.js", 52 | libraryTarget: "commonjs2", 53 | devtoolModuleFilenameTemplate: "../[resource-path]" 54 | }, 55 | devtool: "source-map", 56 | externals: { 57 | vscode: "commonjs vscode" // vscode-module是热更新的临时目录,所以要排除掉。 在这里添加其他不应该被webpack打包的文件, 📖 -> https://webpack.js.org/configuration/externals/ 58 | }, 59 | resolve: { 60 | // 支持读取TypeScript和JavaScript文件, 📖 -> https://github.com/TypeStrong/ts-loader 61 | extensions: [".ts", ".js"] 62 | }, 63 | module: { 64 | rules: [ 65 | { 66 | test: /\.ts$/, 67 | exclude: /node_modules/, 68 | use: [ 69 | { 70 | loader: "ts-loader" 71 | } 72 | ] 73 | } 74 | ] 75 | } 76 | }; 77 | module.exports = config; 78 | ``` 79 | 80 | 这份文件是[webpack-extension](https://github.com/Microsoft/vscode-extension-samples/blob/master/webpack-sample)中的[一部分](https://github.com/Microsoft/vscode-extension-samples/blob/master/webpack-sample/webpack.config.js)。webpack 配置最后输出的就是 JS 对象。 81 | 82 | 在上面的例子里,我们定义了如下内容: 83 | 84 | - `traget`:'node',因为我们的插件运行在 Node.js 环境中。 85 | - `entry`:webpack 使用的入口文件。这就像是`package.json`中的`main`属性,有点不一样的是你还需要给 webpack 提供"source"—— 一般就是`src/extension.ts`,小心不要配置在"output"里了。webpack 可以解析 Typescript,所以我们不需要再单独执行 Typescript 编译了。 86 | - `output`配置告诉 webpack 应该把打包好的文件放在哪里,一般而言我们会放在`dist`文件夹里。在这个例子里,webpack 最后会产生一个`dist/extension.js`文件。 87 | - 在`resolve`和`module/rules`中配置 Typescript 和 Javascript 的解析器。 88 | - `externals`即排除配置,在这里可以配置打包文件不应包含的文件和模块。`vscode`不需要被打包是因为它并不储存在磁盘上,它是 VS Code 热更新生成的临时文件夹。根据插件依赖的具体 node 模块,你可能需要通过这个配置优化打包文件。 89 | 90 | ## 运行 webpack 91 | 92 | --- 93 | 94 | `webpack.config.js`文件创建好之后,webpack 就可以正式开始工作了。你可以从命令行中运行 webpack,不过为了避免重复工作用 npm script 会更有效率。 95 | 96 | 将下列脚本复制到`package.json`的`scripts`中去: 97 | 98 | ```json 99 | "scripts": { 100 | "vscode:prepublish": "webpack --mode production", 101 | "compile": "webpack --mode none", 102 | "watch": "webpack --mode none --watch", 103 | }, 104 | ``` 105 | 106 | `compile`和`watch`脚本是开发时使用的,它们会产生构建文件。`vscode:prepublish`是`vsce`使用的,`vsce`是 VS Code 的打包和发布工具,你需要在发布插件之前运行这个命令。webpack 中的[mode](https://webpack.js.org/concepts/mode/)是控制优化级别的配置项,如果你使用`production`字段,那么就会打包出最小的构建文件,但是也会耗费更多时间,所以我们开发中使用`none`。想要运行上述脚本,我们可以打开终端(命令行)输入`npm run compile`或者从*命令面板*(Ctrl+Shift+P)中使用**运行任务**来开始。 107 | 108 | ## 运行插件 109 | 110 | --- 111 | 112 | 运行插件之前,你需要将`package.json`中的`main`属性指向到构建文件上,也就是我们上面提到的[`"./dist/extension"`](https://github.com/Microsoft/vscode-references-view/blob/d649d01d369e338bbe70c86e03f28269cbf87027/package.json#L26),改好之后我们就可以运行和测试插件了。关于调试配置,请注意更新`launch.json`中的`outFiles`属性。 113 | 114 | ## 测试 115 | 116 | --- 117 | 118 | 插件开发者一般都会给插件源代码进行单元测试,但是有了完备的底层架构支持,插件的源代码可以不依赖测试,webpack 产生的构建文件中也不应该包含任何测试代码。如果需要运行单元测试,只需要简单地编译就好了。在上面的例子里,我们有一个`test-compile`脚本,它会把调用 Typescript 编译器将插件编译至`out`目录中。这样一来我们就有了 JS 文件,再使用下面的`launch.json`就足够应付测试了。 119 | 120 | ```json 121 | { 122 | "name": "Extension Tests", 123 | "type": "extensionHost", 124 | "request": "launch", 125 | "runtimeExecutable": "${execPath}", 126 | "args": [ 127 | "--extensionDevelopmentPath=${workspaceFolder}", 128 | "--extensionTestsPath=${workspaceFolder}/out/test" 129 | ], 130 | "outFiles": ["${workspaceFolder}/out/test/**/*.js"], 131 | "preLaunchTask": "npm: test-compile" 132 | } 133 | ``` 134 | 135 | 这个测试配置对于非 webpack 打包的插件来说也是可以使用的。我们没必要将单元测试打包起来,因为它们不应包含在我们发布的插件里。 136 | 137 | ## 发布 138 | 139 | --- 140 | 141 | 发布前你需要更新`.vscodeignore`文件。现在所有东西都打包到了`dist/extension.js`文件中,所以应该排除这个文件还有`out`文件夹(怕你漏了,特此提醒),以及最重要的`node_modules`文件夹。 142 | 143 | 一般来说,`.vsignore`文件应该是这样的: 144 | 145 | ```bash 146 | .vscode 147 | node_modules 148 | out/ 149 | src/ 150 | tsconfig.json 151 | webpack.config.js 152 | ``` 153 | 154 | ## 迁移插件 155 | 156 | --- 157 | 158 | 用 webpack 迁移现有的插件是很容易的,整个过程就像我们上面的指南一样。真实的例子如 VS Code 的 References 视图就是从这个[pull request](https://github.com/Microsoft/vscode-references-view/pull/50)应用了 webpack 而来的。 159 | 160 | 在里面,你可以看到: 161 | 162 | - `devDependencies`中添加`webpack`,`webpack-cli`和`ts-loader` 163 | - 更新 npm 脚本以便开发时使用 webpack 164 | - 更新调试配置文件`launch.json` 165 | - 添加和修改`webpack.config.js` 166 | - 更新`.vscodeignore`排除`node_modules`和其他开发时产生的临时文件 167 | - 开始享受体积更小、安装更快的插件! 168 | 169 | ## 疑难解答 170 | 171 | --- 172 | 173 | #### 压缩 174 | 175 | 使用`production`模式会执行代码压缩,它会去除源代码中的空格和注释,并把变量名和函数名进行替换——混淆和压缩。不过形如`Function.prototype.name`的代码不会压缩。 176 | 177 | #### webpack critical dependencies 178 | 179 | 当你运行 webpack 时,你可能会碰到像**Critical dependencies: the request of a dependency is an expression**字样的警告。这些警告必须立即处理,一般来说会影响到打包过程。这句话意味着 webpack 不能静态分析某些依赖,一般是由动态使用`require`导致的,比如`require(someDynamicVariable)`。 180 | 181 | 想要处理这类警告,你需要: 182 | 183 | - 将需要打包的部分变成静态的依赖。 184 | - 通过`externals`排除这部分依赖,但是注意它们的 Javascript 文件还是应该保留在我们打包的插件里,在`.vscodeignore`中使用 glob 模式,比如`!node_modules/mySpecialModule`。 185 | 186 | ## 下一步 187 | 188 | - [插件市场](https://code.visualstudio.com/docs/editor/extension-gallery) - 学习更多 VS Code 插件市场的有关内容。 189 | - [测试插件](/working-with-extensions/testing-extension.md) - 测试插件,提高项目质量。 190 | - [持续集成](/working-with-extensions/continuous-integration.md) - 使用 Azure Pipeline 运行插件的 CI 构建。 191 | -------------------------------------------------------------------------------- /docs/working-with-extensions/publish-extension.md: -------------------------------------------------------------------------------- 1 | # 发布插件 2 | 3 | ## vsce —— 发布工具参阅 4 | 5 | [vsce](https://github.com/Microsoft/vsce)是一个用于将插件发布到[市场](https://code.visualstudio.com/docs/editor/extension-gallery)上的命令行工具。 6 | 7 | ## 安装 8 | 9 | --- 10 | 11 | 请确认本机已经安装了[Node.js](https://nodejs.org/),然后运行: 12 | 13 | ```bash 14 | npm install -g vsce 15 | ``` 16 | 17 | ## 使用 18 | 19 | --- 20 | 21 | 然后你就可以在命令行里直接使用`vsce`了。下面是一个快速发布的示例(在你登录和打包好插件之后): 22 | 23 | ```bash 24 | $ vsce publish 25 | Publishing uuid@0.0.1... 26 | Successfully published uuid@0.0.1! 27 | ``` 28 | 29 | 更多可用的命令参数,请使用`vsce --help` 30 | 31 | ## 发布教程 32 | 33 | --- 34 | 35 | !> **注意:** 出于安全考虑,`vsce`不会发布包含用户提供 SVG 图片的插件。 36 | 37 | 发布工具会检查以下内容: 38 | 39 | - `pacakge.json`文件中的 icon 不可以是 SVG。 40 | - `pacakge.json`中的徽章不可以是 SVG,除非来自于[可靠的图标来源](/extensibility-reference/extension-manifest.md#使用认证过的标志) 41 | - `README.md`和`CHANGELOG.md`中的图片链接需要使用`https`协议 42 | - `README.md`和`CHANGELOG.md`中的图片不可以是 SVG,除非来自[可靠的图标来源](/extensibility-reference/extension-manifest.md#使用认证过的标志) 43 | 44 | --- 45 | 46 | VS Code 插件市场的服务是[Visual Studio Team Services](https://visualstudio.microsoft.com/team-services)提供的,因此验证、代理、管理插件都是由这个服务提供的。 47 | 48 | `vsce`只能用[Personal Access Tokens](https://docs.microsoft.com/vsts/integrate/get-started/authentication/pats)发布插件,所以至少要创建一个 Token 以便发布插件。 49 | 50 | #### 获取 Personal Access Token 51 | 52 | 首先,你得有一个[Azure DevOps 组织](https://docs.microsoft.com/azure/devops/organizations/accounts/create-organization-msa-or-work-student)。 53 | 54 | 下面的例子里,我们假设组织名为`vscode`,从你的组织主页(例如:`https://dev.azure.com/vscode` )进入**安全(Security)**页面: 55 | 56 | ![publishers1](https://media.githubusercontent.com/media/Microsoft/vscode-docs/master/api/working-with-extensions/images/publishing-extension/token1.png) 57 | 58 | 选择 Personal Access Token,点击**New Token**创建一个新的 Personal Access Token 59 | 60 | ![publishers2](https://media.githubusercontent.com/media/Microsoft/vscode-docs/master/api/working-with-extensions/images/publishing-extension/token2.png) 61 | 62 | 给 Personal Access Token 添加描述,过期时间等等,你最好把过期时间设置为 1 年,这样你接下就能方便很多,选择**custom defined(用户自定义)**范围,然后点击**Show all scopes(显示全部)** 63 | 64 | ![publishers3](https://media.githubusercontent.com/media/Microsoft/vscode-docs/master/api/working-with-extensions/images/publishing-extension/token3.png) 65 | 66 | 最后,在这个列表中找到**Marketplace**,并勾选**Acquire**和**Manage** 67 | 68 | ![publishers4](https://media.githubusercontent.com/media/Microsoft/vscode-docs/master/api/working-with-extensions/images/publishing-extension/token4.png) 69 | 70 | 点击**Create**,你就会看到新创建的 Personal Access Token 了,复制好,你接下来就会用到这个 token 来创建一个*发行方*了。 71 | 72 | #### 创建一个发行方 73 | 74 | **发行方**是 VS Code 市场有权发布插件的唯一标识,每个插件的[package.json](/extensibility-reference/extension-manifest.md)文件都包含着`publisher`字段。 75 | 76 | 现在我们已经有了[Personal Access Token](#获取Personal-Access-Token),我们马上可以用`vsce`创建一个发行方: 77 | 78 | ```bash 79 | vsce create-publisher (publisher name) 80 | ``` 81 | 82 | `vsce`会记住这个 Personal Access Token,日后你需要再次使用的时候会自动带上。 83 | 84 | ?> 注意:另外,你也可以在市场的发行方[管理页](https://marketplace.visualstudio.com/manage)中创建发行方,然后用这个账号登录`vsce`。 85 | 86 | #### 发行方登录 87 | 88 | 如果你已经有发行方账号了: 89 | 90 | ```bash 91 | vsce login (publisher name) 92 | ``` 93 | 94 | 和`create-publisher`命令类似地,`vsce`会要求输入你的 Personal Access Token。 95 | 96 | 你也可以用命令参数`-p `直接登录然后立即发布插件: 97 | 98 | ```bash 99 | vsce publish -p 100 | ``` 101 | 102 | #### 增量更新插件版本 103 | 104 | 用 SemVer 语义标识符:`major`,`minor`,`patch`增量更新插件版本号。 105 | 106 | 例如,你想把插件从 1.0.0 更新到 1.1.0,那么加上`minor`: 107 | 108 | ```bash 109 | vsce publish minor 110 | ``` 111 | 112 | 插件`package.json`的 version 会先更新,然后才发布插件。 113 | 114 | 你也可以通过命令行指定版本号: 115 | 116 | ```bash 117 | vsce publish 2.0.1 118 | ``` 119 | 120 | #### 下架插件 121 | 122 | 通过指定插件 id`publisher.extension`下架插件: 123 | 124 | ``` 125 | vsce unpublish (publisher name).(extension name) 126 | ``` 127 | 128 | !> **注意:**当你下架插件的时候,市场会移除所有插件的历史统计数据,请在下架前再三考虑,最好还是更新插件吧。 129 | 130 | #### 插件打包 131 | 132 | 你也可能只是想打包一下插件,而不是发布到商店里。用下列命令将插件打包到`.vsix`文件中: 133 | 134 | ``` 135 | vsce package 136 | ``` 137 | 138 | 这个命令会在当前目录生成一个`.vsix`文件,直接从`.vsix`安装插件是允许的,查看[从 VSIX 安装插件](https://github.com/Microsoft/vscode-docs/blob/master/docs/editor/extension-gallery.md#install-from-a-vsix)了解更多内容。 139 | 140 | #### VS Code 版本兼容性 141 | 142 | 当你制作插件的时候,你需要描述插件对 VS Code 的版本兼容性——修改`package.json`中的`engines.vscode`: 143 | 144 | ```json 145 | { 146 | "engines": { 147 | "vscode": "^1.8.0" 148 | } 149 | } 150 | ``` 151 | 152 | `1.8.0`表示你的插件只能兼容`1.8.0`版本的 VS Code,`^1.8.0`则表示你的插件向上兼容,包括`1.8.1, 1.9.0`等等。 153 | 154 | 使用`engines.vscode`可以确保插件安装环境包含了插件依赖的 API。这个机制在稳定版和 Insider 版本都适用。 155 | 156 | 现在我们假设最新的稳定版 API 是`1.8.0`,而`1.9.0`引入了新的 API,所以你可以用`1.9.0-insider`标识插件在 Insider 版中也可正常使用。 157 | 如果你想使用这些刚刚引入的 API,则将依赖版本设置为`^1.9.0`,你的插件则只能安装在`>=1.9.0`的 VS Code 上,也就意味着所有当前的 Insider 版本都可以用得上,而稳定版只有在更新到`1.9.0`才能使用你的插件。 158 | 159 | ## 进阶用法 160 | 161 | --- 162 | 163 | #### 符合市场的插件 164 | 165 | 你可以自定义插件在市场中的外观,查看示例[GO 插件](https://marketplace.visualstudio.com/items/ms-vscode.Go)。 166 | 167 | 下面是一些让你的插件在市场看起来更酷的小提示: 168 | 169 | - 插件根目录下面的`README.md`文件可以用来填充插件市场的页面内容。`vsce`会将 README 中的链接通过下面两种方式修改掉: 170 | - 如果你的`package.json`的`repository`字段是一个 Github 仓库,`vsce`会自动检测,然后相应地调整链接。 171 | - 运行`vsce package`时,加上`--baseContentUrl`和`--baseImagesUrl`标识重载上述行为。 172 | - 插件根目录下的`LICENSE`会成为插件的 license。 173 | - 同样的`CHANGELOG.md`文件会成为插件的发布日志。 174 | - 通过设置`package.json`的`galleryBanner.color`hex 值,修改 banner 的背景色。 175 | - 通过给`package.json`中的`icon`设置一个相对路径,可以将一个`128px`的 PNG 图标放进你的插件中。 176 | 177 | - 参见[插件市场展现小提示](https://github.com/Microsoft/vscode-docs/blob/master/docs/extensionAPI/extension-manifest.md#marketplace-presentation-tips) 178 | 179 | #### `.vscodeignore` 180 | 181 | 创建一个`.vscodeignore`文件可以排除插件目录中的内容。这个文件支持[glob](https://github.com/isaacs/minimatch)模式,每个表达式一行。 182 | 183 | 例如: 184 | 185 | ``` 186 | **/*.ts 187 | **/tsconfig.json 188 | !file.ts 189 | ``` 190 | 191 | 你应该忽略哪些不必在运行时用到的文件。例如:你的插件是用 Typescript 写的,那么你就应该忽略所有的`**/*.ts`文件。 192 | 193 | ?> **注意:**在`devDependencies`列出的开发依赖会被自动忽略,你不必将他们加入到`.vscodeignore`中。 194 | 195 | ##### 预发布步骤 196 | 197 | 你是可以在清单文件中添加预发布步骤的,下面的命令会在插件每次打包时执行: 198 | 199 | ```json 200 | { 201 | "name": "uuid", 202 | "version": "0.0.1", 203 | "publisher": "joaomoreno", 204 | "engines": { 205 | "vscode": "0.10.x" 206 | }, 207 | "scripts": { 208 | "vscode:prepublish": "tsc" 209 | } 210 | } 211 | ``` 212 | 213 | 上面的示例会在每次插件打包时调用 Typescript 编译器。 214 | 215 | ## FAQ 216 | 217 | ##### 问:当我发布插件时遇到了 403 Forbidden(或 401 Unauthorized)错误? 218 | 219 | 答:很有可能是你创建 PAT (Personal Access Token) 时没有选择`all accessible accounts`。你还需要将授权范围设置为`All scopes`,这样发布工具才能工作。 220 | 221 | ##### 问:我没办法用`vsce`工具下架插件? 222 | 223 | 答:你可能改变了插件 ID 或者发行方名称。不过你还可以在[管理页面](https://marketplace.visualstudio.com/manage)发布或者下架插件。 224 | 225 | ##### 问:为什么 vsce 不保留文件属性? 226 | 227 | 答:请注意,当你在 Windows 平台构建和发布插件的时候,所有插件包内的文件会丢失 POSIX 文件属性,或称之为执行位(executable bit)的东西。一些基于这些属性的`node_modules`依赖则会调整工作方式。从 Linux 和 macOS 平台构建则会如预期执行。 228 | 229 | ## 下一步 230 | 231 | - [插件市场](https://code.visualstudio.com/docs/editor/extension-gallery) - 学习更多 VS Code 公共插件市场。 232 | - [测试插件](/working-with-extensions/testing-extension.md) - 添加插件测试,提高插件质量。 233 | -------------------------------------------------------------------------------- /docs/references/commands.md: -------------------------------------------------------------------------------- 1 | # 内置命令 2 | 3 | 这篇文档列出了可能需要与`vscode.commands.executeCommand`一起使用的命令集合. 4 | 5 | 阅读[命令指南]()以了解如何使用`commands`API. 6 | 7 | 下面是一个如何在 VS Code 中打开新文件夹的例子: 8 | 9 | ```javascript 10 | let uri = Uri.file('/some/path/to/folder'); 11 | let success = await commands.executeCommand('vscode.openFolder', uri); 12 | ``` 13 | 14 | ## 命令 15 | 16 | `vscode.executeWorkspaceSymbolProvider` - 执行工作区所有的**符号**供应器函数 17 | 18 | - *query* - 搜索关键词 19 | - *(returns)* - promise函数, 且参数为具有SymbolInformation和DocumentSymbol的实例数组. 20 | 21 | `vscode.executeDefinitionProvider` - 执行所有的**定义**供应器函数 22 | 23 | - *uri* - 文档的Uri 24 | - *position* - 某个符号的位置 25 | - *(returns)* - promise函数, 且参数为Location实例数组. 26 | 27 | `vscode.executeDeclarationProvider` - 执行所有的**声明**供应器函数. 28 | 29 | - *uri* - 文档的Uri 30 | - *position* - 某个符号的位置 31 | - *(returns)* - promise函数, 且参数为Location实例数组. 32 | 33 | `vscode.executeTypeDefinitionProvider` - 执行所有的**类型定义**供应器函数. 34 | 35 | - *uri* - 文档的Uri 36 | - *position* - 某个符号的位置 37 | - *(returns)* - promise函数, 且参数为Location实例数组. 38 | 39 | `vscode.executeImplementationProvider` - 执行所有的**接口**供应器函数 40 | 41 | - *uri* - 文档的Uri 42 | - *position* - 某个符号的位置 43 | - *(returns)* - promise函数, 且参数为Location实例数组 44 | 45 | `vscode.executeHoverProvider` - 执行所有的**悬停**供应器函数. 46 | 47 | - *uri* - 文档的Uri 48 | - *position* - 某个符号的位置 49 | - *(returns)* - promise函数, 且参数为Hover实例数组 50 | 51 | `vscode.executeDocumentHighlights` - 执行**文档高亮**供应器函数. 52 | 53 | - *uri* - 文档的Uri 54 | - *position* - 在文档中的位置 55 | - *(returns)* - promise函数, 且参数为DocumentHighlight实例数组 56 | 57 | `vscode.executeReferenceProvider` - 执行**引用**供应器函数 58 | 59 | - *uri* - 文档的Uri 60 | - *position* - 在文档中的位置 61 | - *(returns)* - promise函数, 且参数为Location实例数组 62 | 63 | `vscode.executeDocumentRenameProvider` - 执行**重命名**供应器函数 64 | 65 | - *uri* - 文档的Uri 66 | - *position* - 在文档中的位置 67 | - *newName* - 新的符号名称 68 | - *(returns)* - promise函数, 且参数为WorkspaceEdit 69 | 70 | `vscode.executeSignatureHelpProvider` - 执行**符号帮助**供应器函数 71 | 72 | - *uri* - 文档的Uri 73 | - *position* - 在文档中的位置 74 | - *triggerCharacter* - (可选的)当用户输入特定字符时(如`,` 或 `(`)触发符号帮助 75 | - *(returns)* - promise函数, 且参数为SignatureHelp 76 | 77 | `vscode.executeDocumentSymbolProvider` - 执行**文档符号**供应器函数 78 | 79 | - *uri* - 文档的Uri 80 | - *(returns)* - promise函数, 且参数为具有SymbolInformation和DocumentSymbol的实例数组 81 | 82 | `vscode.executeCompletionItemProvider` - 执行**自动补全**供应器函数 83 | 84 | - *uri* - 文档的Uri 85 | - *position* - 在文档中的位置 86 | - *triggerCharacter* - (可选的)当用户输入诸如(`,` `(`)之类的字符时触发 87 | - *itemResolveCount* - (可选的)补全的符号数量(数目太大会减慢补全速度) 88 | - *(returns)* - promise函数, 且参数为CompletionList实例 89 | 90 | `vscode.executeCodeActionProvider` - 执行**代码操作小灯泡提示**供应器函数 91 | 92 | - *uri* - 文档的Uri 93 | - *range* - 在文档中的范围 94 | - *(returns)* - promise函数, 且参数为Command实例数组 95 | 96 | `vscode.executeCodeLensProvider` - 执行**CodeLens**供应器函数 97 | 98 | - *uri* - 文档的Uri 99 | - *itemResolveCount* - (可选的)需要解析的lenses数量, 数目太大会影响性能 100 | - *(returns)* - promise函数, 且参数为CodeLens实例数组 101 | 102 | `vscode.executeFormatDocumentProvider` - 执行**格式化文档**供应器函数 103 | 104 | - *uri* - 文档的Uri 105 | - *options* - 配置项 106 | - *(returns)* - promise函数, 且参数为TextEdits数组 107 | 108 | `vscode.executeFormatRangeProvider` - 执行**局部格式化**供应器函数 109 | 110 | - *uri* - 文档的Uri 111 | - *range* - 限制的范围 112 | - *options* - 配置项 113 | - *(returns)* - promise函数, 且参数为TextEdits数组 114 | 115 | `vscode.executeFormatOnTypeProvider` - 执行**格式化文档**供应器函数 116 | 117 | - *uri* - 文档的Uri 118 | - *position* - 在文档中的位置 119 | - *ch* - 在输入某个字符之后进行格式化 120 | - *options* - 配置项 121 | - *(returns)* - promise函数, 且参数为TextEdits数组 122 | 123 | `vscode.executeLinkProvider` - 执行**文档链接**供应器函数 124 | 125 | - *uri* - 文档的Uri 126 | - *(returns)* - promise函数, 且参数为DocumentLink实例数组 127 | 128 | `vscode.executeDocumentColorProvider` - 执行**文档颜色**供应器函数 129 | 130 | - *uri* - 文档的Uri 131 | - *(returns)* - promise函数, 且参数为ColorInfomation对象数组 132 | 133 | `vscode.executeColorPresentationProvider` - 执行**色彩呈现**供应器函数 134 | 135 | - *color* - 需要展示并插入的颜色 136 | - *context* - 上下文对象, 包括uri和影响范围 137 | - *(returns)* - promise函数, 且参数为ColorPresentation对象数组 138 | 139 | `vscode.openFolder` - 在当前窗口或者新的窗口打开一个文件夹或者工作区 140 | 141 | - *uri* - 被打开的文件夹或工作区Uri. 如果未提供, 会打开一个询问提示框 142 | - *newWindow* - (可选的)是否在新窗口打开. 默认在本窗口 143 | 144 | !> **注意:** 在当前窗口打开, 如果未设置`newWindow = true`, 会在指定的工作区或者文件夹开启新的拓展主机进程, 并且关闭当前拓展主机进程. 145 | 146 | `vscode.diff` - 在diff编辑器中打开指定资源以比较它们的内容 147 | 148 | - *left* diff编辑器左边的文件 149 | - *right* diff编辑器右边的文件 150 | - *title* (可选)diff编辑器标题 151 | - *options* (可选)编辑器配置项, 参考`vscode.TextDocumentShowOptions` 152 | 153 | `vscode.open` - 在编辑器打开指定文件 154 | 155 | - *resource* - 要打开的文件 156 | - *columnOrOptions* - (可选)可以是要打开的编辑器列,也可以是编辑器选项,参考`vscode.TextDocumentShowOptions` 157 | 158 | 可以是文本文件、二进制文件、http(s) url. 如果需要更多的配置项, 使用`vscode.window.showTextDocument`代替. 159 | 160 | `vscode.removeFromRecentlyOpened` - 在最近打开的列表中移除一个路径 161 | 162 | - *path* - 被移除的路径 163 | 164 | `vscode.setEditorLayout` - 设置编辑器布局 165 | 166 | - *layout* - 被设置的布局 167 | 168 | 布局是一个对象,带有初始布局方向(可选,0 = 水平布局,1 = 垂直布局),还有一个包含编辑器组的数组。每个编辑器组又有一个尺寸和另一个数组,其中有矩形布局和方向信息。如果设置了编辑器组的大小,每一行或者每一列的总和必须为1。比如一个2x2的网格:`{ orientation: 0, groups: [{ groups: [{}, {}], size: 0.5 }, { groups: [{}, {}], size: 0.5 }] }` 169 | 170 | `cursorMove` - 移动光标到视图的合理位置 171 | 172 | - *Cursor move argument object* 173 | 174 | 可以传递的键值对 175 | 176 | - 'to': 必选, 鼠标要移动到的合理位置 177 | ``` 178 | 'left', 'right', 'up', 'down' 179 | 'wrappedLineStart', 'wrappedLineEnd', 'wrappedLineColumnCenter' 180 | 'wrappedLineFirstNonWhitespaceCharacter', 'wrappedLineLastNonWhitespaceCharacter' 181 | 'viewPortTop', 'viewPortCenter', 'viewPortBottom', 'viewPortIfOutside' 182 | ``` 183 | - 'by': 移动的单位. 默认根据'to'来计算. 184 | ``` 185 | 'line', 'wrappedLine', 'character', 'halfLine' 186 | ``` 187 | - 'value': 单位步数. 默认为'1'. 188 | - 'select': 如果为'true'则会选中. 默认为'false'. 189 | 190 | `editorScroll` - 编辑器滚动方向 191 | 192 | - *Editor scroll argument object* 193 | 194 | 可以传递的键值对 195 | 196 | - 'to': 必须的. 方向值 197 | ``` 198 | 'up', 'down' 199 | ``` 200 | - 'by': 移动的单位. 默认根据'to'来计算. 201 | ``` 202 | 'line', 'wrappedLine', 'page', 'halfPage' 203 | ``` 204 | - 'value': 单位步数. 默认为'1'. 205 | - 'revealCursor': 如果为'true', 在超出滚动视图也会显示光标. 206 | 207 | `revealLine` - 在给定的位置显示行 208 | 209 | - *Reveal line argument object* 210 | 211 | 可以传递的键值对 212 | 213 | - 'lineNumber': 必须的. 行号 214 | - 'at': 显示的合理位置 215 | ``` 216 | 'top', 'center', 'bottom' 217 | ``` 218 | 219 | `editor.unfold` - 展开编辑器内容 220 | 221 | - *Unfold editor argument* 222 | 223 | 可以传递的键值对 224 | 225 | - 'levels': 展开的层级数. 默认为 1. 226 | - 'direction': 如果是'up', 向上展开, 否则向下展开 227 | - 'selectionLines': 要使用展开功能的起始行(从0起)。如果不设置,就会使用当前激活的行(选中区). 228 | 229 | `editor.fold` - 折叠编辑器内容 230 | 231 | - `Fold editor argument` 232 | 233 | 可以传递的键值对 234 | 235 | - 'levels': 折叠的的层级数。默认为1 236 | - 'direction': 如果设置为'up',向上折叠,不然向下折叠 237 | - 'selectionLines': 要使用折叠功能的起始行(从0起)。如果不设置,就会使用当前激活的行(选中区) 238 | 239 | `editor.action.showReferences` - 在文件中显示引用 240 | 241 | - *uri* - 要显示引用的文件 242 | - *position* - 要显示的位置 243 | - *locations* - 位置数组 244 | 245 | `moveActiveEditor` - 通过标签或者组移动激活的编辑器 246 | 247 | - *Active editor move argument* 248 | 249 | 参数 250 | 251 | - 'to': String. 目标位置 252 | - 'by': String. 移动的单位(通过标签或者组). 253 | - 'value': Number. 要移动的位置或者绝对位置值 254 | 255 | ## 简单命令 256 | 257 | 简单的命令不需要参数, 可以在`keybindings.json`的**键盘快捷方式**列表中找到. 在文件底部的注释块中列出了未绑定的命令. 258 | 259 | 查看`keybindings.json`: 260 | 261 | Windows, Linux: **文件** > **首选项** > **键盘快捷方式** > `keybindings.json` 262 | 263 | macOS: **编码** > **首选项** > **键盘快捷方式** > `keybindings.json` -------------------------------------------------------------------------------- /docs/extension-authoring/example-hello-world.md: -------------------------------------------------------------------------------- 1 | # 示例:Hello World 2 | 3 | ## 你的第一个插件 4 | --- 5 | 本节通过Hello World这个完整的项目手把手教你掌握VS Code扩展性概念。 6 | 在本项目中,我们会给VS Code添加一个新的命令,虽然只是用来显示"Hello World"信息。在本节的最后,你将和编辑器编辑器互动,查找用户选中的文本。 7 | #### 预备工作 8 | 请查看[生成插件-预备工作](/extension-authoring/extension-generator?id=预先准备) 9 | 10 | #### 生成新插件 11 | 请查看[生成插件-运行Yo](/extension-authoring/extension-generator?id=运行yo-code😎) 12 | ## 运行插件 13 | --- 14 | - 打开VS Code,选择`文件`>`打开文件夹`,选择你刚刚生成的项目目录 15 | - 点击`F5`或者`Debug`按钮,然后点击`开始` 16 | - 新的VS Code实例会运行在特殊环境中(`Extension Development Host` 17 | - 按下`⇧⌘P`(windows `shift + ctrl + p`),输入命令`Hello world` 18 | - 恭喜!你的第一个VS Code插件执行成功了 19 | 20 | ![](https://raw.githubusercontent.com/Microsoft/vscode-docs/master/docs/extensions/images/example-hello-world/running.png) 21 | ## 插件的目录结构 22 | --- 23 | 24 | 构建完毕之后,你的插件开发目录看起来应该是这样的 25 | ``` 26 | . 27 | ├── .gitignore 28 | ├── .vscode // VS Code 文件 29 | │ ├── launch.json 30 | │ ├── settings.json 31 | │ └── tasks.json 32 | ├── .vscodeignore // 发布插件时忽略的文件 33 | ├── README.md 34 | ├── src 35 | │ └── extension.ts // 插件的入口(源文件) 36 | ├── test // 测试文件夹 37 | │ ├── extension.test.ts // extension.test.js, 如果是 JavaScript 插件的话 38 | │ └── index.ts // index.js, 如果是 JavaScript 插件的话 39 | ├── node_modules 40 | │ ├── vscode // 包含了vscode插件开发时的类型定义文件 41 | │ └── typescript // typescript的编译器 (TypeScript only) 42 | ├── out // 编译出口 (TypeScript only) 43 | │ ├── extension.js // 插件入口 44 | │ ├── extension.js.map 45 | │ └── test 46 | │ ├── extension.test.js 47 | │ ├── extension.test.js.map 48 | │ ├── index.js 49 | │ └── index.js.map 50 | ├── package.json // 插件清单 51 | ├── tsconfig.json // jsconfig.json, 如果是 JavaScript 插件的话 52 | └── vsc-extension-quickstart.md // 快速上手插件开发 53 | ``` 54 | 让我们看看这些文件夹都是干什么用的: 55 | #### 插件清单:`package.json` 56 | - 每个VS Code插件都有`package.json`文件,文件内包含了这个插件功能和用处。 57 | - 当项目启动时,VS Code会立即读取这个文件中的每个`配置(contributes)`部分并作出响应。 58 | - 请阅读[package.json插件清单](/extensibility-reference/extension-manifest.md)参考文档 59 | - 更多信息请参阅[package.json发布内容配置](/extensibility-reference/contribution-points.md)参考文档 60 | 61 | ?> 译者注:为了便于理解,`contribution / contributes`在本教程中译为**发布内容配置/配置**,`contribution points`译为**发布内容配置点/配置点**。 62 | 63 | **示例:基于TypeScript的pacakge.json** 64 | 65 | ```json 66 | { 67 | "name": "myFirstExtension", 68 | "description": "", 69 | "version": "0.0.1", 70 | "publisher": "", 71 | "engines": { 72 | "vscode": "^1.5.0" 73 | }, 74 | "categories": [ 75 | "Other" 76 | ], 77 | "activationEvents": [ 78 | "onCommand:extension.sayHello" 79 | ], 80 | "main": "./out/extension", 81 | "contributes": { 82 | "commands": [{ 83 | "command": "extension.sayHello", 84 | "title": "Hello World" 85 | }] 86 | }, 87 | "scripts": { 88 | "vscode:prepublish": "tsc -p ./", 89 | "compile": "tsc -watch -p ./", 90 | "postinstall": "node ./node_modules/vscode/bin/install", 91 | "test": "node ./node_modules/vscode/bin/test" 92 | }, 93 | "devDependencies": { 94 | "typescript": "^2.0.3", 95 | "vscode": "^1.5.0", 96 | "mocha": "^2.3.3", 97 | "@types/node": "^6.0.40", 98 | "@types/mocha": "^2.2.32" 99 | } 100 | } 101 | ``` 102 | !> 提示: 基于JavaScript的插件没有scripts部分,因为不需要编译。 103 | 104 | 这份`package.json`文件说了什么呢? 105 | - **配置部分(contributes)**给*命令面板*定义了一个叫做`Hello world`的入口,它会调用'extension.sayHello'。 106 | - 当命令"extension.sayHello"调用时,执行`loaded`(激活事件)请求。 107 | - 在"`./out/extension.js`"中,存放着我们的主文件。 108 | 109 | !> 注意:VS Code **不会一启动就加载插件**。插件必须在`activationEvents`中描述它的启动时机,比如`loaded`事件。 110 | #### 生成的代码 111 | 自动生成的代码存放在**extension.ts**(或者**extension.js**中)。 112 | ```typescript 113 | // 'vscode'模块包含了VS Code extensibility API 114 | // 按下述方式导入这个模块 115 | import * as vscode from 'vscode'; 116 | 117 | // 一旦你的插件激活,vscode会立刻调用下述方法 118 | export function activate(context: vscode.ExtensionContext) { 119 | 120 | // 用console输出诊断信息(console.log)和错误(console.error) 121 | // 下面的代码只会在你的插件激活时执行一次 122 | console.log('Congratulations, your extension "my-first-extension" is now active!'); 123 | 124 | // 入口命令已经在package.json文件中定义好了,现在调用registerCommand方法 125 | // registerCommand中的参数必须与package.json中的command保持一致 126 | let disposable = vscode.commands.registerCommand('extension.sayHello', () => { 127 | // 把你的代码写在这里,每次命令执行时都会调用这里的代码 128 | // ... 129 | // 给用户显示一个消息提示 130 | vscode.window.showInformationMessage('Hello World!'); 131 | }); 132 | 133 | context.subscriptions.push(disposable); 134 | } 135 | ``` 136 | - 每个插件都应该在主文件中注册一个`activate()`函数,因为这个函数只会调用一次。你只有`在package.json`中注册了`activationEvents`列表中的事件,激活事件才会被调用。 137 | - 如果插件使用了系统资源(如:生成进程),则需要从主文件中导出名为`deactive()`的函数去清理释放这些资源,VS Code会在关闭时调用这个方法。 138 | - 这个插件导入了VS Code API,然后注册了"extension.sayHello"命令和回调函数,执行后在VS Code中显示一条"Hello World!"消息。 139 | 140 | !> 注意: `package.json`的`contributes`部分给*命令面板*添加了一个调用入口。`extension.ts/.js`定义了`extension.sayHello`的实现。对于 Typescript类型的插件来说,生成的`out/extension.js`会在运行时加载。 141 | #### 其他文件 142 | - `vscode/launch.json` 告诉VS Code启用插件开发模式。它也描述了`.vscode/tasks.json`中需要Typescript编译器的预加载任务。 143 | - `vscode/settings.json` 默认排除外部文件夹。你如果想隐藏一些文件,可以修改这个配置。 144 | - `gitignore` - 告诉git不跟踪哪些文件。 145 | - `vscodeignore` - 告诉打包工具,发布插件时应该忽略哪些文件。 146 | - `README.md` - 为插件的使用用户提供良好的文档。 147 | - `vsc-extension-quickstart.md` - 你的快速开始指南。 148 | - `test/extension.test.ts` - 把你的单元测试放在这里,看看和VS Code API有哪些出入。 149 | ## 插件激活过程 150 | --- 151 | 我们刚刚已经了解了开发目录下的每个文件,现在我们看看你的插件是怎么运行起来的: 152 | 1. 插件开发环境发现了这个插件,然后读取它的`package.json` 153 | 2. 你按下`ctrl shift p`时,*命令面板*显示出已注册的命令列表 154 | 3. 在列表中你找到`package.json`中定义的`Hello world`命令入口 155 | 4. 选中并执行`Hello world`,随即执行真实的"`extension.sayHello`"命令 156 | - 创建`"onCommand:extension.sayHello"`激活事件 157 | - 激活所有注册在`activationEvents`的事件 158 | - Javascript虚拟机加载`./out/extension.js`文件 159 | - VS Code查找导出的`activate`函数,并调用 160 | 5. 调用`"extension.sayHello"`注册的函数 161 | 6. 函数执行,显示出"Hello world"消息 162 | ## 调试插件 163 | --- 164 | 直接在你的代码里打上断点就可以调试了,很简单吧。 165 | 166 | ![调试](https://raw.githubusercontent.com/Microsoft/vscode-docs/master/docs/extensions/images/example-hello-world/hitbp.png) 167 | 168 | !> 注意:VS Code具有解析sourcemap的能力,所以你可以直接在Typescript代码中调试。 169 | 170 | ?>小提示:调试控制台(Debug Console)能输出所有console打印的日志。 171 | 172 | 查看更多关于插件[开发环境](/extension-authoring/developing-extensions.md)的东西。 173 | ## 小小的改造 174 | --- 175 | 试着修改你的`extension.ts`(或者`extension.js`)中`extension.sayHello`的实现,我们把它改造成一个对选中文本计数的功能。 176 | ```typescript 177 | let disposable = vscode.commands.registerCommand('extension.sayHello', () => { 178 | // 每当你执行命令,这里的代码都会执行一次 179 | 180 | let editor = vscode.window.activeTextEditor; 181 | if (!editor) { 182 | return; // 没有打开的编辑器 183 | } 184 | 185 | let selection = editor.selection; 186 | let text = editor.document.getText(selection); 187 | 188 | // 给用户一个消息提示框 189 | vscode.window.showInformationMessage('Selected characters: ' + text.length); 190 | }); 191 | ``` 192 | !> 当你修改了代码,你需要按Ctrl + R(macOS Cmd + R)重启Extension Development Host,或者直接按VS Code上面的重启按钮 193 | 194 | 新建一个文件,输入一些文本然后选中。当你运行**Hello World**命令,你应该能看到字符计数的消息框。 195 | 196 | ![文字计数](https://raw.githubusercontent.com/Microsoft/vscode-docs/master/docs/extensions/images/example-hello-world/selection-length.png) 197 | ## 在本地安装你的插件 198 | --- 199 | 好了,现在你已经完成了一个运行在开发模式下的插件,为了让你的插件运行在所有VS Code实例中,你需要在本地插件目录下新建一个文件夹,然后复制过去: 200 | - Windows: `%USERPROFILE%\.vscode\extensions` 201 | - macOS/Linux: `$HOME\.vscode\extensions` 202 | 203 | ## 发布插件 204 | --- 205 | 参阅[分享插件](/extension-authoring/publish-extension.md) 206 | ## 下一步 207 | --- 208 | 在本篇指引中,我们实现了一个小小的插件。在[示例-Word Count](docs/extension-authoring/example-word-count.md)中你能找到完整的例子,学习如何在Markdown文件中监听编辑器的文档变动事件、显示文本字数。 209 | 210 | 如果你想查看更多extension API的概述,看看这些主题吧: 211 | - [Extension API 概览](/extensibility-reference/overview.md) - 了解完整的VS Code扩展性模型。 212 | - [API原则和模式](/extensibility-reference/principles-patterns.md) - VS Code的扩展性基于这些指导性原则和模式。 213 | - [发布内容配置](/extensibility-reference/contribution-points.md) - 各种各样的VS Code发布内容配置项 214 | - [激活事件](/extensibility-reference/activation-events.md) - VS Code激活事件参考 215 | - [更多插件示例](/extension-authoring/samples.md) - 看看我们的插件示例列表 -------------------------------------------------------------------------------- /docs/extension-authoring/example-word-count.md: -------------------------------------------------------------------------------- 1 | # 示例 Word Count 2 | 3 | 如果你还没有接触过[你的第一个插件](/extension-authoring/example-hello-world.md)章节,我们建议你先去了解一下。 4 | 5 | 本篇示例将会告诉你,如何制作一个Markdown辅助编辑工具。开始之前,我们先了解一下本篇你将接触到的插件功能:当编辑Makrdown文件时状态栏会显示编辑区字数,如果你编辑文档或者打开了另一个md文件字数也会随之改变。 6 | 7 | ![](https://raw.githubusercontent.com/Microsoft/vscode-docs/master/docs/extensions/images/example-word-count/wordcountevent2.gif) 8 | 9 | ?> 小贴士:如果你碰到了什么问题,可以在这里[下载完整的项目](https://github.com/microsoft/vscode-wordcount)进行调试 10 | 11 | ## 本节要点 12 | 本章将通过三个部分让你了解vscode有关的概念: 13 | - [更新状态栏](#更新状态栏) - 在*状态栏*中显示自定义文本 14 | - [订阅事件](#订阅事件) - 通过编辑器事件更新*状态栏* 15 | - [释放插件资源](#释放插件资源) - 比如:释放事件订阅和UI回调函数 16 | 17 | 如果你还不熟悉生成插件的步骤,请先了解之前的章节:[生成插件-运行Yo](/extension-authoring/extension-generator?id=运行yo-code😎) 18 | 19 | 就像你之前在[示例:Hello-world](/extension-authoring/example-hello-world.md)中做的一样,使用`F5`或者`Cmd + R`运行该项目。 20 | 21 | ## 更新状态栏 22 | --- 23 | 将下列代码更新到`extension.ts`中。这段代码声明了一个`WordCounter`类用于控制文本计数并显示到状态栏中,我们依然用了"Hello World"这个命令来执行`updateWordCount`。 24 | 25 | ```typescript 26 | // 'vscode'模块包含了VS Code扩展性API 27 | // 导入你要用到的扩展类 28 | import { 29 | window, 30 | commands, 31 | Disposable, 32 | ExtensionContext, 33 | StatusBarAlignment, 34 | StatusBarItem, TextDocument 35 | } from 'vscode'; 36 | 37 | // 当你的插件激活时,会调用这个方法。'activation'是package.json中定义好的activation events 38 | export function activate(context: ExtensionContext) { 39 | 40 | // 用console对象输出诊断和错误信息(console.log / console.error). 41 | // 下面这行代码,只会在你的插件激活时执行一次 42 | console.log('Congratulations, your extension "WordCount" is now active!'); 43 | 44 | // 新建一个字数计数器 45 | let wordCounter = new WordCounter(); 46 | let disposable = commands.registerCommand('extension.sayHello', () => { 47 | wordCounter.updateWordCount(); 48 | }); 49 | 50 | // 把disposables添加到一个列表中,以便关闭插件时释放资源 51 | context.subscriptions.push(wordCounter); 52 | context.subscriptions.push(disposable); 53 | } 54 | 55 | class WordCounter { 56 | private _statusBarItem: StatusBarItem = window.createStatusBarItem(StatusBarAlignment.Left); 57 | 58 | public updateWordCount() { 59 | 60 | // 获取当前编辑器 61 | let editor = window.activeTextEditor; 62 | if (!editor) { 63 | this._statusBarItem.hide(); 64 | return; 65 | } 66 | 67 | let doc = editor.document; 68 | 69 | // 只对markdown文件生效 70 | if (doc.languageId === "markdown") { 71 | let wordCount = this._getWordCount(doc); 72 | 73 | // 更新状态栏 74 | this._statusBarItem.text = wordCount !== 1 ? `${wordCount} Words` : '1 Word'; 75 | this._statusBarItem.show(); 76 | } else { 77 | this._statusBarItem.hide(); 78 | } 79 | } 80 | 81 | public _getWordCount(doc: TextDocument): number { 82 | let docContent = doc.getText(); 83 | 84 | // 去除多余空格 85 | docContent = docContent.replace(/(< ([^>]+)<)/g, '').replace(/\s+/g, ' '); 86 | docContent = docContent.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); 87 | let wordCount = 0; 88 | if (docContent !== "") { 89 | wordCount = docContent.split(" ").length; 90 | } 91 | return wordCount; 92 | } 93 | 94 | dispose() { 95 | this._statusBarItem.dispose(); 96 | } 97 | } 98 | ``` 99 | 100 | 现在让我们试试更新插件吧。 101 | 102 | 在VS Code中(非开发主机窗口)按下`F5`或者直接按重启按钮。假设你已经打开了一个markdown文件,然后和Hello-World示例一样,我们在*命令面板*中输入`Hello World`启动插件。 103 | 104 | ![](https://github.com/Microsoft/vscode-docs/raw/master/docs/extensions/images/example-word-count/wordcount2.png) 105 | 106 | 很棒,我们接下来做更cool的事情——实时更新字数。 107 | 108 | ## 订阅事件 109 | --- 110 | 111 | 我们先来看看事件中的类方法: 112 | - `onDidChangeTextEditorSelection` - 鼠标位置变动时触发。 113 | - `onDidChangeActiveTextEditor` - 激活编辑器(打开的编辑器)切换的时候触发。 114 | 115 | 为了实现这个目标,我们给`extension.ts`添加一个新类,订阅上述事件然后让`WordCounter`更新字数。 116 | 117 | ?>在实现时,你需要注意我们是如何把**消息订阅( subscription )**转换为**释放器( Disposables )**来管理的,它将监听并释放自己。 118 | 119 | 根据下列代码,将`WordCounterController`类添加到`extension.ts`文件底部。 120 | ```typescript 121 | class WordCounterController { 122 | 123 | private _wordCounter: WordCounter; 124 | private _disposable: Disposable; 125 | 126 | constructor(wordCounter: WordCounter) { 127 | this._wordCounter = wordCounter; 128 | 129 | // 订阅 文本选区变更 和 编辑器激活事件 130 | let subscriptions: Disposable[] = []; 131 | window.onDidChangeTextEditorSelection(this._onEvent, this, subscriptions); 132 | window.onDidChangeActiveTextEditor(this._onEvent, this, subscriptions); 133 | 134 | // 为当前文件更新计数器 135 | this._wordCounter.updateWordCount(); 136 | 137 | // 把两个事件订阅器整合成一个临时容器 138 | this._disposable = Disposable.from(...subscriptions); 139 | } 140 | 141 | dispose() { 142 | this._disposable.dispose(); 143 | } 144 | 145 | private _onEvent() { 146 | this._wordCounter.updateWordCount(); 147 | } 148 | } 149 | ``` 150 | 151 | 我们不希望通过执行命令才启动词汇计数插件,而是markdown文件一打开插件就应该启动。 152 | 153 | 首先,我们将`active`函数替换成这样: 154 | ```typescript 155 | // 输出诊断信息 156 | console.log('Congratulations, your extension "WordCount" is now active!'); 157 | 158 | // 新建一个词汇计数器 159 | let wordCounter = new WordCounter(); 160 | let controller = new WordCounterController(wordCounter); 161 | 162 | // 插件关闭时,释放器会自动释放 163 | context.subscriptions.push(controller); 164 | context.subscriptions.push(wordCounter); 165 | ``` 166 | 167 | 然后,我们必须保证`Markdown`文件打开时才激活。在之前的示例中,我们通过`extension.sayHello`命令激活插件,而我们现在用不到了,删除`package.json`文件中原来的`contributes`键。 168 | ```json 169 | "contributes": { 170 | "commands": 171 | [{ 172 | "command": "extension.sayHello", 173 | "title": "Hello World" 174 | } 175 | ] 176 | } 177 | ``` 178 | 用下面的代码替换掉: 179 | ```json 180 | "activationEvents": [ 181 | "onLanguage:markdown" 182 | ] 183 | ``` 184 | 为[onLanguage: ${language}]()配置一个语言,在这里是"markdown" 。这样一来打开这一类文件就会触发这个事件了。 185 | 186 | 重启插件(按下`Cmd + R`或者重启按钮),然后新建一个`.md`文件,你应该能看到下图的效果。 187 | 188 | ![](https://raw.githubusercontent.com/Microsoft/vscode-docs/master/docs/extensions/images/example-word-count/wordcountevent2.gif) 189 | 190 | 如果你在`active`函数上打了断点,你应该能看到markdown文件被打开时只触发了一次。`WordCountController`构造器运行之后,订阅了编辑器事件,这样我们整个插件就正常运行了。 191 | 192 | ## 自定义状态栏 193 | --- 194 | 195 | VS Code允许你定制状态栏的颜色、图标、提示文本等额外样式。如果你不清楚**状态栏**相关的API,你可以查看该类型的代码提示,你也可以通过`vscode.d.ts`VS Code扩展性API查看,这个文件就在你生成的项目文件夹里,在编辑器中打开`node_modules\vscode\vscode.d.ts`,你能看到完整的扩展性 API和注释。 196 | 197 | ![](https://raw.githubusercontent.com/Microsoft/vscode-docs/master/docs/extensions/images/example-word-count/vscode-d-ts.png) 198 | 199 | 更新StatusBarItem接口的代码 200 | ```typescript 201 | // 更新状态栏 202 | this._statusBarItem.text = wordCount !== 1 ? `$(pencil) ${wordCount} Words` : '$(pencil) 1 Word'; 203 | this._statusBarItem.show(); 204 | ``` 205 | 这样就在计数左边显示了一个[Github Oction](https://octicons.github.com/)的`pencil`图标 206 | 207 | ![](https://raw.githubusercontent.com/Microsoft/vscode-docs/master/docs/extensions/images/example-word-count/wordcount-pencil.png) 208 | 209 | ## 释放插件资源 210 | --- 211 | 212 | 现在,我们来深入了解一下VS Code是怎么通过[释放器(Disposables)](/extensibility-reference/principles-patterns?id=disposables(释放器))控制资源的。 213 | 214 | 当一个插件被激活,它会传入一个`ExtensionContext`对象, 这个对象有一个用于订阅释放器(Disposable)的`subscriptions`方法。插件将=释放器添加到这个订阅列表中,VS Code则会在插件关闭的时候释放这些对象。 215 | 216 | 很多能生成工作区(workspace)或者UI对象的VS Code API(比如:`registerCommand`)会自动返回一个释放器,我们可以直接调用他们的dispose方法释放UI元素。 217 | 218 | 事件则有所不同,比如`onDid*`这类事件订阅器会返回一个释放器。插件通过释放事件的释放器(Disposable)来取消已经订阅的事件。在我们的例子里,`WordCountController`把事件订阅的释放器直接保存到自己的释放器列表中,在插件关闭时释放。 219 | ```typescript 220 | // 订阅选区变动事件和编辑器激活事件 221 | let subscriptions: Disposable[] = []; 222 | window.onDidChangeTextEditorSelection(this._onEvent, this, subscriptions); 223 | window.onDidChangeActiveTextEditor(this._onEvent, this, subscriptions); 224 | 225 | // 把两个事件订阅器生成一个组合的临时容器 226 | this._disposable = Disposable.from(...subscriptions); 227 | ``` 228 | ## 在本地安装你的插件 229 | --- 230 | 231 | 到目前为止,你的插件都还跑在插件开发模式中,要想让你的插件在正常的VS Code中运行起来将你的插件复制到`.vscode/extensions`目录下。 232 | 233 | ## 发布插件 234 | --- 235 | 236 | 参阅[分享插件](/extension-authoring/publish-extension.md) 237 | 238 | ## 下一步 239 | 240 | [插件生成器](/extension-authoring/extension-generator.md) - 学习Yo Code插件生成器的更多选项 241 | 242 | [Extenstion API](/extensibility-reference/overview.md) - 插件API概览 243 | 244 | [发布插件](/extension-authoring/publish-extension.md) - 学会如何在应用市场发布一个公共插件 245 | 246 | [编辑器 API](/extensibility-reference/vscode-api.md) - 学习更多有关文档, 文档编辑器和编辑的内容 247 | 248 | [更多插件示例](/extension-authoring/samples.md) - 在插件示例列表学习其他用法 -------------------------------------------------------------------------------- /docs/references/extension-guidelines.md: -------------------------------------------------------------------------------- 1 | # 插件开发准则 2 | 3 | ## 架构 4 | 5 | VS Code UI 包含了两类元素:容器和容器项。容器是指视图的顶层层级,它包括: 6 | 7 | ![Overview of Visual Studio Code containers elements](https://code.visualstudio.com/assets/api/references/guidelines/architecture-groups.png) 8 | 9 | 1. 活动栏([Activiti Bar](/references/extension-guidelines#视图容器)) 10 | 2. 侧边栏(Sidebar) 11 | 3. 编辑器(Editor) 12 | 4. 面板(Panel) 13 | 5. 状态栏(Status Bar) 14 | 15 | 容器项则在容器的内部,他们的种类就很丰富了: 16 | 17 | ![Overview of Visual Studio Code item elements](https://code.visualstudio.com/assets/api/references/guidelines/architecture-sections.png) 18 | 19 | 1. 视图容器(View Container) 20 | 2. 视图([View](/references/extension-guidelines#视图)) 21 | 3. 视图工具区(View Toolbar) 22 | 4. 侧边栏工具区(Sidebar Toolbar) 23 | 5. 编辑器工具区(Editor Toolbar) 24 | 6. 面板工具区(Pannel Toolbar) 25 | 7. 状态栏项([Status Bar Item](/references/extension-guidelines#状态栏)) 26 | 27 | 28 | ## 通知框 29 | 30 | [通知框](/extension-capabilities/common-capabilities#display-notifications) 会从 VS Code 右下角弹出,它可以展示一些简要的信息。你能够设置的通知类型有三种: 31 | 32 | - [信息提示](https://code.visualstudio.com/api/references/vscode-api#window.showInformationMessage) 33 | - [警告提示](https://code.visualstudio.com/api/references/vscode-api#window.showWarningMessage) 34 | - [错误提示](https://code.visualstudio.com/api/references/vscode-api#window.showErrorMessage) 35 | 36 | 不要过多地发送通知,以免分散用户的注意力。 37 | 38 | ![Information notification](https://code.visualstudio.com/assets/api/references/guidelines/notification-info.png) 39 | 40 | *这条通知是用户**更新版本**后弹出的,注意这个通知中仅仅展示了信息不含任何操作。* 41 | 42 | ![Warning notification](https://code.visualstudio.com/assets/api/references/guidelines/notification-warning.png) 43 | 44 | *这个例子中带有一个黄色的高亮警告,附带 3 个按钮——它要求用户进行介入处理。* 45 | 46 | ![Error notification](https://code.visualstudio.com/assets/api/references/guidelines/notification-error.png) 47 | 48 | *这个例子是无操作的错误通知。* 49 | 50 | ✔建议 51 | - 发送通知的时候不要过分吸引用户的注意力 52 | - 为每个通知添加 **不要再提示** 按钮 53 | - 短时间内只提示一次 54 | 55 | ❌ 不要 56 | - 发送重复通知 57 | - 用于促销广告 58 | - 插件首次安装后用户收集用户反馈 59 | - 没有必要的操作还硬加按钮 60 | 61 | ### 进度通知 62 | 63 | 当你需要展示一个不知何时才能完成的任务进度时(比如:初始化环境),你可以使用进度通知。这种类型的通知应该作为当前上下文(在视图或者编辑器内)处理进度通知类型的最后手段。 64 | 65 | ✔建议 66 | - 提供一个查看详情的链接(比如进度日志) 67 | - 处理过程中给出信息(比如:初始化、构建,等等) 68 | - 提供取消操作(如果可用的话) 69 | - 如果有超时场景,提供倒计时 70 | 71 | ❌ 不要 72 | - 不销毁进度通知 73 | 74 | ![Progress notification](https://code.visualstudio.com/assets/api/references/guidelines/notification-progress.png) 75 | 76 | *这个例子演示了远程连接初始化时的进度通知,它同时也提供了输出日志(details)* 77 | 78 | ## 视图 79 | 80 | [视图](/references/contribution-points#contributesviews)是内容的容器,它们会出现在注入侧边栏或者面板这样的地方。视图可以包含树视图或者自定义视图,这些视图可以包含视图操作。视图可被用户调整位置,比如放到其他视图、活动栏和面板中。请控制你的视图数量以便其他插件的视图还有空间展示。 81 | 82 | ✔建议 83 | - 如果可以的话,使用现有的图标 84 | - 为语言文件使用文件图标 85 | - 用树视图展示数据 86 | - 为每个视图提供活动栏图标 87 | - 控制视图数量最小化 88 | - 控制名称长度最小化 89 | - 克制地使用自定义 webview 视图 90 | 91 | ❌ 不要 92 | - 对已有功能重新造轮子 93 | - 使用树视图项作为唯一的操作入口(如,搜索栏) 94 | - 非必要的情况下也使用自定义 webview 95 | - 在编辑器中使用视图容器装载 webview 96 | 97 | ![Views example](https://code.visualstudio.com/assets/api/references/guidelines/views-example.png) 98 | 99 | *这个例子使用了树视图展示一组测试的测试状态。每种测试结果都有其唯一图标类型与之对应。* 100 | 101 | ### 视图位置 102 | 103 | 视图可被放在[现有的视图容器](/references/contribution-points#contributesviews)中,比如文件管理器、源管理器(SCM)和调试视图容器中。你也可以在活动栏中添加自定义视图容器,然后再往里添加视图。另外,视图可被添加到任何面板或者他们自己所属的自定义视图容器中。 104 | 105 | ![View locations](https://code.visualstudio.com/assets/api/references/guidelines/views-locations.png) 106 | 107 | ### 视图容器 108 | 109 | [视图容器](/references/contribution-points#contributesviewsContainers)是活动栏的一部分,每个容器都有其独有的图标。 110 | 111 | ![View Container](https://code.visualstudio.com/assets/api/references/guidelines/view-container.png) 112 | 113 | 这个例子用了一个边框图标来展示自定义视图容器。 114 | 115 | ### 视图中的进度条 116 | 117 | 如果你的视图在 源(SCM)视图容器中,你也可以[显示进度条](https://code.visualstudio.com/api/references/vscode-api#ProgressLocation) 118 | 119 | ### 欢迎视图 120 | 121 | 当视图没有任何内容时,你可以[添加一些内容来引导用户](/references/contribution-points#contributesviewsWelcome)如何使用你的插件。欢迎视图支持链接和图标。 122 | 123 | ✔建议 124 | - 仅在必要时使用欢迎视图 125 | - 如有需要可使用链接而不是按钮 126 | - 按钮仅用于基础性的操作 127 | - 描述清楚链接指向 128 | - 控制内容的长度 129 | - 控制欢迎视图的数量 130 | - 控制视图中的按钮数量 131 | 132 | ❌ 不要 133 | - 非必要的场景中也使用按钮 134 | - 将欢迎视图当成销售页面 135 | - 每个链接的标题都叫"查看更多" 136 | 137 | ![Welcome Views](https://code.visualstudio.com/assets/api/references/guidelines/welcome-views.png) 138 | 139 | 这个例子使用了一个基础按钮,其他视图则包含了期待用户知晓的具体文档链接。 140 | 141 | ## Webviews 142 | 如果你需要展示的自定义功能超出了VS Code API 的能力,那么你可以使用完全可定制的 [webview](/extension-guides/webview)。再次提示开发者:仅在必要时使用 webview。 143 | 144 | ✔建议 145 | - 仅在绝对必要时使用 webview 146 | - 在合适的场景中启动你的插件 147 | - 为激活窗口打开 webview 148 | - 确保视图中的所有元素都是可定制主题的(查看 [webview-view-sample](https://github.com/microsoft/vscode-extension-samples/blob/main/webview-view-sample/media/main.css)和[color tokens](/references/theme-color)文档) 149 | - 确保你的视图遵循[可访问性指南](https://code.visualstudio.com/docs/editor/accessibility)(色彩对比度、ARIA 标签、键盘导航) 150 | - 在视图的工具区使用命令操作 151 | 152 | ❌ 不要 153 | - 用于广告宣传(包括升级、捐助等等) 154 | - 作为插件的向导页面 155 | - 在所有窗口中打开 156 | - 插件升级后打开(请使用通知) 157 | - 添加和编辑器或者工作区无关的功能 158 | - 重复发明轮子(比如:欢迎页、设置、配置等等) 159 | 160 | ### 例子 161 | 162 | **浏览器预览** 163 | 这个插件在编辑器旁边打开了一个浏览器效果预览 164 | ![Weview Sample - Browser](https://code.visualstudio.com/assets/api/references/guidelines/webview-browser.png) 165 | 166 | **Pull Request** 167 | 这个插件为自定义树视图中的工作区仓库展示了一个 Pull Request 页面,它用 webview 显示了 PR 的详细信息。 168 | 169 | **初次使用培训** 170 | 这个插件打开了一个快速启动页面,它包含了有用的操作、链接和更多信息。这个 Webview 仅仅在用户首次打开特定文件时展示,帮助用户检查是否遵循了特定步骤(比如安装或创建一个文件时)。 171 | 172 | ![Webview Sample - Onboarding](https://code.visualstudio.com/assets/api/references/guidelines/webview-onboarding.png) 173 | 174 | ### webview 视图 175 | 176 | 你可以在任意视图容器(侧边栏和面板)中添加 webview,这样的 webview 被称为 [webview 视图](https://code.visualstudio.com/api/references/vscode-api#WebviewView)。它的使用方式和常规的 webview 是一样的。 177 | 178 | ![Webview View](https://code.visualstudio.com/assets/api/references/guidelines/webview-view.png) 179 | 180 | 这个 webview 视图内容展示了创建一个 PR 所需的下拉菜单、输入框和按钮。 181 | 182 | ## 状态栏 183 | 184 | [状态栏](/extension-capabilities/extending-workbench#状态栏项)位于 VS Code 工作台底部,用于展示和你的工作区相关的信息和操作。状态栏项分为两类:基础的(左)和次级的(右)。状态栏中和整个工作区(状态、问题/警告、同步状态)相关的位于左边,次级状态或者上下文相关的(语言、间距、反馈)处于右边。注意控制添加的状态栏项目数,为其他插件腾出空间。 185 | 186 | ✔建议 187 | - 使用短的文本标签 188 | - 仅在必要时使用图标 189 | - 使用语义清晰的图标 190 | - 把首要(全局)项目放在左边 191 | - 把次要(上下文)项目放在右边 192 | 193 | ❌ 不要 194 | - 添加自定义颜色 195 | - 添加的图标数量在 1 个以上(除非必要) 196 | - 添加的状态栏项数量在 1 个以上(除非必要) 197 | 198 | ![Status Bar Item](https://code.visualstudio.com/assets/api/references/guidelines/statusbar-item.png) 199 | 200 | *这个例子中,状态栏项的信息和整个工作区相关,所以展示在左边* 201 | 202 | ### 进度状态栏项目 203 | 当需要展示静默进度(进度在后台处理)时,建议用带有加载图标(你可以添加旋转动画)的状态栏项来展示。如果进度状态是需要用户注意到的,我们建议你将其提升到通知维度。 204 | 205 | ![Status Bar Progress](https://code.visualstudio.com/assets/api/references/guidelines/status-bar-progress.png) 206 | 207 | *这个例子中,状态栏展示静默进度* 208 | 209 | ### 错误状态栏项 210 | 如果你需要展示的项目出于警示目的需要高亮,你可以使用错误状态栏项。请将错误状态栏项作为特殊场景下的最后手段。 211 | ![Status Bar Error](https://code.visualstudio.com/assets/api/references/guidelines/status-bar-error.png) 212 | 213 | *这个例子中,错误状态栏项展示了文件中的代码错误* 214 | 215 | ## 快速选择 216 | 217 | [快速选择](/extension-capabilities/common-capabilities#quick-pick)是一个展示操作和接受用户输入的简易手段。在选择配置、过滤内容或者从列表中挑选项目时尤为有用。 218 | ![Quick Pick](https://code.visualstudio.com/assets/api/references/guidelines/quickpick.png) 219 | 220 | *快速选择可以包含非常多的选项。而且选项可以由图标、详情和标签组成,而且还包括默认项。在这个例子的顶部,你可以看到多步骤模式下的后退、恢复和前进等操作。* 221 | 222 | ✔建议 223 | - 使用语义清晰的图标 224 | - 使用具体的描述展示当前项(如果需要的话) 225 | - 使用详情提供额外(简短)的说明 226 | - 在需要多选输入的场景中使用多步骤模式(比如:初始化向导) 227 | - 提供一个创建更多的选项(如果需要的话) 228 | 229 | ❌ 不要 230 | - 重复造轮子 231 | - 多种选项公用一个图标 232 | - 列表中超过 6 种图标 233 | 234 | ## 编辑器操作 235 | 编辑器的工具区会展示[编辑器操作](/references/contribution-points#contributescommands)。你可以添加图标作为快速操作,或者在悬浮菜单中添加菜单项(...)。 236 | 237 | ✔建议 238 | - 在特定上下文场景中展示操作 239 | - 尽量使用内置图标库中的图标 240 | - 悬浮菜单中的项目应作为二级操作 241 | 242 | ❌ 不要 243 | - 添加多类图标 244 | - 添加自定义颜色 245 | - 使用 emoji 246 | 247 | ![Editor Actions](https://code.visualstudio.com/assets/api/references/guidelines/editor-actions.png) 248 | 249 | *仅在 HTML 页面中展示这个图标来表示加载页面预览* 250 | 251 | ## 上下文菜单 252 | 253 | [菜单项](/references/contribution-points#contributesmenus)会展示在视图、操作、右击菜单中。要额外注意菜单组中的菜单项要保持其一致性。如果你的插件操作和文件相关,请将操作配置到文件管理器菜单中(适时)。如果插件是针对特定文件类型的,请仅仅在此类场景中展示操作。 254 | 255 | ✔建议 256 | - 当场景合适时才展示操作 257 | - 相似操作分组 258 | - 一个组中的操作过多时,使用子菜单 259 | 260 | ❌ 不要 261 | - 在所有场景中都展示操作 262 | 263 | ![Context Menu](https://code.visualstudio.com/assets/api/references/guidelines/context-menu.png) 264 | 265 | *将 **Copy Github Link** 和其他复制命令放在一起。这个操作只会在 GitHub 仓库项目中可用* 266 | 267 | ## 设置 268 | 269 | [设置](/references/contribution-points#contributesconfiguration)是用户配置插件的入口。设置可以是输入框、布尔值、下拉菜单、列表、键值对。如果你的插件要求用户配置特定设置,你可以打开设置 UI 然后用设置 ID 查询你的插件设置。 270 | 271 | ✔建议 272 | - 为每项设置添加默认值 273 | - 为每项设置添加清晰的描述 274 | - 为复杂设置添加文档链接 275 | - 为相关设置添加链接 276 | - 当用户需要配置特定设置项时,提供设置 ID 链接 277 | 278 | ❌ 不要 279 | - 创建你自己的设置页面/webview 280 | - 使用超长的描述 281 | 282 | ![Settings](https://code.visualstudio.com/assets/api/references/guidelines/settings.png) 283 | 284 | *使用设置 ID 链接到特定设置项上* 285 | 286 | ## 命令面板 287 | 288 | [命令面板](/references/contribution-points#contributescommands)可以找到所有命令。注意:为你的命令使用清晰的名称和标签,便于用户查找。 289 | 290 | ✔建议 291 | - 必要时添加快捷键 292 | - 为命令添加清晰的名字 293 | - 为同类命令分组 294 | 295 | ❌ 不要 296 | - 重写已有的快捷键 297 | - 命名命令时使用 emoji 298 | 299 | ![Command Palette](https://code.visualstudio.com/assets/api/references/guidelines/command-palette.png) 300 | 301 | *命令被分组到 "Debug" 类目中, 而且每个命令都有清晰的名字,少部分命令有其快捷键* --------------------------------------------------------------------------------