Browse Source

HUE-1139 [pig] Autocomplete HDFS paths

The autocompletion now works with HDFS paths too after the keywords LOAD and INTO
Changed key combination to CTRL+Space like Beeswax
Enrico Berti 12 years ago
parent
commit
8dbc7baa46

+ 1 - 1
apps/beeswax/src/beeswax/templates/execute.mako

@@ -366,7 +366,7 @@ ${layout.menubar(section='query')}
 <link rel="stylesheet" href="/static/ext/css/codemirror.css">
 <link rel="stylesheet" href="/static/ext/css/codemirror.css">
 <script src="/static/js/Source/jHue/codemirror-hql.js"></script>
 <script src="/static/js/Source/jHue/codemirror-hql.js"></script>
 <script src="/static/js/Source/jHue/codemirror-hql-hint.js"></script>
 <script src="/static/js/Source/jHue/codemirror-hql-hint.js"></script>
-<script src="/static/ext/js/codemirror-show-hint.js"></script>
+<script src="/static/js/Source/jHue/codemirror-show-hint.js"></script>
 
 
 <link rel="stylesheet" href="/static/ext/css/codemirror-show-hint.css">
 <link rel="stylesheet" href="/static/ext/css/codemirror-show-hint.css">
 
 

+ 66 - 4
apps/pig/src/pig/templates/app.mako

@@ -427,7 +427,7 @@ ${ commonheader(_('Pig'), "pig", user, "100px") | n,unicode }
 <script src="/static/ext/js/codemirror-3.11.js"></script>
 <script src="/static/ext/js/codemirror-3.11.js"></script>
 <link rel="stylesheet" href="/static/ext/css/codemirror.css">
 <link rel="stylesheet" href="/static/ext/css/codemirror.css">
 <script src="/static/ext/js/codemirror-pig.js"></script>
 <script src="/static/ext/js/codemirror-pig.js"></script>
-<script src="/static/ext/js/codemirror-show-hint.js"></script>
+<script src="/static/js/Source/jHue/codemirror-show-hint.js"></script>
 <script src="/static/js/Source/jHue/codemirror-pig-hint.js"></script>
 <script src="/static/js/Source/jHue/codemirror-pig-hint.js"></script>
 <link rel="stylesheet" href="/static/ext/css/codemirror-show-hint.css">
 <link rel="stylesheet" href="/static/ext/css/codemirror-show-hint.css">
 
 
