PluginProbe
Smart Grid-Layout Design for Contact Form 7 / 4.10
Smart Grid-Layout Design for Contact Form 7 v4.10
4.18.0 4.17.0 3.2.0 3.2.1 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 4.0.0 4.0.1 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.10 4.11 4.12 4.13 4.14 All 119 releases
cf7-grid-layout / assets / codemirror / addon / hint / sql-hint.js

sql-hint.js in Smart Grid-Layout Design for Contact Form 7 4.10, at assets/codemirror/addon/hint/sql-hint.js

285 lines 8.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others
2 // Distributed under an MIT license: http://codemirror.net/LICENSE
3
4 (function(mod) {
5 if (typeof exports == "object" && typeof module == "object") // CommonJS
6 mod(require("../../lib/codemirror"), require("../../mode/sql/sql"));
7 else if (typeof define == "function" && define.amd) // AMD
8 define(["../../lib/codemirror", "../../mode/sql/sql"], mod);
9 else // Plain browser env
10 mod(CodeMirror);
11 })(function(CodeMirror) {
12 "use strict";
13
14 var tables;
15 var defaultTable;
16 var keywords;
17 var identifierQuote;
18 var CONS = {
19 QUERY_DIV: ";",
20 ALIAS_KEYWORD: "AS"
21 };
22 var Pos = CodeMirror.Pos, cmpPos = CodeMirror.cmpPos;
23
24 function isArray(val) { return Object.prototype.toString.call(val) == "[object Array]" }
25
26 function getKeywords(editor) {
27 var mode = editor.doc.modeOption;
28 if (mode === "sql") mode = "text/x-sql";
29 return CodeMirror.resolveMode(mode).keywords;
30 }
31
32 function getIdentifierQuote(editor) {
33 var mode = editor.doc.modeOption;
34 if (mode === "sql") mode = "text/x-sql";
35 return CodeMirror.resolveMode(mode).identifierQuote || "`";
36 }
37
38 function getText(item) {
39 return typeof item == "string" ? item : item.text;
40 }
41
42 function wrapTable(name, value) {
43 if (isArray(value)) value = {columns: value}
44 if (!value.text) value.text = name
45 return value
46 }
47
48 function parseTables(input) {
49 var result = {}
50 if (isArray(input)) {
51 for (var i = input.length - 1; i >= 0; i--) {
52 var item = input[i]
53 result[getText(item).toUpperCase()] = wrapTable(getText(item), item)
54 }
55 } else if (input) {
56 for (var name in input)
57 result[name.toUpperCase()] = wrapTable(name, input[name])
58 }
59 return result
60 }
61
62 function getTable(name) {
63 return tables[name.toUpperCase()]
64 }
65
66 function shallowClone(object) {
67 var result = {};
68 for (var key in object) if (object.hasOwnProperty(key))
69 result[key] = object[key];
70 return result;
71 }
72
73 function match(string, word) {
74 var len = string.length;
75 var sub = getText(word).substr(0, len);
76 return string.toUpperCase() === sub.toUpperCase();
77 }
78
79 function addMatches(result, search, wordlist, formatter) {
80 if (isArray(wordlist)) {
81 for (var i = 0; i < wordlist.length; i++)
82 if (match(search, wordlist[i])) result.push(formatter(wordlist[i]))
83 } else {
84 for (var word in wordlist) if (wordlist.hasOwnProperty(word)) {
85 var val = wordlist[word]
86 if (!val || val === true)
87 val = word
88 else
89 val = val.displayText ? {text: val.text, displayText: val.displayText} : val.text
90 if (match(search, val)) result.push(formatter(val))
91 }
92 }
93 }
94
95 function cleanName(name) {
96 // Get rid name from identifierQuote and preceding dot(.)
97 if (name.charAt(0) == ".") {
98 name = name.substr(1);
99 }
100 // replace doublicated identifierQuotes with single identifierQuotes
101 // and remove single identifierQuotes
102 var nameParts = name.split(identifierQuote+identifierQuote);
103 for (var i = 0; i < nameParts.length; i++)
104 nameParts[i] = nameParts[i].replace(new RegExp(identifierQuote,"g"), "");
105 return nameParts.join(identifierQuote);
106 }
107
108 function insertIdentifierQuotes(name) {
109 var nameParts = getText(name).split(".");
110 for (var i = 0; i < nameParts.length; i++)
111 nameParts[i] = identifierQuote +
112 // doublicate identifierQuotes
113 nameParts[i].replace(new RegExp(identifierQuote,"g"), identifierQuote+identifierQuote) +
114 identifierQuote;
115 var escaped = nameParts.join(".");
116 if (typeof name == "string") return escaped;
117 name = shallowClone(name);
118 name.text = escaped;
119 return name;
120 }
121
122 function nameCompletion(cur, token, result, editor) {
123 // Try to complete table, column names and return start position of completion
124 var useIdentifierQuotes = false;
125 var nameParts = [];
126 var start = token.start;
127 var cont = true;
128 while (cont) {
129 cont = (token.string.charAt(0) == ".");
130 useIdentifierQuotes = useIdentifierQuotes || (token.string.charAt(0) == identifierQuote);
131
132 start = token.start;
133 nameParts.unshift(cleanName(token.string));
134
135 token = editor.getTokenAt(Pos(cur.line, token.start));
136 if (token.string == ".") {
137 cont = true;
138 token = editor.getTokenAt(Pos(cur.line, token.start));
139 }
140 }
141
142 // Try to complete table names
143 var string = nameParts.join(".");
144 addMatches(result, string, tables, function(w) {
145 return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;
146 });
147
148 // Try to complete columns from defaultTable
149 addMatches(result, string, defaultTable, function(w) {
150 return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;
151 });
152
153 // Try to complete columns
154 string = nameParts.pop();
155 var table = nameParts.join(".");
156
157 var alias = false;
158 var aliasTable = table;
159 // Check if table is available. If not, find table by Alias
160 if (!getTable(table)) {
161 var oldTable = table;
162 table = findTableByAlias(table, editor);
163 if (table !== oldTable) alias = true;
164 }
165
166 var columns = getTable(table);
167 if (columns && columns.columns)
168 columns = columns.columns;
169
170 if (columns) {
171 addMatches(result, string, columns, function(w) {
172 var tableInsert = table;
173 if (alias == true) tableInsert = aliasTable;
174 if (typeof w == "string") {
175 w = tableInsert + "." + w;
176 } else {
177 w = shallowClone(w);
178 w.text = tableInsert + "." + w.text;
179 }
180 return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;
181 });
182 }
183
184 return start;
185 }
186
187 function eachWord(lineText, f) {
188 var words = lineText.split(/\s+/)
189 for (var i = 0; i < words.length; i++)
190 if (words[i]) f(words[i].replace(/[,;]/g, ''))
191 }
192
193 function findTableByAlias(alias, editor) {
194 var doc = editor.doc;
195 var fullQuery = doc.getValue();
196 var aliasUpperCase = alias.toUpperCase();
197 var previousWord = "";
198 var table = "";
199 var separator = [];
200 var validRange = {
201 start: Pos(0, 0),
202 end: Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).length)
203 };
204
205 //add separator
206 var indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV);
207 while(indexOfSeparator != -1) {
208 separator.push(doc.posFromIndex(indexOfSeparator));
209 indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV, indexOfSeparator+1);
210 }
211 separator.unshift(Pos(0, 0));
212 separator.push(Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).text.length));
213
214 //find valid range
215 var prevItem = null;
216 var current = editor.getCursor()
217 for (var i = 0; i < separator.length; i++) {
218 if ((prevItem == null || cmpPos(current, prevItem) > 0) && cmpPos(current, separator[i]) <= 0) {
219 validRange = {start: prevItem, end: separator[i]};
220 break;
221 }
222 prevItem = separator[i];
223 }
224
225 var query = doc.getRange(validRange.start, validRange.end, false);
226
227 for (var i = 0; i < query.length; i++) {
228 var lineText = query[i];
229 eachWord(lineText, function(word) {
230 var wordUpperCase = word.toUpperCase();
231 if (wordUpperCase === aliasUpperCase && getTable(previousWord))
232 table = previousWord;
233 if (wordUpperCase !== CONS.ALIAS_KEYWORD)
234 previousWord = word;
235 });
236 if (table) break;
237 }
238 return table;
239 }
240
241 CodeMirror.registerHelper("hint", "sql", function(editor, options) {
242 tables = parseTables(options && options.tables)
243 var defaultTableName = options && options.defaultTable;
244 var disableKeywords = options && options.disableKeywords;
245 defaultTable = defaultTableName && getTable(defaultTableName);
246 keywords = getKeywords(editor);
247 identifierQuote = getIdentifierQuote(editor);
248
249 if (defaultTableName && !defaultTable)
250 defaultTable = findTableByAlias(defaultTableName, editor);
251
252 defaultTable = defaultTable || [];
253
254 if (defaultTable.columns)
255 defaultTable = defaultTable.columns;
256
257 var cur = editor.getCursor();
258 var result = [];
259 var token = editor.getTokenAt(cur), start, end, search;
260 if (token.end > cur.ch) {
261 token.end = cur.ch;
262 token.string = token.string.slice(0, cur.ch - token.start);
263 }
264
265 if (token.string.match(/^[.`"\w@]\w*$/)) {
266 search = token.string;
267 start = token.start;
268 end = token.end;
269 } else {
270 start = end = cur.ch;
271 search = "";
272 }
273 if (search.charAt(0) == "." || search.charAt(0) == identifierQuote) {
274 start = nameCompletion(cur, token, result, editor);
275 } else {
276 addMatches(result, search, tables, function(w) {return w;});
277 addMatches(result, search, defaultTable, function(w) {return w;});
278 if (!disableKeywords)
279 addMatches(result, search, keywords, function(w) {return w.toUpperCase();});
280 }
281
282 return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)};
283 });
284 });
285