Skip to content

Commit

Permalink
Update text editor to use monaco. Partially addresses #571 (#1800)
Browse files Browse the repository at this point in the history
* Initial commit for replacing ace with monaco editor

* WIP- Remove ace from TextEditor

* WIP- Integrate vim keybindings

* Ensure editor hasn't been destroyed while loading vim keybindings

* Remove dummy python code for ''

* WIP- Add support for additional themes

* WIP- Fix eslint issues, remove unused functions in LogViewerWidget

* WIP- Fix more eslint and code climate fixes

* WIP- Fix model dispose problem by disposing editor only

* WIP-Remove console.log statement from TextEditorWidget.js

Co-authored-by: Brian Broll <brian.broll@gmail.com>
  • Loading branch information
umesh-timalsina and brollb committed Sep 17, 2020
1 parent c97136f commit a700a9e
Show file tree
Hide file tree
Showing 1,057 changed files with 14,797 additions and 314,908 deletions.
4 changes: 2 additions & 2 deletions config/config.base.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ config.blob.fsDir = process.env.DEEPFORGE_BLOB_DIR || config.blob.fsDir;

config.requirejsPaths.deepforge = './src/common';
config.requirejsPaths['aws-sdk-min'] = './node_modules/aws-sdk/dist/aws-sdk.min';
config.requirejsPaths.ace = './src/visualizers/widgets/TextEditor/lib/ace';
config.requirejsPaths.vs = './node_modules/monaco-editor/min/vs';
config.requirejsPaths.MonacoVim = './node_modules/monaco-vim/dist/monaco-vim';
config.seedProjects.defaultProject = 'project';

config.plugin.allowBrowserExecution = true;
config.plugin.allowServerExecution = true;

config.executor.enable = true;

config.visualization.extraCss.push('deepforge/styles/global.css');

