Skip to content

Instantly share code, notes, and snippets.

@hangxingliu
Last active July 22, 2023 09:51
Show Gist options
  • Save hangxingliu/c18a96779b538001607672bb70d369af to your computer and use it in GitHub Desktop.
Save hangxingliu/c18a96779b538001607672bb70d369af to your computer and use it in GitHub Desktop.
A script for fix Solarized theme in VSCode from 1.12.0 looks like sxxt
#!/usr/bin/env node
//@ts-check
/// <reference types="node" />
// https://github.com/microsoft/vscode/blob/main/extensions/theme-solarized-light/themes/solarized-light-color-theme.json
const VERSION = "2023-07-22";
const AUTHOR = "Liu Yue <hangxingliu@gmail.com>";
const IS_WINDOWS = process.platform == "win32";
const IS_OSX = process.platform == "darwin";
const VSCODE_PATH_WIN = [
"C:/Program Files (x86)/Microsoft VS Code",
"C:/Program Files/Microsoft VS Code",
];
const VSCODE_PATH_OSX = ["/Applications/Visual Studio Code.app/Contents"];
const VSCODE_PATH_LINUX = ["/usr/share/code"];
const VSCODE_PATH_WSL = [
"/mnt/c/Program Files (x86)/Microsoft VS Code",
"/mnt/c/Program Files/Microsoft VS Code",
];
const RESOURCE_DIR = IS_OSX ? "Resources" : "resources";
const EXTENSION_DIR = `${RESOURCE_DIR}/app/extensions`;
const THEME_FILE = `${EXTENSION_DIR}/theme-solarized-light/themes/solarized-light-color-theme.json`;
/** @type {string[]} */
const VSCODE_PATH = [];
if (IS_WINDOWS) VSCODE_PATH.push(...VSCODE_PATH_WIN);
else if (IS_OSX) VSCODE_PATH.push(...VSCODE_PATH_OSX);
else VSCODE_PATH.push(...VSCODE_PATH_LINUX.concat(VSCODE_PATH_WSL));
const WELCOME_INFO = [
`Version: ${VERSION}`,
`Author: ${AUTHOR}`,
"Description: A script for fixing the VSCode Solarized theme that looks like sxxt since version 1.12.0",
"Details:",
" 1. Remove all shit color in blocks of VSCode",
" 2. Change comments from italic to normal",
"Usage:",
" You can provide a parameter to this script as a custom path for VSCode",
" The default paths to locate VSCode are:",
"",
...VSCODE_PATH.map((it) => " " + it),
"",
];
const { join } = require("path");
const { existsSync, writeFileSync, readFileSync } = require("fs");
const dim = (str = "") => `\u001b[2m${str}\u001b[22m`;
const highlight = (str = "") => `\u001b[36m${str}\u001b[39m`;
(function main() {
const args = process.argv.slice(2);
console.log(WELCOME_INFO.join("\n"));
if (args.includes("-h") || args.includes("--help")) return;
if (args[0] === "--debug") return foundThemeFile(args[1]);
let vscodeDirs = VSCODE_PATH;
if (args.length > 0) {
vscodeDirs = args;
console.log("Use the following user-provided path to locate VSCode:");
vscodeDirs.forEach((path) => console.log(dim(` ${path}`)));
}
const filePath = vscodeDirs
.map((it) => join(it, THEME_FILE))
.filter((it) => existsSync(it))[0];
if (!filePath) return fatal(`Can't find VSCode from the paths`);
console.log(`Found VSCode theme file from:\n ${highlight(filePath)}`);
foundThemeFile(filePath);
})();
/** @param {string} filePath */
function foundThemeFile(filePath) {
let json = readText(filePath);
backup();
modify();
function backup() {
console.log("Backing up the theme file ...");
let backupFile = filePath + ".backup";
if (existsSync(backupFile)) return;
writeText(backupFile, json);
console.log(dim(`Backed up original file to:\n ${backupFile}`));
}
function modify() {
//remove comments in JSON
json = json.replace(/\/\/.+$/gm, "");
const obj = JSON.parse(json);
const { colors, tokenColors } = obj;
if (!colors) fatal("`colors` doesn't exist");
if (!Array.isArray(tokenColors))
return fatal("`tokenColors` is not an array");
/**
* @param {string[]} names
* @param {(it:any)=>boolean|undefined} callback
*/
const modifyTokenColor = (names, callback) => {
const items = tokenColors.filter((it) => names.includes(it.name));
if (items.length < 1)
fatal(`Could not find any item about [${names}] from \`tokenColors\``);
items.forEach((it) => {
if (callback(it) === false) return;
console.log(dim(` Updated: ${JSON.stringify(it)}`));
});
};
const modifyColor = (name = "", newValue = "") => {
const prev = colors[name];
if (prev === newValue) return;
if (!newValue) {
console.log(dim(` Deleted: ${name}`));
delete colors[name];
} else {
const log = ` Updated: ${name} = "${newValue}"`;
const comment = prev ? `# original color: ${prev}` : `# new`;
console.log(dim(log.padEnd(64) + comment));
colors[name] = newValue;
}
};
console.log("Fixing comment font ...");
modifyTokenColor(["Comment", "Comments"], (it) => {
if (it.settings.fontStyle !== "italic") return false;
it.settings.fontStyle = "normal";
});
console.log("Fixing color for class name ...");
modifyTokenColor(["Class name"], (it) => {
if (!it.settings.foreground) return false;
it.settings.foreground = "#268BD2";
});
console.log("Fixing color for `Support.construct` ...");
modifyTokenColor(["Support.construct"], (it) => {
if (!it.settings.foreground) return false;
it.settings.foreground = "#D30102";
});
console.log("Fixing default foreground color ...");
const items = tokenColors.filter((it) => !it.name && !it.scope);
if (items.length < 1)
return fatal("Could not find default setting in `tokenColors`");
items.forEach((it) => {
if (!it.settings.foreground) return;
it.settings.foreground = "#586E75";
console.log(dim(` Updated: ${JSON.stringify(it)}`));
});
console.log("Removing terminal colors overwrite ...");
for (const colorName of Object.keys(colors))
if (colorName.startsWith("terminal.")) modifyColor(colorName, "");
console.log("Overwriting editor colors ...");
modifyColor("editor.background", "#FDF6E3");
modifyColor("editor.selectionBackground", "#586E75");
modifyColor("editor.inactiveSelectionBackground", "#EEE8D5");
modifyColor("badge.background", "#007ACC");
modifyColor("activityBarBadge.background", "#007ACC");
modifyColor("editorSuggestWidget.background", "#FFFDF9"); // background - 0.05
modifyColor("editorSuggestWidget.selectedBackground", "#FDF6E3"); // background
modifyColor("editorHoverWidget.background", "#FFFDF9"); // background - 0.05
modifyColor("sideBar.background", "#F4F1E5"); // "sideBar.background": "#EEE8D5" - 0.05
console.log("Saving modified theme ...");
writeText(filePath, JSON.stringify(obj, null, "\t"));
console.log(
"\nSuccess: The theme has been saved! (please reload VSCode for applying)\n"
);
}
}
function fatal(reason = "") {
console.error(`\n\u001b[31mError: ${reason}\u001b[39m\n`);
return process.exit(1);
}
function onPermissionError(reason = "") {
const admin = IS_WINDOWS ? "administrator" : "root";
const msg = `You have not permission to ${reason}, Please make sure you are ${admin}`;
return fatal(msg);
}
function writeText(filePath, content) {
try {
writeFileSync(filePath, content);
} catch (error) {
console.error(`\u001b[31mError: ${error.message}\u001b[39m`);
return onPermissionError(`edit ${filePath}`);
}
}
function readText(filePath) {
try {
return readFileSync(filePath, "utf-8");
} catch (error) {
console.error(`\u001b[31mError: ${error.message}\u001b[39m`);
if (error.code !== "ENOENT") return fatal(`file doesn't exist`);
return onPermissionError(`read file`);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment