如何打造一款属于自己的 Visual Studio Code 颜色主题

如题所述

Visual Studio Code 是我在最近一年中最喜欢的一款编辑器,微软每一次的更新都会给大家带来惊喜,更是令人愈加喜欢。之前一直使用内置的颜色主题 Light+ 和 Dark+ ,但近来突然觉得前者颜色区分度不高,一眼看上去就密密麻麻的一对代码,而后者则是被选中的文本背景色太浅,跟编辑器的背景颜色很相似,很难区分出来,于是萌生了要制作一款自己的颜色主题的想法。经过几天的研究,终于捣鼓出来了 Lei Theme 系列颜色主题。

先来看看其中两款主题的效果:

一般来说,我们并不需要重头来制作一款颜色主题,首先需要选择一款自己最喜欢的颜色主题(或者说先找一款与自己的想法最相似的颜色主题),然后在此基础上进行些许调整即可。另外如果想将颜色主题发布到微软的 Visual Studio Code 扩展商店上,还需要注册一个微软开发者账号,并通过 vsce 工具来发布出去,下文会对此进行详细说明。
tmTheme 格式的颜色主题

TextMate 曾是多年前最流行的代码编辑器之一,其颜色主题的文件后缀为 .tmTheme ,在本文中我们将其简称为 tmTheme 格式。Visual Studio Studio 的颜色主题采用的是标准的 TextMate 主题格式,我们可以参考这篇文章 Writing a TextMate Grammar: Some Lessons Learned ,大概可以理解为这样: 编辑器对代码进行解析后,会为每个元素指定一个 scope ,这个 scope 即表明此元素是一个关键字还是一个常量,又或者是一个标点符号,通过 tmTheme 格式的文件来定义相应 scope 的文字样式。

根据该文章可知道以下是常见的 scope 列表:

comment
constant
constant.character.escape
constant.language
constant.numeric
declaration.section entity.name.section
declaration.tag
deco.folding
entity.name.function
entity.name.tag
entity.name.type
entity.other.attribute-name
entity.other.inherited-class
invalid
invalid.deprecated.trailing-whitespace
keyword
keyword.control.import
keyword.operator.js
markup.heading
markup.list
markup.quote
meta.embedded
meta.preprocessor
meta.section entity.name.section
meta.tag
storage
storage.type.method
string
string source
string.unquoted
support.class
support.constant
support.function
support.type
support.variable
text source
variable
variable.language
variable.other
variable.parameter

以下是一个 tmTheme 格式文件的代码片段:

<dict>
<key>name</key>
<string>Keyword</string>
<key>scope</key>
<string>keyword.control,keyword.other,variable.language,storage.type,storage.modifier,keyword.function</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#0808D1</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Invalid</string>
<key>scope</key>
<string>invalid</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#cd3131</string>
</dict>
</dict>

从上面的代码可以看出,其实这个 tmTheme 格式的文件似乎也挺简单的,然而初学者而言,难的是 不知道 scope 怎么写 ,下文会循序渐进地对此进行说明。
创建颜色主题项目

根据官方文档,我们先执行以下命令安装 Yeoman 代码生成工具来创建一个默认的颜色主题项目:

$ npm install -g yo generator-code

安装完毕之后,进入 ~/.vscode/extensions 目录执行以下命令启动生成器:

$ yo code

说明: ~/.vscode/extensions 表示用户根目录下的 .vscode/extensions 目录,之所以在此处新建项目主要是为了不用发布到扩展商店也可以在本地进行使用,并且方便调试。

选择 New Color Theme 创建颜色主题项目:

_-----_ ╭——————————————————————————╮
| | │ Welcome to the Visual │
|--(o)--| │ Studio Code Extension │
`---------´ │ generator! │
( _´U`_ ) ╰——————————————————————————╯
/___A___\ /
| ~ |
__'.___.'__
´ ` |° ´ Y `

? What type of extension do you want to create?
New Extension (TypeScript)
New Extension (JavaScript)
❯ New Color Theme
New Language Support
New Code Snippets

接着需要在命令行下交互式地填写一些问题,以下是我在执行过程中填写的内容:

? What type of extension do you want to create? New Color Theme
URL (http, https) or file name of the tmTheme file, e.g., http://www.monokai.nl/blog/wp-content/asdev/Monokai.tmTheme.
? URL or file name: http://www.monokai.nl/blog/wp-content/asdev/Monokai.tmTheme
? What's the name of your extension? my-theme
? What's the identifier of your extension? my-theme
? What's the description of your extension?
? What's your publisher name? leizongmin
? What's the name of your theme shown to the user? my-theme
? Select a base theme: Dark

需要说明的是,第一个问题 URL (http, https) or file name of the tmTheme file 需要提供一个已有的 tmTheme 文件作为基础,此处可直接复制示例中的 URL 。

稍等片刻,工具自动生成了项目之后,会提示我们执行以下命令开始编辑代该项目:

$ cd my-theme
$ code .

以下是生成的项目的文件结构:

.
├—— README.md
├—— package.json (扩展信息文件)
├—— themes
│ └—— Monokai.tmTheme (颜色主题定义文件)
└—— vsc-extension-quickstart.md (帮助文件,上面详细说明操作步骤)

首先看看 package.json 文件:

{
"name": "my-theme",
"displayName": "my-theme",
"description": "",
"version": "0.0.1",
"publisher": "leizongmin",
"engines": {
"vscode": "^1.5.0"
},
"categories": [
"Themes"
],
"contributes": {
"themes": [
{
"label": "my-theme",
"uiTheme": "vs-dark",
"path": "./themes/Monokai.tmTheme"
}
]
}
}

contributes 中定义了此扩展项目包含的内容,其中 themes 表示颜色主题,是一个数组,我们可在此处放入多个颜色主题。以下是 themes 中每个元素的定义:

label 表示颜色主题的名称,即在 Preferences: Color Theme 列表中显示的名称
uiTheme 是指编辑器 UI 的颜色,可选为 vs-light 和 vs-dark ,如果我们的颜色主题是深色系的,就选 vs-dark
path 是 tmTheme 文件的位置

为了避免混淆,我们可以将文件 ./themes/Monokai.tmTheme 改名为 ./themes/my-theme.tmTheme ,并修改 package.json 相应的位置。

现在在 Visual Studio Code 中按快捷键 ⌘Command + Shift + P 打开命令面板(Windows / Linux 系统应为 Ctrl + Shift + P ),输入 Color Theme 并按回车,再中列表中选择 my-theme 按回车即可使用刚刚创建的新颜色主题:

从上图可以看出,这其实就是一个标准的 Monokai 主题。
tmTheme 编辑器

从生成的 vsc-extension-quickstart.md 文件中我们得知有一款 Web 版的在线 tmTheme 编辑器 ,通过该编辑器可以进行可视化地编辑 tmTheme 文件。比如以下视频是更改 String 和 Keyword 颜色的示例:
你的浏览器不支持 标签.

主要的操作方法为:

在左侧 Scope Name 列表中选中一项,然后双击 FG 列上的颜色(FG 表示 foreground,即前景颜色),然后选择要更改的颜色即可,可以看到代码预览区域的颜色会实时改变
点击顶部栏的【Download】按钮即可下载编辑后的 tmTheme 文件,直接将其覆盖项目中的 ./themes/my-theme.tmTheme 文件即可
在 Visual Studio Code 中按快捷键 ⌘Command + Shift + P 打开命令面板,输入 Reload Window 并按回车即可看到修改后的颜色主题

但是,在一些实现细节上,Visual Studio Code 并不与该 tmTheme 编辑器一致,所以我们在该在线编辑器上看到的效果可能与 Visual Studio Code 上稍有不同,所以我们可能还需要直接编辑 tmTheme 文件。
如何知道 scope 是什么

下面是这款主题中,模板字符串的渲染效果:

从图中可以看到,模板字符串中的字符串和变量的颜色都是一样的,而假如我想改变模板字符串中变量的颜色,却是无从下手,因为即使翻遍 TextMate 官方文档中关于 tmTheme 的介绍也找不到模板字符串的 scope 是什么。

其实我们可以借助 Visual Studio Code 的开发者工具来找到任意元素的 scope ,以下是演示视频:
你的浏览器不支持 标签.

