在白天,我常常需要淺色的 VSCode 主題;在夜間,我常常需要深色的 VSCode 主題。我不希望每天手動切換兩次 VSCode 主題,所以我開發了這個可以自動切換主題的 VSCode 擴充套件 —— Dynamic Theme。
特性
- ? 根據時間點自動切換主題
- ? 自定義要切換的深色或淺色主題
- ? 自定義深色或淺色主題的開始時間
- ?? 通過 VSCode 命令更新擴充套件設定
擴充套件的設定項
在專案的 package.json 中宣告擴充套件的設定項。常常將副檔名作為設定項的字首,設定項的預設值也在此處進行宣告,在擴充套件程式碼中通過 VSCode Extension API 進行獲取。
"configuration": [
{
"type": "object",
"title": "Dynamic Theme configuration",
"properties": {
"dynamic-theme.dark": {
"type": "string",
"default": "Default Dark+",
"description": "Dark Theme"
},
"dynamic-theme.light": {
"type": "string",
"default": "Default Light+",
"description": "Light theme"
},
"dynamic-theme.darkTime": {
"type": "string",
"default": "20:00",
"description": "Hour(24h) of the start of the dark theme. Format HH:MM"
},
"dynamic-theme.lightTime": {
"type": "string",
"default": "7:00",
"description": "Hour(24h) of the start of the light theme. Format HH:MM"
}
}
}
]
- dynamic-theme.dark 深色主題
- dynamic-theme.light 淺色主題
- dynamic-theme.darkTime 深色主題開始時間
- dynamic-theme.darkTime 淺色主題開始時間
擴充套件的命令
在專案的 package.json 檔案中宣告擴充套件要註冊的命令。常常將副檔名作為命令的字首,在擴充套件程式碼中通過 VSCode Extension API 獲取命令並進行註冊。
"commands": [
{
"command": "dynamic-theme.dark",
"title": "Dynamic Theme: Set dark theme"
},
{
"command": "dynamic-theme.light",
"title": "Dynamic Theme: Set light theme"
},
{
"command": "dynamic-theme.darkTime",
"title": "Dynamic Theme: Set dark theme time. Format HH:MM"
},
{
"command": "dynamic-theme.lightTime",
"title": "Dynamic Theme: Set light theme time. Format HH:MM"
}
]
- dynamic-theme.dark 設定深色主題
- dynamic-theme.light 設定淺色主題
- dynamic-theme.darkTime 設定深色主題開始時間
- dynamic-theme.darkTime 設定淺色主題開始時間
編寫擴充套件的入口
import { updateTheme } from './update'
import { registerCommands } from './commands'
import { workspace } from 'vscode'
import type { ExtensionContext, ConfigurationChangeEvent, Event } from 'vscode'
export function activate({ subscriptions }: ExtensionContext) {
const { onDidChangeConfiguration } = workspace
updateTheme()
subscriptions.push(
onDidChangeConfiguration(() => updateTheme()),
...registerCommands()
)
}
在擴充套件啟用時將執行 activate
函式。update
函式用於檢查設定並更新 VSCode 主題。
在 subscriptions 中可新增一次性用品(disposables)。當配置發生更改時發出 onDidChangeConfiguration
事件,同樣檢查設定並更新 VSCode 主題。在 subscriptions 還新增了註冊命令。
更新 VSCode 主題
update.ts 就做了一件事,獲取配置,更新主題。
import type { IOptions } from './types'
import {
parseTime,
updateEditorTheme,
getExtensionConfiguration,
} from './helpers'
export function updateTheme() {
const { dark, light, darkTime, lightTime } = getExtensionConfiguration()
const date = new Date()
const hours = date.getHours() + date.getMinutes() / 60
parseTime(lightTime) <= hours && hours < parseTime(darkTime)
? updateEditorTheme(light)
: updateEditorTheme(dark)
}
註冊 VSCode 命令
在 package.json 中宣告瞭四個擴充套件的命令:
- dynamic-theme.dark 設定深色主題
- dynamic-theme.light 設定淺色主題
- dynamic-theme.darkTime 設定深色主題開始時間
- dynamic-theme.darkTime 設定淺色主題開始時間
設定時間時通過 VSCode Extension API 調出一個輸入框即可。設定主題時期望開啟選擇主題 picker,但是貌似 VSCode 貌似並沒有提供這個 API。只好通過讀取所有主題,並生成一個 picker 的方式展示,缺點是無法像設定 VSCode 主題那樣實時預覽主題。
commands.ts
import { commands, window } from 'vscode'
import {
updateExtensionConfiguration,
getThemeList,
parseTime,
} from './helpers'
export enum Commands {
hello = 'helloWorld',
dark = 'dark',
light = 'light',
darkTime = 'darkTime',
lightTime = 'lightTime',
}
const commandPrefix = 'dynamic-theme.'
export function registerCommands() {
const light = commands.registerCommand(commandPrefix + Commands.light, () => {
const themeList = getThemeList()
window.showQuickPick(themeList).then(res => {
if (res !== undefined) {
updateExtensionConfiguration(Commands.light, res)
}
})
})
const dark = commands.registerCommand(commandPrefix + Commands.dark, () => {
const themeList = getThemeList()
window.showQuickPick(themeList).then(res => {
if (res !== undefined) {
updateExtensionConfiguration(Commands.dark, res)
}
})
})
const lightTime = commands.registerCommand(
commandPrefix + Commands.lightTime,
() => {
window.showInputBox().then(res => {
if (res !== undefined) {
updateExtensionConfiguration(Commands.lightTime, res)
}
})
}
)
const darkTime = commands.registerCommand(
commandPrefix + Commands.darkTime,
() => {
window.showInputBox().then((res: any) => {
if (res !== undefined) {
updateExtensionConfiguration(Commands.darkTime, res)
}
})
}
)
return [dark, light, darkTime, lightTime]
}