Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implements Commands Key mapping #1876

Merged
merged 5 commits into from
Jun 3, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 0 additions & 136 deletions app/accelerators.js

This file was deleted.

131 changes: 28 additions & 103 deletions app/config.js
Original file line number Diff line number Diff line change
@@ -1,82 +1,31 @@
const {statSync, renameSync, readFileSync, writeFileSync} = require('fs');
const vm = require('vm');

const {dialog} = require('electron');
const gaze = require('gaze');
const Config = require('electron-config');
const notify = require('./notify');
const _paths = require('./config/paths');
const _import = require('./config/import');
const _openConfig = require('./config/open');

// local storage
const winCfg = new Config({
defaults: {
windowPosition: [50, 50],
windowSize: [540, 380]
}
});

const path = _paths.confPath;
const pathLegacy = _paths.pathLegacy;
const win = require('./config/windows');
const {cfgPath, cfgDir} = require('./config/paths');

const watchers = [];

// watch for changes on config every 2s on windows
// https://github.com/zeit/hyper/pull/1772
const watchCfg = process.platform === 'win32' ? {interval: 2000} : {};
let cfg = {};

function watch() {
// watch for changes on config every 2s
// windows interval: https://github.com/zeit/hyper/pull/1772
gaze(path, process.platform === 'win32' ? {interval: 2000} : {}, function (err) {
const _watch = function () {
gaze(cfgPath, watchCfg, function (err) {
if (err) {
throw err;
}
this.on('changed', () => {
try {
if (exec(readFileSync(path, 'utf8'))) {
notify('Hyper configuration reloaded!');
watchers.forEach(fn => fn());
}
} catch (err) {
dialog.showMessageBox({
Copy link
Contributor

@albinekb albinekb May 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR changes from displaying a dialog to just a notification, correct?

I think it's nice with the dialog since you need to click "OK" to close it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I won't change it since using a dialog prevent hyper from opening.

message: `An error occurred loading your configuration (${path}): ${err.message}`,
buttons: ['Ok']
});
}
cfg = _import();
notify('Configuration updated', 'Hyper configuration reloaded!');
watchers.forEach(fn => fn());
});
this.on('error', () => {
// Ignore file watching errors
});
});
}

let _str; // last script
function exec(str) {
if (str === _str) {
return false;
}
_str = str;
const script = new vm.Script(str);
const module = {};
script.runInNewContext({module});
if (!module.exports) {
throw new Error('Error reading configuration: `module.exports` not set');
}
const _cfg = module.exports;
if (!_cfg.config) {
throw new Error('Error reading configuration: `config` key is missing');
}
_cfg.plugins = _cfg.plugins || [];
_cfg.localPlugins = _cfg.localPlugins || [];
cfg = _cfg;
return true;
}

// 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.replace(/\r?\n/g, '\r\n');
}
};

exports.subscribe = function (fn) {
watchers.push(fn);
Expand All @@ -85,39 +34,9 @@ exports.subscribe = function (fn) {
};
};

exports.init = function () {
// for backwards compatibility with hyperterm
// (prior to the rename), we try to rename
// on behalf of the user
try {
statSync(pathLegacy);
renameSync(pathLegacy, path);
} catch (err) {
// ignore
}

try {
exec(readFileSync(path, 'utf8'));
} catch (err) {
console.log('read error', path, err.message);
const defaultConfig = readFileSync(_paths.defaultConfig);
try {
console.log('attempting to write default config to', path);
exec(defaultConfig);

writeFileSync(
path,
process.platform === 'win32' ? crlfify(defaultConfig.toString()) : defaultConfig);
} catch (err) {
throw new Error(`Failed to write config to ${path}: ${err.message}`);
}
}
watch();
};

exports.getConfigDir = function () {
// expose config directory to load plugin from the right place
return _paths.confDir;
return cfgDir;
};

exports.getConfig = function () {
Expand All @@ -135,14 +54,20 @@ exports.getPlugins = function () {
};
};

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());
exports.getKeymaps = function () {
return cfg.keymaps;
};

exports.extendKeymaps = function (keymaps) {
if (keymaps) {
cfg.keymaps = keymaps;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm.. I don't like mutating stuff like this. But I think we do this in other places? Maybe that's a job for another PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah we do this alot...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm OK with this for now, but we should clean it all up

}
};

exports.setup = function () {
cfg = _import();
_watch();
};

exports.getWin = win.get;
exports.winRecord = win.recordState;
41 changes: 41 additions & 0 deletions app/config/import.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const {writeFileSync, readFileSync} = require('fs');
const {defaultCfg, cfgPath} = require('./paths');
const _init = require('./init');
const _keymaps = require('./keymaps');

const _write = function (path, data) {
// 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.
const crlfify = function (str) {
return str.replace(/\r?\n/g, '\r\n');
};
const format = process.platform === 'win32' ? crlfify(data.toString()) : data;
writeFileSync(path, format, 'utf8');
};

const _importConf = function () {
try {
const _defaultCfg = readFileSync(defaultCfg, 'utf8');
try {
const _cfgPath = readFileSync(cfgPath, 'utf8');
return {userCfg: _cfgPath, defaultCfg: _defaultCfg};
} catch (err) {
_write(cfgPath, defaultCfg);
return {userCfg: {}, defaultCfg: _defaultCfg};
}
} catch (err) {
console.log(err);
}
};

const _import = function () {
const cfg = _init(_importConf());

if (cfg) {
cfg.keymaps = _keymaps.import(cfg.keymaps);
}
return cfg;
};

module.exports = _import;
44 changes: 44 additions & 0 deletions app/config/init.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
const vm = require('vm');
const notify = require('../notify');

const _extract = function (script) {
const module = {};
script.runInNewContext({module});
if (!module.exports) {
throw new Error('Error reading configuration: `module.exports` not set');
}
return module.exports;
};

const _syntaxValidation = function (cfg) {
Copy link
Contributor

@albinekb albinekb May 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const _syntaxValidation = function (cfg) {
    try {
      return new vm.Script(cfg, { filename: '.hyper.js', displayErrors: true })
    } catch (error) {
      notify(`Error loading config: ${error.name}, see DevTools for more info`)
      console.error('Error loading config:', error)
      return
    }
}

tested:

_syntaxValidation(`
const c = 'a'
const b = 'd'
const c = '2'
`)

notify: Error loading config: SyntaxError, see DevTools for more info
console:

 Error loading config:
 .hyper.js:4
const c = '2'
          ^^^
SyntaxError: Identifier 'c' has already been declared

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you commenting as an error or a test?

Copy link
Contributor

@albinekb albinekb May 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

haha the comment was to update _syntaxValidation to the code i wrote in my comment,
making it show what type of error happened, and log the row in .hyper.js to console

the blocks under is to show what it does

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done 👍

try {
return new vm.Script(cfg, {filename: '.hyper.js', displayErrors: true});
} catch (err) {
notify(`Error loading config: ${err.name}, see DevTools for more info`);
console.error('Error loading config:', err);
return;
}
};

const _extractDefault = function (cfg) {
return _extract(_syntaxValidation(cfg));
};

// init config
const _init = function (cfg) {
const script = _syntaxValidation(cfg.userCfg);
if (script) {
const _cfg = _extract(script);
if (!_cfg.config) {
_cfg.plugins = _cfg.plugins || [];
_cfg.localPlugins = _cfg.localPlugins || [];
_cfg.keymaps = _cfg.keymaps || {};
notify('Error reading configuration: `config` key is missing');
return _extractDefault(cfg.defaultCfg);
}
return _cfg;
}
return _extractDefault(cfg.defaultCfg);
};

module.exports = _init;
Loading