Răsfoiți Sursa

HUE-1729 [spark] Syntax highlighting for Scala and Java and hints

Added Java, Scala and Python autocomplete
Editor mode changes dinamycally now
Got rid of unused code
Enrico Berti 12 ani în urmă
părinte
comite
38b4cc578c

+ 20 - 105
apps/spark/src/spark/templates/app.mako

@@ -511,10 +511,11 @@ ${ commonheader(None, "spark", user) | n,unicode }
 <script src="/spark/static/js/spark.ko.js" type="text/javascript" charset="utf-8"></script>
 <script src="/static/ext/js/routie-0.3.0.min.js" type="text/javascript" charset="utf-8"></script>
 <script src="/static/ext/js/codemirror-3.11.js"></script>
-<script src="/static/js/clike.js"></script>
+<script src="/static/js/codemirror-clike.js"></script>
 <script src="/static/js/codemirror-python.js"></script>
 <script src="/static/js/codemirror-show-hint.js"></script>
-<script src="/static/js/codemirror-pig-hint.js"></script>
+<script src="/static/js/codemirror-python-hint.js"></script>
+<script src="/static/js/codemirror-clike-hint.js"></script>
 <script src="/beeswax/static/js/autocomplete.utils.js" type="text/javascript" charset="utf-8"></script>
 
 <link rel="stylesheet" href="/spark/static/css/spark.css">
@@ -556,9 +557,6 @@ ${ commonheader(None, "spark", user) | n,unicode }
   var viewModel = new SparkViewModel(appProperties);
   ko.applyBindings(viewModel);
 
