實現自動切換主題的 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]
}

鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章