hyper/app/config.js

158 lines
3.8 KiB
JavaScript
Raw Normal View History

const {homedir} = require('os');
2016-10-06 07:28:43 -08:00
const {statSync, renameSync, readFileSync, writeFileSync} = require('fs');
const {resolve} = require('path');
2016-07-07 06:46:58 -08:00
const vm = require('vm');
const {dialog} = require('electron');
const isDev = require('electron-is-dev');
const gaze = require('gaze');
const Config = require('electron-config');
2016-07-08 06:40:27 -08:00
const notify = require('./notify');
2016-07-07 06:46:58 -08:00
// local storage
const winCfg = new Config({
defaults: {
windowPosition: [50, 50],
windowSize: [540, 380]
}
});
let configDir = homedir();
if (isDev) {
// if a local config file exists, use it
try {
const devDir = resolve(__dirname, '..');
const devConfig = resolve(devDir, '.hyper.js');
statSync(devConfig);
configDir = devDir;
console.log('using config file:', devConfig);
} catch (err) {
// ignore
}
}
const path = resolve(configDir, '.hyper.js');
const pathLegacy = resolve(configDir, '.hyperterm.js');
const watchers = [];
2016-07-07 06:46:58 -08:00
let cfg = {};
function watch() {
gaze(path, function (err) {
if (err) {
throw err;
}
this.on('changed', () => {
try {
if (exec(readFileSync(path, 'utf8'))) {
2016-10-06 07:28:43 -08:00
notify('Hyper configuration reloaded!');
watchers.forEach(fn => fn());
}
} catch (err) {
dialog.showMessageBox({
message: `An error occurred loading your configuration (${path}): ${err.message}`,
buttons: ['Ok']
});
}
});
this.on('error', () => {
// Ignore file watching errors
});
2016-07-07 06:46:58 -08:00
});
}
let _str; // last script
function exec(str) {
if (str === _str) {
return false;
}
_str = str;
2016-07-07 06:46:58 -08:00
const script = new vm.Script(str);
2016-07-07 06:50:18 -08:00
const module = {};
script.runInNewContext({module});
2016-07-07 06:50:18 -08:00
if (!module.exports) {
throw new Error('Error reading configuration: `module.exports` not set');
}
2016-07-07 12:49:10 -08:00
const _cfg = module.exports;
if (!_cfg.config) {
2016-07-07 06:49:11 -08:00
throw new Error('Error reading configuration: `config` key is missing');
}
2016-07-07 12:49:10 -08:00
_cfg.plugins = _cfg.plugins || [];
_cfg.localPlugins = _cfg.localPlugins || [];
cfg = _cfg;
return true;
2016-07-07 06:46:58 -08:00
}
// This method will take text formatted as Unix line endings and transform it
// to text formatted with DOS line endings. We do this because the default
// text editor on Windows (notepad) doesn't Deal with LF files. Still. In 2017.
function crlfify(str) {
return str.split('\n').map(x => x.indexOf('\r') < 0 ? x : `${x}\r`).join('\n');
}
exports.subscribe = function (fn) {
watchers.push(fn);
return () => {
watchers.splice(watchers.indexOf(fn), 1);
};
};
2016-07-07 06:46:58 -08:00
exports.init = function () {
2016-10-06 07:28:43 -08:00
// for backwards compatibility with hyperterm
// (prior to the rename), we try to rename
2016-10-06 07:28:43 -08:00
// on behalf of the user
try {
2016-10-06 07:31:31 -08:00
statSync(pathLegacy);
2016-10-06 07:28:43 -08:00
renameSync(pathLegacy, path);
} catch (err) {
// ignore
}
2016-07-07 06:46:58 -08:00
try {
exec(readFileSync(path, 'utf8'));
} catch (err) {
console.log('read error', path, err.message);
const defaultConfig = readFileSync(resolve(__dirname, 'config-default.js'));
try {
console.log('attempting to write default config to', path);
exec(defaultConfig);
writeFileSync(
path,
process.platform === 'win32' ? crlfify(defaultConfig.toString()) : defaultConfig);
2016-07-07 06:46:58 -08:00
} catch (err) {
throw new Error(`Failed to write config to ${path}: ${err.message}`);
2016-07-07 06:46:58 -08:00
}
}
watch();
};
exports.getConfigDir = function () {
// expose config directory to load plugin from the right place
return configDir;
};
2016-07-07 12:49:10 -08:00
exports.getConfig = function () {
return cfg.config;
};
exports.getPlugins = function () {
return {
plugins: cfg.plugins,
localPlugins: cfg.localPlugins
};
2016-07-07 06:46:58 -08:00
};
exports.window = {
get() {
const position = winCfg.get('windowPosition');
const size = winCfg.get('windowSize');
return {position, size};
},
recordState(win) {
winCfg.set('windowPosition', win.getPosition());
winCfg.set('windowSize', win.getSize());
}
};