构建 Visual Studio Code 扩展
Visual Studio Code 扩展开发
Visual Studio Code 扩展开发
我不喜欢帖子里长篇大论的介绍,因为你知道自己来这里的原因,不需要那些废话。我们直接进入正题吧……
假设
- 您了解Visual Studio Code (VS Code)
- 你熟悉VS Code 中的扩展,并且使用过一些,但之前从未构建过
- 你至少了解一点TypeScript /JavaScript 和 Node.js
如果您真的不了解其中任何一个,那也没关系,因为我们不会过多关注代码,但如果您不明白什么,请在下面留言,我会尽快回复您。
我可以构建什么样的扩展?
您可以随心所欲地构建任何内容。您可以构建几种主要的扩展“类型”,以便更好地了解从哪里开始。让我们根据您可能想要实现的功能来细分它们。
1. 自定义 VS Code 的外观和感觉
这是什么意思?颜色主题和图标主题。颜色主题实际上是你的第一个扩展程序的一个很好的起点。为了更好地理解,我们先来进一步分解一下它们。
- 颜色主题
这类扩展可以自定义 VS Code 的视觉外观。您可以更改用户界面 (UI) 中众多不同方面的颜色。这可能会让人不知所措。使用您喜欢但想要调整的现有主题是开始创建您实际会用到的自定义主题的好方法。这样做会为您提供大量颜色更改的示例,您可以调整它们并快速查看结果。不过,我们很快就会看到从头开始是多么容易。
在撰写这篇文章时,我最喜欢的主题是Sarah Drasner的《夜猫子》
- 图标主题
这类扩展可以自定义与文件/文件夹类型相关的图形。Material Icon Theme(我使用的就是这个)就是一个很好的例子。
2.扩展现有功能
这是什么意思?这意味着 VS Code 中有一些现有的功能/特性,但你希望它能有更多功能。一个简单的例子是创建新的键盘映射,让那些习惯使用其他编辑器中某些键盘快捷键的用户更容易使用。一个类似的例子是一个扩展,它提供代码片段来生成可在 Node.js 应用程序中复用的通用代码。
以下是一些简单的例子:
- Sublime Text键盘映射扩展
- 代码片段扩展Vue.js 代码片段
更复杂的例子:
3. 添加新功能
这是什么意思?这意味着 VS Code 不提供您想要使用的某些功能。在这种情况下,我们会构建一个扩展来添加该功能。
例子:
-
问题:不支持与 Chrome 调试器连接以进行前端 Web 开发。
解决方案:Chrome 扩展程序的调试器
-
问题:编写 Python 代码时,没有对智能补全(Intellisense)的原生支持
解决方案:Python扩展
-
问题:没有原生支持集成 Twitch 聊天消息来控制代码行的高亮显示
4. 将其他扩展程序聚合到一个地方
这是什么意思?您可以将许多扩展程序整合到一个扩展包中,以帮助实现特定的重点/操作类别。本质上,市面上有很多扩展程序本身就非常适合您正在进行的开发类型,但您可能并未全部了解它们。有人可以将它们整合在一起,以便更轻松地找到并一次性安装。
Angular Essentials扩展包就是一个例子,它将一系列 Angular 相关的扩展打包到一处。查看GitHub上的源代码,了解创建一个扩展包需要哪些步骤。
这些类型的扩展由其文件驱动,用于定义要包含在包中的其他扩展。请参阅 Angular Essentials 的package.json
package.json
中的示例。
如何构建扩展?
您可以从颜色主题扩展开始,这是最简单的扩展之一。现在让我们逐步构建一个这样的扩展。
构建颜色主题扩展
让我们从头开始构建一个颜色主题扩展,以便体验一下如何创建我们的第一个扩展。我们将使用 VS Code Yeoman 生成器,因此请确保在终端/命令提示符中执行以下命令:
npm i -g generator-code
这将安装 Yeoman CLI 工具和 VS Code 模板/脚手架生成器作为其中的选项
安装完成后,转到您想要用于开发的主文件夹/目录(例如cd /my/dev/folder
:)并运行以下命令开始:
yo code
系统将提示您选择要创建的扩展程序类型。使用键盘箭头键移动到“新建颜色主题”选项,然后按下Enter
。
接下来,系统会提示您选择导入或转换现有颜色主题。请选择“否,重新开始”
从这里开始,提示将要求您提供有关扩展的详细信息。
name
:这决定了它将在当前目录中创建的文件夹。identifier
:这将在扩展市场中用于供其他人找到它,因此如果您计划稍后发布它,请确保它是唯一的(我通常使用我的用户名,后跟扩展/主题的名称)。description
:用于描述您的扩展程序的较长的文本- 主题名称:这是用户在 VS Code 中切换主题时(安装后)将看到的选项文本
base theme
:这为您提供了创建主题的起点,而无需费力从头开始。选择最适合您想要创建的颜色主题类型的选项:深色、浅色、高对比度
输入完所有颜色主题选项后,按下Enter
最后一个提示符对应的键,开始生成所有内容。您将在终端/命令提示符中看到一些进度,其中显示了正在生成的文件和文件夹。
完成后,您应该会看到一条消息,内容如下:“要开始使用 Visual Studio Code 进行编辑,请使用以下命令:”运行下面显示的命令,您将看到 VS Code 打开颜色主题扩展的文件夹。
使用键盘快捷键在 VS Code 中打开调试器视图CTRL/CMD + SHIFT + D
(或点击带有 bug 的图标)。点击绿色的“播放”按钮(如下图所示)即可开始调试/运行你的颜色主题扩展。
运行后,您将看到一个新的 VS Code 实例打开,标题为“扩展开发主机”。这是一个独立的 VS Code 实例,其中加载了您的扩展程序。在上一步中,在终端/命令提示符中生成此颜色主题扩展时,我为基本主题选择了“深色”选项,因此我在 VS Code 的扩展开发主机实例中看到它是默认颜色。根据您在此步骤中选择的基本主题,您可能会看到不同的颜色。让我们测试一下如何更改主题的颜色。
返回已打开扩展文件夹的另一个 VS Code 实例。展开“主题”文件夹,然后双击该.json
文件以打开/查看内容。
editor.background
现在,在 JSON 文件中找到该键colors
。将鼠标悬停在值上,string
即可在 VS Code 中调出颜色选择器视图。小心地将鼠标移到颜色选择器弹出视图中,并将颜色更改为其他颜色。您将看到string
值发生变化。
保存更改后,您将看到 VS Code 的“扩展开发主机”将自动更新并显示颜色变化。
大功告成!恭喜你成功创建了你的第一个 Visual Studio Code 扩展!欢迎继续调整.json
文件中的颜色选项,进一步自定义你的颜色主题扩展。
构建更多的东西
创建颜色主题扩展固然很好,但它并没有深入讲解如何在 VS Code 中增强或创建功能。让我们来演示如何创建一个扩展,它会创建一个文件,列出我们在 VS Code 中使用的所有扩展。
转到您想要用于开发的主文件夹/目录(例如:)cd /my/dev/folder
并运行以下命令开始:
yo code
系统将提示您选择要创建的扩展类型。使用键盘箭头键移动到“新建扩展(TypeScript)”选项,然后按下Enter
键。
从这里开始,提示将要求您提供有关扩展的详细信息。
name
:这决定了它将在当前目录中创建的文件夹。identifier
:这将在扩展市场中用于供其他人找到它,因此如果您计划稍后发布它,请确保它是唯一的(我通常使用我的用户名,后跟扩展/主题的名称)。description
:用于描述您的扩展程序的较长的文本- 主题名称:这是用户在 VS Code 中切换主题时(安装后)将看到的选项文本
git repository
:这让你可以选择是否将项目初始化为新的 git 存储库package manager
:在 npm 和 yarn 之间选择你喜欢的
切换到新生成的扩展的目录并在 VS Code 中打开它
VS Code 扩展利用了package.json
其清单,并在常规选项之外添加了更多选项。我们不会详细介绍所有选项,但为了实现此扩展,我们需要更改一些选项。
-
打开
package.json
文件并找到activationEvents
密钥。它定义了什么操作会激活你的扩展程序。目前,它被定义为在触发“helloWorld”命令时激活你的扩展程序。你会看到它以字符串值的形式出现"onCommand:extension.helloWorld"
。为了确保与新扩展程序的意图保持一致,请将其替换helloWorld
为createList
我们将要创建的命令的名称。 -
在该键下方不远处,
activationEvents
你会发现另一个键contributes
。它定义了你的扩展程序可以“贡献” VS Code 的多种方式。目前它只定义了一个选项,即通过commands
选项。这是一个数组,定义了扩展程序将通过命令面板提供给 VS Code 的各种命令。你应该看到一个定义为 的命令extension.helloWorld
。该命令的“extension”部分在 VS Code 中连接命令时充当命名空间,而“helloWorld”部分则为扩展程序中的命令创建了一个唯一的名称。我们需要确保它的更改与我们在 中更新的内容相匹配,activationEvents
因此请在helloWorld
此处将其替换为createList
。 -
命令定义中的键
title
提供了将在命令面板中显示给用户的文本。将此键的值更改为Create List
。我们将在此文件中更改的最后一项是在下面添加另一个键,title
因此请在值的末尾添加一个逗号title
,然后按“Enter”键换行。添加一个键"category"
(智能感知也会弹出来提供帮助)并赋予其值"Extension Lister"
。这category
有助于在视觉上对命令进行分组,使它们在命令面板中显示为“: ”(例如:“Extension Listener: Create List”)
让我们开始构建此扩展的功能。在src
文件夹中,您将看到一个文件extension.ts
。这是用于加载扩展及其相应功能的主文件。请花点时间阅读代码中的注释,它们有助于描述为您生成的部分代码……认真阅读一遍,然后再回来。
现在您对代码已经比较熟悉了,让我们来设置第一个命令。首先,我们需要更新命令代码,使其与我们在 中所做的更改相匹配package.json
。找到代码registerCommand('extension.helloWorld'
并将其替换helloWorld
为createList
。
好的,命令已正确连接,我们可以开始收集扩展列表了。VS Code API 提供了一个命名空间,extensions
其中包含数组下实例中所有可用扩展的列表all
。我们通过语句访问该 API import * as vscode from 'vscode';
。由于这已经在(第 17 行)中完成了,因此registerCommand
让我们获取该数组并将其赋值给一个常量。用以下代码替换该代码行vscode.window.showInformationMessage('Hello World!');
(以及其上方的注释):
const activeExtensions = vscode.extensions.all;
如果您在此行设置断点并运行和调试扩展,您会注意到该数组实际上包含了该扩展所运行的 VS Code 实例中所有已安装且可用的扩展。您可以立即尝试一下,但这不是必需的。这是一个好的开始,但如果您检查扩展集合,您会注意到它包含 VS Code 内置的扩展、当前未启用的扩展以及主题扩展。
由于我们获取的扩展超出了我们想要包含在列表范围内的内容(活动、非主题类型扩展),因此我们需要先过滤掉其中一些结果。添加以下数组方法 ,filter
以捕获范围内的扩展。
const activeExtensions = vscode.extensions.all.filter(
(extension: vscode.Extension<any>) => {
return (
extension.isActive && // make sure it is active
!extension.packageJSON.isBuiltin && // don't include built in
!extension.packageJSON.categories.some(
// don't include themes
(category: string) => category.toLocaleLowerCase() === 'themes'
)
);
}
);
接下来,我们要将写入文件的内容格式化为: 。这样可以方便共享,并允许其他人快速安装扩展程序。为此,我们需要遍历扩展程序数组,以创建要写入文件的内容字符串。使用以下代码完成此操作,并在定义和分配数组<extension name>: <extension marketplace URL>
后添加它:activeExtensions
let extensionListData = ''; // variable to hold the file contents as a string
activeExtensions.forEach((extension: vscode.Extension<any>) => {
// thanks to TypeScript and the exposed Extension type from the VS Code API we get intellisense to see the properties of each extension.
// In particular we want to read the display name property found in the `packageJSON` object and generate the URL using the extension ID property
extensionListData += `${
extension.packageJSON.displayName
}: https://marketplace.visualstudio.com/items?itemName=${extension.id}\n`;
});
此时,我们已获得所需的数据,并且数据格式已调整为人类可读的格式,因此我们可以询问用户希望将文件保存在何处。对于可视化提示和队列,VS Code 通过其window
命名空间提供了选项。我们特别需要这个showSaveDialog
函数。我们可以为其提供一些选项/参数,以便在此对话框中创建更好的用户体验。我们知道这只是一个纯文本文件,因此我们将提供一个过滤选项,用于将文件类型限制为*.txt
。
当用户在保存对话框中完成操作后,文件生成的 URI(通用资源标识符)将在 Promise 的.then()
resolve 函数中返回给我们。我们需要先确保 URI 确实已提供。如果没有,我们可以使用 来显示一个错误对话框vscode.window.showErrorMessage()
。一旦我们至少知道有一个值,我们就可以将其写入文件,但我们先等等。以下代码实现了本节讨论的内容:
vscode.window.showSaveDialog({ filters: { '*': ['txt'] } }).then(uri => {
if (!uri) {
// This pops up an error notification dialog
vscode.window.showErrorMessage(
'You must select a file location to create the extension list'
);
return; // Don't proceed if we don't have a file URI to write to
}
// We'll add the code to write to a file here next...
});
我们希望实现在操作系统文件系统上写入文件的功能,但又不想让这些代码污染我们的主要扩展代码。让我们创建一个单独的文件来处理将文件写入文件系统的操作。点击图标或使用键盘快捷键 打开 VS Code 的文件资源管理器视图CTRL/CMD + SHIFT + E
。右键单击src
文件夹,然后选择“新建文件”。
输入名称file-manager
并按 Enter 键完成文件创建。VS Code 应该会自动打开该文件,如果没有,请双击它。我们不会详细介绍以下代码,因为它与 VS Code 扩展的创建无关,但要知道它负责将内容写入文件。如果您愿意,可以随时查看代码。将以下代码添加到文件file-manager.ts
并保存:
import { promises } from 'fs'; // leverage the Node.js file system module's functions
export function writeExtensionListFile(uri: string, data: any) {
return promises.writeFile(uri, data);
}
现在,我们可以从我们创建的文件中导入该writeExtensionListFile()
函数file-manager.ts
来处理上一步。再次打开该extension.ts
文件,并在vscode
导入语句之后添加一个 import 语句(位于第 3 行):
import { writeExtensionListFile } from './file-manager';
太棒了,我们开始用吧。找到 ,在showSaveDialog
检查值的部分后面uri
添加以下代码:
// Provide the full path on the file system for the file to write to and the contents we want to write to that file
writeExtensionListFile(uri.fsPath, extensionListData)
.then(() => {
// if the file was created successfully show an alert notification
vscode.window.showInformationMessage(
'Extension list was successfully created'
);
})
.catch((error: any) => {
// if the file failed to be created show an error notification
vscode.window.showErrorMessage(
'There was an issue creating the extension list'
);
console.error(error);
});
这段代码的作用是什么?它调用函数writeExtensionListFile
并传入完整的文件系统路径值(uri
对象的一个属性)以及我们想要写入的内容。如果操作成功,我们会通过vscode.window.showInformationMessage()
函数告知用户,否则会显示一条错误消息vscode.window.showErrorMessage()
。
如果出现问题,请使用以下 GitHub 存储库作为已完成代码的参考:VS Code Extension Lister
我们来运行一下测试一下怎么样?点击F5
开始调试,或者在 VS Code 中打开调试视图,然后点击绿色的“播放”按钮。
然后,您将看到一个新的 VS Code 实例加载,标题为“扩展开发主机”,您的扩展正在其中运行。使用键盘快捷键打开命令面板CTRL/CMD + SHIFT + P
,然后键入lister
以查看我们扩展可用的命令。
按下键盘上的“Enter”键,系统将提示您选择文件的位置和名称。选择文件的位置和名称,然后点击“保存”按钮。您将在 VS Code 的右下角看到一条成功通知。
为了确保万无一失,请前往您保存文件的位置并打开它来查看内容。您应该会看到您正在使用的所有活跃扩展程序及其市场网址的完整列表。
恭喜您创建了另一个 VS Code 扩展,并且添加了新功能!
我如何发布扩展?
与其在这里重复写同样的信息,不如看看发布扩展文档。VS Code 网站上提供的文档非常简单易懂,所以请查看该文档了解更多详细信息。
我应该去哪里了解更多信息?
了解更多关于 VS Code 扩展开发的信息,最好的去处是官方VS Code API 文档网站。在那里,您会在左侧看到一个可扩展的目录,其中详细列出了扩展开发相关的重要主题。
结束语
如果您还有其他问题尚未得到解答,请在评论区告诉我。我会定期查看,并会及时回复,或者如果更合适的话,我会以更合适的形式发布帖子。
感谢您阅读这篇文章,希望它对您有所帮助。
连接方式:
文章来源:https://dev.to/azure/building-a-visual-studio-code-extension-dkj