温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何开发一个提示颜色代码的VS Code插件

发布时间:2022-10-24 17:00:04 来源:亿速云 阅读:360 作者:iii 栏目:软件技术

今天小编给大家分享一下如何开发一个提示颜色代码的VS Code插件的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

需求

我在写css时,经常会有颜色选择困难症,虽然VS Code内置的插件提供了取色器,但在256^3的颜色中去选取,未必能找到符合期望的颜色。于是我想要是有个颜色提示插件就好了,只要我输入# + 颜色名,就能以代码提示的方式,将对应的颜色列出来供我选择。

获取颜色

首先第一件事就是要有现成的颜色代码,很快我就找到了这个网站:中国色

这个网站提供了500多种颜色的rgb值以及hex值,打开浏览器控制台,输入colorsArray就能全部拿到,这就是我想要的。

从网站底部的信息来看,这个网站是山寨自日本色,颜色据称来自中科院科技情报编委会名词室编写、科学出版社1957年出版的《色谱》。

这个颜色来源是否可信我无从考证,随便百度一下“中国传统色”,就可以找到很多版本的所谓中国色,我在github上还找到了另一个接近2k star的中国色项目:中国传统颜色手册,这个网站使用的颜色与前者完全不同,是来自于一篇现在已经无法查看的新浪博客,颜色数量我没有统计,粗略估计在200以内。

初始化项目

安装开发工具

 npm i -g yo generator-code

新建项目

 yo code

Hello World

初始项目中有个Hello World,用VS Code打开项目,然后按F5(或者点击“运行-->启动调试”)可以开启调试窗口。

然后在调试窗口下 Ctrl + Shift + P (或者点击“设置-->命令面板”),输入并选择 Hello World 命令,就会在编辑器右下角弹出一个消息提示。

extension.ts是插件的入口文件:

 import * as vscode from 'vscode';    // activate方法会在插件被激活时调用  export function activate(context: vscode.ExtensionContext) {            // 注册命令,第一个参数是命令名称,第二参数是回调      let disposable = vscode.commands.registerCommand('chinese-colors.helloWorld', () => {          // 弹出消息提示          vscode.window.showInformationMessage('Hello World from Chinese Colors!');      });        // 添加到插件上下文      context.subscriptions.push(disposable);  }    // deactivate方法会在插件失活时调用  export function deactivate() {}

package.json

查看package.json,其中比较重要的两项:

 {      "activationEvents": [          "onCommand:chinese-colors.helloWorld"      ],      "contributes": {          "commands": [              {                  "command": "chinese-colors.helloWorld",                  "title": "Hello World"              }          ]      },  }

activationEvents是插件的激活配置,它是一个数组,每一项对应一个激活插件的条件,格式为“<类型>:<名称>”,onCommand是调用命令(也就是上面的输入Hello World)。

contributes:一般翻译为贡献点,配置了一个“chinese-colors.helloWorld”,与activationEvents配置项对应。

其他packege.json配置见下表:

名称必要类型说明
namestring插件名称,必须为小写且不能有空格。
versionstring插件版本
publisherstring发布者
enginesobject一个至少包含vscode键值对的对象,该键表示的是本插件可兼容的VS Code的版本,其值不能为*。比如 ^0.10.5 表示插件兼容VS Code的最低版本是0.10.5
licensestring授权。如果有授权文档LICENSE.md,可以把license值设为"SEE LICENSE IN LICENSE.md"
displayNamestring插件市场中显示的名字。
descriptionstring描述,说明本插件是什么以及做什么。
categoriesstring[]插件类型:[Languages, Snippets, Linters, Themes, Debuggers, Other]
keywordsarray一组 关键字 或者 标记,方便在插件市场中查找。
galleryBannerobject插件市场中横幅的样式。
previewboolean在市场中把本插件标记为预览版本。
mainstring插件的入口文件。
contributesobject一个描述插件 贡献点 的对象。
activationEventsarray一组用于本插件的激活事件。
dependenciesobject生产环境Node.js依赖项。
devDependenciesobject开发环境Node.js依赖项。
extensionDependenciesarray一组本插件所需的其他插件的ID值。格式 ${publisher}.${name}。比如:vscode.csharp
scriptsobject和 npm的 scripts一样,但还有一些额外VS Code特定字段。
iconstring一个128x128像素图标的路径。

用户自定配置项

颜色代码有多种表示方式,比较常用的是16进制(#ffffff)和rgb(255,255,255)这两种,因此我需要让用户自己选择采用哪种方式。

在contributes中有个configuration,允许用户对插件进行一些自定义配置。

package.json

 {      // ...      "contributes": {          "configuration": [{              "title": "color mode",// 配置项名称              "properties": {                  // 配置属性                  "RGB": {                      "type": "boolean",  // 属性值类型                      "default": false,   // 属性默认值                      "description": "控制预设的中国色采用RGB格式"    // 属性描述                  }              }          }]      },  }

这样就可以在扩展设置中进行一些自定义的设置:

我们可以通过workspace.getConfiguration()获取用户的配置。

 import { workspace } from "vscode";  const configuration = workspace.getConfiguration();  const isRGB = configuration.RGB;

代码补全

API

代码补全API:

vscode.languages.registerCompletionItemProvider(selector, provider, …triggerCharacters)

该方法有三个参数:

参数Description
selector: string/string[]选择编程语言,比如python
provider供应者配置对象
triggerCharacters: string/string[]触发字符, 比如 .:

register completion item provider(注册完成件供应者),这个provider也是比较费解的一个词,直译是供应者,我猜:代码补全就相当于插件给我们供应了代码,所以叫provider。

provider是一个对象,要求必须包含一个叫provideCompletionItems的方法,该方法需要返回一个数组,数组的每一项是一个CompletionItem对象,规定了代码提示和补全的规则。

官方示例

 import * as vscode from 'vscode';    export function activate(context: vscode.ExtensionContext) {        // 注册供应者:languages.registerCompletionItemProvider      const provider2 = vscode.languages.registerCompletionItemProvider(          'plaintext',// plaintext,表示对txt文档激活该插件          {              // 实现provideCompletionItems方法              // document的内容见下文,position为当前光标的位置              provideCompletionItems(document: vscode.TextDocument, position: vscode.Position) {                    // 获取当前这行代码                  const linePrefix = document.lineAt(position).text.substr(0, position.character);                  // 如果这行代码不是以console.结尾,返回undefined,表示不会弹出代码提示                  if (!linePrefix.endsWith('console.')) {                      return undefined;                  }                    // 返回CompletionItem对象组成的数组,补全代码列表:log、warn、error                  // CompletionItem对象可以自己创建,也可以像下面这样new vscode.CompletionItem的方式创建                  // vscode.CompletionItem()有两个参数:                   // 第一个是补全的代码,第二个是代码类型,用于控制显示在每一行提示前的图标                  // vscode.CompletionItemKind.Method表示该代码是一个方法                  return [                      new vscode.CompletionItem('log', vscode.CompletionItemKind.Method),                      new vscode.CompletionItem('warn', vscode.CompletionItemKind.Method),                      new vscode.CompletionItem('error', vscode.CompletionItemKind.Method),                  ];              }          },          '.' // 以.作为触发      );        context.subscriptions.push(provider2);  }

provideCompletionItems参数:

position:当前光标所处的位置。

document:用于获取、控制文档的内容或状态,这里列举几个常用的方法和属性:

  • 方法:

    • getWordRangeAtPosition(position): Range:获取指定位置单词的范围(起始位置)

    • getText(Range):string:获取指定范围的文本

    • lineAt(position):string:获取指定位置的文本

    • validatePosition(position):Position:获取鼠标停留的位置

  • 属性

    • lineCount:总代码行数

    • languageId:语言名称

    • isClosed:当前文件是否关闭

    • isDirty:当前文件的代码是否更改未保存

CompletionItem对象

CompletionItem对象可以通过new vscode.CompletionItem()的方式创建,但它默认只能补全代码,不能自定义替换,并不能满足我的需求,因此需要自己创建。

CompletionItem对象包含的属性:

属性说明
detail: string语义化描述
documentation: string语义化描述
filterText: string代码过滤。匹配输入的内容,没有设置时,使用label
insertText: string插入、补全的代码。没有设置时,使用label
label: string默认的匹配代码、补全代码
kind代码类型,控制显示代码提示前的图标
sortText: string排序文本,与sortText匹配的提示代码会排在靠前的位置
textEdit对补全代码进行编辑,如果设置了textEdit,insertText会失效

kind的取值:

  • Class

  • Color

  • Constructor

  • Enum

  • Field

  • File

  • Function

  • Interface

  • Keyword

  • Method

  • Module

  • Property

  • Reference

  • Snippet

  • Text

  • Unit

  • Value

  • Variable

简单的示例

 import * as vscode from "vscode";  import { CompletionItemKind } from "vscode";    export function activate(context: vscode.ExtensionContext) {    const cc = vscode.languages.registerCompletionItemProvider(      "css",      {        provideCompletionItems() {                  return [              {                  detail: '#66ccff',                  documentation: '天依蓝',                  kind: CompletionItemKind.Color,                  filterText: `#66ccff天依蓝`,                  label: '天依蓝',                  insertText: '#66ccff'              },              {                  detail: '#39c5bb',                  documentation: '初音绿',                  kind: CompletionItemKind.Color,                  filterText: `#39c5bb初音绿`,                  label: '初音绿',                  insertText: '#39c5bb'              }          ];        },      },      "#"    );    context.subscriptions.push(cc);  }    export function deactivate() {}

记得要在package.json里配置激活:

"activationEvents": [     "onLanguage:css"   ]

中国色插件

package.json关键配置:

 {      "activationEvents": [          "onLanguage:css",          "onLanguage:scss",          "onLanguage:sass",          "onLanguage:less",          "onLanguage:stylus",          "onLanguage:html",          "onLanguage:xml",          "onLanguage:json",          "onLanguage:javascript",          "onLanguage:typescript",          "onLanguage:javascriptreact",          "onLanguage:typescriptreact",          "onLanguage:vue",          "onLanguage:vue-html"      ],      "contributes": {          "configuration": [{              "title": "Chinese Colors",              "properties": {                  "RGB": {                      "type": "boolean",                      "default": false,                      "description": "控制预设的中国色采用RGB格式"                  }              }          }]      },  }

颜色列表colors.ts

 // 声明Color类型  export type Color = {    rgb: number[];    hex: string;    name: string;    phonics: string;  };    // 这里只列两个颜色  export const colors: Color[] = [    {      rgb: [92, 34, 35],      hex: "#5c2223",      name: "暗玉紫",      phonics: "anyuzi",    },    {      rgb: [238, 162, 164],      hex: "#eea2a4",      name: "牡丹粉红",      phonics: "mudanfenhong",    },    // ...  ]

extensions.ts

 import * as vscode from "vscode";  import { workspace, CompletionItemKind } from "vscode";  import { colors, Color } from "./colors";    const isRgb = workspace.getConfiguration().RGB;    export function activate(context: vscode.ExtensionContext) {    const cc = vscode.languages.registerCompletionItemProvider(      [        "css",        "scss",        "sass",        "less",        "stylus",        "html",        "xml",        "json",        "javascript",        "typescript",        "javascriptreact",        "typescriptreact",        "vue",        "vue-html",      ],// activationEvents      {        provideCompletionItems() {          const list = [] as CompletionItemKind[];            colors.forEach((color: Color) => {            list.push({              detail: isRgb ? rgb : hex,              documentation: color.name,              kind: CompletionItemKind.Color,              filterText: "#" + color.name + color.phonics,              label: color.name,              insertText: isRgb ? rgb : hex,            });          });          return list;        },      },      "#"    );    context.subscriptions.push(cc);  }    export function deactivate() {}

如此,代码补全的功能已经基本实现,实际开发时,为了便于维护,需要将这部分逻辑抽离出来。

颜色预览

接下来,需要实现颜色的预览,虽然VS Code内置的插件已经实现了这项功能,但我的需求是:不仅能预览颜色,还得显示颜色名称。

API

实现颜色预览需要用到装饰效果,涉及以下这些API:

window.createTextEditorDecorationType(options):创建装饰效果的类型

window.activeTextEditor.setDecorations(decorationType, decorations):添加装饰效果至文档

window.onDidChangeActiveTextEditor:文档内容变化事件

workspace.onDidChangeTextDocument:切换文档事件

官方示例

首先来看一下官方提供的示例片段

import * as vscode from 'vscode'; // 插件激活时调用 export function activate(context: vscode.ExtensionContext) {	console.log('decorator sample is activated');	let timeout: NodeJS.Timer | undefined = undefined;     // 为small numbers创建装饰效果类型	const smallNumberDecorationType = vscode.window.createTextEditorDecorationType({         // 以下是装饰效果的样式	borderWidth: '1px',	borderStyle: 'solid',	overviewRulerColor: 'blue',	overviewRulerLane: vscode.OverviewRulerLane.Right,	light: {	// 亮色主题下的边框颜色	borderColor: 'darkblue'	},	dark: {	// 暗色主题下的边框颜色	borderColor: 'lightblue'	}	});	// 为large numbers创建装饰效果类型	const largeNumberDecorationType = vscode.window.createTextEditorDecorationType({	cursor: 'crosshair',	// 设置装饰的背景颜色, 在package.json中可以配置该名称对应的颜色	backgroundColor: { id: 'myextension.largeNumberBackground' }	});     // activeEditor是当前活跃(展示)的文档编辑器实例	let activeEditor = vscode.window.activeTextEditor;     // updateDecorations方法,在每次文档被更新或切换文档时调用。	function updateDecorations() {	if (!activeEditor) {	return;	}         // 匹配数字的正则	const regEx = /\d+/g;         // 获取文档的文本	const text = activeEditor.document.getText();         // 装饰效果数组,用于归集每一个Decoration对象	const smallNumbers: vscode.DecorationOptions[] = [];	const largeNumbers: vscode.DecorationOptions[] = [];	let match;	while ((match = regEx.exec(text))) {             // 获取匹配结果的起始位置	const startPos = activeEditor.document.positionAt(match.index);// 开始位置	const endPos = activeEditor.document.positionAt(match.index + match[0].length);// 结束位置             // Decoration对象	const decoration = {                 // 装饰效果的位置                 range: new vscode.Range(startPos, endPos),                  // 鼠标悬停(hover)的提示信息                 hoverMessage: 'Number **' + match[0] + '**'              };             // 将符合的结果归集	if (match[0].length < 3) {	smallNumbers.push(decoration);	} else {	largeNumbers.push(decoration);	}	}         // 添加装饰效果	activeEditor.setDecorations(smallNumberDecorationType, smallNumbers);	activeEditor.setDecorations(largeNumberDecorationType, largeNumbers);	}     // 给方法节流	function triggerUpdateDecorations(throttle = false) {	if (timeout) {	clearTimeout(timeout);	timeout = undefined;	}	if (throttle) {	timeout = setTimeout(updateDecorations, 500);	} else {	updateDecorations();	}	}     // 打开文档时调用一次	if (activeEditor) {	triggerUpdateDecorations();	}     	// 切换文档时调用	vscode.window.onDidChangeActiveTextEditor(editor => {         // 这一步赋值是必须的,确保activeEditor是当前打开的文档编辑器实例	activeEditor = editor;	if (editor) {	triggerUpdateDecorations();	}	}, null, context.subscriptions);     // 文档内容发送改变时调用	vscode.workspace.onDidChangeTextDocument(event => {	if (activeEditor && event.document === activeEditor.document) {	triggerUpdateDecorations(true);	}	}, null, context.subscriptions); }

DecorationType

DecorationType是通过window.createTextEditorDecorationType(options)创建的对象,它主要用来设置装饰效果的样式,其实就是css样式,比如border、color、backgroundColor等等。

如果要在匹配结果之前或之后添加装饰,可以添加before/after字段进行设置,还可以分别给dark、light模式配置不同的样式。

const decorationType =  window.createTextEditorDecorationType({     // 在匹配位置之前添加装饰效果:     before: {         color: '#eee',         backgroundColor: '#fff',         width: 'fit-content'     } })

由于该方法支持的样式字段有限,有些样式(比如line-height)无法在options里直接添加,但我们可以在任意字段后添加分号,将这些样式写在后面,比如:

const decorationType =  window.createTextEditorDecorationType({     // 在匹配位置之后添加装饰效果:     after: {         color: '#333',         backgroundColor: '#fff',         width: 'fit-content',         height: '0.8em',         // fontSize: '0.6em', 这么设置是无效的,因为并不支持fontSize字段,         // 但我们可以将其添加在任意字段后面         fontStyle: 'normal;font-size:0.6em;line-height:0.8em'     } })

具体支持哪些字段,可以查看此API的官方文档:

VS Code API | Visual Studio Code Extension API

Decoration对象

Decoration对象有三个属性:

  • range:装饰效果的位置,range对象可以通过new vscode.Range(start, end)创建

  • hoverMessage:鼠标悬停时的提示信息

  • renderOptions:和decorationType类似,可以单独对每一个装饰效果设置样式。但只支持before、after、dark、light四个字段,也就是说,无法再对匹配的内容本身设置样式。

示例

由于实现的代码比较长,和上述官方示例其实差不多,这里就不再贴出来了,感兴趣的可以我去文章开头的仓库地址查看。

值得一提的是,为了颜色的名称在不同的颜色背景下都能清晰的显现,我这里用到了一个计算对比色的方法,贴出来供参考:

// 通过hex值计算应该使用的字体颜色 function getContrastColor(hexcolor: string) {   const r = parseInt(hexcolor.substring(1, 2), 16)   const g = parseInt(hexcolor.substring(3, 4), 16)   const b = parseInt(hexcolor.substring(5, 6), 16)   const yiq = (r * 299 + g * 587 + b * 114) / 1000   return yiq >= 8 ? 'black' : 'white' }

插件打包

打包命令:

vsce package

如果打包失败,可能的原因:

  • packege.json缺少上文表格中必要的配置项

  • VS Code版本与packege.json里设置的版本不兼容

  • 根目录下缺少README.md文件

  • 根目录下缺少LICENSE.md文件

以上就是“如何开发一个提示颜色代码的VS Code插件”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI