codemirror-sql-hint.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // Licensed to Cloudera, Inc. under one
  2. // or more contributor license agreements. See the NOTICE file
  3. // distributed with this work for additional information
  4. // regarding copyright ownership. Cloudera, Inc. licenses this file
  5. // to you under the Apache License, Version 2.0 (the
  6. // "License"); you may not use this file except in compliance
  7. // with the License. You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. (function () {
  17. var keywords, keywordsU, keywordsL;
  18. function getKeywords(editor) {
  19. var mode = editor.doc.modeOption;
  20. if (mode === "sql") mode = "text/x-sql";
  21. var _keywordsObj = CodeMirror.resolveMode(mode).keywords;
  22. var _keywords = "";
  23. for (var keyword in _keywordsObj) {
  24. _keywords += keyword.toUpperCase() + " ";
  25. }
  26. return _keywords;
  27. }
  28. function forEach(arr, f) {
  29. for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);
  30. }
  31. function arrayContains(arr, item) {
  32. if (!Array.prototype.indexOf) {
  33. var i = arr.length;
  34. while (i--) {
  35. if (arr[i] === item) {
  36. return true;
  37. }
  38. }
  39. return false;
  40. }
  41. return arr.indexOf(item) != -1;
  42. }
  43. function scriptHint(editor, _keywords, getToken) {
  44. // Find the token at the cursor
  45. var cur = editor.getCursor(), token = getToken(editor, cur), tprop = token;
  46. // If it's not a 'word-style' or dot token, ignore the token.
  47. if (!/^[\.\w$_]*$/.test(token.string)) {
  48. token = tprop = {start: cur.ch, end: cur.ch, string: "", state: token.state,
  49. className: token.string == "." ? "hiveql-type" : null};
  50. }
  51. if (!context) var context = [];
  52. context.push(tprop);
  53. var completionList = getCompletions(token, context);
  54. //prevent autocomplete for last word, instead show dropdown with one word
  55. if (completionList.length == 1) {
  56. completionList.push(" ");
  57. }
  58. return {list: completionList,
  59. from: CodeMirror.Pos(cur.line, token.start),
  60. to: CodeMirror.Pos(cur.line, token.end)};
  61. }
  62. CodeMirror.catalogTables = "";
  63. CodeMirror.catalogFields = "";
  64. CodeMirror.possibleTable = false;
  65. CodeMirror.possibleSoloField = false;
  66. CodeMirror.tableFieldMagic = false;
  67. CodeMirror.sqlHint = function (editor) {
  68. keywords = getKeywords(editor);
  69. keywordsU = keywords.split(" ");
  70. keywordsL = keywords.toLowerCase().split(" ");
  71. return scriptHint(editor, keywords, function (e, cur) {
  72. return e.getTokenAt(cur);
  73. });
  74. };
  75. function getCompletions(token, context) {
  76. var catalogTablesL = CodeMirror.catalogTables.toLowerCase().split(" ");
  77. var catalogFieldsL = CodeMirror.catalogFields.toLowerCase().split(" ");
  78. var found = [], start = token.string, extraFound = [];
  79. function maybeAdd(str) {
  80. if (str.indexOf(start) == 0 && !arrayContains(found, str)) found.push(str);
  81. }
  82. function maybeAddToExtra(str) {
  83. var _match = str;
  84. if (_match.indexOf("fa-magic") > -1) {
  85. _match = _match.substring(_match.indexOf("FROM ") + 5);
  86. }
  87. if (_match.indexOf(start) == 0 && !arrayContains(found, str)) extraFound.push(str);
  88. }
  89. function gatherCompletions(obj) {
  90. if (obj.indexOf(".") == 0) {
  91. forEach(catalogFieldsL, maybeAdd);
  92. }
  93. else {
  94. if (!CodeMirror.possibleTable) {
  95. if (CodeMirror.tableFieldMagic) {
  96. var _specialCatalogTablesL = CodeMirror.catalogTables.toLowerCase().split(" ");
  97. for (var i = 0; i < _specialCatalogTablesL.length; i++) {
  98. _specialCatalogTablesL[i] = "<i class='fa fa-magic'></i> FROM " + _specialCatalogTablesL[i];
  99. }
  100. forEach(_specialCatalogTablesL, maybeAddToExtra);
  101. }
  102. if (CodeMirror.possibleSoloField) {
  103. forEach(catalogFieldsL, maybeAddToExtra);
  104. }
  105. forEach(keywordsU, maybeAdd);
  106. forEach(keywordsL, maybeAdd);
  107. }
  108. else {
  109. forEach(catalogTablesL, maybeAddToExtra);
  110. forEach(keywordsU, maybeAdd);
  111. forEach(keywordsL, maybeAdd);
  112. }
  113. }
  114. }
  115. if (context) {
  116. // If this is a property, see if it belongs to some object we can
  117. // find in the current environment.
  118. var obj = context.pop(), base;
  119. base = obj.string;
  120. while (base != null && context.length)
  121. base = base[context.pop().string];
  122. if (base != null) gatherCompletions(base);
  123. }
  124. return extraFound.sort().concat(found.sort());
  125. }
  126. })();