实现自动切换主题的 VSCode 扩展
在白天,我常常需要浅色的 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]
}

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号