mirror of
https://github.com/apache/zeppelin
synced 2026-05-24 09:38:26 +00:00
Get paragraph editor mode from backend
This commit is contained in:
parent
52f42071d2
commit
20132ca9ff
9 changed files with 111 additions and 50 deletions
|
|
@ -251,6 +251,7 @@ public abstract class Interpreter {
|
|||
private String className;
|
||||
private boolean defaultInterpreter;
|
||||
private Map<String, InterpreterProperty> properties;
|
||||
private Map<String, Object> editor;
|
||||
private String path;
|
||||
|
||||
public RegisteredInterpreter(String name, String group, String className,
|
||||
|
|
@ -266,6 +267,7 @@ public abstract class Interpreter {
|
|||
this.className = className;
|
||||
this.defaultInterpreter = defaultInterpreter;
|
||||
this.properties = properties;
|
||||
this.editor = new HashMap<>();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
|
@ -292,6 +294,10 @@ public abstract class Interpreter {
|
|||
return properties;
|
||||
}
|
||||
|
||||
public Map<String, Object> getEditor() {
|
||||
return editor;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -250,6 +250,9 @@ public class NotebookServer extends WebSocketServlet implements
|
|||
case SAVE_INTERPRETER_BINDINGS:
|
||||
saveInterpreterBindings(conn, messagereceived);
|
||||
break;
|
||||
case EDITOR_SETTING:
|
||||
getEditorSetting(conn, notebook, messagereceived);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -1457,7 +1460,7 @@ public class NotebookServer extends WebSocketServlet implements
|
|||
}
|
||||
|
||||
/**
|
||||
* This callback is for praragraph that runs on RemoteInterpreterProcess
|
||||
* This callback is for paragraph that runs on RemoteInterpreterProcess
|
||||
* @param paragraph
|
||||
* @param out
|
||||
* @param output
|
||||
|
|
@ -1569,11 +1572,24 @@ public class NotebookServer extends WebSocketServlet implements
|
|||
if (id.equals(interpreterGroupId)) {
|
||||
broadcast(
|
||||
note.getId(),
|
||||
new Message(OP.ANGULAR_OBJECT_REMOVE).put("name", name).put(
|
||||
"noteId", noteId).put("paragraphId", paragraphId));
|
||||
new Message(OP.ANGULAR_OBJECT_REMOVE)
|
||||
.put("name", name)
|
||||
.put("noteId", noteId)
|
||||
.put("paragraphId", paragraphId));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void getEditorSetting(NotebookSocket conn, Notebook notebook, Message fromMessage)
|
||||
throws IOException {
|
||||
String replName = (String) fromMessage.get("magic");
|
||||
String noteId = getOpenNoteId(conn);
|
||||
Note note = notebook.getNote(noteId);
|
||||
Message resp = new Message(OP.EDITOR_SETTING);
|
||||
resp.put("editor", note.getEditorSetting(replName));
|
||||
conn.send(serializeMessage(resp));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
"angular-elastic": "~2.4.2",
|
||||
"angular-elastic-input": "~2.2.0",
|
||||
"angular-xeditable": "0.1.12",
|
||||
"highlightjs": "^9.2.0",
|
||||
"highlightjs": "^9.4.0",
|
||||
"lodash": "~3.9.3",
|
||||
"angular-filter": "~0.5.4",
|
||||
"ngtoast": "~2.0.0",
|
||||
|
|
@ -62,7 +62,7 @@
|
|||
"highlight.pack.js",
|
||||
"styles/github.css"
|
||||
],
|
||||
"version": "8.4.0",
|
||||
"version": "9.4.0",
|
||||
"name": "highlightjs"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
angular.module('zeppelinWebApp').controller('ParagraphCtrl', function($scope, $rootScope, $route, $window,
|
||||
$routeParams, $location, $timeout, $compile,
|
||||
$http, websocketMsgSrv, baseUrlSrv, ngToast,
|
||||
$http, $q, websocketMsgSrv, baseUrlSrv, ngToast,
|
||||
saveAsService, esriLoader) {
|
||||
var ANGULAR_FUNCTION_OBJECT_NAME_PREFIX = '_Z_ANGULAR_FUNC_';
|
||||
$scope.parentNote = null;
|
||||
|
|
@ -78,15 +78,6 @@ angular.module('zeppelinWebApp').controller('ParagraphCtrl', function($scope, $r
|
|||
|
||||
var angularObjectRegistry = {};
|
||||
|
||||
var editorModes = {
|
||||
'ace/mode/python': /^%(\w*\.)?(pyspark|python)\s*$/,
|
||||
'ace/mode/scala': /^%(\w*\.)?spark\s*$/,
|
||||
'ace/mode/r': /^%(\w*\.)?(r|sparkr|knitr)\s*$/,
|
||||
'ace/mode/sql': /^%(\w*\.)?\wql/,
|
||||
'ace/mode/markdown': /^%md/,
|
||||
'ace/mode/sh': /^%sh/
|
||||
};
|
||||
|
||||
// Controller init
|
||||
$scope.init = function(newParagraph, note) {
|
||||
$scope.paragraph = newParagraph;
|
||||
|
|
@ -538,7 +529,7 @@ angular.module('zeppelinWebApp').controller('ParagraphCtrl', function($scope, $r
|
|||
$scope.aceChanged = function() {
|
||||
$scope.dirtyText = $scope.editor.getSession().getValue();
|
||||
$scope.startSaveTimer();
|
||||
$scope.setParagraphMode($scope.editor.getSession(), $scope.dirtyText, $scope.editor.getCursorPosition());
|
||||
setParagraphMode($scope.editor.getSession(), $scope.dirtyText, $scope.editor.getCursorPosition());
|
||||
};
|
||||
|
||||
$scope.aceLoaded = function(_editor) {
|
||||
|
|
@ -576,37 +567,11 @@ angular.module('zeppelinWebApp').controller('ParagraphCtrl', function($scope, $r
|
|||
// not applying emacs key binding while the binding override Ctrl-v. default behavior of paste text on windows.
|
||||
}
|
||||
|
||||
$scope.setParagraphMode = function(session, paragraphText, pos) {
|
||||
// Evaluate the mode only if the first 30 characters of the paragraph have been modified or the the position is undefined.
|
||||
if ((typeof pos === 'undefined') || (pos.row === 0 && pos.column < 30)) {
|
||||
// If paragraph loading, use config value if exists
|
||||
if ((typeof pos === 'undefined') && $scope.paragraph.config.editorMode) {
|
||||
session.setMode($scope.paragraph.config.editorMode);
|
||||
} else {
|
||||
// Defaults to spark mode
|
||||
var newMode = 'ace/mode/scala';
|
||||
// Test first against current mode
|
||||
var oldMode = session.getMode().$id;
|
||||
if (!editorModes[oldMode] || !editorModes[oldMode].test(paragraphText)) {
|
||||
for (var key in editorModes) {
|
||||
if (key !== oldMode) {
|
||||
if (editorModes[key].test(paragraphText)) {
|
||||
$scope.paragraph.config.editorMode = key;
|
||||
session.setMode(key);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
$scope.paragraph.config.editorMode = newMode;
|
||||
session.setMode(newMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var remoteCompleter = {
|
||||
getCompletions: function(editor, session, pos, prefix, callback) {
|
||||
if (!$scope.editor.isFocused()) { return;}
|
||||
if (!$scope.editor.isFocused()) {
|
||||
return;
|
||||
}
|
||||
|
||||
pos = session.getTextRange(new Range(0, 0, pos.row, pos.column)).length;
|
||||
var buf = session.getValue();
|
||||
|
|
@ -662,7 +627,7 @@ angular.module('zeppelinWebApp').controller('ParagraphCtrl', function($scope, $r
|
|||
autoAdjustEditorHeight(_editor.container.id);
|
||||
});
|
||||
|
||||
$scope.setParagraphMode($scope.editor.getSession(), $scope.editor.getSession().getValue());
|
||||
setParagraphMode($scope.editor.getSession(), $scope.editor.getSession().getValue());
|
||||
|
||||
// autocomplete on '.'
|
||||
/*
|
||||
|
|
@ -737,6 +702,51 @@ angular.module('zeppelinWebApp').controller('ParagraphCtrl', function($scope, $r
|
|||
}
|
||||
};
|
||||
|
||||
var getEditorSetting = function(interpreterName) {
|
||||
var deferred = $q.defer();
|
||||
websocketMsgSrv.getEditorSetting(interpreterName);
|
||||
$timeout(
|
||||
$scope.$on('editorSetting', function(event, data) {
|
||||
deferred.resolve(data);
|
||||
}
|
||||
), 1000);
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
var setParagraphMode = function(session, paragraphText, pos) {
|
||||
// Evaluate the mode only if the the position is undefined
|
||||
// or the first 30 characters of the paragraph have been modified
|
||||
// or cursor position is at beginning of second line.(in case user hit enter after typing %magic)
|
||||
if ((typeof pos === 'undefined') || (pos.row === 0 && pos.column < 30) || (pos.row === 1 && pos.column === 0)) {
|
||||
// If paragraph loading, use config value if exists
|
||||
if ((typeof pos === 'undefined') && $scope.paragraph.config.editorMode) {
|
||||
session.setMode($scope.paragraph.config.editorMode);
|
||||
} else {
|
||||
var magic;
|
||||
// set editor mode to default interpreter syntax if paragraph text doesn't start with '%'
|
||||
if (!paragraphText.startsWith('%')) {
|
||||
magic = $scope.$parent.interpreterBindings[0].group;
|
||||
} else {
|
||||
var replNameRegexp = /%(.+?)\s/g;
|
||||
var match = replNameRegexp.exec(paragraphText);
|
||||
if (match) {
|
||||
magic = match[1];
|
||||
}
|
||||
}
|
||||
if (magic) {
|
||||
var promise = getEditorSetting(magic);
|
||||
promise.then(function(editorSetting) {
|
||||
if (!_.isEmpty(editorSetting.editor)) {
|
||||
var mode = 'ace/mode/' + editorSetting.editor.language;
|
||||
$scope.paragraph.config.editorMode = mode;
|
||||
session.setMode(mode);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var autoAdjustEditorHeight = function(id) {
|
||||
var editor = $scope.editor;
|
||||
var height = editor.getSession().getScreenLength() * editor.renderer.lineHeight +
|
||||
|
|
@ -2259,7 +2269,6 @@ angular.module('zeppelinWebApp').controller('ParagraphCtrl', function($scope, $r
|
|||
var noteId = $route.current.pathParams.noteId;
|
||||
$http.get(baseUrlSrv.getRestApiBase() + '/helium/suggest/' + noteId + '/' + $scope.paragraph.id)
|
||||
.success(function(data, status, headers, config) {
|
||||
console.log('Suggested apps %o', data);
|
||||
$scope.suggestion = data.body;
|
||||
})
|
||||
.error(function(err, status, headers, config) {
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@ angular.module('zeppelinWebApp').factory('websocketEvents',
|
|||
action: function(dialog) {
|
||||
dialog.close();
|
||||
angular.element('#loginModal').modal({
|
||||
show: 'true'
|
||||
});
|
||||
show: 'true'
|
||||
});
|
||||
}
|
||||
}, {
|
||||
label: 'Cancel',
|
||||
|
|
@ -97,6 +97,8 @@ angular.module('zeppelinWebApp').factory('websocketEvents',
|
|||
$rootScope.$broadcast('updateProgress', data);
|
||||
} else if (op === 'COMPLETION_LIST') {
|
||||
$rootScope.$broadcast('completionList', data);
|
||||
} else if (op === 'EDITOR_SETTING') {
|
||||
$rootScope.$broadcast('editorSetting', data);
|
||||
} else if (op === 'ANGULAR_OBJECT_UPDATE') {
|
||||
$rootScope.$broadcast('angularObjectUpdate', data);
|
||||
} else if (op === 'ANGULAR_OBJECT_REMOVE') {
|
||||
|
|
|
|||
|
|
@ -180,6 +180,15 @@ angular.module('zeppelinWebApp').service('websocketMsgSrv', function($rootScope,
|
|||
});
|
||||
},
|
||||
|
||||
getEditorSetting: function(replName) {
|
||||
websocketEvents.sendNewEvent({
|
||||
op: 'EDITOR_SETTING',
|
||||
data: {
|
||||
magic: replName
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
isConnected: function() {
|
||||
return websocketEvents.isConnected();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -650,6 +650,21 @@ public class Note implements Serializable, ParagraphJobListener {
|
|||
this.info = info;
|
||||
}
|
||||
|
||||
public Interpreter getRepl(String name) {
|
||||
return factory.getInterpreter(id(), name);
|
||||
}
|
||||
|
||||
public Map<String, Object> getEditorSetting(String replName) {
|
||||
Interpreter intp = getRepl(replName);
|
||||
Map<String, Object> editor = new HashMap<>();
|
||||
try {
|
||||
editor = intp.findRegisteredInterpreterByClassName(intp.getClassName()).getEditor();
|
||||
} catch (NullPointerException e) {
|
||||
editor.put("language", "text");
|
||||
}
|
||||
return editor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeStatusChange(Job job, Status before, Status after) {
|
||||
if (jobListenerFactory != null) {
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ public class Paragraph extends Job implements Serializable, Cloneable {
|
|||
}
|
||||
|
||||
public Interpreter getRepl(String name) {
|
||||
return factory.getInterpreter(note.getId(), name);
|
||||
return note.getRepl(name);
|
||||
}
|
||||
|
||||
public Interpreter getCurrentRepl() {
|
||||
|
|
|
|||
|
|
@ -76,6 +76,10 @@ public class Message {
|
|||
INSERT_PARAGRAPH, // [c-s] create new paragraph below current paragraph
|
||||
// @param target index
|
||||
|
||||
EDITOR_SETTING, // [c-s] ask paragraph editor setting
|
||||
// @param magic magic keyword written in paragraph
|
||||
// ex) spark.spark or spark
|
||||
|
||||
COMPLETION, // [c-s] ask completion candidates
|
||||
// @param id
|
||||
// @param buf current code
|
||||
|
|
|
|||
Loading…
Reference in a new issue