从开发者工具中我们可以看到模板字符串中 ${ 的样式是:

token block ts punctuation definition meta string begin function arrow new expr template expression template-expression

而模板变量 file 的样式是:

token block ts meta variable other readwrite string function arrow new expr template expression

再结合文首对于 scope 介绍的文章,我们假设我们要的 scope 名为 template.expression 。接着打开文件 ./themes/my-theme.tmTheme ,仿照该文件的格式,我们添加以下代码在对应位置:

<dict>
<key>name</key>
<string>Template Expression</string>
<key>scope</key>
<string>template.expression</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#23C4FA</string>
</dict>
</dict>

再按快捷键 ⌘Command + Shift + P 打开命令面板,执行 Reload Window ,此时可以看到模板字符串中的变量颜色跟字符串的颜色不一样了:

tmTheme 文件处理规则

尽管已经实现了我们想要的效果,相信阅读到这里的时候很多人还是一头雾水,并不知道为何 scope 是 template.expression 。我在刚开始时虽然也猜想到是像 CSS 的类选择器一样,但还是不太确定,直到阅读到 Visual Studio Code 的源码后才得以印证。

以下是 Visual Studio Code 源码中负责处理 tmTheme 的 scope 的程序文件 src/vs/workbench/services/themes/electron-browser/stylesContributions.ts ( 点此查看完整文件 ):

export class TokenStylesContribution {

public contributeStyles(themeId: string, themeDocument: IThemeDocument, cssRules: string[]): void {
let theme = new Theme(themeId, themeDocument);
theme.getSettings().forEach((s: IThemeSetting, index, arr) => {
// @martin TS(2.0.2) - s.scope is already a string[] so no need for all this checking.
// However will add a cast at split to keep semantic in case s.scope is wrongly typed.
let scope: string | string[] = s.scope;
let settings = s.settings;
if (scope && settings) {
let rules = Array.isArray(scope) ? <string[]>scope : (scope as string).split(',');
let statements = this._settingsToStatements(settings);
rules.forEach(rule => {
rule = rule.trim().replace(/ /g, '.'); // until we have scope hierarchy in the editor dom: replace spaces with .

cssRules.push(`.monaco-editor.${theme.getSelector()} .token.${rule} { ${statements} }`);
});
}
});
}

private _settingsToStatements(settings: IThemeSettingStyle): string {
let statements: string[] = [];

for (let settingName in settings) {
const value = settings[settingName];
switch (settingName) {
case 'foreground':
let foreground = new Color(value);
statements.push(`color: ${foreground};`);
break;
case 'background':
// do not support background color for now, see bug 18924
//let background = new Color(value);
//statements.push(`background-color: ${background};`);
break;
case 'fontStyle':
let segments = value.split(' ');
segments.forEach(s => {
switch (s) {
case 'italic':
statements.push(`font-style: italic;`);
break;
case 'bold':
statements.push(`font-weight: bold;`);
break;
case 'underline':
statements.push(`text-decoration: underline;`);
break;
}
});
}
}
return statements.join(' ');
}
}

我们再来回顾一下上文 tmTheme 文件每一项 scope 的配置内容:

<dict>
<key>name</key>
<string>Template Expression</string>
<key>scope</key>
<string>template.expression</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>http://www.315nk.com/app/?23C4FA</string>
</dict>
</dict>

其中第一项 name 表示的是我们给该规则起的名称; scope 则是适用的 scope ,如果多个可以用逗号分隔,比如 User-defined constant 的 scope 值就为 constant.character, constant.other ; settings 则是具体的样式信息,比如颜色值。

从源码中可以看出,支持的样式只有 foreground 和 fontStyle ,而 background 则从注释中可以看出由于某原因导致 Visual Studio Code 暂时不支持。

scope 值为 template.expression 则可被认为是 CSS 类选择器 token.template.expression ,在前文的 Developer Tools 的演示视频中,模板字符串的变量名在渲染时其 HTML 为 <span class="token block ts meta variable other readwrite string function arrow new expr template expression">...</span> ,如果我们熟悉 CSS 的话应该能一眼就看出来 .token.template.expression 是会匹配到该标签的。所以,我们可以简单地把 scope 当作是 CSS 的类选择器。

需要注意的是,如果我们在定义 scope 时写得不够详细,可能会错误地匹配到其他元素,致使调好了一部分,另一部分却被调坏了,所以要做得完美也并非易事。
发布到扩展商店

要将扩展发布到扩展商店以便让更多人可以使用到,我们需要借助 vsce 命令行工具,可以参考文档 vsce - Publishing Tool Reference 。以下是其基本步骤:

安装 vsce 命令行工具。执行命令 npm install -g vsce
注册 Visual Studio Team Services 账号,并获取到 Access Token
创建 Publisher。执行命令 vsce create-publisher
登录到 Publisher。执行命令 vsce login
发布扩展。执行命令 vsce publish

详细操作步骤建议参考相应的官方文档。

本文并没有详细到手把手教地去讲解如何打造一款 Visual Studio Code 颜色主题,仅仅是提到了几个我在折腾过程中认为比较关键,而又很难通过文档去查到的要点。爱折腾是程序员的天性,希望本文能让爱折腾的你少走一些弯路,把喜爱的 Visual Studio Code 玩出花来。
温馨提示:内容为网友见解,仅供参考
无其他回答

如何打造一款属于自己的 Visual Studio Code 颜色主题
Visual Studio Studio 的颜色主题采用的是标准的 TextMate 主题格式,我们可以参考这篇文章Writing a TextMate Grammar: Some Lessons Learned,大概可以理解为这样:编辑器对代码进行解析后,会为每个元素指定一个scope,这个scope即表明此元素是一个关键字还是一个常量,又或者是一个标点符号,通过tmTheme...

怎么设置Visual Studio代码窗口背景颜色
打开Visual Studio,在菜单栏找到【工具】点击工具栏下的【选项】在选项对话框中,点击【环境】→【字体和颜色】在右侧选择【纯文本】,然后点击项背景色右侧的【自定义】4 在颜色对话框中,右侧色调、饱和度、亮度栏,分别输入84、91、205 单击【添加到自定义颜色】→【确定】5 回到选项对话框中,点...

【VisualStudio Code】怎么配置‘美观实用’的VScode开发环境
首先,从 Visual Studio Code 官网下载对应操作系统(Mac、Linux 或 Windows)的安装包。安装过程非常简单,只需按照安装程序的指引操作,点击“下一步”和“选项”以自定义安装路径和环境包。对于初始界面的配置,推荐安装汉化的插件以提高使用体验。文件图标应选择“Material Icon Theme”,它能提供丰富的...

怎么设置Visual Studio代码窗口背景颜色
第1步,打开VisualStudio。第2步,打开“工具”--“选项”第3步,在“环境”--“常规”--“颜色主题”中,可以进行Visual Studio的主题设定。一共有三个主题供选择,蓝色,浅色,深色(不同版本上可供选择的主题也有区别)。如果选择“蓝色”,“浅色”,则代码窗口的颜色默认是白色的。如果选择“深...

codecomposerstudio怎么设置背景颜色
VisualStudioCode设置主题背景颜色如下:“点击“文件”——“首选项”——“颜色主题”,即可设置背景颜色啦。如果只想更改背景颜色的话,那么在VisualStudioCode编辑模式下依次敲击键盘上的按键Ctrl+K——>Ctrl+t,然后用键盘上的上下键或用鼠标点击即可预览和设置背景颜色。

Visual Studio Code(VSCode)的下载安装、扩展商店、颜色主题
Visual Studio Code (VSCode)的下载、安装、扩展商店、以及颜色主题设置是初学者快速上手的重要步骤。首先,访问官网code.visualstudio.com,选择对应操作系统(如Windows 10 64位)的下载链接。下载时需注意,Windows提供User Installer和System Installer,System版本适合多用户环境。下载完成后,安装时建议勾...

怎么设置Visual Studio代码窗口背景颜色
1、在“工具“菜单下的”选项“里的”环境“下的”字体和颜色“项里修改背景色即可。2、工具:Visual Studio 2010 3、步骤:①打开Visual Studio 2010,单击”工具“,在下拉菜单中单击”选项“:②在弹出的窗口,”环境“下找到”字体和颜色“单击,然后修改项背景色,然后确定即可完成代码窗口颜色的...

如何打造一款属于自己的 Visual Studio Code 颜色主题
无论是对Monokai主题的追求,还是对更顺畅安装体验的期待,或者对新功能的探索,这次更新无疑为用户提供了更多定制和提升工作效率的可能性。如果你是Visual Studio Code的用户,现在正是下载并体验这些新特性的绝佳时机。无论你是新手还是资深开发者,这次的更新都将为你的编码生活带来新的色彩和便利。

visual studio code教程:基础使用和自定义设置
snippet 主体可以这样写,JavaScript 代码:25、Choice是提供可选值的Placeholder。其语法为一系列用逗号隔开,并最终被两个竖线圈起来的枚举值,比如 {1|one,two,three|} 。当光标跳转到该位置的时候,用户将会被提供多个值(one或two或 three)以供选择。工具\/材料 visual studio code Windows系统 ...

Visual Studio 2012怎么设置颜色主题
在“选项”界面,“常规”处,“视觉体验”里面的“颜色主题”下拉框可以选择颜色主题。例如:Blue、浅色、深色等。此处选择“深色”,点击“确定”,重启Visual Studio 2012即可。当然,你还可以下载Visual Studio 2012升级包,升级后,会有更多颜色主题供你选择。方法2:菜单栏点击“工具(T)”,然后...

相似回答