实现自动切换主题的 VSCode 扩展

在白天,我常常需要浅色的 VSCode 主题;在夜间,我常常需要深色的 VSCode 主题。我不希望每天手动切换两次 VSCode 主题,所以我开发了这个可以自动切换主题的 VSCode 扩展 —— Dynamic Theme。

image

特性

  • 🌄 根据时间点自动切换主题
  • 🎨 自定义要切换的深色或浅色主题
  • 🕔 自定义深色或浅色主题的开始时间
  • 👨‍💻 通过 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 主题那样实时预览主题。

image

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]
}

链接

posted @ 2021-08-08 17:29  guangzan  阅读(1549)  评论(0编辑  收藏  举报