UNPKG

alacritty-theme-switch

Version:
161 lines (160 loc) 8.49 kB
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var _ThemeManager_instances, _ThemeManager_config, _ThemeManager_themes, _ThemeManager_themesPaths, _ThemeManager_backupPath, _ThemeManager_configPath, _ThemeManager_setConfig, _ThemeManager_getActiveThemes; import { errAsync, okAsync, ResultAsync } from "neverthrow"; import { DirectoryIsFileError } from "../utils/fs-errors.js"; import { safeEnsureDir, safeStat, safeWalkAll, } from "../utils/fs-utils.js"; import { isToml, safeParseToml } from "../utils/toml-utils.js"; import { createBackup, parseConfig, writeConfigToFile, } from "./config-operations.js"; import { NoThemesFoundError, ThemeNotFoundError, ThemeNotTOMLError, } from "./errors.js"; import { Theme } from "./theme.js"; /** * Theme manager encapsulates all operations related to theme management. * @internal Use `createThemeManager` to create an instance. */ class ThemeManager { constructor(config, themes, backupPath, configPath) { _ThemeManager_instances.add(this); /** Alacritty configuration */ _ThemeManager_config.set(this, void 0); /** All available themes */ _ThemeManager_themes.set(this, void 0); /** Set of all available themes' paths */ _ThemeManager_themesPaths.set(this, void 0); /** Path to the backup file */ _ThemeManager_backupPath.set(this, void 0); /** Path to the Alacritty configuration file */ _ThemeManager_configPath.set(this, void 0); __classPrivateFieldSet(this, _ThemeManager_config, config, "f"); __classPrivateFieldSet(this, _ThemeManager_themes, themes, "f"); __classPrivateFieldSet(this, _ThemeManager_themesPaths, new Set(themes.map((theme) => theme.path)), "f"); __classPrivateFieldSet(this, _ThemeManager_backupPath, backupPath, "f"); __classPrivateFieldSet(this, _ThemeManager_configPath, configPath, "f"); } /** * Configuration getter * @returns The current parsed Alacritty configuration */ getConfig() { return __classPrivateFieldGet(this, _ThemeManager_config, "f"); } /** * Lists themes. * @returns A list of all available themes */ listThemes() { const activeThemes = __classPrivateFieldGet(this, _ThemeManager_instances, "m", _ThemeManager_getActiveThemes).call(this); return __classPrivateFieldGet(this, _ThemeManager_themes, "f").map((theme) => new Theme(theme.path, theme.themeContent, activeThemes.has(theme.path))); } /** * Returns the first active theme. */ getFirstActiveTheme() { const activeThemes = __classPrivateFieldGet(this, _ThemeManager_instances, "m", _ThemeManager_getActiveThemes).call(this); return __classPrivateFieldGet(this, _ThemeManager_themes, "f").find((theme) => activeThemes.has(theme.path)); } /** * Applies the selected theme to the Alacritty configuration. * @param selectedTheme - Theme to apply * @returns A ResultAsync containing the applied theme or an error */ applyTheme(selectedTheme) { return createBackup(__classPrivateFieldGet(this, _ThemeManager_configPath, "f"), __classPrivateFieldGet(this, _ThemeManager_backupPath, "f")) .andThen(() => { const newConfig = structuredClone(this.getConfig()); newConfig.general ??= {}; newConfig.general.import ??= []; // Remove all themes from import entries first newConfig.general.import = newConfig.general.import.filter((importEntryPath) => !__classPrivateFieldGet(this, _ThemeManager_themesPaths, "f").has(importEntryPath)); // Then add the selected theme there newConfig.general.import.push(selectedTheme.path); return okAsync(newConfig); }) .andThen((newConfig) => { return writeConfigToFile(__classPrivateFieldGet(this, _ThemeManager_configPath, "f"), newConfig).map(() => { __classPrivateFieldGet(this, _ThemeManager_instances, "m", _ThemeManager_setConfig).call(this, newConfig); return selectedTheme; }); }); } /** * Applies the theme with the given filename. * @param name - Filename of the theme to apply * @returns A ResultAsync containing the applied theme or an error */ applyThemeByFilename(name) { const theme = this.listThemes().find((theme) => theme.path.endsWith(name)); if (theme === undefined) { return errAsync(new ThemeNotFoundError(name)); } if (!isToml(theme.path)) { return errAsync(new ThemeNotTOMLError(theme.path)); } return safeStat(theme.path) .andThen(() => this.applyTheme(theme)) .mapErr((error) => new ThemeNotFoundError(theme.path, { cause: error })); } /** * Loads all themes from the given directory. * If the directory doesn't exist, it will be created. * If the directory exists but is a file, an error will be returned. * If the directory exists and contains TOML files, they will be parsed and returned. * If the directory exists and contains no TOML files, an error will be returned. * * @param themeDirPath - Path to the directory containing custom themes' files * @returns A ResultAsync containing an array of all themes or an error */ static loadThemes(themeDirPath) { return safeEnsureDir(themeDirPath) .andThen(() => safeStat(themeDirPath)) .andThen((stat) => { return stat.isFile ? errAsync(new DirectoryIsFileError(themeDirPath)) : okAsync(stat); }) .andThen(() => { const entriesResult = safeWalkAll(themeDirPath, { exts: ["toml"], includeFiles: true, includeDirs: false, }); return entriesResult.andThen((entries) => { if (entries.length === 0) { return errAsync(new NoThemesFoundError(themeDirPath)); } const themesResults = entries.map((entry) => { return safeParseToml(entry.path).map((themeContent) => new Theme(entry.path, themeContent, null)); }); return ResultAsync.combine(themesResults); }); }); } } _ThemeManager_config = new WeakMap(), _ThemeManager_themes = new WeakMap(), _ThemeManager_themesPaths = new WeakMap(), _ThemeManager_backupPath = new WeakMap(), _ThemeManager_configPath = new WeakMap(), _ThemeManager_instances = new WeakSet(), _ThemeManager_setConfig = function _ThemeManager_setConfig(config) { __classPrivateFieldSet(this, _ThemeManager_config, config, "f"); }, _ThemeManager_getActiveThemes = function _ThemeManager_getActiveThemes() { const config = this.getConfig(); const imports = config.general?.import ?? []; const activeThemes = imports.filter((i) => __classPrivateFieldGet(this, _ThemeManager_themesPaths, "f").has(i)); return new Set(activeThemes); }; /** * Factory function for creating a theme manager. */ export function createThemeManager(params) { return ThemeManager.loadThemes(params.themesDirPath) .andThen((themes) => { return parseConfig(params.configPath).map((config) => { return new ThemeManager(config, themes, params.backupPath, params.configPath); }); }); }