Home Download Buy Blog Forum Support

A few questions on a completions plugin

A few questions on a completions plugin

Postby gatapia on Tue Apr 03, 2012 12:49 am

Hi All,

FIrstly, this is my first play around the plugin system so I'm very new to this so please excuse any unintended stupid questions. Now, I'm trying to write a plugin to enhance the JavaScript auto completion functionality. But I was wondering a few things which I'm having trouble finding info about:
* Is it possible for my plugin to get access to the Snippets/Buffer Contents generated completions, i.e. Can I just return completions from my on_query_completions function and ensure that will be the only list of completions displayed?
* For testing purposes I have hard coded some completions, this works in some cases however, sometimes even though I return this list the status bar still says: 'No available completions', why are my completions being ignored?
* How can I set a scope for my plugin? Even though I'm being performance concious I'd rather not even be notified of say python auto completions when I only care about JS
* How can I force my plugin to also get called when in comments (support auto-complete for comments). Currently my on_query_completions is not fired when CTRL+ENTER in comments.
* Finally does sublime keep a cached files map (CTRL + P is so fast that I assume it does). Is this available to the plugin ecosystem?

Thanks all
gatapia
 
Posts: 5
Joined: Sun Apr 01, 2012 4:55 am

Re: A few questions on a completions plugin

Postby agibsonsw on Tue Apr 03, 2012 10:30 am

Here is an extract from my 'on_query_completions'. It's for Python, but you can gain a few hints from it.

match_selector allows you to target/scope the completions behaviour. Remove '-comments' if you wish;
'prefix' allows you to check what they've typed as the trigger, and 'locations' gains you access to preceding text;
extract_completions enables reading of the default completions list;
INHIBIT_WORD_COMPLETIONS and INHIBIT_EXPLICIT_COMPLETIONS enables you to prevent the default completions from appearing.

Code: Select all
import sublime, sublime_plugin

py_funcs = [
   ("__import__()\t__import__ fn",
      "__import__(${1:name}${2:[, globals, locals, fromlist, level]})$0"),
   ("abs()\tabs fn", "abs(${1:number})$0"),
   ("all()\tall fn", "all(${1:iterable})$0"),
   ("any()\tany fn", "any(${1:iterable})$0"),
   ("bin()\tbin fn", "bin(${1:integer})$0"),
   ("bool()\tbool fn", "bool(${1:[value]})$0"),
   ("super()\tsuper fn", "super(${1:type}${2:[, object/type]})$0"),
   ("tuple()\ttuple fn/ctor", "tuple(${1:[iterable]})$0"),
   ("type()\ttype fn", "type(${1:object})$0"),
   ("type()\ttype ctor", "type(${1:name}, ${2:bases}, ${3:dict})$0"),
   ("unichr()\tunichr fn", "unichr(${1:[integer]})$0"),
   ("unicode()\tunicode fn", "unicode(${1:[object, ]}${2:encoding}${3:[, errors]})$0"),
   ("vars()\tvars fn", "vars(${1:[object]})$0"),
   ("xrange()\txrange fn", "xrange(${1:[start, ]}${2:stop}${3:[, step]})$0"),
   ("zip()\tzip fn", "zip(${1:iterable})$0")
]

py_members = [             # methods and attributes
   ("add()\tset", "add(${1:elem})$0"),
   ("append()\tMutable", "append(${1:x})$0"),
   ("split()\tstring", "split(${1:[sep]}${2:[, maxsplit]})$0"),
   ("splitlines()\tstring", "splitlines(${1:[keepends]})$0"),
   ("writelines()\tfile", "writelines(${1:sequence})$0"),
   ("zfill()\tstring", "zfill(${1:width})$0")
]

subl_methods = [
   ("active_group()\tST Window", "active_group()$0"),
   ("active_view()\tST Window", "active_view()$0"),
   ("active_view_in_group()\tST Window", "active_view_in_group(${1:group})$0"),
   ("active_window()\tsublime", "active_window()$0"),
   ("add()\tST RegionSet", "add(${1:region})$0"),
   ("add_all()\tST RegionSet", "add_all(${1:region_set})$0"),
   ("add_on_change()\tST Settings", "add_on_change(${1:key}, ${2:on_change})$0"),
   ("window()\tST View", "window()$0"),
   ("windows()\tsublime", "windows()$0"),
   ("word()\tST View", "word(${1:region/pt})$0")
]

sublime_methods_all = list(py_members)
sublime_methods_all.extend(subl_methods)

class PythonCompletions(sublime_plugin.EventListener):
   def on_query_completions(self, view, prefix, locations):
      global py_funcs, py_members, subl_methods, subl_methods_all
      if not view.match_selector(locations[0], 'source.python -string -comment -constant'):
         return []
      completions = []
      pt = locations[0] - len(prefix) - 1
      ch = view.substr(sublime.Region(pt, pt + 1))    # the character before the trigger
      is_dot = (ch == '.')
      if is_dot: completions = py_members
      if not is_dot: completions = py_funcs
      if view.find("(?:from|import)\s+sublime", 0) is not None and is_dot:
         completions = sublime_methods_all      # include Python methods/attributes
      compl_default = [view.extract_completions(prefix)]
      compl_default = [(item + "\tDefault", item) for sublist in compl_default
         for item in sublist if len(item) > 3]       # flatten
      compl_default = list(set(compl_default))      # make unique
      compl_full = list(completions)
      compl_full.extend(compl_default)
      compl_full.sort()
      return (compl_full, sublime.INHIBIT_WORD_COMPLETIONS |
         sublime.INHIBIT_EXPLICIT_COMPLETIONS)

I've attached my JS completions file as well, as it may save you some typing ;). Mine exhibit specific behaviour. For example, it prepends 'window' or 'document' for some members.
Attachments
AndyJS.zip
JavaScript compl
(10.06 KiB) Downloaded 119 times
"I'm here to save your life. But if I'm going to do that, I'll need total uninanonynymity." Me Myself & Irene.
agibsonsw
 
Posts: 901
Joined: Fri Jan 27, 2012 9:11 pm

Re: A few questions on a completions plugin

Postby agibsonsw on Tue Apr 03, 2012 10:44 am

My JS completions list includes CSS properties, listed at the bottom. They are preceded by an underscore but you could find/replace the underscores.
"I'm here to save your life. But if I'm going to do that, I'll need total uninanonynymity." Me Myself & Irene.
agibsonsw
 
Posts: 901
Joined: Fri Jan 27, 2012 9:11 pm

Re: A few questions on a completions plugin

Postby agibsonsw on Tue Apr 03, 2012 12:06 pm

* For testing purposes I have hard coded some completions, this works in some cases however, sometimes even though I return this list the status bar still says: 'No available completions', why are my completions being ignored?
* How can I force my plugin to also get called when in comments (support auto-complete for comments). Currently my on_query_completions is not fired when CTRL+ENTER in comments.
* Finally does sublime keep a cached files map (CTRL + P is so fast that I assume it does). Is this available to the plugin ecosystem?