config.storage.autoMerge.enable = true;
Expand Down
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
"lodash.merge": "^4.6.2",
"lodash.template": "^4.4.0",
"minimatch": "^3.0.4",
"monaco-editor": "^0.20.0",
"monaco-vim": "^0.1.7",
"mongodb": "^2.2.10",
"node-fetch": "^2.6.0",
"pacote": "^11.1.10",
Expand Down
4 changes: 3 additions & 1 deletion src/visualizers/panels/LogViewer/LogViewerControl.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ define([
};

LogViewerControl.prototype._onLoad = function (id) {
this.getFullDescriptor(id).then(desc => this._widget.addNode(desc));
this.getFullDescriptor(id).then(desc => {
this._widget.addNode(desc);
});
};

LogViewerControl.prototype._onUpdate = function (id) {
Expand Down
3 changes: 2 additions & 1 deletion src/visualizers/panels/LogViewer/LogViewerPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ define([

//set Widget title
this.setTitle('');
const config = {language: 'plaintext', displayMiniMap: false};

this.widget = new LogViewerWidget(this.logger, this.$el);
this.widget = new LogViewerWidget(this.logger, this.$el, config);

this.widget.setTitle = function (title) {
self.setTitle(title);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ define([
//set Widget title
this.setTitle('');

const config = {language: 'yaml'};
const config = {language: 'yaml', displayMiniMap: false};
this.widget = new TextEditorWidget(this.logger, this.$el, config);

this.widget.setTitle = function (title) {
Expand Down
126 changes: 15 additions & 111 deletions src/visualizers/widgets/LogViewer/LogViewerWidget.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*globals define, _*/
/*globals define, _, monaco*/
/*jshint browser: true*/

define([
Expand All @@ -9,134 +9,38 @@ define([
) {
'use strict';

var LogViewerWidget,
ANSI_COLORS = [
'black',
'red',
'green',
'yellow',
'blue',
'magenta',
'cyan',
'gray'
];

LogViewerWidget = function () {
const LogViewerWidget = function () {
this.readOnly = true;
TextEditorWidget.apply(this, arguments);
this._el.addClass('log-viewer');
this.editor.setTheme('ace/theme/twilight');
this.editor.setShowPrintMargin(false);
this.editor.renderer.setScrollMargin(0, 75);
this.addKeyListeners();

// Override the textlayer to add support for ansi colors
this.customizeAce();
this.editor.updateOptions({
lineNumbers: this.getLineNumbers
});
this.setReadOnly(true);
};

_.extend(LogViewerWidget.prototype, TextEditorWidget.prototype);

LogViewerWidget.prototype.addKeyListeners = function() {
// Need to add key listeners to the container itself since ace is in read-only mode
this._el.on('keydown', event => {
// ctrl-alt-pagedown -> EOF
if (event.key === 'PageDown' && event.altKey && (event.ctrlKey || event.metaKey)) {
this.editor.gotoLine(Infinity);
event.stopPropagation();
event.preventDefault();
}
// ctrl-alt-pagedown -> beginning of file
if (event.key === 'PageUp' && event.altKey && (event.ctrlKey || event.metaKey)) {
this.editor.gotoLine(0);
event.stopPropagation();
event.preventDefault();
}
});
};

LogViewerWidget.prototype.getHeader = function(desc) {
return `Console logging for Operation "${desc.name}":\n`;
};

LogViewerWidget.prototype.customizeAce = function() {
var textLayer = this.editor.renderer.$textLayer,
renderToken = textLayer.$renderToken;

textLayer.$renderToken = function(builder, col, token, value) {
// check for ansi color
var ansiBuilder = LogViewerWidget.renderAnsiFromText(value),
newToken;

for (var i = 1; i < ansiBuilder.length; i+= 3) {
builder.push(ansiBuilder[i-1]);
value = ansiBuilder[i];
newToken = {
type: token.type,
value: value
};
col = renderToken.call(this, builder, col, newToken, value);
builder.push(ansiBuilder[i+1]);
}

return col;
};
};

// Get the editor text and update wrt ansi colors
LogViewerWidget.renderAnsiFromText = function(remaining) {
var r = /\[[0-6][0-9]?(;[0-9]([0-7]))?m/,
match,
ansiCode,
text,
color,
nextColor = 'default',
builder = [];

color = color || nextColor;
while (remaining) {
match = remaining.match(r);
if (match) {
ansiCode = match[0];
if (match[1] && match[1][1] === '3') { // foreground color
nextColor = ANSI_COLORS[match[2]] || null;
}
text = remaining.substring(0, match.index);
remaining = remaining.substring(match.index+ansiCode.length);
} else {
text = remaining;
remaining = '';
}

// Add a "span" node w/ the appropriate color class
builder.push(`<span class='ansi-${color}'>`, text, '</span>');

color = nextColor;
nextColor = 'default';
}
return builder;
LogViewerWidget.prototype.getLineNumbers = function(lineno) {
return lineno - 2;
};

LogViewerWidget.prototype.getSessionOptions = function() {
return {
firstLineNumber: -1
};
};

LogViewerWidget.prototype.addNode = function (desc) {
var atEOF = this.editor.getLastVisibleRow()+1 ===
this.editor.session.getLength();

LogViewerWidget.prototype.addNode = function(desc) {
TextEditorWidget.prototype.addNode.call(this, desc);

if (atEOF) { // Scroll to bottom
this.editor.gotoLine(Infinity);
}
const revealLineno = Math.ceil(this.model.getLineCount()/2);
this.editor.revealLineInCenter(
revealLineno,
monaco.editor.ScrollType.Smooth
);
};

LogViewerWidget.prototype.getDefaultEditorOptions = function() {
const opts = TextEditorWidget.prototype.getDefaultEditorOptions.call(this);
opts.fontFamily = 'bitstream vera sans mono';
opts.fontSize = '10pt';
opts.fontSize = 10;
return opts;
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*globals define */
/*globals define, monaco*/
/*jshint browser: true*/

define([
Expand All @@ -18,13 +18,12 @@ define([
TextEditorWidget.call(this, logger, container);
this.lineOffset = 0;
// Add the shift-enter command
this.editor.commands.addCommand({
name: 'executeOrStopJob',
bindKey: {
mac: 'Shift-Enter',
win: 'Shift-Enter'
},
exec: () => this.executeOrStopJob()
this.editor.addCommand(
monaco.KeyMod.Shift | monaco.KeyCode.Enter,
this.executeOrStopJob
);
this.editor.updateOptions({
lineNumbers: this.updateOffset.bind(this)
});
};

Expand All @@ -50,40 +49,16 @@ define([
OperationCodeEditorWidget.prototype.setLineOffset = function (offset) {
if (this.lineOffset !== offset) {
this.lineOffset = offset;
this.updateOffset();
}
};

OperationCodeEditorWidget.prototype.updateOffset = function () {
OperationCodeEditorWidget.prototype.updateOffset = function (originalLineNumber) {
var lines,
actualOffset;

lines = this.currentHeader.match(/\n/g);
actualOffset = this.lineOffset - (lines ? lines.length : 0);
this.editor.setOption('firstLineNumber', actualOffset);
};

OperationCodeEditorWidget.prototype.getCompleter = function () {
var completer = TextEditorWidget.prototype.getCompleter.call(this),
getBasicCompletions = completer.getCompletionsFor,
self = this;

// TODO: update completions for python stuff
completer.getCompletionsFor = function(obj) {
if (obj === 'attributes') {
return self.getOperationAttributes().map(attr => {
return {
name: attr,
value: attr,
score: 4,
meta: 'operation'
};
});
} else {
return getBasicCompletions.apply(this, arguments);
}
};
return completer;
actualOffset = this.lineOffset - (lines ? lines.length + 1 : 0);
return (originalLineNumber + actualOffset);
};

return OperationCodeEditorWidget;
Expand Down
60 changes: 60 additions & 0 deletions src/visualizers/widgets/TextEditor/MonacoLanguages.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"python": {
"id": "python",
"extensions": [
".py",
".pyc"
],
"aliases": [
"py",
"PY"
],
"mimetypes": [
"application/text"
],
"comment": "#"
},
"javascript": {
"id": "javascript",
"extensions": [
"js",
"jsx"
],
"mimetypes": [
"application/text"
],
"comment": "//"
},
"yaml": {
"id": "yaml",
"extensions": [
"yaml",
"yml"
],
"aliases": [
"yml",
"yaml",
"YML",
"YAML"
],
"mimetypes": [
"application/text"
],
"comment": "#"
},
"plaintext": {
"id": "plaintext",
"extensions": [
"txt",
"text"
],
"aliases": [
"text",
"PLAINTEXT"
],
"mimetypes": [
"application/text"
],
"comment": "#"
}
}
36 changes: 36 additions & 0 deletions src/visualizers/widgets/TextEditor/MonacoThemesProvider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/* globals monaco, define */

define(['text!./Themes/themelist.json'], function (ThemeList) {
const DEFAULT_THEMES = ['vs-dark', 'vs', 'hc-black'];
ThemeList = JSON.parse(ThemeList);

class MonacoThemesProvider {
constructor() {
this.importedThemes = DEFAULT_THEMES;
this.themes = DEFAULT_THEMES.concat(Object.keys(ThemeList));
}

async setTheme(theme) {
if (this.importedThemes.includes(theme)){
monaco.editor.setTheme(theme);
} else if (this.themes.includes(theme)){
const themeData = await this._importTheme(theme);
monaco.editor.defineTheme(theme, themeData);
monaco.editor.setTheme(theme);
} else {
monaco.editor.setTheme(DEFAULT_THEMES[0]);
}
}

async _importTheme(theme) {
return new Promise((resolve, reject) => {
const importName = `text!widgets/TextEditor/Themes/${(ThemeList[theme])}.json`;
require([importName], (themeJSON) => {
resolve(JSON.parse(themeJSON));
}, reject);
});
}
}

return MonacoThemesProvider;
});

0 comments on commit a700a9e

Please sign in to comment.