@@ -466,10 +466,31 @@ ${ commonheader(_('Pig'), "pig", user, "100px") | n,unicode }
   $(document).ready(function () {
   $(document).ready(function () {
     viewModel.updateScripts();
     viewModel.updateScripts();
 
 
+    var USER_HOME = "/user/${ user }/";
+
     var scriptEditor = $("#scriptEditor")[0];
     var scriptEditor = $("#scriptEditor")[0];
 
 
-    CodeMirror.commands.autocomplete = function(cm) {
-      CodeMirror.showHint(cm, CodeMirror.pigHint);
+    CodeMirror.commands.autocomplete = function (cm) {
+      var _line = codeMirror.getLine(codeMirror.getCursor().line);
+      var _partial = _line.substring(0, codeMirror.getCursor().ch);
+      if (_partial.indexOf("'") > -1 && _partial.indexOf("'") == _partial.lastIndexOf("'") && (_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;
+        }
+        showHdfsAutocomplete(_autocompleteUrl + "?format=json");
+      }
+      else {
+        CodeMirror.isPath = false;
+        CodeMirror.showHint(cm, CodeMirror.pigHint);
+      }
     }
     }
     var codeMirror = CodeMirror(function (elt) {
     var codeMirror = CodeMirror(function (elt) {
       scriptEditor.parentNode.replaceChild(elt, scriptEditor);
       scriptEditor.parentNode.replaceChild(elt, scriptEditor);
@@ -478,9 +499,50 @@ ${ commonheader(_('Pig'), "pig", user, "100px") | n,unicode }
       readOnly: false,
       readOnly: false,
       lineNumbers: true,
       lineNumbers: true,
       mode: "text/x-pig",
       mode: "text/x-pig",
-      extraKeys: {"Shift-Space": "autocomplete"}
+      extraKeys: {"Ctrl-Space": "autocomplete"},
+      onKeyEvent: function (e, s) {
+        if (s.type == "keyup") {
+          if (s.keyCode == 191) {
+            var _line = codeMirror.getLine(codeMirror.getCursor().line);
+            var _partial = _line.substring(0, codeMirror.getCursor().ch);
+            var _path = _partial.substring(_partial.lastIndexOf("'") + 1);
+            if (_path[0] == "/") {
+              if (_path.lastIndexOf("/") != 0) {
+                showHdfsAutocomplete("/filebrowser/view" + _partial.substring(_partial.lastIndexOf("'") + 1) + "?format=json");
+              }
+            }
+            else {
+              showHdfsAutocomplete("/filebrowser/view" + USER_HOME + _partial.substring(_partial.lastIndexOf("'") + 1) + "?format=json");
+            }
+          }
+        }
+      }
     });
     });
 
 
+    function showHdfsAutocomplete(path) {
+      $.getJSON(path, function (data) {
+        CodeMirror.currentFiles = [];
+        if (data.error != null) {
+          $.jHueNotify.error(data.error);
+        }
+        else {
+          $(data.files).each(function (cnt, item) {
+            if (item.name != ".") {
+              var _ico = "icon-file-alt";
+              if (item.type == "dir") {
+                _ico = "icon-folder-close";
+              }
+              CodeMirror.currentFiles.push('<i class="' + _ico + '"></i> ' + item.name);
+            }
+          });
+          CodeMirror.isPath = true;
+          window.setTimeout(function () {
+            CodeMirror.showHint(codeMirror, CodeMirror.pigHint);
+          }, 100);  // timeout for IE8
+        }
+      });
+    }
+
     codeMirror.on("focus", function () {
     codeMirror.on("focus", function () {
       if (codeMirror.getValue() == LABELS.NEW_SCRIPT_CONTENT) {
       if (codeMirror.getValue() == LABELS.NEW_SCRIPT_CONTENT) {
         codeMirror.setValue("");
         codeMirror.setValue("");

+ 33 - 10
desktop/core/static/js/Source/jHue/codemirror-pig-hint.js

@@ -37,6 +37,14 @@
     var cur = editor.getCursor(), token = getToken(editor, cur), tprop = token;
     var cur = editor.getCursor(), token = getToken(editor, cur), tprop = token;
     // If it's not a 'word-style' token, ignore the token.
     // If it's not a 'word-style' token, ignore the token.
 
 
+    if (token.string.indexOf("'") == 0){
+      CodeMirror.isPath = true;
+      token.string = token.string.substring(1, token.string.length);
+    }
+    if (token.string.indexOf("/") > -1){
+      token.string = token.string.substring(token.string.lastIndexOf("/") + 1);
+    }
+
     if (!/^[\w$_]*$/.test(token.string)) {
     if (!/^[\w$_]*$/.test(token.string)) {
       token = tprop = {start: cur.ch, end: cur.ch, string: "", state: token.state,
       token = tprop = {start: cur.ch, end: cur.ch, string: "", state: token.state,
         className: token.string == ":" ? "pig-type" : null};
         className: token.string == ":" ? "pig-type" : null};
@@ -57,6 +65,9 @@
       to: CodeMirror.Pos(cur.line, token.end)};
       to: CodeMirror.Pos(cur.line, token.end)};
   }
   }
 
 
+  CodeMirror.isPath = false;
+  CodeMirror.currentFiles = [];
+
   CodeMirror.pigHint = function (editor) {
   CodeMirror.pigHint = function (editor) {
     return scriptHint(editor, pigKeywordsU, function (e, cur) {
     return scriptHint(editor, pigKeywordsU, function (e, cur) {
       return e.getTokenAt(cur);
       return e.getTokenAt(cur);
@@ -99,21 +110,33 @@
     var found = [], start = token.string;
     var found = [], start = token.string;
 
 
     function maybeAdd(str) {
     function maybeAdd(str) {
-      if (str.indexOf(start) == 0 && !arrayContains(found, str)) found.push(str);
+      var stripped = strip(str).replace(/(?:(?:^|\n)\s+|\s+(?:$|\n))/g,'').replace(/\s+/g,' ');
+      if (stripped.indexOf(start) == 0 && !arrayContains(found, str)) found.push(str);
+    }
+
+    function strip(html){
+      var tmp = document.createElement("DIV");
+      tmp.innerHTML = html;
+      return tmp.textContent||tmp.innerText;
     }
     }
 
 
     function gatherCompletions(obj) {
     function gatherCompletions(obj) {
-      if (obj == ":") {
-        forEach(pigTypesL, maybeAdd);
+      if (CodeMirror.isPath || obj.indexOf("'") == 0){
+        forEach(CodeMirror.currentFiles, maybeAdd);
       }
       }
       else {
       else {
-        forEach(pigBuiltinsU, maybeAdd);
-        forEach(pigBuiltinsL, maybeAdd);
-        forEach(pigBuiltinsC, maybeAdd);
-        forEach(pigTypesU, maybeAdd);
-        forEach(pigTypesL, maybeAdd);
-        forEach(pigKeywordsU, maybeAdd);
-        forEach(pigKeywordsL, maybeAdd);
+        if (obj == ":") {
+          forEach(pigTypesL, maybeAdd);
+        }
+        else {
+          forEach(pigBuiltinsU, maybeAdd);
+          forEach(pigBuiltinsL, maybeAdd);
+          forEach(pigBuiltinsC, maybeAdd);
+          forEach(pigTypesU, maybeAdd);
+          forEach(pigTypesL, maybeAdd);
+          forEach(pigKeywordsU, maybeAdd);
+          forEach(pigKeywordsL, maybeAdd);
+        }
       }
       }
     }
     }
 
 

+ 21 - 2
desktop/core/static/ext/js/codemirror-show-hint.js → desktop/core/static/js/Source/jHue/codemirror-show-hint.js

@@ -27,7 +27,8 @@ CodeMirror.showHint = function(cm, getHints, options) {
     for (var i = 0; i < completions.length; ++i) {
     for (var i = 0; i < completions.length; ++i) {
       var elt = hints.appendChild(document.createElement("li"));
       var elt = hints.appendChild(document.createElement("li"));
       elt.className = "CodeMirror-hint" + (i ? "" : " CodeMirror-hint-active");
       elt.className = "CodeMirror-hint" + (i ? "" : " CodeMirror-hint-active");
-      elt.appendChild(document.createTextNode(completions[i]));
+      //elt.appendChild(document.createTextNode(completions[i]));
+      elt.innerHTML = completions[i];
       elt.hintId = i;
       elt.hintId = i;
     }
     }
     var pos = cm.cursorCoords(options.alignWithWord !== false ? data.from : null);
     var pos = cm.cursorCoords(options.alignWithWord !== false ? data.from : null);
@@ -134,9 +135,27 @@ CodeMirror.showHint = function(cm, getHints, options) {
       cm.off("scroll", onScroll);
       cm.off("scroll", onScroll);
     }
     }
     function pick() {
     function pick() {
-      cm.replaceRange(completions[selectedHint], data.from, data.to);
+      var _insertion = strip(completions[selectedHint]).replace(/(?:(?:^|\n)\s+|\s+(?:$|\n))/g,'').replace(/\s+/g,' ');
+      if (CodeMirror.isPath){
+        var _curRange = cm.getRange(data.from, data.to);
+        if (_curRange.indexOf("/") > -1){
+          _insertion = _curRange.substring(0, _curRange.lastIndexOf("/") + 1) + _insertion;
+        }
+        else {
+          if (_curRange != ""){
+            _insertion = "'" + _insertion;
+          }
+        }
+      }
+      cm.replaceRange(_insertion, data.from, data.to);
       close();
       close();
     }
     }
+    function strip(html){
+      var tmp = document.createElement("DIV");
+      tmp.innerHTML = html;
+      return tmp.textContent||tmp.innerText;
+    }
+
     var once, lastPos = cm.getCursor(), lastLen = cm.getLine(lastPos.line).length;
     var once, lastPos = cm.getCursor(), lastLen = cm.getLine(lastPos.line).length;
     function cursorActivity() {
     function cursorActivity() {
       clearTimeout(once);
       clearTimeout(once);