Enforce max-statement/line & further unify UI

This commit is contained in:
RabsRincon
2018-03-24 23:12:27 +01:00
parent 0437f8db8e
commit abb391f112
14 changed files with 580 additions and 500 deletions

View File

@@ -8,8 +8,8 @@
},
"rules": {
"eqeqeq": ["error", "smart"],
"max-statements": ["warn", 50],
"max-len": ["warn", 120, { "ignoreRegExpLiterals": true }],
"max-statements": ["error", 50],
"max-len": ["error", 120, { "ignoreRegExpLiterals": true }],
"eol-last": ["error", "always"],
"semi": ["error", "always"],
"indent": ["error", 4, { "SwitchCase": 1 }],

10
app.js
View File

@@ -241,7 +241,9 @@ function ClientOptionsHandler(fileSources) {
}), 'name');
const supportsBinary = compilerPropsAT(languages, res => !!res, 'supportsBinary', true);
const supportsExecutePerLanguage = compilerPropsAT(languages, (res, lang) => supportsBinary[lang.id] && !!res, 'supportsExecute', true);
const supportsExecutePerLanguage = compilerPropsAT(languages, (res, lang) => {
return supportsBinary[lang.id] && !!res;
}, 'supportsExecute', true);
const supportsExecute = Object.values(supportsExecutePerLanguage).some((value) => value);
const libs = {};
@@ -303,7 +305,8 @@ function ClientOptionsHandler(fileSources) {
doCache: doCache
};
this.setCompilers = compilers => {
const blacklistedKeys = ['exe', 'versionFlag', 'versionRe', 'compilerType', 'demangler', 'objdumper', 'postProcess'];
const blacklistedKeys = ['exe', 'versionFlag', 'versionRe', 'compilerType', 'demangler', 'objdumper',
'postProcess'];
const copiedCompilers = JSON.parse(JSON.stringify(compilers));
_.each(options.compilers, (compiler, compilersKey) => {
_.each(compiler, (_, propKey) => {
@@ -649,7 +652,8 @@ Promise.all([findCompilers(), aws.initConfig(awsProps)])
}));
webServer.use(express.static(staticDir));
} else {
//assume that anything not dev is just production this gives sane defaults for anyone who isn't messing with this
/* Assume that anything not dev is just production.
* This gives sane defaults for anyone who isn't messing with this */
logger.info(" serving static files from '" + staticDir + "'");
webServer.use(express.static(staticDir, {maxAge: staticMaxAgeSecs * 1000}));
}

View File

@@ -269,7 +269,9 @@ class BaseCompiler {
const outputFilebase = "output";
const outputFilename = this.getOutputFilename(dirPath, outputFilebase);
options = _.compact(this.prepareArguments(options, filters, backendOptions, inputFilename, outputFilename));
options = _.compact(
this.prepareArguments(options, filters, backendOptions, inputFilename, outputFilename)
);
const execOptions = this.getDefaultExecOptions();

View File

@@ -46,7 +46,9 @@ function execute(command, args, options) {
// AP: Run Windows-volume executables in winTmp. Otherwise, run in tmpDir (which may be undefined).
// https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options
const child = child_process.spawn(command, args, {
cwd: options.customCwd ? options.customCwd : (command.startsWith("/mnt") && process.env.wsl) ? process.env.winTmp : process.env.tmpDir,
cwd: options.customCwd ? options.customCwd : (
(command.startsWith("/mnt") && process.env.wsl) ? process.env.winTmp : process.env.tmpDir
),
env: env,
detached: process.platform === 'linux'
});

View File

@@ -125,7 +125,9 @@ class CompileHandler {
_.each(this.compilersById, compilerInLang => {
if (response === undefined) {
_.each(compilerInLang, compiler => {
if (response === undefined && (compiler.compiler.id === compilerId || compiler.compiler.alias === compilerId)) {
if (response === undefined &&
(compiler.compiler.id === compilerId || compiler.compiler.alias === compilerId)) {
response = compiler;
}
});
@@ -195,7 +197,8 @@ class CompileHandler {
const {source, options, backendOptions, filters} = this.parseRequest(req, compiler);
const remote = compiler.getRemote();
if (remote) {
req.url = req.originalUrl; // Undo any routing that was done to get here (i.e. /api/* path has been removed)
// Undo any routing that was done to get here (i.e. /api/* path has been removed)
req.url = req.originalUrl;
this.proxy.web(req, res, {target: remote}, e => {
logger.error("Proxy error: ", e);
next(e);

View File

@@ -77,9 +77,7 @@ class PascalDemangler {
demangle(text) {
if (!text.endsWith(':')) return false;
if (this.shouldIgnoreSymbol(text)) {
return false;
}
if (this.shouldIgnoreSymbol(text)) return false;
text = text.substr(0, text.length - 1);
@@ -91,13 +89,12 @@ class PascalDemangler {
}
}
let unmangledGlobalVar;
if (text.startsWith("U_$OUTPUT_$$_")) {
unmangledGlobalVar = text.substr(13).toLowerCase();
let unmangledGlobalVar = text.substr(13).toLowerCase();
this.symbolStore.Add(text, unmangledGlobalVar);
return unmangledGlobalVar;
} else if (text.startsWith("U_OUTPUT_")) {
unmangledGlobalVar = text.substr(9).toLowerCase();
let unmangledGlobalVar = text.substr(9).toLowerCase();
this.symbolStore.Add(text, unmangledGlobalVar);
return unmangledGlobalVar;
}

View File

@@ -8,8 +8,8 @@
},
"rules": {
"eqeqeq": ["error", "smart"],
"max-statements": ["warn", 50],
"max-len": ["warn", 120, { "ignoreRegExpLiterals": true }],
"max-statements": ["error", 50],
"max-len": ["error", 120, { "ignoreRegExpLiterals": true }],
"strict": ["error", "safe"],
"eol-last": ["error", "always"],
"semi": ["error", "always"],

View File

@@ -131,6 +131,16 @@ Ast.prototype.onCompilerClose = function (id) {
};
Ast.prototype.updateState = function () {
this.container.setState(this.currentState());
};
Ast.prototype.currentState = function () {
var state = {
id: this._compilerid,
editorid: this._editorid
};
this.fontScale.addState(state);
return state;
};
Ast.prototype.onCompilerClose = function (id) {

View File

@@ -93,28 +93,15 @@ function Cfg(hub, container, state) {
}
};
this.toggles = new Toggles(this.domRoot.find('.options'), state.options);
this.cfgVisualiser = new vis.Network(this.domRoot.find('.graph-placeholder')[0],
this.defaultCfgOutput, this.networkOpts);
this.cfgVisualiser.on('dragEnd', _.bind(this.saveState, this));
this.cfgVisualiser.on('zoom', _.bind(this.saveState, this));
this.toggleNavigationButton = this.domRoot.find('.toggle-navigation');
this.toggleNavigationButton.on('click', _.bind(function () {
this.networkOpts.interaction.navigationButtons = this.toggleNavigationButton.hasClass('active');
this.cfgVisualiser.setOptions(this.networkOpts);
}, this));
this.togglePhysicsButton = this.domRoot.find('.toggle-physics');
this.togglePhysicsButton.on('click', _.bind(function () {
this.networkOpts.physics.enabled = this.togglePhysicsButton.hasClass('active');
// change only physics.enabled option to preserve current node locations
this.cfgVisualiser.setOptions({
physics: {enabled: this.networkOpts.physics.enabled}
});
}, this));
this.initButtons(state);
this.initCallbacks();
this.compilerId = state.id;
this._editorid = state.editorid;
this._binaryFilter = false;
@@ -137,24 +124,13 @@ function Cfg(hub, container, state) {
}
}, this));
this.eventHub.on('compilerClose', this.onCompilerClose, this);
this.eventHub.on('compileResult', this.onCompileResult, this);
this.eventHub.on('compiler', this.onCompiler, this);
this.eventHub.on('filtersChange', this.onFiltersChange, this);
this.container.on('destroy', this.close, this);
this.container.on('resize', this.resize, this);
this.container.on('shown', this.resize, this);
this.eventHub.emit('cfgViewOpened', this.compilerId);
this.eventHub.emit('requestFilters', this.compilerId);
this.eventHub.emit('requestCompiler', this.compilerId);
this.initCallbacks();
this.adaptStructure = function (names) {
return _.map(names, function (name) {
return {name: name};
});
};
this.updateButtons();
this.setTitle();
}
@@ -203,6 +179,57 @@ Cfg.prototype.onFiltersChange = function (id, filters) {
}
};
Cfg.prototype.initButtons = function (state) {
this.toggles = new Toggles(this.domRoot.find('.options'), state.options);
this.toggleNavigationButton = this.domRoot.find('.toggle-navigation');
this.toggleNavigationTitle = this.toggleNavigationButton.prop('title');
this.togglePhysicsButton = this.domRoot.find('.toggle-physics');
this.togglePhysicsTitle = this.togglePhysicsButton.prop('title');
};
Cfg.prototype.initCallbacks = function () {
this.eventHub.on('compilerClose', this.onCompilerClose, this);
this.eventHub.on('compileResult', this.onCompileResult, this);
this.eventHub.on('compiler', this.onCompiler, this);
this.eventHub.on('filtersChange', this.onFiltersChange, this);
this.container.on('destroy', this.close, this);
this.container.on('resize', this.resize, this);
this.container.on('shown', this.resize, this);
this.eventHub.emit('cfgViewOpened', this.compilerId);
this.eventHub.emit('requestFilters', this.compilerId);
this.eventHub.emit('requestCompiler', this.compilerId);
this.togglePhysicsButton.on('click', _.bind(function () {
this.networkOpts.physics.enabled = this.togglePhysicsButton.hasClass('active');
// change only physics.enabled option to preserve current node locations
this.cfgVisualiser.setOptions({
physics: {enabled: this.networkOpts.physics.enabled}
});
}, this));
this.toggleNavigationButton.on('click', _.bind(function () {
this.networkOpts.interaction.navigationButtons = this.toggleNavigationButton.hasClass('active');
this.cfgVisualiser.setOptions({interaction: {
navigationButtons: this.networkOpts.interaction.navigationButtons}
});
}, this));
this.toggles.on('change', _.bind(function () {
this.updateButtons();
this.saveState();
}, this));
};
Cfg.prototype.updateButtons = function () {
var formatButtonTitle = function (button, title) {
button.prop('title', '[' + (button.hasClass('active') ? 'ON' : 'OFF') + '] ' + title);
};
formatButtonTitle(this.togglePhysicsButton, this.togglePhysicsTitle);
formatButtonTitle(this.toggleNavigationButton, this.toggleNavigationTitle);
};
Cfg.prototype.resize = function () {
if (this.cfgVisualiser.canvas) {
var height = this.domRoot.height() - this.domRoot.find('.top-bar').outerHeight(true);
@@ -212,7 +239,8 @@ Cfg.prototype.resize = function () {
};
Cfg.prototype.setTitle = function () {
this.container.setTitle(this._compilerName + ' Graph Viewer (Editor #' + this._editorid + ', Compiler #' + this.compilerId + ')');
this.container.setTitle(
this._compilerName + ' Graph Viewer (Editor #' + this._editorid + ', Compiler #' + this.compilerId + ')');
};
Cfg.prototype.assignLevels = function (data) {

View File

@@ -68,6 +68,7 @@ var languages = options.languages;
function Compiler(hub, container, state) {
this.container = container;
this.hub = hub;
this.eventHub = hub.createEventHub();
this.compilerService = hub.compilerService;
this.domRoot = container.getElement();
@@ -75,31 +76,12 @@ function Compiler(hub, container, state) {
this.id = state.id || hub.nextCompilerId();
this.sourceEditorId = state.source || 1;
this.settings = JSON.parse(local.get('settings', '{}'));
// If we don't have a language, but a compiler, find the corresponding language.
this.currentLangId = state.lang;
if (!this.currentLangId && state.compiler) {
this.currentLangId = this.langOfCompiler(state.compiler);
}
if (!this.currentLangId && languages[this.settings.defaultLanguage]) {
this.currentLangId = languages[this.settings.defaultLanguage].id;
}
if (!this.currentLangId) {
this.currentLangId = _.keys(languages)[0];
}
this.originalCompilerId = state.compiler;
if (state.compiler)
this.compiler = this.findCompiler(this.currentLangId, state.compiler);
else
this.compiler = this.findCompiler(this.currentLangId, options.defaultCompiler[this.currentLangId]);
if (!this.compiler) {
var compilers = this.compilerService.compilersByLang[this.currentLangId];
if (compilers) this.compiler = _.values(compilers)[0];
}
this.initLang(state);
this.initCompiler(state);
this.infoByLang = {};
this.deferCompiles = hub.deferred;
this.needsCompile = false;
this.options = state.options || options.compileOptions[this.currentLangId];
this.filters = new Toggles(this.domRoot.find('.filters'), patchOldFilters(state.filters));
this.source = '';
this.assembly = [];
this.colours = [];
@@ -113,18 +95,7 @@ function Compiler(hub, container, state) {
this.prevDecorations = [];
this.alertSystem = new Alert();
this.initButtons();
this.initLibraries(state);
this.linkedFadeTimeoutId = -1;
this.getGroupsInUse = function () {
var currentLangCompilers = _.map(this.getCurrentLangCompilers(), _.identity, this);
return _.map(_.uniq(currentLangCompilers, false, function (compiler) {
return compiler.group;
}), function (compiler) {
return {value: compiler.group, label: compiler.groupName || compiler.group};
});
};
this.domRoot.find('.compiler-picker').selectize({
sortField: 'name',
@@ -133,7 +104,7 @@ function Compiler(hub, container, state) {
searchField: ['name'],
optgroupField: 'group',
optgroups: this.getGroupsInUse(),
options: _.map(this.getCurrentLangCompilers(), _.identity, this),
options: _.map(this.getCurrentLangCompilers(), _.identity),
items: this.compiler ? [this.compiler.id] : []
}).on('change', _.bind(function (e) {
var val = $(e.target).val();
@@ -146,15 +117,6 @@ function Compiler(hub, container, state) {
this.onCompilerChange(val);
}
}, this));
var optionsChange = _.debounce(_.bind(function (e) {
this.onOptionsChange($(e.target).val());
}, this), 800);
this.optionsField
.val(this.options)
.on('change', optionsChange)
.on('keyup', optionsChange);
this.filterExecuteButton.toggle(options.supportsExecute);
this.outputEditor = monaco.editor.create(this.domRoot.find('.monaco-placeholder')[0], {
scrollBeyondLastLine: false,
@@ -168,6 +130,181 @@ function Compiler(hub, container, state) {
},
lineNumbersMinChars: options.embedded ? 1 : 5
});
this.initButtons(state);
this.initLibraries(state);
this.initEditorActions();
this.mouseMoveThrottledFunction = _.throttle(_.bind(this.onMouseMove, this), 250);
this.initCallbacks();
// Handle initial settings
this.onSettingsChange(this.settings);
this.sendCompiler();
this.updateCompilerInfo();
this.updateButtons();
this.updateLibsDropdown();
this.saveState();
}
Compiler.prototype.clearEditorsLinkedLines = function () {
this.eventHub.emit('editorSetDecoration', this.sourceEditorId, -1, false);
};
Compiler.prototype.getGroupsInUse = function () {
var currentLangCompilers = _.map(this.getCurrentLangCompilers(), _.identity);
return _.map(_.uniq(currentLangCompilers, false, function (compiler) {
return compiler.group;
}), function (compiler) {
return {value: compiler.group, label: compiler.groupName || compiler.group};
});
};
Compiler.prototype.close = function () {
this.eventHub.unsubscribe();
this.eventHub.emit('compilerClose', this.id);
this.outputEditor.dispose();
};
Compiler.prototype.initPanerButtons = function () {
var outputConfig = _.bind(function () {
return Components.getOutput(this.id, this.sourceEditorId);
}, this);
this.container.layoutManager.createDragSource(this.outputBtn, outputConfig);
this.outputBtn.click(_.bind(function () {
var insertPoint = this.hub.findParentRowOrColumn(this.container) ||
this.container.layoutManager.root.contentItems[0];
insertPoint.addChild(outputConfig);
}, this));
var cloneComponent = _.bind(function () {
return {
type: 'component',
componentName: 'compiler',
componentState: this.currentState()
};
}, this);
var createOptView = _.bind(function () {
return Components.getOptViewWith(this.id, this.source, this.lastResult.optOutput, this.getCompilerName(),
this.sourceEditorId);
}, this);
var createAstView = _.bind(function () {
return Components.getAstViewWith(this.id, this.source, this.lastResult.astOutput, this.getCompilerName(),
this.sourceEditorId);
}, this);
var createGccDumpView = _.bind(function () {
return Components.getGccDumpViewWith(this.id, this.getCompilerName(), this.sourceEditorId,
this.lastResult.gccDumpOutput);
}, this);
var createCfgView = _.bind(function () {
return Components.getCfgViewWith(this.id, this.sourceEditorId);
}, this);
var panerDropdown = this.domRoot.find('.pane-dropdown');
var togglePannerAdder = function () {
panerDropdown.dropdown('toggle');
};
this.container.layoutManager
.createDragSource(this.domRoot.find('.btn.add-compiler'), cloneComponent)
._dragListener.on('dragStart', togglePannerAdder);
this.domRoot.find('.btn.add-compiler').click(_.bind(function () {
var insertPoint = this.hub.findParentRowOrColumn(this.container) ||
this.container.layoutManager.root.contentItems[0];
insertPoint.addChild(cloneComponent);
}, this));
this.container.layoutManager
.createDragSource(this.optButton, createOptView)
._dragListener.on('dragStart', togglePannerAdder);
this.optButton.click(_.bind(function () {
var insertPoint = this.hub.findParentRowOrColumn(this.container) ||
this.container.layoutManager.root.contentItems[0];
insertPoint.addChild(createOptView);
}, this));
this.container.layoutManager
.createDragSource(this.astButton, createAstView)
._dragListener.on('dragStart', togglePannerAdder);
this.astButton.click(_.bind(function () {
var insertPoint = this.hub.findParentRowOrColumn(this.container) ||
this.container.layoutManager.root.contentItems[0];
insertPoint.addChild(createAstView);
}, this));
this.container.layoutManager
.createDragSource(this.gccDumpButton, createGccDumpView)
._dragListener.on('dragStart', togglePannerAdder);
this.gccDumpButton.click(_.bind(function () {
var insertPoint = this.hub.findParentRowOrColumn(this.container) ||
this.container.layoutManager.root.contentItems[0];
insertPoint.addChild(createGccDumpView);
}, this));
this.container.layoutManager
.createDragSource(this.cfgButton, createCfgView)
._dragListener.on('dragStart', togglePannerAdder);
this.cfgButton.click(_.bind(function () {
var insertPoint = this.hub.findParentRowOrColumn(this.container) ||
this.container.layoutManager.root.contentItems[0];
insertPoint.addChild(createCfgView);
}, this));
};
Compiler.prototype.undefer = function () {
this.deferCompiles = false;
if (this.needsCompile) this.compile();
};
// TODO: need to call resize if either .top-bar or .bottom-bar resizes, which needs some work.
// Issue manifests if you make a window where one compiler is small enough that the buttons spill onto two lines:
// reload the page and the bottom-bar is off the bottom until you scroll a tiny bit.
Compiler.prototype.resize = function () {
var topBarHeight = this.domRoot.find('.top-bar').outerHeight(true);
var bottomBarHeight = this.domRoot.find('.bottom-bar').outerHeight(true);
this.outputEditor.layout({
width: this.domRoot.width(),
height: this.domRoot.height() - topBarHeight - bottomBarHeight
});
};
Compiler.prototype.initLang = function (state) {
// If we don't have a language, but a compiler, find the corresponding language.
this.currentLangId = state.lang;
if (!this.currentLangId && state.compiler) {
this.currentLangId = this.langOfCompiler(state.compiler);
}
if (!this.currentLangId && languages[this.settings.defaultLanguage]) {
this.currentLangId = languages[this.settings.defaultLanguage].id;
}
if (!this.currentLangId) {
this.currentLangId = _.keys(languages)[0];
}
};
Compiler.prototype.initCompiler = function (state) {
this.originalCompilerId = state.compiler;
if (state.compiler)
this.compiler = this.findCompiler(this.currentLangId, state.compiler);
else
this.compiler = this.findCompiler(this.currentLangId, options.defaultCompiler[this.currentLangId]);
if (!this.compiler) {
var compilers = this.compilerService.compilersByLang[this.currentLangId];
if (compilers) this.compiler = _.values(compilers)[0];
}
};
Compiler.prototype.initEditorActions = function () {
this.outputEditor.addAction({
id: 'viewsource',
label: 'Scroll to source',
@@ -210,183 +347,6 @@ function Compiler(hub, container, state) {
}, this)
});
var clearEditorsLinkedLines = _.bind(function () {
this.eventHub.emit('editorSetDecoration', this.sourceEditorId, -1, false);
}, this);
this.outputEditor.onMouseMove(_.bind(function (e) {
this.mouseMoveThrottledFunction(e);
if (this.linkedFadeTimeoutId !== -1) {
clearTimeout(this.linkedFadeTimeoutId);
this.linkedFadeTimeoutId = -1;
}
}, this));
this.mouseMoveThrottledFunction = _.throttle(_.bind(this.onMouseMove, this), 250);
this.outputEditor.onMouseLeave(_.bind(function () {
this.linkedFadeTimeoutId = setTimeout(_.bind(function () {
clearEditorsLinkedLines();
this.linkedFadeTimeoutId = -1;
}, this), 5000);
}, this));
this.fontScale = new FontScale(this.domRoot, state, this.outputEditor);
this.fontScale.on('change', _.bind(function () {
this.saveState();
}, this));
this.filters.on('change', _.bind(this.onFilterChange, this));
this.initCallbacks();
this.onSettingsChange(this.settings);
this.sendCompiler();
this.updateCompilerInfo();
this.updateButtons();
var outputConfig = _.bind(function () {
return Components.getOutput(this.id, this.sourceEditorId);
}, this);
this.container.layoutManager.createDragSource(this.outputBtn, outputConfig);
this.outputBtn.click(_.bind(function () {
var insertPoint = hub.findParentRowOrColumn(this.container) ||
this.container.layoutManager.root.contentItems[0];
insertPoint.addChild(outputConfig);
}, this));
var cloneComponent = _.bind(function () {
return {
type: 'component',
componentName: 'compiler',
componentState: this.currentState()
};
}, this);
var createOptView = _.bind(function () {
return Components.getOptViewWith(this.id, this.source, this.lastResult.optOutput, this.getCompilerName(),
this.sourceEditorId);
}, this);
var createAstView = _.bind(function () {
return Components.getAstViewWith(this.id, this.source, this.lastResult.astOutput, this.getCompilerName(),
this.sourceEditorId);
}, this);
var createGccDumpView = _.bind(function () {
return Components.getGccDumpViewWith(this.id, this.getCompilerName(), this.sourceEditorId,
this.lastResult.gccDumpOutput);
}, this);
var createCfgView = _.bind(function () {
return Components.getCfgViewWith(this.id, this.sourceEditorId);
}, this);
var panerDropdown = this.domRoot.find('.pane-dropdown');
var togglePannerAdder = function () {
panerDropdown.dropdown('toggle');
};
this.container.layoutManager
.createDragSource(this.domRoot.find('.btn.add-compiler'), cloneComponent)
._dragListener.on('dragStart', togglePannerAdder);
this.domRoot.find('.btn.add-compiler').click(_.bind(function () {
var insertPoint = hub.findParentRowOrColumn(this.container) ||
this.container.layoutManager.root.contentItems[0];
insertPoint.addChild(cloneComponent);
}, this));
this.container.layoutManager
.createDragSource(this.optButton, createOptView)
._dragListener.on('dragStart', togglePannerAdder);
this.optButton.click(_.bind(function () {
var insertPoint = hub.findParentRowOrColumn(this.container) ||
this.container.layoutManager.root.contentItems[0];
insertPoint.addChild(createOptView);
}, this));
this.container.layoutManager
.createDragSource(this.astButton, createAstView)
._dragListener.on('dragStart', togglePannerAdder);
this.astButton.click(_.bind(function () {
var insertPoint = hub.findParentRowOrColumn(this.container) ||
this.container.layoutManager.root.contentItems[0];
insertPoint.addChild(createAstView);
}, this));
this.container.layoutManager
.createDragSource(this.gccDumpButton, createGccDumpView)
._dragListener.on('dragStart', togglePannerAdder);
this.gccDumpButton.click(_.bind(function () {
var insertPoint = hub.findParentRowOrColumn(this.container) ||
this.container.layoutManager.root.contentItems[0];
insertPoint.addChild(createGccDumpView);
}, this));
this.container.layoutManager
.createDragSource(this.cfgButton, createCfgView)
._dragListener.on('dragStart', togglePannerAdder);
this.cfgButton.click(_.bind(function () {
var insertPoint = hub.findParentRowOrColumn(this.container) ||
this.container.layoutManager.root.contentItems[0];
insertPoint.addChild(createCfgView);
}, this));
this.updateLibsDropdown();
this.compileClearCache.on('click', _.bind(function () {
this.compilerService.cache.reset();
this.compile();
}, this));
// Dismiss the popover on escape.
$(document).on('keyup.editable', _.bind(function (e) {
if (e.which === 27) {
this.libsButton.popover('hide');
}
}, this));
// Dismiss on any click that isn't either in the opening element, inside
// the popover or on any alert
$(document).on('click', _.bind(function (e) {
var elem = this.libsButton;
var target = $(e.target);
if (!target.is(elem) && elem.has(target).length === 0 && target.closest('.popover').length === 0) {
elem.popover('hide');
}
}, this));
this.eventHub.on('initialised', this.undefer, this);
this.saveState();
}
Compiler.prototype.close = function () {
this.eventHub.unsubscribe();
this.eventHub.emit('compilerClose', this.id);
this.outputEditor.dispose();
};
Compiler.prototype.undefer = function () {
this.deferCompiles = false;
if (this.needsCompile) this.compile();
};
// TODO: need to call resize if either .top-bar or .bottom-bar resizes, which needs some work.
// Issue manifests if you make a window where one compiler is small enough that the buttons spill onto two lines:
// reload the page and the bottom-bar is off the bottom until you scroll a tiny bit.
Compiler.prototype.resize = function () {
var topBarHeight = this.domRoot.find('.top-bar').outerHeight(true);
var bottomBarHeight = this.domRoot.find('.bottom-bar').outerHeight(true);
this.outputEditor.layout({
width: this.domRoot.width(),
height: this.domRoot.height() - topBarHeight - bottomBarHeight
});
};
// Gets the filters that will actually be used (accounting for issues with binary
@@ -490,11 +450,11 @@ Compiler.prototype.getBinaryForLine = function (line) {
// TODO: use ContentWidgets? OverlayWidgets?
// Use highlight providers? hover providers? highlight providers?
Compiler.prototype.setAssembly = function (assembly) {
this.assembly = assembly;
Compiler.prototype.setAssembly = function (asm) {
this.assembly = asm;
if (!this.outputEditor || !this.outputEditor.getModel()) return;
var currentTopLine = this.outputEditor.getCompletelyVisibleLinesRangeInViewport().startLineNumber;
this.outputEditor.getModel().setValue(assembly.length ? _.pluck(assembly, 'text').join('\n') : "<No assembly generated>");
this.outputEditor.getModel().setValue(asm.length ? _.pluck(asm, 'text').join('\n') : "<No assembly generated>");
this.outputEditor.revealLine(currentTopLine);
var addrToAddrDiv = {};
var decorations = [];
@@ -725,7 +685,10 @@ Compiler.prototype.onCfgViewClosed = function (id) {
}
};
Compiler.prototype.initButtons = function () {
Compiler.prototype.initButtons = function (state) {
this.filters = new Toggles(this.domRoot.find('.filters'), patchOldFilters(state.filters));
this.fontScale = new FontScale(this.domRoot, state, this.outputEditor);
this.optButton = this.domRoot.find('.btn.view-optimization');
this.astButton = this.domRoot.find('.btn.view-ast');
this.gccDumpButton = this.domRoot.find('.btn.view-gccdump');
@@ -770,6 +733,10 @@ Compiler.prototype.initButtons = function () {
this.filterDemangleTitle = this.filterDemangleButton.prop('title');
this.noBinaryFiltersButtons = this.domRoot.find('.nonbinary');
this.filterExecuteButton.toggle(options.supportsExecute);
this.optionsField.val(this.options);
this.initPanerButtons();
};
Compiler.prototype.initLibraries = function (state) {
@@ -796,7 +763,8 @@ Compiler.prototype.updateButtons = function () {
// We can support intel output if the compiler supports it, or if we're compiling
// to binary (as we can disassemble it however we like).
var formatFilterTitle = function (button, title) {
button.prop('title', '[' + (button.hasClass('active') ? 'ON' : 'OFF') + '] ' + title + (button.prop('disabled') ? ' [LOCKED]' : ''));
button.prop('title', '[' + (button.hasClass('active') ? 'ON' : 'OFF') + '] ' + title +
(button.prop('disabled') ? ' [LOCKED]' : ''));
};
var isIntelFilterDisabled = !this.compiler.supportsIntel && !filters.binary;
this.filterIntelButton.prop('disabled', isIntelFilterDisabled);
@@ -844,8 +812,10 @@ Compiler.prototype.updateButtons = function () {
}
};
Compiler.prototype.initCallbacks = function () {
this.filters.on('change', _.bind(this.onFilterChange, this));
this.fontScale.on('change', _.bind(this.saveState, this));
this.container.on('destroy', this.close, this);
this.container.on('resize', this.resize, this);
this.container.on('shown', this.resize, this);
@@ -887,6 +857,46 @@ Compiler.prototype.initCallbacks = function () {
}
}, this);
this.eventHub.on('languageChange', this.onLanguageChange, this);
var optionsChange = _.debounce(_.bind(function (e) {
this.onOptionsChange($(e.target).val());
}, this), 800);
this.optionsField
.on('change', optionsChange)
.on('keyup', optionsChange);
this.outputEditor.onMouseLeave(_.bind(function () {
this.linkedFadeTimeoutId = setTimeout(_.bind(function () {
this.clearEditorsLinkedLines();
this.linkedFadeTimeoutId = -1;
}, this), 5000);
}, this));
this.compileClearCache.on('click', _.bind(function () {
this.compilerService.cache.reset();
this.compile();
}, this));
// Dismiss the popover on escape.
$(document).on('keyup.editable', _.bind(function (e) {
if (e.which === 27) {
this.libsButton.popover('hide');
}
}, this));
// Dismiss on any click that isn't either in the opening element, inside
// the popover or on any alert
$(document).on('click', _.bind(function (e) {
var elem = this.libsButton;
var target = $(e.target);
if (!target.is(elem) && elem.has(target).length === 0 && target.closest('.popover').length === 0) {
elem.popover('hide');
}
}, this));
this.eventHub.on('initialised', this.undefer, this);
};
Compiler.prototype.onOptionsChange = function (options) {
@@ -1065,8 +1075,7 @@ function getNumericToolTip(value) {
return null;
}
var getAsmInfo = function (opcode) {
function getAsmInfo(opcode) {
var cacheName = 'asm/' + opcode;
var cached = OpcodeCache.get(cacheName);
if (cached) {
@@ -1088,7 +1097,7 @@ var getAsmInfo = function (opcode) {
cache: true
});
});
};
}
Compiler.prototype.onMouseMove = function (e) {
if (e === null || e.target === null || e.target.position === null) return;
@@ -1096,22 +1105,27 @@ Compiler.prototype.onMouseMove = function (e) {
var hoverAsm = this.assembly[e.target.position.lineNumber - 1];
if (hoverAsm) {
// We check that we actually have something to show at this point!
this.eventHub.emit('editorSetDecoration', this.sourceEditorId, hoverAsm.source && !hoverAsm.source.file ? hoverAsm.source.line : -1, false);
this.eventHub.emit('editorSetDecoration', this.sourceEditorId, hoverAsm.source && !hoverAsm.source.file ?
hoverAsm.source.line : -1, false);
}
}
var currentWord = this.outputEditor.getModel().getWordAtPosition(e.target.position);
if (currentWord && currentWord.word) {
var word = currentWord.word;
currentWord.range = new monaco.Range(e.target.position.lineNumber, currentWord.startColumn, e.target.position.lineNumber, currentWord.endColumn);
// Avoid throwing an exception if somehow (How?) we have a non existent lineNumber. c.f. https://sentry.io/matt-godbolt/compiler-explorer/issues/285270358/
var startColumn = currentWord.startColumn;
// Avoid throwing an exception if somehow (How?) we have a non existent lineNumber.
// c.f. https://sentry.io/matt-godbolt/compiler-explorer/issues/285270358/
if (e.target.position.lineNumber < this.outputEditor.getModel().getLineCount()) {
// Hacky workaround to check for negative numbers. c.f. https://github.com/mattgodbolt/compiler-explorer/issues/434
// Hacky workaround to check for negative numbers.
// c.f. https://github.com/mattgodbolt/compiler-explorer/issues/434
var lineContent = this.outputEditor.getModel().getLineContent(e.target.position.lineNumber);
if (lineContent[currentWord.startColumn - 2] === '-') {
word = '-' + word;
currentWord.range.startColumn -= 1;
startColumn -= 1;
}
}
currentWord.range = new monaco.Range(e.target.position.lineNumber, Math.max(startColumn, 1),
e.target.position.lineNumber, currentWord.endColumn);
var numericToolTip = getNumericToolTip(word);
if (numericToolTip) {
this.decorations.numericToolTip = {
@@ -1376,4 +1390,3 @@ Compiler.prototype.onOutputClosed = function (compilerId) {
module.exports = {
Compiler: Compiler
};

View File

@@ -105,6 +105,7 @@ function Diff(hub, container, state) {
this.eventHub.on('compileResult', this.onCompileResult, this);
this.eventHub.on('compiler', this.onCompiler, this);
this.eventHub.on('compilerClose', this.onCompilerClose, this);
this.eventHub.on('settingsChange', this.onSettingsChange, this);
this.eventHub.on('themeChange', this.onThemeChange, this);
this.container.on('destroy', function () {
this.eventHub.unsubscribe();
@@ -117,6 +118,7 @@ function Diff(hub, container, state) {
this.eventHub.emit('resendCompilation', this.rhs.id);
this.eventHub.emit('findCompilers');
this.eventHub.emit('requestTheme');
this.eventHub.emit('requestSettings');
this.updateCompilerNames();
this.updateCompilers();
@@ -216,6 +218,14 @@ Diff.prototype.onThemeChange = function (newTheme) {
this.outputEditor.updateOptions({theme: newTheme.monaco});
};
Diff.prototype.onSettingsChange = function (newSettings) {
this.outputEditor.updateOptions({
minimap: {
enabled: newSettings.showMinimap
}
});
};
module.exports = {
Diff: Diff,
getComponent: function (lhs, rhs) {

View File

@@ -50,6 +50,7 @@ function Editor(hub, state, container) {
this.container = container;
this.domRoot = container.getElement();
this.domRoot.html($('#codeEditor').html());
this.hub = hub;
this.eventHub = hub.createEventHub();
// Should probably be its own function somewhere
this.settings = JSON.parse(local.get('settings', '{}'));
@@ -67,23 +68,10 @@ function Editor(hub, state, container) {
this.editorSourceByLang = {};
this.alertSystem = new Alert();
this.languageBtn = this.domRoot.find('.change-language');
var langKeys = _.keys(languages);
// Ensure that the btn is disabled if we don't have nothing to select
// Note that is might be disabled for other reasons beforehand
if (langKeys.length <= 1) {
this.languageBtn.prop("disabled", true);
}
this.currentLanguage = languages[langKeys[0]];
this.waitingForLanguage = state.source && !state.lang;
if (languages[this.settings.defaultLanguage]) {
this.currentLanguage = languages[this.settings.defaultLanguage];
}
if (languages[state.lang]) {
this.currentLanguage = languages[state.lang];
} else if (this.settings.newEditorLastLang && languages[hub.lastOpenedLangId]) {
this.currentLanguage = languages[hub.lastOpenedLangId];
}
this.langKeys = _.keys(languages);
this.initLanguage(state);
var root = this.domRoot.find(".monaco-placeholder");
var legacyReadOnly = state.options && !!state.options.readOnly;
this.editor = monaco.editor.create(root[0], {
@@ -117,6 +105,210 @@ function Editor(hub, state, container) {
foldAction.run();
}
this.initEditorActions();
this.initButtons(state);
this.initCallbacks();
var usableLanguages = _.filter(languages, function (language) {
return hub.compilerService.compilersByLang[language.id];
});
this.languageBtn.selectize({
sortField: 'name',
valueField: 'id',
labelField: 'name',
searchField: ['name'],
options: _.map(usableLanguages, _.identity),
items: [this.currentLanguage.id]
}).on('change', _.bind(function (e) {
this.onLanguageChange($(e.target).val());
}, this));
this.selectize = this.languageBtn[0].selectize;
// We suppress posting changes until the user has stopped typing by:
// * Using _.debounce() to run emitChange on any key event or change
// only after a delay.
// * Only actually triggering a change if the document text has changed from
// the previous emitted.
this.lastChangeEmitted = null;
this.onSettingsChange(this.settings);
// this.editor.on("keydown", _.bind(function () {
// // Not strictly a change; but this suppresses changes until some time
// // after the last key down (be it an actual change or a just a cursor
// // movement etc).
// this.debouncedEmitChange();
// }, this));
this.updateTitle();
this.updateState();
}
// If compilerId is undefined, every compiler will be pinged
Editor.prototype.maybeEmitChange = function (force, compilerId) {
var source = this.getSource();
if (!force && source === this.lastChangeEmitted) return;
this.lastChangeEmitted = source;
this.eventHub.emit('editorChange', this.id, this.lastChangeEmitted, this.currentLanguage.id, compilerId);
};
Editor.prototype.updateState = function () {
var state = {
id: this.id,
source: this.getSource(),
lang: this.currentLanguage.id
};
this.fontScale.addState(state);
this.container.setState(state);
};
Editor.prototype.setSource = function (newSource) {
this.editor.getModel().setValue(newSource);
};
Editor.prototype.getSource = function () {
return this.editor.getModel().getValue();
};
Editor.prototype.initLanguage = function (state) {
this.currentLanguage = languages[this.langKeys[0]];
this.waitingForLanguage = state.source && !state.lang;
if (languages[this.settings.defaultLanguage]) {
this.currentLanguage = languages[this.settings.defaultLanguage];
}
if (languages[state.lang]) {
this.currentLanguage = languages[state.lang];
} else if (this.settings.newEditorLastLang && languages[this.hub.lastOpenedLangId]) {
this.currentLanguage = languages[this.hub.lastOpenedLangId];
}
};
Editor.prototype.initCallbacks = function () {
this.fontScale.on('change', _.bind(this.updateState, this));
this.container.on('resize', this.resize, this);
this.container.on('shown', this.resize, this);
this.container.on('open', _.bind(function () {
this.eventHub.emit('editorOpen', this.id);
}, this));
this.container.on('destroy', this.close, this);
this.container.layoutManager.on('initialised', function () {
// Once initialized, let everyone know what text we have.
this.maybeEmitChange();
}, this);
this.eventHub.on('compilerOpen', this.onCompilerOpen, this);
this.eventHub.on('compilerClose', this.onCompilerClose, this);
this.eventHub.on('compiling', this.onCompiling, this);
this.eventHub.on('compileResult', this.onCompileResponse, this);
this.eventHub.on('selectLine', this.onSelectLine, this);
this.eventHub.on('editorSetDecoration', this.onEditorSetDecoration, this);
this.eventHub.on('settingsChange', this.onSettingsChange, this);
this.eventHub.on('conformanceViewOpen', this.onConformanceViewOpen, this);
this.eventHub.on('conformanceViewClose', this.onConformanceViewClose, this);
this.eventHub.on('resize', this.resize, this);
this.editor.getModel().onDidChangeContent(_.bind(function () {
this.debouncedEmitChange();
this.updateState();
}, this));
this.editor.onMouseLeave(_.bind(function () {
this.fadeTimeoutId = setTimeout(_.bind(function () {
this.clearCompilerLinkedLines();
this.fadeTimeoutId = -1;
}, this), 5000);
}, this));
this.mouseMoveThrottledFunction = _.throttle(_.bind(function (e) {
if (e !== null && e.target !== null && this.settings.hoverShowSource && e.target.position !== null) {
this.tryCompilerLinkLine(e.target.position.lineNumber, false);
}
}, this), 250);
this.editor.onMouseMove(_.bind(function (e) {
this.mouseMoveThrottledFunction(e);
// This can't be throttled or we can clear a timeout where we're already outside
if (this.fadeTimeoutId !== -1) {
clearTimeout(this.fadeTimeoutId);
this.fadeTimeoutId = -1;
}
}, this));
this.eventHub.on('initialised', this.maybeEmitChange, this);
};
Editor.prototype.initButtons = function (state) {
this.fontScale = new FontScale(this.domRoot, state, this.editor);
this.languageBtn = this.domRoot.find('.change-language');
// Ensure that the buttonn is disabled if we don't have nothing to select
// Note that is might be disabled for other reasons beforehand
if (this.langKeys.length <= 1) {
this.languageBtn.prop("disabled", true);
}
var addCompilerButton = this.domRoot.find('.btn.add-compiler');
var paneAdderDropdown = this.domRoot.find('.add-pane');
var togglePaneAdder = function () {
paneAdderDropdown.dropdown('toggle');
};
// NB a new compilerConfig needs to be created every time; else the state is shared
// between all compilers created this way. That leads to some nasty-to-find state
// bugs e.g. https://github.com/mattgodbolt/compiler-explorer/issues/225
var getCompilerConfig = _.bind(function () {
return Components.getCompiler(this.id, this.currentLanguage.id);
}, this);
var getConformanceConfig = _.bind(function () {
return Components.getConformanceView(this.id, this.getSource());
}, this);
this.container.layoutManager
.createDragSource(addCompilerButton, getCompilerConfig)
._dragListener.on('dragStart', togglePaneAdder);
addCompilerButton.click(_.bind(function () {
var insertPoint = this.hub.findParentRowOrColumn(this.container) ||
this.container.layoutManager.root.contentItems[0];
insertPoint.addChild(getCompilerConfig);
}, this));
this.conformanceViewerButton = this.domRoot.find('.btn.conformance');
this.container.layoutManager
.createDragSource(this.conformanceViewerButton, getConformanceConfig)
._dragListener.on('dragStart', togglePaneAdder);
this.conformanceViewerButton.click(_.bind(function () {
var insertPoint = this.hub.findParentRowOrColumn(this.container) ||
this.container.layoutManager.root.contentItems[0];
insertPoint.addChild(getConformanceConfig);
}, this));
};
Editor.prototype.changeLanguage = function (newLang) {
this.selectize.setValue(newLang);
};
Editor.prototype.clearCompilerLinkedLines = function () {
_.each(this.asmByCompiler, _.bind(function (asms, compilerId) {
this.eventHub.emit('compilerSetDecorations', compilerId, -1, false);
}, this));
};
Editor.prototype.tryCompilerLinkLine = function (thisLineNumber, reveal) {
_.each(this.asmByCompiler, _.bind(function (asms, compilerId) {
var targetLines = [];
_.each(asms, function (asmLine, i) {
if (asmLine.source && asmLine.source.file === null &&
asmLine.source.line === thisLineNumber) {
targetLines.push(i + 1);
}
});
this.eventHub.emit('compilerSetDecorations', compilerId, targetLines, reveal);
}, this));
};
Editor.prototype.initEditorActions = function () {
this.editor.addAction({
id: 'compile',
label: 'Compile',
@@ -167,185 +359,14 @@ function Editor(hub, state, container) {
contextMenuGroupId: 'navigation',
contextMenuOrder: 1.5,
run: function (ed) {
tryCompilerLinkLine(ed.getPosition().lineNumber, true);
this.tryCompilerLinkLine(ed.getPosition().lineNumber, true);
}
});
var tryCompilerLinkLine = _.bind(function (thisLineNumber, reveal) {
_.each(this.asmByCompiler, _.bind(function (asms, compilerId) {
var targetLines = [];
_.each(asms, function (asmLine, i) {
if (asmLine.source && asmLine.source.file === null &&
asmLine.source.line === thisLineNumber) {
targetLines.push(i + 1);
}
});
this.eventHub.emit('compilerSetDecorations', compilerId, targetLines, reveal);
}, this));
}, this);
var clearCompilerLinkedLines = _.bind(function () {
_.each(this.asmByCompiler, _.bind(function (asms, compilerId) {
this.eventHub.emit('compilerSetDecorations', compilerId, -1, false);
}, this));
}, this);
this.editor.onMouseLeave(_.bind(function () {
this.fadeTimeoutId = setTimeout(_.bind(function () {
clearCompilerLinkedLines();
this.fadeTimeoutId = -1;
}, this), 5000);
}, this));
this.mouseMoveThrottledFunction = _.throttle(_.bind(function (e) {
if (e !== null && e.target !== null && this.settings.hoverShowSource && e.target.position !== null) {
tryCompilerLinkLine(e.target.position.lineNumber, false);
}
}, this), 250);
this.editor.onMouseMove(_.bind(function (e) {
this.mouseMoveThrottledFunction(e);
// This can't be throttled or we can clear a timeout where we're already outside
if (this.fadeTimeoutId !== -1) {
clearTimeout(this.fadeTimeoutId);
this.fadeTimeoutId = -1;
}
}, this));
this.updateEditorLayout = _.bind(function () {
var topBarHeight = this.domRoot.find(".top-bar").outerHeight(true) || 0;
this.editor.layout({width: this.domRoot.width(), height: this.domRoot.height() - topBarHeight});
}, this);
this.fontScale = new FontScale(this.domRoot, state, this.editor);
this.fontScale.on('change', _.bind(this.updateState, this));
var usableLanguages = _.filter(languages, function (language) {
return hub.compilerService.compilersByLang[language.id];
});
this.languageBtn.selectize({
sortField: 'name',
valueField: 'id',
labelField: 'name',
searchField: ['name'],
options: _.map(usableLanguages, _.identity),
items: [this.currentLanguage.id]
}).on('change', _.bind(function (e) {
this.onLanguageChange($(e.target).val());
}, this));
this.changeLanguage = function (newLang) {
this.languageBtn[0].selectize.setValue(newLang);
};
// We suppress posting changes until the user has stopped typing by:
// * Using _.debounce() to run emitChange on any key event or change
// only after a delay.
// * Only actually triggering a change if the document text has changed from
// the previous emitted.
this.lastChangeEmitted = null;
this.onSettingsChange(this.settings);
this.editor.getModel().onDidChangeContent(_.bind(function () {
this.debouncedEmitChange();
this.updateState();
}, this));
// this.editor.on("keydown", _.bind(function () {
// // Not strictly a change; but this suppresses changes until some time
// // after the last key down (be it an actual change or a just a cursor
// // movement etc).
// this.debouncedEmitChange();
// }, this));
container.on('resize', this.updateEditorLayout);
container.on('shown', this.updateEditorLayout);
container.on('open', _.bind(function () {
this.eventHub.emit('editorOpen', this.id);
}, this));
container.on('destroy', this.close, this);
this.container.layoutManager.on('initialised', function () {
// Once initialized, let everyone know what text we have.
this.maybeEmitChange();
}, this);
this.eventHub.on('compilerOpen', this.onCompilerOpen, this);
this.eventHub.on('compilerClose', this.onCompilerClose, this);
this.eventHub.on('compiling', this.onCompiling, this);
this.eventHub.on('compileResult', this.onCompileResponse, this);
this.eventHub.on('selectLine', this.onSelectLine, this);
this.eventHub.on('editorSetDecoration', this.onEditorSetDecoration, this);
this.eventHub.on('settingsChange', this.onSettingsChange, this);
this.eventHub.on('conformanceViewOpen', this.onConformanceViewOpen, this);
this.eventHub.on('conformanceViewClose', this.onConformanceViewClose, this);
this.eventHub.on('resize', this.updateEditorLayout, this);
// NB a new compilerConfig needs to be created every time; else the state is shared
// between all compilers created this way. That leads to some nasty-to-find state
// bugs e.g. https://github.com/mattgodbolt/compiler-explorer/issues/225
var compilerConfig = _.bind(function () {
return Components.getCompiler(this.id, this.currentLanguage.id);
}, this);
var addCompilerButton = this.domRoot.find('.btn.add-compiler');
var paneAdderDropdown = this.domRoot.find('.add-pane');
var togglePaneAdder = function () {
paneAdderDropdown.dropdown('toggle');
};
this.container.layoutManager
.createDragSource(addCompilerButton, compilerConfig)
._dragListener.on('dragStart', togglePaneAdder);
addCompilerButton.click(_.bind(function () {
var insertPoint = hub.findParentRowOrColumn(this.container) ||
this.container.layoutManager.root.contentItems[0];
insertPoint.addChild(compilerConfig);
}, this));
var conformanceConfig = _.bind(function () {
return Components.getConformanceView(this.id, this.getSource());
}, this);
this.conformanceViewerButton = this.domRoot.find('.btn.conformance');
this.container.layoutManager
.createDragSource(this.conformanceViewerButton, conformanceConfig)
._dragListener.on('dragStart', togglePaneAdder);
this.conformanceViewerButton.click(_.bind(function () {
var insertPoint = hub.findParentRowOrColumn(this.container) ||
this.container.layoutManager.root.contentItems[0];
insertPoint.addChild(conformanceConfig);
}, this));
this.updateTitle();
this.eventHub.on('initialised', this.maybeEmitChange, this);
this.updateState();
}
// If compilerId is undefined, every compiler will be pinged
Editor.prototype.maybeEmitChange = function (force, compilerId) {
var source = this.getSource();
if (!force && source === this.lastChangeEmitted) return;
this.lastChangeEmitted = source;
this.eventHub.emit('editorChange', this.id, this.lastChangeEmitted, this.currentLanguage.id, compilerId);
};
Editor.prototype.updateState = function () {
var state = {
id: this.id,
source: this.getSource(),
lang: this.currentLanguage.id
};
this.fontScale.addState(state);
this.container.setState(state);
};
Editor.prototype.setSource = function (newSource) {
this.editor.getModel().setValue(newSource);
};
Editor.prototype.getSource = function () {
return this.editor.getModel().getValue();
Editor.prototype.resize = function () {
var topBarHeight = this.domRoot.find(".top-bar").outerHeight(true) || 0;
this.editor.layout({width: this.domRoot.width(), height: this.domRoot.height() - topBarHeight});
};
Editor.prototype.onSettingsChange = function (newSettings) {

View File

@@ -79,15 +79,6 @@ function Opt(hub, container, state) {
this.eventHub.emit("optViewOpened", this._compilerid);
}
// TODO: de-dupe with compiler etc
Opt.prototype.resize = function () {
var topBarHeight = this.domRoot.find(".top-bar").outerHeight(true);
this.optEditor.layout({
width: this.domRoot.width(),
height: this.domRoot.height() - topBarHeight
});
};
Opt.prototype.onEditorChange = function (id, source) {
if (this._editorid === id) {
this.code = source;
@@ -103,8 +94,10 @@ Opt.prototype.onCompileResult = function (id, compiler, result, lang) {
}
}
};
Opt.prototype.setTitle = function () {
this.container.setTitle(this._compilerName + " Opt Viewer (Editor #" + this._editorid + ", Compiler #" + this._compilerid + ")");
this.container.setTitle(
this._compilerName + " Opt Viewer (Editor #" + this._editorid + ", Compiler #" + this._compilerid + ")");
};
Opt.prototype.getDisplayableOpt = function (optResult) {
@@ -161,7 +154,6 @@ Opt.prototype.onCompiler = function (id, compiler, options, editorid) {
}
};
// TODO: de-dupe with compiler etc
Opt.prototype.resize = function () {
var topBarHeight = this.domRoot.find(".top-bar").outerHeight(true);
this.optEditor.layout({
@@ -170,22 +162,17 @@ Opt.prototype.resize = function () {
});
};
Opt.prototype.onEditorChange = function (id, source) {
if (this._editorid === id) {
this.code = source;
this.optEditor.setValue(source);
}
};
Opt.prototype.setTitle = function () {
this.container.setTitle(this._compilerName + " Opt Viewer (Editor #" + this._editorid + ", Compiler #" + this._compilerid + ")");
};
Opt.prototype.getDisplayableOpt = function (optResult) {
return "**" + optResult.optType + "** - " + optResult.displayString;
};
Opt.prototype.updateState = function () {
this.container.setState(this.currentState());
};
Opt.prototype.currentState = function () {
var state = {
id: this._compilerid,
editorid: this._editorid
};
this.fontScale.addState(state);
return state;
};
Opt.prototype.close = function () {

View File

@@ -148,7 +148,9 @@ function setupSettings(root, settings, onChange, langId) {
var isStoredUsable = false;
colourSchemeSelect.empty();
_.each(colour.schemes, function (scheme) {
if (!scheme.themes || scheme.themes.length === 0 || scheme.themes.indexOf(newTheme) !== -1 || scheme.themes.indexOf('all') !== -1) {
if (!scheme.themes || scheme.themes.length === 0 || scheme.themes.indexOf(newTheme) !== -1 ||
scheme.themes.indexOf('all') !== -1) {
colourSchemeSelect.append($('<option value="' + scheme.name + '">' + scheme.desc + "</option>"));
if (newThemeStoredScheme === scheme.name) {
isStoredUsable = true;
@@ -159,7 +161,8 @@ function setupSettings(root, settings, onChange, langId) {
colourSchemeSelect.val(isStoredUsable ? newThemeStoredScheme : colourSchemeSelect.first().val());
} else {
// This should never happen. In case it does, lets use the default one
colourSchemeSelect.append($('<option value="' + colour.schemes[0].name + '">' + colour.schemes[0].desc + "</option>"));
colourSchemeSelect.append(
$('<option value="' + colour.schemes[0].name + '">' + colour.schemes[0].desc + "</option>"));
colourSchemeSelect.val(colourSchemeSelect.first().val());
}
colourSchemeSelect.trigger('change');