def complete(self, sym, file, wide=False, **backend_args): completions = [] ## Have to do this the "old fashioned" way by looking at the actual file buffer, scraping for the module name, ## scraping for the imports, then collecting the names, which may or may not be visible. for view in filter(None, [w.find_open_file(file) for w in sublime.windows()]): ## Logging.log('ghc-mod complete: view = {0}'.format(view), Logging.LOG_DEBUG) _, project_name = Common.locate_cabal_project_from_view(view) backend = self.project_backends.get(project_name) ## Accumulate the source's module and imports: mod_dict = {} ## Symbols for the 'module' modname_region = view.find(self.MODNAME_RE, 0) if modname_region: modname = self.MODNAME_MATCH.search( view.substr(modname_region)).group(1) if modname: mod_dict[modname] = (False, '') for imp_region in view.find_all(r'^import\s+(qualified\s+)'): imp_text = Common.get_line_contents(view, imp_region) ##print('imp_text \'{0}\''.format(imp_text)) imp = self.IMPORT_MATCH.search(imp_text) import_name = imp.group('import') if imp and import_name and import_name not in mod_dict: mod_dict[import_name] = (imp.group('isqual') is not None, imp.group('qual')) ## Adapted from the ghc-mod ghc-comp.el source: These modules are automagically 'preloaded' along with ## any other modules imported by the primary source module. Note that if the user already imports one of ## these modules explicitly, it won't get added. for preload in [ 'Prelude', 'Control.Applicative', 'Control.Exception', 'Control.Monad', 'Data.Char', 'Data.List', 'Data.Maybe', 'System.IO' ]: if preload not in mod_dict: mod_dict[preload] = (False, None) completion_modules = [(modname, ) + mod_dict[modname] for modname in mod_dict] ## 'sum' will flatten the list-of-lists created by the comprehension... if Settings.COMPONENT_DEBUG.completions: print('completion_modules:\n{0}\nunique-ified\n{1}'.format( pprint.pformat(completion_modules), pprint.pformat(list(set(completion_modules))))) completions = sum([ self.collect_completions(backend, mod, sym.qualified_name()) for mod in list(set(completion_modules)) ], []) return self.dispatch_callbacks(filter(None, completions), None, **backend_args)
def on_query_completions(self, view, _prefix, locations): if not HAS_SUBLIME_REPL or not Common.is_haskell_repl(view): return [] repl = sublimerepl.manager.repl_view(view) line_contents = Common.get_line_contents(view, locations[0]) command = COMMAND_RE.match(line_contents) if command: return self.repl_commands_completions() imp = IMPORT_RE.match(line_contents) if imp: mod = imp.group('module') repl_id = KNOWN_REPLS.get_repl_view(repl.external_id) cwd = repl_id.path if repl_id else None return (autocomplete.AUTO_COMPLETER.get_module_completions_for( mod, current_dir=cwd), sublime.INHIBIT_WORD_COMPLETIONS | sublime.INHIBIT_EXPLICIT_COMPLETIONS) # ???? completions = [] if Settings.PLUGIN.inhibit_completions and len(completions) != 0: return (completions, sublime.INHIBIT_WORD_COMPLETIONS | sublime.INHIBIT_EXPLICIT_COMPLETIONS) return completions
def get_completions(self, view, locations): "Get all the completions related to the current file." current_file_name = view.file_name() if not current_file_name: return [] Logging.log('AutoCompleter.get_completions.', Logging.LOG_DEBUG) self.current_filename = current_file_name project_name = Common.locate_cabal_project_from_view(view)[1] line_contents = Common.get_line_contents(view, locations[0]) qsymbol = Common.get_qualified_symbol(line_contents) qualified_prefix = qsymbol.qualified_name() Logging.log('qsymbol {0}'.format(qsymbol), Logging.LOG_DEBUG) Logging.log('current_file_name {0} qualified_prefix {1}'.format(current_file_name, qualified_prefix), Logging.LOG_DEBUG) view_settings = view.settings() wide = view_settings.get('subhask_wide_completion') suggestions = [] completions = [] if qsymbol.module: if qsymbol.is_import_list: current_module = Utils.head_of(BackendManager.active_backend().module(project_name, current_file_name)) if current_module and current_module.location.project: # Search for declarations of qsymbol.module within current project q_module = Utils.head_of(BackendManager.active_backend().scope_modules(project_name, current_file_name, lookup=qsymbol.module, search_type='exact')) if q_module is not None: if q_module.by_source(): proj_module = BackendManager.active_backend().resolve(file=q_module.location.filename, exports=True) if proj_module: suggestions = proj_module.declarations.values() elif q_module.by_cabal(): cabal_module = Utils.head_of(BackendManager.active_backend().module(project_name, lookup=q_module.name, search_type='exact', package=q_module.location.package.name)) if cabal_module: suggestions = cabal_module.declarations.values() else: suggestions = BackendManager.active_backend().complete(qualified_prefix, current_file_name, wide=wide) completions = make_completions(suggestions) else: with self.cache as cache_: if wide: completions += cache_.global_completions() else: completions += cache_.files.get(current_file_name, cache_.global_completions()) completions += self.keyword_completions(qsymbol.name) sort_completions(completions) return completions
def do_query_completions(self, view, prefix, locations): # Defer starting the backend until as late as possible... if Settings.COMPONENT_DEBUG.event_viewer or Settings.COMPONENT_DEBUG.completions: print('{0} invoked (prefix: {1}).'.format(type(self).__name__ + '.on_query_completions', prefix)) completions = None with self.backend_mgr: begin_time = time.clock() # Only suggest symbols if the current file is part of a Cabal project. filename = view.file_name() line_contents = Common.get_line_contents(view, locations[0]) project_name = Common.locate_cabal_project_from_view(view)[1] completion_flags = 0 if not Settings.PLUGIN.add_word_completions: completion_flags = completion_flags | sublime.INHIBIT_WORD_COMPLETIONS if not Settings.PLUGIN.add_default_completions: completion_flags = completion_flags | sublime.INHIBIT_EXPLICIT_COMPLETIONS curselector = view.scope_name(locations[0]) if Regexs.LANGUAGE_RE.search(line_contents): completions = self.autocompleter.get_lang_completions(project_name) elif Regexs.OPTIONS_GHC_RE.search(line_contents): completions = self.autocompleter.get_flag_completions(project_name) elif 'meta.import.haskell' in curselector: # Inside an import: Complete the imported module name: completions = self.autocompleter.get_import_completions(project_name, filename, locations, line_contents) elif 'meta.declaration.exports.haskell' in curselector: # Export list export_module = Autocomplete.EXPORT_MODULE_RE.search(line_contents) if export_module: # qsymbol = Common.get_qualified_symbol_at_region(view, view.sel()[0]) # TODO: Implement pass else: # Add current file's completions: completions = self.autocompleter.get_completions(view, locations) end_time = time.clock() if Settings.COMPONENT_DEBUG.event_viewer or Settings.COMPONENT_DEBUG.completions: print('time to get completions: {0} seconds'.format(end_time - begin_time)) print('completion flag: {0}'.format(completion_flags)) # Don't put completions with special characters (?, !, ==, etc.) # into completion because that wipes all default Sublime completions: # See http://www.sublimetext.com/forum/viewtopic.php?t=8659 # TODO: work around this # comp = [c for c in completions if NO_SPECIAL_CHARS_RE.match(c[0].split('\t')[0])] # if Settings.PLUGIN.inhibit_completions and len(comp) != 0: # return (comp, sublime.INHIBIT_WORD_COMPLETIONS | sublime.INHIBIT_EXPLICIT_COMPLETIONS) # return comp return (completions, completion_flags) # if completions else None
def get_completions(self, view, locations): "Get all the completions related to the current file." current_file_name = view.file_name() if not current_file_name: return [] if Settings.COMPONENT_DEBUG.completions: print('AutoCompleter.get_completions.') self.current_filename = current_file_name _, project_name = Common.locate_cabal_project_from_view(view) line_contents = Common.get_line_contents(view, locations[0]) qsymbol = Common.get_qualified_symbol(line_contents) qualified_prefix = qsymbol.qualified_name() if Settings.COMPONENT_DEBUG.completions: print('qsymbol {0}'.format(qsymbol)) print('current_file_name {0} qualified_prefix {1}'.format(current_file_name, qualified_prefix)) view_settings = view.settings() wide = view_settings.get('subhask_wide_completion') backend = BackendManager.active_backend() suggestions = [] completions = [] if qsymbol.module: if qsymbol.is_import_list: current_module = Utils.head_of(backend.module(project_name, current_file_name)) if current_module and current_module.location.project: # Search for declarations of qsymbol.module within current project q_module = Utils.head_of(backend.scope_modules(project_name, current_file_name, lookup=qsymbol.module, search_type='exact')) if q_module is not None: if q_module.by_source(): proj_module = backend.resolve(file=q_module.location.filename, exports=True) if proj_module: suggestions = proj_module.declarations.values() elif q_module.by_cabal(): cabal_module = Utils.head_of(backend.module(project_name, lookup=q_module.name, search_type='exact', package=q_module.location.package.name)) if cabal_module: suggestions = cabal_module.declarations.values() else: if Settings.COMPONENT_DEBUG.completions: print('completions: querying module-specific completions') suggestions = backend.complete(qsymbol, current_file_name, wide=wide) completions = make_completions(suggestions) else: with self.cache as cache_: if wide: if Settings.COMPONENT_DEBUG.completions: print('completions: returning global completions') completions += cache_.global_completions() else: if Settings.COMPONENT_DEBUG.completions: print('completions: returning file-specific completions') completions += cache_.files.get(current_file_name, cache_.global_completions()) completions += self.keyword_completions(qsymbol.name) sort_completions(completions) return completions
def get_completions(self, view, locations): "Get all the completions related to the current file." current_file_name = view.file_name() if not current_file_name: return [] if Settings.COMPONENT_DEBUG.completions: print('AutoCompleter.get_completions.') self.current_filename = current_file_name _, project_name = Common.locate_cabal_project_from_view(view) line_contents = Common.get_line_contents(view, locations[0]) qsymbol = Common.get_qualified_symbol(line_contents) qualified_prefix = qsymbol.qualified_name() if Settings.COMPONENT_DEBUG.completions: print('qsymbol {0}'.format(qsymbol)) print('current_file_name {0} qualified_prefix {1}'.format( current_file_name, qualified_prefix)) view_settings = view.settings() wide = view_settings.get('subhask_wide_completion') backend = BackendManager.active_backend() suggestions = [] completions = [] if qsymbol.module: if qsymbol.is_import_list: current_module = Utils.head_of( backend.module(project_name, current_file_name)) if current_module and current_module.location.project: # Search for declarations of qsymbol.module within current project q_module = Utils.head_of( backend.scope_modules(project_name, current_file_name, lookup=qsymbol.module, search_type='exact')) if q_module is not None: if q_module.by_source(): proj_module = backend.module( None, file=q_module.location.filename) if proj_module: suggestions = proj_module.exports elif q_module.by_cabal(): cabal_module = Utils.head_of( backend.module( project_name, lookup=q_module.name, search_type='exact', package=q_module.location.package.name)) if cabal_module: suggestions = cabal_module.exports else: if Settings.COMPONENT_DEBUG.completions: print('completions: querying module-specific completions') suggestions = backend.complete(qsymbol, current_file_name, wide=wide) completions = make_completions(suggestions) else: with self.cache as cache_: if wide: if Settings.COMPONENT_DEBUG.completions: print('completions: returning global completions') completions += cache_.global_completions() else: if Settings.COMPONENT_DEBUG.completions: print( 'completions: returning file-specific completions') completions += cache_.files.get( current_file_name, cache_.global_completions()) completions += self.keyword_completions(qsymbol.name) sort_completions(completions) return completions