2017-09-16 03:49:10 -08:00
|
|
|
const fs = require('fs');
|
2016-07-08 06:40:27 -08:00
|
|
|
const notify = require('./notify');
|
2018-04-16 06:17:17 -08:00
|
|
|
const {_import, getDefaultConfig} = require('./config/import');
|
2017-05-26 08:23:25 -08:00
|
|
|
const _openConfig = require('./config/open');
|
2017-06-02 16:03:47 -08:00
|
|
|
const win = require('./config/windows');
|
|
|
|
|
const {cfgPath, cfgDir} = require('./config/paths');
|
2018-04-16 06:17:17 -08:00
|
|
|
const {getColorMap} = require('./utils/colors');
|
2017-01-04 16:05:19 -09:00
|
|
|
|
2016-07-07 07:16:48 -08:00
|
|
|
const watchers = [];
|
2016-07-07 06:46:58 -08:00
|
|
|
let cfg = {};
|
2017-08-12 14:23:48 -08:00
|
|
|
let _watcher;
|
2016-07-07 06:46:58 -08:00
|
|
|
|
2018-04-16 06:17:17 -08:00
|
|
|
const _watch = function() {
|
2017-08-12 14:23:48 -08:00
|
|
|
if (_watcher) {
|
|
|
|
|
return _watcher;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-16 05:49:43 -08:00
|
|
|
const onChange = () => {
|
2018-04-16 06:17:17 -08:00
|
|
|
// Need to wait 100ms to ensure that write is complete
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
cfg = _import();
|
|
|
|
|
notify('Configuration updated', 'Hyper configuration reloaded!');
|
|
|
|
|
watchers.forEach(fn => fn());
|
|
|
|
|
checkDeprecatedConfig();
|
|
|
|
|
}, 100);
|
2017-09-16 05:49:43 -08:00
|
|
|
};
|
|
|
|
|
|
2018-04-16 06:17:17 -08:00
|
|
|
// Windows
|
2017-09-16 03:49:10 -08:00
|
|
|
if (process.platform === 'win32') {
|
2018-04-16 06:17:17 -08:00
|
|
|
// watch for changes on config every 2s on Windows
|
2017-09-16 03:49:10 -08:00
|
|
|
// https://github.com/zeit/hyper/pull/1772
|
2017-09-16 05:49:43 -08:00
|
|
|
_watcher = fs.watchFile(cfgPath, {interval: 2000}, (curr, prev) => {
|
|
|
|
|
if (curr.mtime === 0) {
|
2018-04-16 06:17:17 -08:00
|
|
|
//eslint-disable-next-line no-console
|
2017-09-16 05:49:43 -08:00
|
|
|
console.error('error watching config');
|
|
|
|
|
} else if (curr.mtime !== prev.mtime) {
|
|
|
|
|
onChange();
|
|
|
|
|
}
|
|
|
|
|
});
|
2018-04-16 06:17:17 -08:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// macOS/Linux
|
|
|
|
|
setWatcher();
|
|
|
|
|
function setWatcher() {
|
|
|
|
|
try {
|
|
|
|
|
_watcher = fs.watch(cfgPath, eventType => {
|
|
|
|
|
if (eventType === 'rename') {
|
|
|
|
|
_watcher.close();
|
|
|
|
|
// Ensure that new file has been written
|
|
|
|
|
setTimeout(() => setWatcher(), 500);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} catch (e) {
|
|
|
|
|
//eslint-disable-next-line no-console
|
|
|
|
|
console.error('Failed to watch config file:', cfgPath, e);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2017-09-16 05:49:43 -08:00
|
|
|
_watcher.on('change', onChange);
|
|
|
|
|
_watcher.on('error', error => {
|
2018-04-16 06:17:17 -08:00
|
|
|
//eslint-disable-next-line no-console
|
2017-09-16 05:49:43 -08:00
|
|
|
console.error('error watching config', error);
|
|
|
|
|
});
|
2017-09-16 03:49:10 -08:00
|
|
|
}
|
2017-06-02 16:03:47 -08:00
|
|
|
};
|
2017-01-19 05:11:35 -09:00
|
|
|
|
2018-04-16 06:17:17 -08:00
|
|
|
exports.subscribe = fn => {
|
2016-07-07 07:16:48 -08:00
|
|
|
watchers.push(fn);
|
|
|
|
|
return () => {
|
|
|
|
|
watchers.splice(watchers.indexOf(fn), 1);
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2018-04-16 06:17:17 -08:00
|
|
|
exports.getConfigDir = () => {
|
2017-01-04 16:05:19 -09:00
|
|
|
// expose config directory to load plugin from the right place
|
2017-06-02 16:03:47 -08:00
|
|
|
return cfgDir;
|
2017-01-04 16:05:19 -09:00
|
|
|
};
|
|
|
|
|
|
2018-04-16 06:17:17 -08:00
|
|
|
exports.getConfig = () => {
|
2016-07-07 12:49:10 -08:00
|
|
|
return cfg.config;
|
|
|
|
|
};
|
|
|
|
|
|
2018-04-16 06:17:17 -08:00
|
|
|
exports.openConfig = () => {
|
2017-05-26 08:23:25 -08:00
|
|
|
return _openConfig();
|
|
|
|
|
};
|
|
|
|
|
|
2018-04-16 06:17:17 -08:00
|
|
|
exports.getPlugins = () => {
|
2016-07-07 12:49:10 -08:00
|
|
|
return {
|
|
|
|
|
plugins: cfg.plugins,
|
|
|
|
|
localPlugins: cfg.localPlugins
|
|
|
|
|
};
|
2016-07-07 06:46:58 -08:00
|
|
|
};
|
2016-10-01 17:44:34 -08:00
|
|
|
|
2018-04-16 06:17:17 -08:00
|
|
|
exports.getKeymaps = () => {
|
2017-06-02 16:03:47 -08:00
|
|
|
return cfg.keymaps;
|
|
|
|
|
};
|
|
|
|
|
|
2018-04-16 06:17:17 -08:00
|
|
|
exports.setup = () => {
|
2017-06-02 16:03:47 -08:00
|
|
|
cfg = _import();
|
|
|
|
|
_watch();
|
2018-04-16 06:17:17 -08:00
|
|
|
checkDeprecatedConfig();
|
2017-06-02 16:03:47 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
exports.getWin = win.get;
|
|
|
|
|
exports.winRecord = win.recordState;
|
2018-04-16 06:17:17 -08:00
|
|
|
exports.windowDefaults = win.defaults;
|
|
|
|
|
|
|
|
|
|
const getDeprecatedCSS = function(config) {
|
|
|
|
|
const deprecated = [];
|
|
|
|
|
const deprecatedCSS = ['x-screen', 'x-row', 'cursor-node', '::selection'];
|
|
|
|
|
deprecatedCSS.forEach(css => {
|
|
|
|
|
if ((config.css && config.css.indexOf(css) !== -1) || (config.termCSS && config.termCSS.indexOf(css) !== -1)) {
|
|
|
|
|
deprecated.push(css);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return deprecated;
|
|
|
|
|
};
|
|
|
|
|
exports.getDeprecatedCSS = getDeprecatedCSS;
|
|
|
|
|
|
|
|
|
|
const checkDeprecatedConfig = function() {
|
|
|
|
|
if (!cfg.config) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const deprecated = getDeprecatedCSS(cfg.config);
|
|
|
|
|
if (deprecated.length === 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const deprecatedStr = deprecated.join(', ');
|
|
|
|
|
notify('Configuration warning', `Your configuration uses some deprecated CSS classes (${deprecatedStr})`);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
exports.fixConfigDefaults = decoratedConfig => {
|
|
|
|
|
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);
|
|
|
|
|
return decoratedConfig;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
exports.htermConfigTranslate = config => {
|
|
|
|
|
const cssReplacements = {
|
|
|
|
|
'x-screen x-row([ {.[])': '.xterm-rows > div$1',
|
|
|
|
|
'.cursor-node([ {.[])': '.terminal-cursor$1',
|
|
|
|
|
'::selection([ {.[])': '.terminal .xterm-selection div$1',
|
|
|
|
|
'x-screen a([ {.[])': '.terminal a$1',
|
|
|
|
|
'x-row a([ {.[])': '.terminal a$1'
|
|
|
|
|
};
|
|
|
|
|
Object.keys(cssReplacements).forEach(pattern => {
|
|
|
|
|
const searchvalue = new RegExp(pattern, 'g');
|
|
|
|
|
const newvalue = cssReplacements[pattern];
|
|
|
|
|
config.css = config.css && config.css.replace(searchvalue, newvalue);
|
|
|
|
|
config.termCSS = config.termCSS && config.termCSS.replace(searchvalue, newvalue);
|
|
|
|
|
});
|
|
|
|
|
return config;
|
|
|
|
|
};
|