私が独学で VSCode プラグインを開発した過程を記録します。カラー コード プロンプトを使用して伝統的な中国の色を取得する Visual Studio Code 拡張機能を実装します。
公式ドキュメント:code.visualstudio.com/api
各種公式ドキュメント提供されているプラグインの例: github.com/microsoft/v…
CSS を書くとき、色の選択に苦労することがよくあります。組み込みプラグイン カラーピッカーが提供されていますが、256^3 色から選択する場合、期待どおりの色が見つからない場合があります。 # カラー名
を入力する限り、対応する色がリストされ、コード プロンプトの形式で選択できるカラー プロンプト プラグインが必要でした。 [推奨学習: "vscode 入門チュートリアル "]
VS Code プラグイン マーケットを探し回りましたが、同様のプラグインが見つかりませんでした。最終的にプラグインを作成することにしました。私自身、学ぶ姿勢を持って、その学習過程を記録しました。
これが最終結果です:
デモではピンインを使用していますが、漢字を直接使用することも可能です。
VS Code プラグイン マーケットで「中国色」または「中国色」を検索して、私が作成したプラグインを見つけてください。
倉庫のアドレス: taiyouki/chinese-colors
最初に、既製のカラーコードを用意する必要があります。この Web サイトを見つけますか: 中国色
この Web サイトでは、500 色以上の RGB 値と 16 進値が提供されています。ブラウザ コンソールを開いて、colorsArray と入力して、それらをすべて取得します。ここに私が望むものだけを。
ウェブサイトの下部にある情報から判断すると、このウェブサイトは偽の Japanese color であり、この色は来ると言われています。中国科学院科学技術情報編集委員会より 「クロマトグラフィー」は用語集によって書かれ、1957 年にサイエンス プレスから出版されました。
この色のソースが信頼できるかどうかを確認する方法はありません。百度で「繁体字中国語の色」を検索すると、いわゆる中国の色のさまざまなバージョンが見つかります。また、別の中国語の色も見つけました。 github に 2,000 個近くの星が付いている色です。プロジェクト: 中国の伝統的な色マニュアル。この Web サイトで使用されている色は、前のものとは完全に異なります。現在利用できなくなった Sina ブログからのものです。統計はありません。色数は多少異なりますが、おおよそ200色以内と考えられます。
開発ツールのインストール
npm i -g yo generator-code
新しいプロジェクト
yo code
構成は次のとおりです:
最初のプロジェクトに 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() {}
View package.json
、より重要なもののうち 2 つ:
{ "activationEvents": [ "onCommand:chinese-colors.helloWorld" ], "contributes": { "commands": [ { "command": "chinese-colors.helloWorld", "title": "Hello World" } ] }, }
activationEvents はプラグインのアクティベーション設定です。配列です。各項目はプラグインをアクティベートするための条件に対応します。形式は "
contributes: 一般に貢献ポイントとして翻訳され、「chinese-colors.helloWorld」が構成され、activationEvents 構成項目に対応します。
その他の package.json 構成を以下の表に示します。
名称 | 必要 | 类型 | 说明 |
---|---|---|---|
name |
是 | string |
插件名称,必须为小写且不能有空格。 |
version |
是 | string |
插件版本 |
publisher |
是 | string |
发布者 |
engines |
是 | object |
一个至少包含vscode 键值对的对象,该键表示的是本插件可兼容的VS Code的版本,其值不能为* 。比如 ^0.10.5 表示插件兼容VS Code的最低版本是0.10.5 。 |
license |
否 | string |
授权。如果有授权文档LICENSE.md,可以把license 值设为"SEE LICENSE IN LICENSE.md" 。 |
displayName |
否 | string |
插件市场中显示的名字。 |
description |
否 | string |
描述,说明本插件是什么以及做什么。 |
categories |
否 | string[] |
插件类型:[Languages, Snippets, Linters, Themes, Debuggers, Other]
|
keywords |
否 | array |
一组 关键字 或者 标记,方便在插件市场中查找。 |
galleryBanner |
否 | object |
插件市场中横幅的样式。 |
preview |
否 | boolean |
在市场中把本插件标记为预览版本。 |
main |
否 | string |
插件的入口文件。 |
contributes |
否 | object |
一个描述插件 贡献点 的对象。 |
activationEvents |
否 | array |
一组用于本插件的激活事件。 |
dependencies |
否 | object |
生产环境Node.js依赖项。 |
devDependencies |
否 | object |
开发环境Node.js依赖项。 |
extensionDependencies |
否 | array |
一组本插件所需的其他插件的ID值。格式 ${publisher}.${name} 。比如:vscode.csharp 。 |
scripts |
否 | object |
和 npm的 scripts 一样,但还有一些额外VS Code特定字段。 |
icon |
否 | string |
一个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:
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
:用于获取、控制文档的内容或状态,这里列举几个常用的方法和属性:
方法:
属性
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的取值:
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:
window.createTextEditorDecorationType(options)
:创建装饰效果的类型
window.activeTextEditor.setDecorations(decorationType, decorations)
:添加装饰效果至文档
window.onDidChangeActiveTextEditor
:文档内容变化事件
workspace.onDidChangeTextDocument
:切换文档事件
首先来看一下官方提供的示例片段
完整实例: github.com/microsoft/v…
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是通过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对象有三个属性:
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
如果打包失败,可能的原因:
更多关于VSCode的相关知识,请访问:vscode教程!
以上がカラーコードを要求する VS Code プラグインを開発します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。