mirror of
https://github.com/quine-global/hyper.git
synced 2026-01-12 20:18:41 -09:00
add config types
This commit is contained in:
parent
b099bb1218
commit
6debd1e7f2
11 changed files with 147 additions and 58 deletions
|
|
@ -5,12 +5,13 @@ import _openConfig from './config/open';
|
|||
import win from './config/windows';
|
||||
import {cfgPath, cfgDir} from './config/paths';
|
||||
import {getColorMap} from './utils/colors';
|
||||
import {parsedConfig, configOptions} from '../lib/config';
|
||||
|
||||
const watchers: any[] = [];
|
||||
let cfg: Record<string, any> = {};
|
||||
let cfg: parsedConfig = {} as any;
|
||||
let _watcher: fs.FSWatcher;
|
||||
|
||||
export const getDeprecatedCSS = (config: Record<string, any>) => {
|
||||
export const getDeprecatedCSS = (config: configOptions) => {
|
||||
const deprecated: string[] = [];
|
||||
const deprecatedCSS = ['x-screen', 'x-row', 'cursor-node', '::selection'];
|
||||
deprecatedCSS.forEach((css) => {
|
||||
|
|
@ -124,15 +125,15 @@ export const getWin = win.get;
|
|||
export const winRecord = win.recordState;
|
||||
export const windowDefaults = win.defaults;
|
||||
|
||||
export const fixConfigDefaults = (decoratedConfig: any) => {
|
||||
const defaultConfig = getDefaultConfig()?.config;
|
||||
export const fixConfigDefaults = (decoratedConfig: configOptions) => {
|
||||
const defaultConfig = getDefaultConfig().config!;
|
||||
decoratedConfig.colors = getColorMap(decoratedConfig.colors) || {};
|
||||
// We must have default colors for xterm css.
|
||||
decoratedConfig.colors = Object.assign({}, defaultConfig.colors, decoratedConfig.colors);
|
||||
decoratedConfig.colors = {...defaultConfig.colors, ...decoratedConfig.colors};
|
||||
return decoratedConfig;
|
||||
};
|
||||
|
||||
export const htermConfigTranslate = (config: Record<string, any>) => {
|
||||
export const htermConfigTranslate = (config: configOptions) => {
|
||||
const cssReplacements: Record<string, string> = {
|
||||
'x-screen x-row([ {.[])': '.xterm-rows > div$1',
|
||||
'.cursor-node([ {.[])': '.terminal-cursor$1',
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@ import {sync as mkdirpSync} from 'mkdirp';
|
|||
import {defaultCfg, cfgPath, legacyCfgPath, plugs, defaultPlatformKeyPath} from './paths';
|
||||
import {_init, _extractDefault} from './init';
|
||||
import notify from '../notify';
|
||||
import {rawConfig} from '../../lib/config';
|
||||
|
||||
let defaultConfig: Record<string, any> | undefined;
|
||||
let defaultConfig: rawConfig;
|
||||
|
||||
const _write = (path: string, data: any) => {
|
||||
// This method will take text formatted as Unix line endings and transform it
|
||||
|
|
@ -92,41 +93,46 @@ const _importConf = () => {
|
|||
console.error(err);
|
||||
}
|
||||
|
||||
let defaultCfgRaw = '';
|
||||
try {
|
||||
const defaultCfgRaw = readFileSync(defaultCfg, 'utf8');
|
||||
const _defaultCfg = _extractDefault(defaultCfgRaw);
|
||||
// Importing platform specific keymap
|
||||
try {
|
||||
const content = readFileSync(defaultPlatformKeyPath(), 'utf8');
|
||||
const mapping = JSON.parse(content) as Record<string, string | string[]>;
|
||||
_defaultCfg.keymaps = mapping;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
// Import user config
|
||||
try {
|
||||
const userCfg = readFileSync(cfgPath, 'utf8');
|
||||
return {userCfg, defaultCfg: _defaultCfg};
|
||||
} catch (err) {
|
||||
_write(cfgPath, defaultCfgRaw);
|
||||
return {userCfg: defaultCfgRaw, defaultCfg: _defaultCfg};
|
||||
}
|
||||
defaultCfgRaw = readFileSync(defaultCfg, 'utf8');
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
const _defaultCfg = _extractDefault(defaultCfgRaw) as rawConfig;
|
||||
|
||||
// Importing platform specific keymap
|
||||
let content = '{}';
|
||||
try {
|
||||
content = readFileSync(defaultPlatformKeyPath(), 'utf8');
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
const mapping = JSON.parse(content) as Record<string, string | string[]>;
|
||||
_defaultCfg.keymaps = mapping;
|
||||
|
||||
// Import user config
|
||||
let userCfg: string;
|
||||
try {
|
||||
userCfg = readFileSync(cfgPath, 'utf8');
|
||||
} catch (err) {
|
||||
_write(cfgPath, defaultCfgRaw);
|
||||
userCfg = defaultCfgRaw;
|
||||
}
|
||||
|
||||
return {userCfg, defaultCfg: _defaultCfg};
|
||||
};
|
||||
|
||||
export const _import = () => {
|
||||
const imported = _importConf();
|
||||
defaultConfig = imported?.defaultCfg;
|
||||
defaultConfig = imported.defaultCfg;
|
||||
const result = _init(imported!);
|
||||
return result;
|
||||
};
|
||||
|
||||
export const getDefaultConfig = () => {
|
||||
if (!defaultConfig) {
|
||||
defaultConfig = _importConf()?.defaultCfg;
|
||||
defaultConfig = _importConf().defaultCfg;
|
||||
}
|
||||
return defaultConfig;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import vm from 'vm';
|
||||
import notify from '../notify';
|
||||
import mapKeys from '../utils/map-keys';
|
||||
import {parsedConfig, rawConfig, configOptions} from '../../lib/config';
|
||||
|
||||
const _extract = (script?: vm.Script): Record<string, any> => {
|
||||
const module: Record<string, any> = {};
|
||||
|
|
@ -24,22 +25,24 @@ const _extractDefault = (cfg: string) => {
|
|||
};
|
||||
|
||||
// init config
|
||||
const _init = (cfg: {userCfg: string; defaultCfg: Record<string, any>}) => {
|
||||
const _init = (cfg: {userCfg: string; defaultCfg: rawConfig}): parsedConfig => {
|
||||
const script = _syntaxValidation(cfg.userCfg);
|
||||
if (script) {
|
||||
const _cfg = _extract(script);
|
||||
if (!_cfg.config) {
|
||||
const _cfg = script && (_extract(script) as rawConfig);
|
||||
return {
|
||||
config: (() => {
|
||||
if (_cfg?.config) {
|
||||
return _cfg.config;
|
||||
} else {
|
||||
notify('Error reading configuration: `config` key is missing');
|
||||
return cfg.defaultCfg;
|
||||
return cfg.defaultCfg.config || ({} as configOptions);
|
||||
}
|
||||
})(),
|
||||
// Merging platform specific keymaps with user defined keymaps
|
||||
_cfg.keymaps = mapKeys(Object.assign({}, cfg.defaultCfg.keymaps, _cfg.keymaps));
|
||||
keymaps: mapKeys({...cfg.defaultCfg.keymaps, ..._cfg?.keymaps}),
|
||||
// Ignore undefined values in plugin and localPlugins array Issue #1862
|
||||
_cfg.plugins = (_cfg.plugins && _cfg.plugins.filter(Boolean)) || [];
|
||||
_cfg.localPlugins = (_cfg.localPlugins && _cfg.localPlugins.filter(Boolean)) || [];
|
||||
return _cfg;
|
||||
}
|
||||
return cfg.defaultCfg;
|
||||
plugins: (_cfg?.plugins && _cfg.plugins.filter(Boolean)) || [],
|
||||
localPlugins: (_cfg?.localPlugins && _cfg.localPlugins.filter(Boolean)) || []
|
||||
};
|
||||
};
|
||||
|
||||
export {_init, _extractDefault};
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import {availableExtensions} from './plugins/extensions';
|
|||
import {install} from './plugins/install';
|
||||
import {plugs} from './config/paths';
|
||||
import mapKeys from './utils/map-keys';
|
||||
import {configOptions} from '../lib/config';
|
||||
|
||||
// local storage
|
||||
const cache = new Config();
|
||||
|
|
@ -187,10 +188,7 @@ if (cache.get('hyper.plugins') !== id || process.env.HYPER_FORCE_UPDATE) {
|
|||
const baseConfig = config.getConfig();
|
||||
if (baseConfig['autoUpdatePlugins']) {
|
||||
// otherwise update plugins every 5 hours
|
||||
setInterval(
|
||||
updatePlugins,
|
||||
ms(baseConfig['autoUpdatePlugins'] === true ? '5h' : (baseConfig['autoUpdatePlugins'] as string))
|
||||
);
|
||||
setInterval(updatePlugins, ms(baseConfig['autoUpdatePlugins'] === true ? '5h' : baseConfig['autoUpdatePlugins']));
|
||||
}
|
||||
})();
|
||||
|
||||
|
|
@ -372,7 +370,7 @@ function decorateEntity(base: any, key: string, type: 'object' | 'function') {
|
|||
return decorated;
|
||||
}
|
||||
|
||||
function decorateObject(base: any, key: string) {
|
||||
function decorateObject<T>(base: T, key: string): T {
|
||||
return decorateEntity(base, key, 'object');
|
||||
}
|
||||
|
||||
|
|
@ -381,14 +379,14 @@ function decorateClass(base: any, key: string) {
|
|||
}
|
||||
|
||||
export const getDeprecatedConfig = () => {
|
||||
const deprecated: Record<string, any> = {};
|
||||
const deprecated: Record<string, {css: string[]}> = {};
|
||||
const baseConfig = config.getConfig();
|
||||
modules.forEach((plugin) => {
|
||||
if (!plugin.decorateConfig) {
|
||||
return;
|
||||
}
|
||||
// We need to clone config in case of plugin modifies config directly.
|
||||
let configTmp;
|
||||
let configTmp: configOptions;
|
||||
try {
|
||||
configTmp = plugin.decorateConfig(JSON.parse(JSON.stringify(baseConfig)));
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
import {CONFIG_LOAD, CONFIG_RELOAD} from '../constants/config';
|
||||
import {HyperActions} from '../hyper';
|
||||
import {configOptions} from '../config';
|
||||
|
||||
export function loadConfig(config: any): HyperActions {
|
||||
export function loadConfig(config: configOptions): HyperActions {
|
||||
return {
|
||||
type: CONFIG_LOAD,
|
||||
config
|
||||
};
|
||||
}
|
||||
|
||||
export function reloadConfig(config: any): HyperActions {
|
||||
export function reloadConfig(config: configOptions): HyperActions {
|
||||
const now = Date.now();
|
||||
return {
|
||||
type: CONFIG_RELOAD,
|
||||
|
|
|
|||
77
lib/config.d.ts
vendored
Normal file
77
lib/config.d.ts
vendored
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
import {FontWeight} from 'xterm';
|
||||
|
||||
export type configOptions = {
|
||||
autoUpdatePlugins: boolean | string;
|
||||
backgroundColor: string;
|
||||
bell: string;
|
||||
bellSound: string | null;
|
||||
bellSoundURL: string | null;
|
||||
borderColor: string;
|
||||
colors: {
|
||||
black: string;
|
||||
blue: string;
|
||||
cyan: string;
|
||||
green: string;
|
||||
lightBlack: string;
|
||||
lightBlue: string;
|
||||
lightCyan: string;
|
||||
lightGreen: string;
|
||||
lightMagenta: string;
|
||||
lightRed: string;
|
||||
lightWhite: string;
|
||||
lightYellow: string;
|
||||
magenta: string;
|
||||
red: string;
|
||||
white: string;
|
||||
yellow: string;
|
||||
};
|
||||
copyOnSelect: boolean;
|
||||
css: string;
|
||||
cursorAccentColor: string;
|
||||
cursorBlink: boolean;
|
||||
cursorColor: string;
|
||||
cursorShape: 'BEAM' | 'UNDERLINE' | 'BLOCK';
|
||||
defaultSSHApp: boolean;
|
||||
disableLigatures: boolean;
|
||||
env: Record<string, string>;
|
||||
fontFamily: string;
|
||||
fontSize: number;
|
||||
fontWeight: FontWeight;
|
||||
fontWeightBold: FontWeight;
|
||||
foregroundColor: string;
|
||||
letterSpacing: number;
|
||||
lineHeight: number;
|
||||
macOptionSelectionMode: string;
|
||||
modifierKeys: {
|
||||
altIsMeta: boolean;
|
||||
cmdIsMeta: boolean;
|
||||
};
|
||||
padding: string;
|
||||
quickEdit: boolean;
|
||||
scrollback: number;
|
||||
selectionColor: string;
|
||||
shell: string;
|
||||
shellArgs: string[];
|
||||
showHamburgerMenu: boolean | '';
|
||||
showWindowControls: string;
|
||||
termCSS: string;
|
||||
uiFontFamily: string;
|
||||
updateChannel: 'stable' | 'canary';
|
||||
useConpty: boolean;
|
||||
webGLRenderer: boolean;
|
||||
windowSize: [number, number];
|
||||
};
|
||||
|
||||
export type rawConfig = {
|
||||
config?: configOptions;
|
||||
plugins?: string[];
|
||||
localPlugins?: string[];
|
||||
keymaps?: Record<string, string | string[]>;
|
||||
};
|
||||
|
||||
export type parsedConfig = {
|
||||
config: configOptions;
|
||||
plugins: string[];
|
||||
localPlugins: string[];
|
||||
keymaps: Record<string, string[]>;
|
||||
};
|
||||
|
|
@ -1,15 +1,17 @@
|
|||
import {configOptions} from '../config';
|
||||
|
||||
export const CONFIG_LOAD = 'CONFIG_LOAD';
|
||||
export const CONFIG_RELOAD = 'CONFIG_RELOAD';
|
||||
|
||||
export interface ConfigLoadAction {
|
||||
type: typeof CONFIG_LOAD;
|
||||
config: any;
|
||||
config: configOptions;
|
||||
now?: number;
|
||||
}
|
||||
|
||||
export interface ConfigReloadAction {
|
||||
type: typeof CONFIG_RELOAD;
|
||||
config: any;
|
||||
config: configOptions;
|
||||
now: number;
|
||||
}
|
||||
|
||||
|
|
|
|||
2
lib/hyper.d.ts
vendored
2
lib/hyper.d.ts
vendored
|
|
@ -96,7 +96,7 @@ export type uiState = {
|
|||
rows: number | null;
|
||||
scrollback: number;
|
||||
selectionColor: string;
|
||||
showHamburgerMenu: string;
|
||||
showHamburgerMenu: boolean | '';
|
||||
showWindowControls: string;
|
||||
termCSS: string;
|
||||
uiFontFamily: string;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import {addNotificationMessage} from './actions/notifications';
|
|||
import {loadConfig, reloadConfig} from './actions/config';
|
||||
import HyperContainer from './containers/hyper';
|
||||
import configureStore from './store/configure-store';
|
||||
import {configOptions} from './config';
|
||||
|
||||
// On Linux, the default zoom was somehow changed with Electron 3 (or maybe 2).
|
||||
// Setting zoom factor to 1.2 brings back the normal default size
|
||||
|
|
@ -31,8 +32,8 @@ Object.defineProperty(window, 'rpc', {get: () => rpc});
|
|||
Object.defineProperty(window, 'config', {get: () => config});
|
||||
Object.defineProperty(window, 'plugins', {get: () => plugins});
|
||||
|
||||
const fetchFileData = (configData: any) => {
|
||||
const configInfo = Object.assign({}, configData, {bellSound: null});
|
||||
const fetchFileData = (configData: configOptions) => {
|
||||
const configInfo: configOptions = {...configData, bellSound: null};
|
||||
if (!configInfo.bell || configInfo.bell.toUpperCase() !== 'SOUND' || !configInfo.bellSoundURL) {
|
||||
store_.dispatch(reloadConfig(configInfo));
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ const reducer = (state = initial, action: HyperActions) => {
|
|||
ret.modifierKeys = config.modifierKeys;
|
||||
}
|
||||
|
||||
if (allowedHamburgerMenuValues.has(config.showHamburgerMenu)) {
|
||||
if (allowedHamburgerMenuValues.has(config.showHamburgerMenu as any)) {
|
||||
ret.showHamburgerMenu = config.showHamburgerMenu;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -363,10 +363,10 @@ const loadModules = () => {
|
|||
})
|
||||
.filter((mod: any) => Boolean(mod));
|
||||
|
||||
const deprecatedPlugins: Record<string, any> = plugins.getDeprecatedConfig();
|
||||
const deprecatedPlugins = plugins.getDeprecatedConfig();
|
||||
Object.keys(deprecatedPlugins).forEach((name) => {
|
||||
const {css} = deprecatedPlugins[name];
|
||||
if (css) {
|
||||
if (css.length > 0) {
|
||||
console.warn(`Warning: "${name}" plugin uses some deprecated CSS classes (${css.join(', ')}).`);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue