|
2 | 2 |
|
3 | 3 | import sys |
4 | 4 | import os |
| 5 | +import re |
5 | 6 | from functools import partial |
6 | 7 |
|
7 | 8 | import sublime |
|
13 | 14 | from .SQLToolsAPI.Storage import Storage, Settings |
14 | 15 | from .SQLToolsAPI.Connection import Connection |
15 | 16 | from .SQLToolsAPI.History import History |
| 17 | +from .SQLToolsAPI.Completion import Completion |
16 | 18 |
|
17 | 19 | SYNTAX_PLAIN_TEXT = 'Packages/Text/Plain text.tmLanguage' |
18 | 20 | SYNTAX_SQL = 'Packages/SQL/SQL.tmLanguage' |
@@ -265,56 +267,85 @@ def selectFunction(callback): |
265 | 267 |
|
266 | 268 | @staticmethod |
267 | 269 | def on_query_completions(view, prefix, locations): |
268 | | - completions = view.extract_completions(prefix) |
269 | | - |
270 | | - if prefix == "": |
271 | | - currentPoint = locations[0] |
272 | | - lineStartPoint = view.line(currentPoint).begin() |
273 | | - lineStartToLocation = sublime.Region(lineStartPoint, currentPoint) |
274 | | - try: |
275 | | - # everything after last space is a prefix |
276 | | - prefix = view.substr(lineStartToLocation).split(" ").pop() |
277 | | - except Exception: |
278 | | - pass |
| 270 | + # skip completions, if no connection |
| 271 | + if ST.conn is None: |
| 272 | + return None |
| 273 | + |
| 274 | + if not len(locations): |
| 275 | + return None |
279 | 276 |
|
280 | 277 | selectors = settings.get('selectors', []) |
281 | | - if not selectors: |
282 | | - return completions + ST.getAutoCompleteList(prefix) |
283 | | - for selector in selectors: |
284 | | - if view.match_selector(locations[0], selector): |
285 | | - return completions + ST.getAutoCompleteList(prefix) |
286 | | - return None |
| 278 | + selectorMatched = False |
| 279 | + if selectors: |
| 280 | + for selector in selectors: |
| 281 | + if view.match_selector(locations[0], selector): |
| 282 | + selectorMatched = True |
| 283 | + break |
| 284 | + |
| 285 | + if not selectorMatched: |
| 286 | + return None |
| 287 | + |
| 288 | + # completions enabled? if yes, determine which type |
| 289 | + completionType = settings.get('autocompletion', 'smart') |
| 290 | + if not completionType: |
| 291 | + return None # autocompletion disabled |
| 292 | + completionType = str(completionType).strip() |
| 293 | + if completionType not in ['basic', 'smart']: |
| 294 | + completionType = 'smart' |
| 295 | + |
| 296 | + # no completions inside strings |
| 297 | + if view.match_selector(locations[0], 'string'): |
| 298 | + return None |
| 299 | + |
| 300 | + # sublimePrefix = prefix |
| 301 | + # sublimeCompletions = view.extract_completions(sublimePrefix, locations[0]) |
| 302 | + |
| 303 | + # preferably get prefix ourselves instead of using default sublime "prefix". |
| 304 | + # Sublime will return only last portion of this preceding text. Given: |
| 305 | + # SELECT table.col| |
| 306 | + # sublime will return: "col", and we need: "table.col" |
| 307 | + # to know more precisely which completions are more appropriate |
| 308 | + |
| 309 | + # get a Region that starts at the beginning of current line |
| 310 | + # and ends at current cursor position |
| 311 | + currentPoint = locations[0] |
| 312 | + lineStartPoint = view.line(currentPoint).begin() |
| 313 | + lineStartToLocation = sublime.Region(lineStartPoint, currentPoint) |
| 314 | + try: |
| 315 | + lineStr = view.substr(lineStartToLocation) |
| 316 | + prefix = re.split('[^\w.]+', lineStr).pop() |
| 317 | + except Exception as e: |
| 318 | + Log(e) |
| 319 | + pass |
| 320 | + |
| 321 | + # determine desired keywords case from settings |
| 322 | + formatSettings = settings.get('format', {}) |
| 323 | + keywordCase = formatSettings.get('keyword_case', 'upper') |
| 324 | + uppercaseKeywords = (keywordCase.lower() == 'upper') |
| 325 | + |
| 326 | + inhibit = False |
| 327 | + completion = Completion(uppercaseKeywords, ST.tables, ST.columns, ST.functions) |
| 328 | + |
| 329 | + if completionType == 'basic': |
| 330 | + ST.autoCompleteList = completion.getBasicAutoCompleteList(prefix) |
| 331 | + else: |
| 332 | + # use current paragraph as sql text to parse |
| 333 | + sqlRegion = expand_to_paragraph(view, currentPoint) |
| 334 | + sql = view.substr(sqlRegion) |
| 335 | + sqlToCursorRegion = sublime.Region(sqlRegion.begin(), currentPoint) |
| 336 | + sqlToCursor = view.substr(sqlToCursorRegion) |
| 337 | + ST.autoCompleteList, inhibit = completion.getAutoCompleteList(prefix, sql, sqlToCursor) |
| 338 | + |
| 339 | + # safe check here, so even if we return empty completions and inhibit is true |
| 340 | + # we return empty completions to show default sublime completions |
| 341 | + if ST.autoCompleteList is None or len(ST.autoCompleteList) == 0: |
| 342 | + return None |
| 343 | + |
| 344 | + if inhibit: |
| 345 | + return (ST.autoCompleteList, sublime.INHIBIT_WORD_COMPLETIONS) |
| 346 | + |
| 347 | + return ST.autoCompleteList |
287 | 348 |
|
288 | | - @staticmethod |
289 | | - def getAutoCompleteList(word): |
290 | | - ST.autoCompleteList = [] |
291 | | - for w in ST.tables: |
292 | | - try: |
293 | | - if word.lower() in w.lower(): |
294 | | - ST.autoCompleteList.append( |
295 | | - ("{0}\t({1})".format(w, 'Table'), w)) |
296 | | - except UnicodeDecodeError: |
297 | | - continue |
298 | | - |
299 | | - for w in ST.columns: |
300 | | - try: |
301 | | - if word.lower() in w.lower(): |
302 | | - w = w.split(".") |
303 | | - ST.autoCompleteList.append(("{0}\t({1})".format( |
304 | | - w[1], w[0] + ' Col'), w[1])) |
305 | | - except Exception: |
306 | | - continue |
307 | | - |
308 | | - for w in ST.functions: |
309 | | - try: |
310 | | - if word.lower() in w.lower(): |
311 | | - ST.autoCompleteList.append( |
312 | | - ("{0}\t({1})".format(w, 'Func'), w)) |
313 | | - except Exception: |
314 | | - continue |
315 | | - |
316 | | - ST.autoCompleteList.sort() |
317 | | - return (ST.autoCompleteList) |
318 | 349 |
|
319 | 350 | # # |
320 | 351 | # # Commands |
@@ -533,6 +564,7 @@ def reload(): |
533 | 564 | import imp |
534 | 565 | imp.reload(sys.modules[__package__ + ".SQLToolsAPI"]) |
535 | 566 | imp.reload(sys.modules[__package__ + ".SQLToolsAPI.Utils"]) |
| 567 | + imp.reload(sys.modules[__package__ + ".SQLToolsAPI.Completion"]) |
536 | 568 | imp.reload(sys.modules[__package__ + ".SQLToolsAPI.Storage"]) |
537 | 569 | imp.reload(sys.modules[__package__ + ".SQLToolsAPI.History"]) |
538 | 570 | imp.reload(sys.modules[__package__ + ".SQLToolsAPI.Log"]) |
|
0 commit comments