1. Do you get an error message in the console (Ctrl-')? Perhaps you can post your (zipped) completions - there may be a syntax error. Is the file named '.sublime-completions'?
2. As mentioned, you could remove '-comments' - this is also mentioned in the default settings. [Personally, I'd rather live without this - it's too intrusive :( ].
3. Do you want access to all the files in your project, or just open files? What is your aim?
"I'm here to save your life. But if I'm going to do that, I'll need total uninanonynymity." Me Myself & Irene.
agibsonsw
 
Posts: 901
Joined: Fri Jan 27, 2012 9:11 pm

Re: A few questions on a completions plugin

Postby gatapia on Tue Apr 03, 2012 10:12 pm

Thanks for the great answers agibsonsw.

1. No no error and no the file is a plugin not a sublime-completions file. I'll add to gihub soon and send link, however I don't think its my plugin as even with a super simple plugin (i.e. return [('testing',)]) this still happens in certain cases. For instance in the method:
def on_query_completions(self, vi|, prefix, locations):
If I ctrl+enter here then I do not get my 'testing' completion, infact the name 'view' is automatically being inserted without showing an auto completion list.

2. Thanks
3. I'm parsing files for auto completion purposes and I figured if I can check a cache before reading them in it could save time. These files are not necessarily open files but they are in the project.
gatapia
 
Posts: 5
Joined: Sun Apr 01, 2012 4:55 am

Re: A few questions on a completions plugin

Postby agibsonsw on Tue Apr 03, 2012 10:48 pm

@gatapia

I would need to see your code, but Ctrl-Space is usually the key-sequence that produces the auto-complete list. If the code is correct then it's likely to be a scoping rule. The scope for auto-completions is in the default settings file, but can be overridden by user settings or syntax-specific settings (or by your code).

The following code indicates how you can extract completions from open tabs/files; it would need to be modified to scope JS files only. You can either use 'view.match_selector(0,'source.js')' for each view (easier!) or use the os library to read each file extension.

To extract completions from all files in the project - whether open or not - would be more of a challenge. You would probably need to open each file, then use a regex (or extract_completions) to create your list. This should probably be run (if at all ;) ) as a TextCommand, to build and store these additional completions. [There is an auto_complete list in the file '.sublime-workspace', but it's really a history of auto-complete usage and not particularly useful.]

It might be worth considering using the open/close file events. This way, you could open a file temporarily, it's completions could be extracted, and then you could close the file. But I'm guessing, as I don't know your ultimate aim :lol: .

Code: Select all
import sublime_plugin, sublime

class AutocompleteAll(sublime_plugin.EventListener):

    def on_query_completions(self, view, prefix, locations):
        window = sublime.active_window()
        # get results from each tab
        results = [v.extract_completions(prefix) for v in window.views() if v.buffer_id() != view.buffer_id()]
        results = [(item,item) for sublist in results for item in sublist] #flatten
        results = list(set(results)) # make unique
        results.sort() # sort
        return results
"I'm here to save your life. But if I'm going to do that, I'll need total uninanonynymity." Me Myself & Irene.
agibsonsw
 
Posts: 901
Joined: Fri Jan 27, 2012 9:11 pm

Re: A few questions on a completions plugin

Postby agibsonsw on Tue Apr 03, 2012 10:58 pm

Additional: If you consider using the open event to extract completions, you would need to persist (pickle!) this list and then extract it into a global variable-list. Otherwise, you would have to re-open the same file whenever you re-start ST. But I'm just thinking out loud ;)
"I'm here to save your life. But if I'm going to do that, I'll need total uninanonynymity." Me Myself & Irene.
agibsonsw
 
Posts: 901
Joined: Fri Jan 27, 2012 9:11 pm

Re: A few questions on a completions plugin

Postby gatapia on Wed Apr 04, 2012 12:09 am

'but can be overridden by user settings or syntax-specific settings':
This must be the problem, as its not my code. I'll go through all settings. I guess it could also be docblockr or codeintel doing some fancy things here also.

And yes, currently I'm just using os.path to read all files in the background and pickling to disk so this works well also.

I think most 'hurdles' are now out of my way and I just need to code this.

Your first code sample was really great and I got a lot out of it, namely the compl_default, and the sublime.INHIBIT_WORD_COMPLETIONS | sublime.INHIBIT_EXPLICIT_COMPLETIONS flags. So thanks heaps for your effort.

BTW, I'm actually working on a plugin to handle google closure (https://developers.google.com/closure/c ... r-compiler) javascript which is very descriptive about its meta data so its perfectly suited to IDE like features. Currently however I'm just toying with the idea and trying to see if its a feasible side project. If your interested at all I've got this experiment on github (https://github.com/gatapia/sublime_sett ... Command.py) (as part of my ST2 settings repo I use to share settings between computers), but again this is just a scratch pad at the moment.

Thanks heaps
gatapia
 
Posts: 5
Joined: Sun Apr 01, 2012 4:55 am

Re: A few questions on a completions plugin

Postby agibsonsw on Wed Apr 04, 2012 8:34 am

Hello @gatapia.

I've only just glanced at this Google closure thing. Being of a cynical turn-of-mind.. now Google can not only trawl our web-sites, but they can even read, and interpret, our JavaScript code :o :lol:
"I'm here to save your life. But if I'm going to do that, I'll need total uninanonynymity." Me Myself & Irene.
agibsonsw
 
Posts: 901
Joined: Fri Jan 27, 2012 9:11 pm


Return to Plugin Development

Who is online

Users browsing this forum: No registered users and 5 guests