示例#1
0
    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)
示例#2
0
    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
示例#3
0
    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
示例#4
0
    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
示例#6
0
    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