-  var HIVE_AUTOCOMPLETE_BASE_URL = "${ autocomplete_base_url | n,unicode }";
-  var HIVE_AUTOCOMPLETE_FAILS_SILENTLY_ON = [503]; // error codes from beeswax/views.py - autocomplete
-
   var codeMirror;
 
   $(document).ready(function () {
@@ -571,88 +569,27 @@ ${ commonheader(None, "spark", user) | n,unicode }
     var logsAtEnd = true;
     var forceLogsAtEnd = false;
 
-    function storeVariables() {
-      CodeMirror.availableVariables = [];
-      var _val = codeMirror.getValue();
-      var _groups = _val.replace(/==/gi, "").split("=");
-      $.each(_groups, function (cnt, item) {
-        if (cnt < _groups.length - 1) {
-          var _blocks = $.trim(item).replace(/\n/gi, " ").split(" ");
-          CodeMirror.availableVariables.push(_blocks[_blocks.length - 1]);
-        }
-        if (item.toLowerCase().indexOf("split") > -1 && item.toLowerCase().indexOf("into") > -1) {
-          try {
-            var _split = item.substring(item.toLowerCase().indexOf("into"));
-            var _possibleVariables = $.trim(_split.substring(4, _split.indexOf(";"))).split(",");
-            $.each(_possibleVariables, function (icnt, iitem) {
-              if (iitem.toLowerCase().indexOf("if") > -1) {
-                CodeMirror.availableVariables.push($.trim(iitem).split(" ")[0]);
-              }
-            });
-          }
-          catch (e) {
-          }
-        }
-      });
-    }
-
-    var KLASS = "org.apache.hcatalog.pig.HCatLoader";
-
-    CodeMirror.onAutocomplete = function (data, from, to) {
-      if (CodeMirror.isHCatHint && data.indexOf(KLASS) > -1) {
-        codeMirror.replaceRange(" ", to, to);
-        codeMirror.setCursor(to);
-        CodeMirror.isHCatHint = false;
-        showHiveAutocomplete("default");
+    function getLanguageHint() {
+      var _hint = null;
+      switch (viewModel.currentScript().language()) {
+        case "java":
+          _hint = CodeMirror.javaHint;
+          break;
+        case "scala":
+          _hint = CodeMirror.scalaHint;
+          break;
+        case "python":
+          _hint = CodeMirror.pythonHint;
+          break;
       }
-    };
+      return _hint;
+    }
 
     CodeMirror.commands.autocomplete = function (cm) {
       $(document.body).on("contextmenu", function (e) {
         e.preventDefault(); // prevents native menu on FF for Mac from being shown
       });
-      storeVariables();
-      var _line = codeMirror.getLine(codeMirror.getCursor().line);
-      var _partial = _line.substring(0, codeMirror.getCursor().ch);
-      if (_partial.indexOf("'") > -1 && _partial.indexOf("'") == _partial.lastIndexOf("'")) {
-        CodeMirror.isHCatHint = false;
-        CodeMirror.isTable = false;
-        if (_partial.toLowerCase().indexOf("load") > -1 || _partial.toLowerCase().indexOf("into") > -1) {
-          var _path = _partial.substring(_partial.lastIndexOf("'") + 1);
-          var _autocompleteUrl = "/filebrowser/view";
-          if (_path.indexOf("/") == 0) {
-            _autocompleteUrl += _path.substr(0, _path.lastIndexOf("/"));
-          }
-          else if (_path.indexOf("/") > 0) {
-            _autocompleteUrl += USER_HOME + _path.substr(0, _path.lastIndexOf("/"));
-          }
-          else {
-            _autocompleteUrl += USER_HOME;
-          }
-          var _showHCatHint = false;
-          if (_line.indexOf(KLASS) == -1) {
-            if (_partial.indexOf("'") == _partial.length - 1) {
-              _showHCatHint = true;
-            }
-            showHdfsAutocomplete(_autocompleteUrl + "?format=json", _showHCatHint);
-          }
-          else {
-            var _db = _partial.substring(_partial.lastIndexOf("'") + 1);
-            if (_db.indexOf(".") > -1) {
-              showHiveAutocomplete(_db.substring(0, _db.length - 1));
-            }
-            else {
-              showHiveAutocomplete("default");
-            }
-          }
-        }
-      }
-      else {
-        CodeMirror.isPath = false;
-        CodeMirror.isTable = false;
-        CodeMirror.isHCatHint = false;
-        CodeMirror.showHint(cm, CodeMirror.pigHint);
-      }
+      CodeMirror.showHint(cm, getLanguageHint());
     }
     codeMirror = CodeMirror(function (elt) {
       scriptEditor.parentNode.replaceChild(elt, scriptEditor);
@@ -660,7 +597,7 @@ ${ commonheader(None, "spark", user) | n,unicode }
       value: scriptEditor.value,
       readOnly: false,
       lineNumbers: true,
-      mode: "text/x-" + viewModel.currentScript().language(), // TODO update to language dynamically
+      mode: "text/x-" + viewModel.currentScript().language(),
       extraKeys: {
         "Ctrl-Space": "autocomplete",
         "Ctrl-Enter": function () {
@@ -676,16 +613,6 @@ ${ commonheader(None, "spark", user) | n,unicode }
       },
       onKeyEvent: function (e, s) {
         if (s.type == "keyup") {
-          if (s.keyCode == 190) {
-            if (codeMirror.getValue().indexOf(KLASS) > -1) {
-              var _line = codeMirror.getLine(codeMirror.getCursor().line);
-              var _partial = _line.substring(0, codeMirror.getCursor().ch);
-              var _db = _partial.substring(_partial.lastIndexOf("'") + 1);
-              if (_partial.replace(/ /g, '').toUpperCase().indexOf("LOAD") == _partial.replace(/ /g, '').lastIndexOf("'") - 4) {
-                showHiveAutocomplete(_db.substring(0, _db.length - 1));
-              }
-            }
-          }
           if (s.keyCode == 191) {
             var _line = codeMirror.getLine(codeMirror.getCursor().line);
             var _partial = _line.substring(0, codeMirror.getCursor().ch);
@@ -719,24 +646,12 @@ ${ commonheader(None, "spark", user) | n,unicode }
           CodeMirror.isPath = true;
           CodeMirror.isHCatHint = showHCatHint;
           window.setTimeout(function () {
-            CodeMirror.showHint(codeMirror, CodeMirror.pigHint);
+            CodeMirror.showHint(codeMirror,  getLanguageHint());
           }, 100);  // timeout for IE8
         }
       });
     }
 
-    hac_getTables("default", function(){}); //preload tables for the default db
-
-    function showHiveAutocomplete(databaseName) {
-      CodeMirror.isPath = false;
-      CodeMirror.isTable = true;
-      CodeMirror.isHCatHint = false;
-      hac_getTables(databaseName, function (tables) {
-        CodeMirror.catalogTables = tables;
-        CodeMirror.showHint(codeMirror, CodeMirror.pigHint);
-      });
-    }
-
     codeMirror.on("focus", function () {
       if (codeMirror.getValue() == LABELS.NEW_SCRIPT_CONTENT[viewModel.currentScript().language()]) {
         codeMirror.setValue("");

+ 6 - 0
apps/spark/static/js/spark.ko.js

@@ -106,6 +106,12 @@ var SparkScript = function (sparkScript) {
   self.name.subscribe(function (name) {
     self.updateParentModel();
   });
+
+  self.language.subscribe(function (lang) {
+    if (typeof codeMirror != "undefined"){
+      codeMirror.setOption("mode", "text/x-" + lang);
+    }
+  });
 }
 
 var Workflow = function (wf) {

+ 122 - 0
desktop/core/static/js/codemirror-clike-hint.js

@@ -0,0 +1,122 @@
+(function () {
+  function forEach(arr, f) {
+    for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);
+  }
+
+  function arrayContains(arr, item) {
+    if (!Array.prototype.indexOf) {
+      var i = arr.length;
+      while (i--) {
+        if (arr[i] === item) {
+          return true;
+        }
+      }
+      return false;
+    }
+    return arr.indexOf(item) != -1;
+  }
+
+  //Call this from outside environment to add more words to the list that might be specific to your component
+  //or taken from a current view model. They will show first in the list.
+  CodeMirror.addKeywords=function(keywords){
+    addedKeywords=keywords;
+  };
+
+  function scriptHint(editor, _keywords, getToken) {
+    // Find the token at the cursor
+    var cur = editor.getCursor(), token = getToken(editor, cur), tprop = token;
+
+    // If it's not a 'word-style' token, ignore the token.
+    if (!/^[\w$_]*$/.test(token.string)) {
+        token = tprop = {start: cur.ch, end: cur.ch, string: "", state: token.state,
+                         className: null};
+    }
+
+    if (!context) var context = [];
+    context.push(tprop);
+
+    var completionList = getCompletions(token, context, _keywords);
+
+    return {list: completionList,
+            from: CodeMirror.Pos(cur.line, token.start),
+            to: CodeMirror.Pos(cur.line, token.end)};
+  }
+
+  //Offers completion for C-sharp, C++, Java and Scala
+  function csharpHint(editor) {
+    return scriptHint(editor, getAllKeywords(csharpKeywords), function (e, cur) {return e.getTokenAt(cur);});
+    }
+  CodeMirror.csharpHint = csharpHint; // deprecated
+
+  function javaHint(editor) {
+    return scriptHint(editor, getAllKeywords(javaKeywords), function (e, cur) {return e.getTokenAt(cur);});
+    }
+  CodeMirror.javaHint = javaHint; // deprecated
+
+  function scalaHint(editor) {
+    return scriptHint(editor, getAllKeywords(scalaKeywords), function (e, cur) {return e.getTokenAt(cur);});
+    }
+  CodeMirror.scalaHint = scalaHint; // deprecated
+
+  var addedKeywords="";
+
+  //below are all the reserved words plus some of the more common method names
+  //but the list is no way pretending to be complete
+  var clikeKeywordString="abstract assert boolean break byte case catch char class const do default double else enum false "+
+  "finally for float goto if int interface long new null private protected public return short static string switch throw "+
+  "this try var void true using volatile while ";
+
+  var csharpKeywords="as await base bool checked continue decimal delegate event explicit extern finally fixed "+
+  "foreach implicit in internal is lock namespace object operator out override params readonly ref sbyte sealed sizeof stackalloc "+
+  "typeof uint ulong unchecked unsafe ushort virtual add alias ascending descending dynamic from get "+
+  "global group into join let orderby partial remove select set value var yield "+
+  "Byte Char Contains Count DateTime DateTimeOffset Decimal Double IndexOf "+
+  "LastIndexOf FirstIndexOf Format Substring Trim Length continue delete function Remove Split Replace with "+
+  "Range Guid Int16 Int32 Int64 Object SByte Single String TimeSpan UInt16 UInt32 UInt64 virtual";
+
+  var javaKeywords="concat extends final format implements import instanceof native "+
+  "package strictfp  super synchronized throws transient "+
+  "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable "+
+  "Compiler Double Exception Float Integer length Long Math Number Object Package Pair Process printl"+
+  "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String "+
+  "replace replaceAll replaceFirst substring toUpperCase toLowerCase trim"+
+  "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void";
+
+  var scalaKeywords="assume require print println printf readLine readBoolean readByte readShort " +
+  "readChar readInt readLong readFloat readDouble " +
+  "AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " +
+  "Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable " +
+  "Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " +
+  "Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " +
+  "StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector :: #:: ";
+
+  function getAllKeywords(keywordString) {
+    var newKeywords=(addedKeywords+clikeKeywordString+keywordString).split(" ");
+    return newKeywords;
+  }
+
+  function getCompletions(token, context, _keywords) {
+    var found = [], start = token.string;
+    function maybeAdd(str) {
+     //searches with all lower case
+    if (str.indexOf(start.toLowerCase()) == 0 && !arrayContains(found, str)) found.push(str);
+    //searches with first letter upper case
+    if (str.indexOf(start.charAt(0).toUpperCase() + start.slice(1)) == 0 && !arrayContains(found, str)) found.push(str);
+    }
+
+  function gatherCompletions(_obj) {
+    forEach(_keywords,maybeAdd);
+    }
+
+    if (context) {
+      var obj = context.pop(), base;
+
+      if (obj.type== "variable")
+        base = obj.string;
+      while (base != null && context.length)
+        base = base[context.pop().string];
+      if (base != null) gatherCompletions(base);
+    }
+    return found;
+  }
+})();

+ 0 - 0
desktop/core/static/js/clike.js → desktop/core/static/js/codemirror-clike.js


+ 0 - 1
desktop/core/static/js/codemirror-python-hint.js

@@ -45,7 +45,6 @@
     return scriptHint(editor, pythonKeywordsU, function (e, cur) {return e.getTokenAt(cur);});
   }
   CodeMirror.pythonHint = pythonHint; // deprecated
-  CodeMirror.registerHelper("hint", "python", pythonHint);
 
   var pythonKeywords = "and del from not while as elif global or with assert else if pass yield"
 + "break except import print class exec in raise continue finally is return def for lambda try";

+ 5 - 0
desktop/core/static/js/codemirror-show-hint.js

@@ -1,3 +1,8 @@
+CodeMirror.registerHelper = function(what, language, hinter) {
+  // avoids JS errors for the unsupported method
+  console.error("Hello Hue dev, we are currently using a version of CodeMirror 3 that does not support .registerHelper. Please use the CodeMirror.languageHint = languageHint syntax instead");
+}
+
 CodeMirror.showHint = function(cm, getHints, options) {
   if (!options) options = {};
   var startCh = cm.getCursor().ch, continued = false;