自制Vscode插件,到点自动切换主题 auto-theme-switch

511 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第22天,点击查看活动详情

我平时在亮环境中会使用亮色主题,暗环境中会使用暗色主题,一般来说都是早上和晚上切换,都是手动进行切换,但是每天都手动切换就很不程序员了,所以就决定搞个到点切换主题的时间插件

目前已经发布,感兴趣的可以看看 auto-theme-switch

初始化插件模板

初始化就直接根据 Vscode文档

npm install -g yo generator-code

生成出代码之后,先配置一下希望要的配置,我期望能够配置:

  • 自定义暗亮色主题
  • 自定义时间
  • 自定义开关

然后需要在package.json中描述配置,后面这些配置就会在安装了插件的 vscode 中出现

 "contributes": {
    "configuration": {
      "type": "object",
      "title": "auto-theme-switch",
      "properties": {
        "switchConfig.darkTheme": {
          "type": "string",
          "default": "Visual Studio Dark",
          "description": "Dark Theme"
        },
        "switchConfig.lightTheme": {
          "type": "string",
          "default": "Visual Studio Light",
          "description": "Light theme"
        },
        "switchConfig.darkTime": {
          "type": "string",
          "default": "18:00",
          "description": "switch to dark theme at this time"
        },
        "switchConfig.lightTime": {
          "type": "string",
          "default": "6:00",
          "description": "switch to light theme at this time"
        },
        "switchConfig.open": {
          "type": "boolean",
          "default": true,
          "description": "whether open auto-theme-switch"
        }
      }
    }
  }

读取配置

配置完想要的配置就要去读取了,先写下读取配置的方法

// src/config.js
import { workspace,ConfigurationChangeEvent, Disposable } from "vscode";

let listener: Disposable;

export interface Config {
  darkTheme: string;
  lightTheme: string;
  darkTime: string;
  lightTime: string;
  open: boolean,
}
export const config: Config = {
  darkTheme: "",
  lightTheme: "",
  darkTime: "",
  lightTime: "",
  open: true,
};

export function getConfig(e?: ConfigurationChangeEvent) {
  if (e && !e.affectsConfiguration("switchConfig")) return;
  const switchConfig = workspace.getConfiguration("switchConfig");
  config.darkTheme = switchConfig.get("darkTheme", "Visual Studio Dark");
  config.lightTheme = switchConfig.get("lightTheme", "Visual Studio Light");
  config.darkTime = switchConfig.get("darkTime", "18:00");
  config.lightTime = switchConfig.get("lightTime", "6:00");
  config.open = switchConfig.get("open", true);
}

export function configActivate(callback: () => void) {
  listener = workspace.onDidChangeConfiguration((e: ConfigurationChangeEvent) => {
    getConfig(e);
    callback();
  });
}
export function configDeactivate() {
  listener.dispose();
}

用 getConfig 读取配置,并且用 workspace.onDidChangeConfiguration 来监听配置的改变,本来可以只读 vscode 初始化的一次,但为了动态修改,就加上了,顺便再加上取消的函数

然后在 extension.ts 入口函数和销毁函数里写下这两个函数

// src/extension.ts
export function activate() {
  getConfig();
   configActivate(() => {
       // 这里等会用来监听改变重新启动监听即可
   });
}
export function deactivate() {
  configDeactivate();
}

切换主题

简单写下时间的判断,通过 userConfig.update 更新主题的字段值,并且启动定时任务

// src/extension.ts
import { workspace } from 'vscode';
import { config, getConfig, configActivate, configDeactivate } from './config';
import { getHours, getNow, scheduleEvery } from './utils';

const THEME_KEY = 'workbench.colorTheme';
const userConfig = workspace.getConfiguration();

export function switchThemeByTime() {
  if(!config.open) return;

  const hours = getNow();
  const lightTime = getHours(config.lightTime);
  const darkTime = getHours(config.darkTime);

  if (lightTime <= hours && hours < darkTime) {
    userConfig.update(THEME_KEY, config.lightTheme, true);
    scheduleEvery(darkTime);
  } else {
    userConfig.update(THEME_KEY, config.darkTheme, true);
    scheduleEvery(hours + lightTime);
  }
}

定时也是简单的用了 setTimeout

// src/utils.ts
import { switchThemeByTime } from "./extension";

export function getNow():number {
  const time = new Date();
  return time.getHours() + time.getMinutes() / 60;
}

export function getHours(timeStr: string):number  {
  const time = timeStr.split(':');
  return +time[0] + +time[1] / 60;
}

let timer: NodeJS.Timeout;
export function scheduleEvery(hours: number) {
  const now = getNow();
  const diff = hours - now;
  clearTimeout(timer);
  timer = setTimeout(() => {
    switchThemeByTime();
  }, diff * 60 * 60 * 1000);
}

现在功能已经开发完成,F5 即可测试,后面就是打包发布了,仓库在这里

image.png

总结

其实以前也写过两个插件,一个是 wxml 格式化小程序,一个是周杰伦定时叫喝水,所以写起来还是很顺手的,本来想在底部栏加个开关的,方便关闭,因为有时候白天也有暗的情况,有机会再加上