From d46fd84445330c370d61c9cf38fc5e2c90236e08 Mon Sep 17 00:00:00 2001
From: Marijn Haverbeke <marijnh@gmail.com>
Date: Thu, 14 Aug 2014 18:02:28 +0200
Subject: [PATCH] [sql-hint addon] Clean up, fix handling of whitespace

Closes #2761
---
 addon/hint/sql-hint.js | 110 ++++++++++++++++++++---------------------
 mode/sql/index.html    |  10 +++-
 2 files changed, 62 insertions(+), 58 deletions(-)

diff --git a/addon/hint/sql-hint.js b/addon/hint/sql-hint.js
index fd58b8834..cc756a248 100644
--- a/addon/hint/sql-hint.js
+++ b/addon/hint/sql-hint.js
@@ -21,7 +21,7 @@
 
   function getKeywords(editor) {
     var mode = editor.doc.modeOption;
-    if(mode === "sql") mode = "text/x-sql";
+    if (mode === "sql") mode = "text/x-sql";
     return CodeMirror.resolveMode(mode).keywords;
   }
 
@@ -32,12 +32,12 @@
   }
 
   function addMatches(result, search, wordlist, formatter) {
-    for(var word in wordlist) {
-      if(!wordlist.hasOwnProperty(word)) continue;
-      if(Array.isArray(wordlist)) {
+    for (var word in wordlist) {
+      if (!wordlist.hasOwnProperty(word)) continue;
+      if (Array.isArray(wordlist)) {
         word = wordlist[word];
       }
-      if(match(search, word)) {
+      if (match(search, word)) {
         result.push(formatter(word));
       }
     }
@@ -49,33 +49,30 @@
     var string = token.string.substr(1);
     var prevCur = Pos(cur.line, token.start);
     var table = editor.getTokenAt(prevCur).string;
-    if( !tables.hasOwnProperty( table ) ){
+    if (!tables.hasOwnProperty(table))
       table = findTableByAlias(table, editor);
-    }
     var columns = tables[table];
-    if(!columns) {
-      return;
-    }
-    addMatches(result, string, columns,
-        function(w) {return "." + w;});
+    if (!columns) return;
+
+    addMatches(result, string, columns, function(w) {return "." + w;});
   }
 
   function eachWord(lineText, f) {
-    if( !lineText ){return;}
+    if (!lineText) return;
     var excepted = /[,;]/g;
-    var words = lineText.split( " " );
-    for( var i = 0; i < words.length; i++ ){
-      f( words[i]?words[i].replace( excepted, '' ) : '' );
+    var words = lineText.split(" ");
+    for (var i = 0; i < words.length; i++) {
+      f(words[i]?words[i].replace(excepted, '') : '');
     }
   }
 
-  function convertCurToNumber( cur ){
+  function convertCurToNumber(cur) {
     // max characters of a line is 999,999.
-    return cur.line + cur.ch / Math.pow( 10, 6 );
+    return cur.line + cur.ch / Math.pow(10, 6);
   }
 
-  function convertNumberToCur( num ){
-    return Pos(Math.floor( num ), +num.toString().split( '.' ).pop());
+  function convertNumberToCur(num) {
+    return Pos(Math.floor(num), +num.toString().split('.').pop());
   }
 
   function findTableByAlias(alias, editor) {
@@ -86,26 +83,26 @@
     var table = "";
     var separator = [];
     var validRange = {
-      start: Pos( 0, 0 ),
-      end: Pos( editor.lastLine(), editor.getLineHandle( editor.lastLine() ).length )
+      start: Pos(0, 0),
+      end: Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).length)
     };
 
     //add separator
-    var indexOfSeparator = fullQuery.indexOf( CONS.QUERY_DIV );
-    while( indexOfSeparator != -1 ){
-      separator.push( doc.posFromIndex(indexOfSeparator));
-      indexOfSeparator = fullQuery.indexOf( CONS.QUERY_DIV, indexOfSeparator+1);
+    var indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV);
+    while(indexOfSeparator != -1) {
+      separator.push(doc.posFromIndex(indexOfSeparator));
+      indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV, indexOfSeparator+1);
     }
-    separator.unshift( Pos( 0, 0 ) );
-    separator.push( Pos( editor.lastLine(), editor.getLineHandle( editor.lastLine() ).text.length ) );
+    separator.unshift(Pos(0, 0));
+    separator.push(Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).text.length));
 
-    //find valieRange
+    //find valid range
     var prevItem = 0;
-    var current = convertCurToNumber( editor.getCursor() );
-    for( var i=0; i< separator.length; i++){
-      var _v = convertCurToNumber( separator[i] );
-      if( current > prevItem && current <= _v ){
-        validRange = { start: convertNumberToCur( prevItem ), end: convertNumberToCur( _v ) };
+    var current = convertCurToNumber(editor.getCursor());
+    for (var i=0; i< separator.length; i++) {
+      var _v = convertCurToNumber(separator[i]);
+      if (current > prevItem && current <= _v) {
+        validRange = { start: convertNumberToCur(prevItem), end: convertNumberToCur(_v) };
         break;
       }
       prevItem = _v;
@@ -113,52 +110,51 @@
 
     var query = doc.getRange(validRange.start, validRange.end, false);
 
-    for(var i=0; i < query.length; i++){
+    for (var i = 0; i < query.length; i++) {
       var lineText = query[i];
-      eachWord( lineText, function( word ){
+      eachWord(lineText, function(word) {
         var wordUpperCase = word.toUpperCase();
-        if( wordUpperCase === aliasUpperCase && tables.hasOwnProperty( previousWord ) ){
+        if (wordUpperCase === aliasUpperCase && tables.hasOwnProperty(previousWord)) {
             table = previousWord;
         }
-        if( wordUpperCase !== CONS.ALIAS_KEYWORD ){
+        if (wordUpperCase !== CONS.ALIAS_KEYWORD) {
           previousWord = word;
         }
       });
-      if( table ){ break; }
+      if (table) break;
     }
     return table;
   }
 
-  function sqlHint(editor, options) {
+  CodeMirror.registerHelper("hint", "sql", function(editor, options) {
     tables = (options && options.tables) || {};
     keywords = keywords || getKeywords(editor);
     var cur = editor.getCursor();
-    var token = editor.getTokenAt(cur), end = token.end;
     var result = [];
-    var search = token.string.trim();
-
+    var token = editor.getTokenAt(cur), start, end, search;
+    if (token.string.match(/^\.?[\w@]+$/)) {
+      search = token.string;
+      start = token.start;
+      end = token.end;
+    } else {
+      start = end = cur.ch;
+      search = "";
+    }
     if (search.charAt(0) == ".") {
       columnCompletion(result, editor);
       if (!result.length) {
-        while (token.start && search.charAt(0) == ".") {
+        while (start && search.charAt(0) == ".") {
           token = editor.getTokenAt(Pos(cur.line, token.start - 1));
+          start = token.start;
           search = token.string + search;
         }
-        addMatches(result, search, tables,
-                   function(w) {return w;});
+        addMatches(result, search, tables, function(w) {return w;});
       }
     } else {
-      addMatches(result, search, keywords,
-                 function(w) {return w.toUpperCase();});
-      addMatches(result, search, tables,
-                 function(w) {return w;});
+      addMatches(result, search, tables, function(w) {return w;});
+      addMatches(result, search, keywords, function(w) {return w.toUpperCase();});
     }
 
-    return {
-      list: result,
-        from: Pos(cur.line, token.start),
-        to: Pos(cur.line, end)
-    };
-  }
-  CodeMirror.registerHelper("hint", "sql", sqlHint);
+    return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)};
+  });
 });
diff --git a/mode/sql/index.html b/mode/sql/index.html
index 79a2e74e0..7dd5f3075 100644
--- a/mode/sql/index.html
+++ b/mode/sql/index.html
@@ -7,6 +7,9 @@
 <link rel="stylesheet" href="../../lib/codemirror.css" />
 <script src="../../lib/codemirror.js"></script>
 <script src="sql.js"></script>
+<link rel="stylesheet" href="../../addon/hint/show-hint.css" />
+<script src="../../addon/hint/show-hint.js"></script>
+<script src="../../addon/hint/sql-hint.js"></script>
 <style>
 .CodeMirror {
     border-top: 1px solid black;
@@ -68,7 +71,12 @@ window.onload = function() {
     smartIndent: true,
     lineNumbers: true,
     matchBrackets : true,
-    autofocus: true
+    autofocus: true,
+    extraKeys: {"Ctrl-Space": "autocomplete"},
+    hintOptions: {tables: {
+      users: {name: null, score: null, birthDate: null},
+      countries: {name: null, population: null, size: null}
+    }}
   });
 };
 </script>
-- 
GitLab