Ejemplo n.º 1
0
    def select_project(self, on_selected, filter_project):
        '''Select a project from a generated project list. Execution flow continues into the :py:function:`on_selected`
        function with the project's name and the project's base directory. The :py:function:`filter_project` filters
        projects before they are shown (see :py:method:`get_projects`.)
        '''
        projs = [(name, info) for (name, info) in self.get_projects().items()
                 if not filter_project or filter_project(name, info)]

        def run_selected(psel):
            on_selected(psel[0], psel[1]['path'])

        if not projs:
            Common.show_status_message("No active projects found.", is_ok=False, priority=5)
        elif len(projs) == 1:
            # There's only one project, build it
            run_selected(projs[0])
        else:
            _, cabal_project_name = Common.locate_cabal_project_from_view(self.window.active_view())
            Logging.log('Current project: {0}'.format(cabal_project_name))

            # Sort by name
            projs.sort(key=lambda p: p[0])

            current_project_idx = next((i for i, p in enumerate(projs) if p[0] == cabal_project_name), -1)

            def on_done(idx):
                if idx != -1:
                    run_selected(projs[idx])

            self.window.show_quick_panel(list(map(lambda m: [m[0], m[1]['path']], projs)), on_done, 0, current_project_idx)
Ejemplo n.º 2
0
    def run(self, edit):
        selections = list(self.view.sel())

        if not self.is_infos_valid(selections):
            SublimeHaskellExpandSelectionExpression.Infos = [
                ExpandSelectionInfo(self.view, s) for s in selections
            ]

        if not self.is_infos_valid(selections):
            Common.show_status_message(
                'Unable to retrieve expand selection info', False)
            return

        selinfo = [i.expand() for i in self.Infos]
        self.view.sel().clear()
        self.view.sel().add_all([sel.region for sel in selinfo])

        Common.output_panel(
            self.view.window(),
            '\n'.join([
                UnicodeOpers.use_unicode_operators(sel.typename)
                for sel in selinfo
            ]),
            panel_name='sublime_haskell_expand_selection_expression',
            syntax='Haskell-SublimeHaskell')
Ejemplo n.º 3
0
    def show_types(self, types):
        if not types:
            Common.show_status_message("Can't infer type", False)
            return

        types = sorted(filter(
            lambda t: t.region(self.view).contains(self.view.sel()[0]), types),
                       key=lambda t: t.region(self.view).size())
        self.output_view = Common.output_panel(self.view.window(),
                                               '',
                                               panel_name=TYPES_PANEL_NAME,
                                               syntax='Haskell-SublimeHaskell',
                                               panel_display=False)

        regions = []
        for typ in types:
            Common.output_text(self.output_view,
                               '{0}\n'.format(typ.show(self.view)),
                               clear=False)
            regions.append(
                sublime.Region(
                    self.output_view.size() - 1 -
                    len(UnicodeOpers.use_unicode_operators(typ.typename)),
                    self.output_view.size() - 1))
        self.output_view.add_regions('types', regions, 'comment', '',
                                     sublime.DRAW_OUTLINED)
        Common.show_panel(self.view.window(), panel_name=TYPES_PANEL_NAME)
Ejemplo n.º 4
0
    def select_project(self, on_selected, filter_project):
        projs = [(name, info) for (name, info) in self.get_projects().items()
                 if not filter_project or filter_project(name, info)]

        def run_selected(psel):
            on_selected(psel[0], psel[1]['path'])

        if not projs:
            Common.show_status_message("No active projects found.",
                                       is_ok=False,
                                       priority=5)
        elif len(projs) == 1:
            # There's only one project, build it
            run_selected(projs[0])
        else:
            _, cabal_project_name = Common.locate_cabal_project_from_view(
                self.window.active_view())
            Logging.log('Current project: {0}'.format(cabal_project_name))

            # Sort by name
            projs.sort(key=lambda p: p[0])

            current_project_idx = next(
                (i for i, p in enumerate(projs) if p[0] == cabal_project_name),
                -1)

            def on_done(idx):
                if idx != -1:
                    run_selected(projs[idx])

            self.window.show_quick_panel(
                list(map(lambda m: [m[0], m[1]['path']], projs)), on_done, 0,
                current_project_idx)
Ejemplo n.º 5
0
    def run(self, edit, **args):
        kw_module = args.get('module')
        self.backend = BackendManager.active_backend()

        if not kw_module:
            kw_decl = args.get('decl')
            if kw_decl is None:
                qsymbol = Common.get_qualified_symbol_at_region(self.view, self.view.sel()[0])
                kw_decl = qsymbol.qualified_name()

            current_file_name = self.view.file_name()

            # Phase 1: Get the candidate import modules: the backend's query_import returns the (flag, list) tuple.
            # If successful (flag == True), then invoke add_import to add the import to the module's existing
            # modules.
            (status, self.candidates) = self.backend.query_import(kw_decl, current_file_name)
            if status:
                if len(self.candidates) == 1:
                    self.add_import(edit, self.candidates[0].module.name)
                else:
                    self.view.window().show_quick_panel([[c.module.name] for c in self.candidates], self.on_done)
            else:
                if len(self.candidates) == 1:
                    Common.show_status_message(self.candidates[0])
                else:
                    sublime.message_dialog('\n'.join(self.candidates))
        else:
            self.add_import(edit, kw_module)
Ejemplo n.º 6
0
 def run(self):
     self.view = self.window.active_view()
     if not self.view:
         Common.show_status_message("No file active", False)
     else:
         project_dir, project_name = Common.locate_cabal_project_from_view(
             self.view)
         if not project_dir:
             Common.show_status_message("Not in project", False)
         ## FIXME:
         proj_info = BackendManager.active_backend().project(project_name)
         self.project_name = project_name
         self.project_dir = project_dir
         self.names = ['lib:{0}'.format(project_name)]
         if proj_info:
             self.names.extend([
                 'exe:{0}'.format(executable['name'])
                 for executable in proj_info['description']['executables']
             ])
             self.names.extend([
                 'test:{0}'.format(test['name'])
                 for test in proj_info['description']['tests']
             ])
         if len(self.names) > 1:
             self.window.show_quick_panel(self.names, self.on_done)
         else:
             self.on_done(0)
Ejemplo n.º 7
0
def select_project(window, on_selected, filter_project=None):
    projs = [(name, info) for (name, info) in get_projects().items()
             if not filter_project or filter_project(name, info)]

    def run_selected(psel):
        on_selected(psel[0], psel[1]['path'])

    if len(projs) == 0:
        Common.show_status_message(
            "No projects found, did you add a '.cabal' file?",
            is_ok=False,
            priority=5)
        return
    if len(projs) == 1:  # There's only one project, build it
        run_selected(projs[0])
        return

    _, cabal_project_name = Common.get_cabal_project_dir_and_name_of_view(
        window.active_view())
    Logging.log('Current project: {0}'.format(cabal_project_name))

    # Sort by name
    projs.sort(key=lambda p: p[0])

    current_project_idx = next(
        (i for i, p in enumerate(projs) if p[0] == cabal_project_name), -1)

    def on_done(idx):
        if idx != -1:
            run_selected(projs[idx])

    window.show_quick_panel(list(map(lambda m: [m[0], m[1]['path']], projs)),
                            on_done, 0, current_project_idx)
Ejemplo n.º 8
0
 def on_done(self, inp):
     self.packages = hsdev.client.cabal_list(input)
     if not self.packages:
         Common.show_status_message("Package {0} not found".format(inp))
     else:
         self.window.show_quick_panel(
             [([p.name] + ([p.synopsis] if p.synopsis else []))
              for p in self.packages], self.on_select)
Ejemplo n.º 9
0
 def show_types(self, types):
     if types:
         self.types = types
         self.output_view = Common.output_panel(self.view.window(), '',
                                                panel_name=TYPES_PANEL_NAME,
                                                syntax='Haskell-SublimeHaskell')
         self.view.window().show_quick_panel([t.typename for t in self.types], self.on_done, 0, -1, self.on_changed)
     else:
         Common.show_status_message("Can't infer type", False)
Ejemplo n.º 10
0
 def on_resp(self, resp):
     self.status_msg.stop()
     self.decls.extend(resp)
     if not self.decls:
         Common.show_status_message("Search '{0}' not found".format(self.search_str))
     else:
         hayoo_results = [[decl.module.name + ': ' + decl.brief(use_unicode=False),
                           decl.defined_module().location] for decl in self.decls]
         self.window.show_quick_panel(hayoo_results, self.on_select)
Ejemplo n.º 11
0
 def on_resp(self, resp):
     self.status_msg.stop()
     self.decls = resp
     if not self.decls:
         Common.show_status_message("Hayoo '{0}': not found".format(self.search_str))
         return
     brief_decls = [[decl.module.name + ': ' + decl.brief(use_unicode=False),
                     decl.defined_module().location] for decl in self.decls]
     self.window.show_quick_panel(brief_decls, self.on_select)
Ejemplo n.º 12
0
 def on_done(self, sym):
     self.decls = BackendManager.active_backend().symbol(lookup=sym, search_type='regex')
     self.decls.sort(key=lambda d: d.module.name)
     if self.decls:
         module_decls = [['{0}: {1}'.format(decl.module.name, decl.brief(use_unicode=True)),
                          str(decl.defined_module().location)] for decl in self.decls]
         self.window.show_quick_panel(module_decls, self.on_select)
     else:
         Common.show_status_message("Nothing found for: {0}".format(sym))
Ejemplo n.º 13
0
    def on_candidate_selected(self, idx):
        if idx >= 0:
            (module_name, ident_name) = self.candidates[idx]
            info = BackendManager.active_backend().whois('{0}.{1}'.format(module_name, ident_name), self.view.file_name())

            if info:
                self.show_symbol_info(info[0])
            else:
                Common.show_status_message("Can't get info for {0}.{1}".format(module_name, ident_name), False)
Ejemplo n.º 14
0
    def run(self, _edit):
        qsymbol = Common.get_qualified_symbol_at_region(self.view, self.view.sel()[0])

        if Common.is_haskell_symbol_info(self.view):  # Go to within symbol info window
            loc = self.view.settings().get('location')
            if loc:
                self.view.window().open_file(loc, sublime.ENCODED_POSITION)
            else:
                Common.show_status_message('Source location of {0} not found'.format(qsymbol.name), False)
        else:
            backend = BackendManager.active_backend()
            whois_name = qsymbol.qualified_name()
            full_name = qsymbol.full_name()
            current_file_name = self.view.file_name()

            candidates = []
            module_candidates = []
            if not qsymbol.is_module():
                candidates = [decl for decl in backend.whois(whois_name, current_file_name) if decl.by_source()]
                if candidates:
                    if candidates[0].has_source_location():
                        self.view.window().open_file(candidates[0].get_source_location(), sublime.ENCODED_POSITION)
                    else:
                        cands = candidates[:]
                        candidates = []
                        for cand in cands:
                            for i in cand.imported:
                                candidates = [sym for sym in backend.symbol(lookup=cand.name, search_type='exact', source=True)
                                              if sym.module.name == i.module]
                                if candidates and candidates[0].has_source_location():
                                    self.view.window().open_file(candidates[0].get_source_location(), sublime.ENCODED_POSITION)
                    return
                else:
                    candidates = backend.symbol(lookup=qsymbol.name, search_type='exact', source=True)
            else:
                module_candidates = [m for m in backend.list_modules(source=True, module=full_name) if m.name == full_name]

            if not candidates and not module_candidates:
                Common.show_status_message('Declaration {0} not found'.format(qsymbol.name), False)
            else:
                candidates_len = len(candidates) if candidates is not None else 0
                module_candidates_len = len(module_candidates) if module_candidates is not None else 0

                if candidates_len + module_candidates_len == 1:
                    if candidates_len == 1:
                        self.view.window().open_file(candidates[0].get_source_location(), sublime.ENCODED_POSITION)
                    elif module_candidates_len == 1:
                        self.view.window().open_file(module_candidates[0].location.filename)
                    return
                else:
                    # many candidates
                    self.select_candidates = [([c.brief(use_unicode=False), c.get_source_location()], True) for c in candidates]
                    self.select_candidates += [([m.name, m.location.filename], False) for m in module_candidates]

                    just_names = [c[0] for c in self.select_candidates]
                    self.view.window().show_quick_panel(just_names, self.on_done, 0, 0, self.on_highlighted)
Ejemplo n.º 15
0
    def on_inspected(self, result):
        imp_module = None

        if self.view.is_dirty():
            # Use the buffer's contents
            pyresult = json.loads(result).get('result')
            if pyresult is not None:
                if Logging.is_log_level(Logging.LOG_DEBUG):
                    pprint.pprint(pyresult, width=80)
                modinfo = pyresult.get('module')
                if modinfo is not None:
                    imp_module = HsDevResultParse.parse_module(modinfo)
        else:
            # Otherwise, use the actual file
            imp_module = Utils.head_of(
                hsdev.client.module(file=self.current_file_name))

        if imp_module is not None:
            imports = sorted(imp_module.imports, key=lambda i: i.position.line)
            after = [i for i in imports if i.module > self.module_name]

            insert_line = 0
            insert_gap = False

            if len(after) > 0:
                # Insert before after[0]
                insert_line = after[0].position.line - 1
            elif len(imports) > 0:
                # Insert after all imports
                insert_line = imports[-1].position.line
            elif len(imp_module.declarations) > 0:
                # Insert before first declaration
                insert_line = min([
                    d.position.line for d in imp_module.declarations.values()
                ]) - 1
                insert_gap = True
            else:
                # Try to add the import just after the "where" of the module declaration
                contents = self.view.substr(sublime.Region(
                    0, self.view.size()))
                mod_decl = re.search('module.*where', contents, re.MULTILINE)
                if mod_decl is not None:
                    insert_line = mod_decl.end()
                    insert_gap = True
                else:
                    # Punt! Insert at the end of the file
                    insert_line = self.view.rowcol(self.view.size())[0]

            insert_text = 'import {0}\n'.format(
                self.module_name) + ('\n' if insert_gap else '')

            point = self.view.text_point(insert_line, 0)
            self.view.insert(self.edit, point, insert_text)

            Common.show_status_message(
                'Import {0} added'.format(self.module_name), True)
Ejemplo n.º 16
0
def run_build(view, project_name, project_dir, config):
    # Don't build if a build is already running for this project
    # We compare the project_name for simplicity (projects with same
    # names are of course possible, but unlikely, so we let them wait)
    if project_name in PROJECTS_BEING_BUILT:
        Logging.log(
            "Waiting for build action on '%s' to complete." % project_name,
            Logging.LOG_WARNING)
        Common.show_status_message('Already building %s' % project_name,
                                   is_ok=False,
                                   priority=5)
        return

    # Set project as building
    PROJECTS_BEING_BUILT.add(project_name)

    build_tool_name = Settings.PLUGIN.haskell_build_tool
    if build_tool_name == 'stack' and not is_stack_project(
            project_dir):  # rollback to cabal
        build_tool_name = 'cabal'

    tool = BUILD_TOOL[build_tool_name]

    # Title of tool: Cabal, Stack
    tool_title = tool['name']
    # Title of action: Cleaning, Building, etc.
    action_title = config['message']
    # Tool name: cabal
    tool_name = tool['command']
    # Tool arguments (commands): build, clean, etc.
    tool_steps = config['steps'][build_tool_name]

    # Config override
    override_config = Settings.get_project_setting(view, 'stack_config_file')

    override_args = []
    if override_config:
        override_args = ['--stack-yaml', override_config]
    # Assemble command lines to run (possibly multiple steps)
    commands = [[tool_name] + step + override_args for step in tool_steps]

    Logging.log('running build commands: {0}'.format(commands),
                Logging.LOG_TRACE)

    def done_callback():
        # Set project as done being built so that it can be built again
        PROJECTS_BEING_BUILT.remove(project_name)

    # Run them
    ParseOutput.run_chain_build_thread(view,
                                       project_dir,
                                       '{0} {1} with {2}'.format(
                                           action_title, project_name,
                                           tool_title),
                                       commands,
                                       on_done=done_callback)
Ejemplo n.º 17
0
 def run(self):
     view = self.window.active_view()
     if not view:
         Common.show_status_message("No file active", False)
     else:
         project_dir = Common.locate_cabal_project_from_view(view)[0]
         if not project_dir:
             self.window.run_command(
                 "sublime_haskell_repl_ghci_current_file", {})
         else:
             self.window.run_command("sublime_haskell_repl_cabal", {})
Ejemplo n.º 18
0
    def run_build(self, view, project_name, project_dir, config):
        # Don't build if a build is already running for this project
        # We compare the project_name for simplicity (projects with same
        # names are of course possible, but unlikely, so we let them wait)
        if project_name in self.PROJECTS_BEING_BUILT:
            Logging.log("Waiting for build action on '%s' to complete." % project_name, Logging.LOG_WARNING)
            Common.show_status_message('Already building %s' % project_name, is_ok=False, priority=5)
            return

        # Set project as building
        self.PROJECTS_BEING_BUILT.add(project_name)

        Logging.log('project build tool: {0}'.format(Settings.get_project_setting(view, 'haskell_build_tool')),
                    Logging.LOG_DEBUG)
        Logging.log('settings build tool: {0}'.format(Settings.PLUGIN.haskell_build_tool), Logging.LOG_DEBUG)

        build_tool_name = Settings.get_project_setting(view, 'haskell_build_tool', Settings.PLUGIN.haskell_build_tool)
        if build_tool_name == 'stack' and not self.is_stack_project(project_dir):  # rollback to cabal
            build_tool_name = 'cabal'

        tool = self.BUILD_TOOL[build_tool_name]

        # Title of tool: Cabal, Stack
        tool_title = tool['name']
        # Title of action: Cleaning, Building, etc.
        action_title = config['message']
        # Tool name: cabal
        tool_name = tool['command']
        # Tool arguments (commands): build, clean, etc.
        tool_steps = config['steps'][build_tool_name]

        # Config override
        override_config = Settings.get_project_setting(view, 'active_stack_config')

        override_args = []
        if override_config:
            override_args = ['--stack-yaml', override_config]
        # Assemble command lines to run (possibly multiple steps)
        commands = [[tool_name] + override_args + step if isinstance(step, list) else step for step in tool_steps]

        Logging.log('running build commands: {0}'.format(commands), Logging.LOG_TRACE)

        def done_callback():
            # Set project as done being built so that it can be built again
            self.PROJECTS_BEING_BUILT.remove(project_name)

        # Run them
        msg = '{0} {1} with {2}\ncommands:\n{3}'.format(action_title, project_name, tool_title, commands)
        Logging.log(msg, Logging.LOG_DEBUG)
        Common.show_status_message_process(msg, priority=3)
        Utils.run_async('wait_for_chain_to_complete', self.wait_for_chain_to_complete, view, project_dir, msg, commands,
                        on_done=done_callback)
Ejemplo n.º 19
0
 def run(self, _edit):
     errs = errors_for_view(self.view)
     if not errs:
         Common.show_status_message("No errors or warnings!", priority=5)
     else:
         cur_point = symbols.Region.from_region(self.view, self.view.sel()[0])
         prev_err = next(filter(lambda e: e.region < cur_point, reversed(errs)), None)
         # Cycle around to the last error if we run off the first
         if prev_err is None:
             prev_err = errs[-1]
         self.view.sel().clear()
         self.view.sel().add(prev_err.region.to_region(self.view))
         goto_error(self.view, prev_err)
Ejemplo n.º 20
0
    def run(self, _edit, **kwargs):
        filename = kwargs.get('filename')
        module_name = kwargs.get('module_name')
        package_name = kwargs.get('package_name')
        symdb = kwargs.get('db')
        name = kwargs.get('name')
        qname = kwargs.get('qname')
        no_browse = kwargs.get('no_browse') or False

        if qname:
            self.full_name = qname
            self.current_file_name = self.view.file_name()
            # Try whois it, followed by file symbol and wider module searches
            self.candidates = self.collect_candidates(qname, name, filename, module_name, package_name, symdb)
        else:
            self.current_file_name = self.view.file_name()

            qsymbol = Common.get_qualified_symbol(qname) \
                      if qname \
                      else Common.get_qualified_symbol_at_region(self.view, self.view.sel()[0])
            module_word = qsymbol.module
            ident = qsymbol.name

            if ident is None:  # module
                if not no_browse:
                    self.view.window().run_command('sublime_haskell_browse_module', {'module_name': module_word,
                                                                                     'scope': self.current_file_name})
                return

            if not module_word and not ident:
                Common.show_status_message('No symbol selected', False)
                return

            self.whois_name = qsymbol.qualified_name()
            self.full_name = qsymbol.full_name()

            self.candidates = (BackendManager.active_backend().whois(self.whois_name, self.current_file_name) or [])[:1]

            if not self.candidates:
                self.candidates = BackendManager.active_backend().lookup(self.full_name, self.current_file_name)

            if not self.candidates:
                self.candidates = BackendManager.active_backend().symbol(lookup=self.full_name, search_type='exact')

        if not self.candidates:
            Common.show_status_message('Symbol {0} not found'.format(self.full_name))
        elif len(self.candidates) == 1:
            self.show_symbol_info(self.candidates[0])
        elif not no_browse:
            results = [[c.qualified_name(), c.defined_module().location.to_string()] for c in self.candidates]
            self.view.window().show_quick_panel(results, self.on_done)
Ejemplo n.º 21
0
 def run(self):
     view = self.window.active_view()
     if not view:
         Common.show_status_message("No file active", False)
     else:
         opts = Settings.PLUGIN.ghci_opts or []
         self.window.run_command(
             "repl_open",
             repl_args(cmd=["ghci", "$file"] + opts,
                       loaded=view.file_name(),
                       caption="ghci: {0}".format(
                           os.path.basename(view.file_name()))))
         KNOWN_REPLS.set_repl_view(
             sublimerepl.repl_external_id(view.file_name()), view)
Ejemplo n.º 22
0
 def wrapper(self, *args, **kwargs):
     if Settings.PLUGIN.enable_hsdev:
         Logging.log("Invoking '{0}' command via hsdev".format(cmdname),
                     Logging.LOG_TRACE)
         return outer_fn(self, *args, **kwargs)
     elif Settings.PLUGIN.enable_ghc_mod:
         Logging.log(
             "Invoking '{0}' command via ghc-mod".format(cmdname),
             Logging.LOG_TRACE)
         self.view.window().run_command(
             'sublime_haskell_ghc_mod_{0}'.format(cmdname))
     else:
         Common.show_status_message(
             'Check/Lint: both hsdev and ghc-mod are disabled', False)
Ejemplo n.º 23
0
    def add_import(self, edit, module_name):
        contents = self.view.substr(sublime.Region(0, self.view.size()))

        # Truncate contents to the module declaration and the imports list, if present.
        imports_list = list(re.finditer('^import.*$', contents, re.MULTILINE))
        if len(imports_list) > 0:
            contents = contents[0:imports_list[-1].end()]

        # Phase 2: Ask the backend to turn the contents into a list of Module objects:
        imp_module = self.backend.contents_to_module(contents)
        if imp_module is not None:
            imports = sorted(imp_module.imports, key=lambda i: i.position.line)
            after = [imp for imp in imports if imp.module > module_name]

            insert_line = 0
            insert_gap = False

            if len(after) > 0:
                # Insert before after[0]
                insert_line = after[0].position.line - 1
            elif len(imports) > 0:
                # Insert after all imports
                insert_line = imports[-1].position.line
            elif len(imp_module.declarations) > 0:
                # Insert before first declaration
                insert_line = min([
                    d.position.line for d in imp_module.declarations.values()
                ]) - 1
                insert_gap = True
            else:
                # Try to add the import just after the "where" of the module declaration
                contents = self.view.substr(sublime.Region(
                    0, self.view.size()))
                mod_decl = re.search('module.*where', contents, re.MULTILINE)
                if mod_decl is not None:
                    insert_line = mod_decl.end()
                    insert_gap = True
                else:
                    # Punt! Insert at the end of the file
                    insert_line = self.view.rowcol(self.view.size())[0]

            insert_text = 'import {0}\n'.format(module_name) + (
                '\n' if insert_gap else '')

            point = self.view.text_point(insert_line, 0)
            self.view.insert(edit, point, insert_text)

            Common.show_status_message('Import {0} added'.format(module_name),
                                       True)
Ejemplo n.º 24
0
    def run(self, _edit, **kwargs):
        module_name = kwargs.get('module_name')
        filename = kwargs.get('filename')
        symdb = kwargs.get('db')
        scope = kwargs.get('scope')

        self.candidates = []
        self.current_file_name = self.view.window().active_view().file_name()

        the_module = None
        project_name = Common.locate_cabal_project_from_view(self.view.window().active_view())[1]

        if filename:
            the_module = Utils.head_of(BackendManager.active_backend().module(project_name, file=filename))
            if not the_module:
                Common.show_status_message('Module {0} not found'.format(filename))
                return
        elif module_name:
            cand_mods = self.candidate_modules(project_name, module_name, scope, symdb)
            if len(cand_mods) == 0:
                Common.show_status_message('Module {0} not found'.format(module_name))
                return
            elif len(cand_mods) == 1:
                the_module = self.get_module_info(project_name, cand_mods[0], module_name)
                if the_module:
                    the_module = Utils.head_of(the_module)
            else:
                self.candidates.extend([(m, [m.name, m.location.to_string()]) for m in cand_mods])
        else:
            if self.current_file_name:
                cand_mods = BackendManager.active_backend().scope_modules(project_name, self.current_file_name)
            else:
                symbol_db = symbols.PackageDb.from_string(symdb) if symdb else None
                cand_mods = BackendManager.active_backend().list_modules(symdb=symbol_db)
            self.candidates.extend([(m, [m.name, m.location.to_string()]) for m in cand_mods])

        if the_module:
            self.candidates = sorted(list(the_module.declarations.values()), key=lambda d: d.brief())
            results = [[decl.brief(use_unicode=False),
                        decl.docs.splitlines()[0] if decl.docs else ''] for decl in self.candidates]
            self.view.window().show_quick_panel(results, self.on_symbol_selected)
        else:
            self.candidates.sort(key=lambda c: c[1][0])
            self.view.window().show_quick_panel([c[1] for c in self.candidates], self.on_done)
Ejemplo n.º 25
0
    def run(self, _edit):
        if Common.is_haskell_symbol_info(self.view):
            pack = self.view.settings().get('package')
            mod = self.view.settings().get('module')
            if pack and mod:
                webbrowser.open('http://hackage.haskell.org/package/{0}/docs/{1}.html'.format(pack, mod.replace('.', '-')))
        else:
            project_name = Common.locate_cabal_project_from_view(self.view)[1]
            qsymbol = Common.get_qualified_symbol_at_region(self.view, self.view.sel()[0])

            modules = []
            if qsymbol.is_module():  # module
                scope = self.view.file_name()
                if scope:
                    modules = [m for m in BackendManager.active_backend().scope_modules(project_name,
                                                                                        scope,
                                                                                        lookup=qsymbol.module,
                                                                                        search_type='exact')
                               if m.by_cabal()]
                else:
                    modules = [m for m in BackendManager.active_backend().list_modules(symdb=m.location.db)
                               if m.name == qsymbol.module and m.by_cabal()]
            else:  # symbol
                scope = self.view.file_name()
                if scope:
                    decls = BackendManager.active_backend().whois(qsymbol.qualified_name(), file=scope) or \
                            BackendManager.active_backend().lookup(qsymbol.full_name(), file=scope) or \
                            BackendManager.active_backend().symbol(lookup=qsymbol.full_name(), search_type='exact')
                    if not decls:
                        Common.show_status_message('Module for symbol {0} not found'.format(qsymbol.full_name()))
                        return
                    modules = [decl.defined_module() for decl in decls]

            if len(modules) == 0:
                Common.show_status_message('Module {0} not found'.format(qsymbol.module))
            elif len(modules) == 1:
                pkg_id = modules[0].location.package.package_id()
                pkg_name = modules[0].name.replace('.', '-')
                webbrowser.open('http://hackage.haskell.org/package/{0}/docs/{1}.html'.format(pkg_id, pkg_name))
            else:
                self.candidates = modules[:]
                mod_strings = [[m.name, m.location.package.package_id()] for m in self.candidates]
                self.view.window().show_quick_panel(mod_strings, self.on_done)
Ejemplo n.º 26
0
 def run(self, _edit):
     errs = errors_for_view(self.view)
     if not errs:
         Common.show_status_message('No errors or warnings!', priority=5)
     else:
         view_pt = self.view.sel()[0]
         # Bump just past the view's point, just in case we're sitting on top of the current
         cur_point = symbols.Region.from_region(self.view, view_pt)
         err_iter = filter(lambda e: e.region > cur_point, errs)
         next_err = next(err_iter, None)
         # If the view's point is really on top of the start of an error, move to the next, otherwise,
         # we'll just keep sitting on top of the current error and never move.
         if next_err is not None and next_err.region.start == cur_point.start:
             next_err = next(err_iter, None)
         # Cycle around to the first error if we run off the end of the list.
         if next_err is None:
             next_err = errs[0]
         self.view.sel().clear()
         self.view.sel().add(next_err.region.to_region(self.view))
         goto_error(self.view, next_err)
Ejemplo n.º 27
0
    def run(self, edit, **kwargs):
        current_file_name = kwargs.get('filename', self.view.file_name())
        project_name = Common.locate_cabal_project_from_view(self.view)[1]
        backend = BackendManager.active_backend()

        imp_module = Utils.head_of(backend.module(project_name, file=current_file_name))
        if imp_module:
            imports = sorted(imp_module.imports, key=lambda i: i.position.line)

            supported, result = backend.clean_imports(current_file_name)
            print(result)
            if supported:
                if len(imports) == len(result):
                    Logging.log('replacing imports for {0}'.format(current_file_name), Logging.LOG_TRACE)
                    erased = 0
                    for imp, new_imp in zip(imports, result):
                        point = self.view.text_point(imp.position.line - 1 - erased, 0)
                        if new_imp.endswith('()'):
                            self.view.erase(edit, self.view.full_line(point))
                            erased = erased + 1
                        else:
                            self.view.replace(edit, self.view.line(point), new_imp)
                else:
                    Common.show_status_message('different number of imports: {0} and {1}'.format(len(imports), len(result)))
            else:
                if len(result) == 1:
                    Common.show_status_message(result[0])
                else:
                    sublime.message_dialog('\n'.join(result))
        else:
            Common.show_status_message('Clean Imports failed: module not scanned')
Ejemplo n.º 28
0
    def run(self, edit, **kwargs):
        filename = kwargs.get('filename')
        decl = kwargs.get('decl')
        module_name = kwargs.get('module_name')

        self.full_name = decl
        self.current_file_name = filename
        self.edit = edit

        if module_name is not None:
            self.add_import(module_name)
            return

        if not self.current_file_name:
            self.current_file_name = self.view.file_name()

        if not self.full_name:
            qsymbol = Common.get_qualified_symbol_at_region(
                self.view,
                self.view.sel()[0])
            self.full_name = qsymbol.qualified_name()

        if hsdev.client.whois(self.full_name, self.current_file_name):
            Common.show_status_message('Symbol {0} already in scope'.format(
                self.full_name))
        else:
            self.candidates = hsdev.client.lookup(self.full_name,
                                                  self.current_file_name)

            if not self.candidates:
                Common.show_status_message('Symbol {0} not found'.format(
                    self.full_name))
            elif len(self.candidates) == 1:
                self.add_import(self.candidates[0].module.name)
            else:
                self.view.window().show_quick_panel([[c.module.name]
                                                     for c in self.candidates],
                                                    self.on_done)
Ejemplo n.º 29
0
    def run(self, **kwargs):
        project = kwargs.get('project') or False
        decls = []

        if project:
            project_name = Common.locate_cabal_project_from_view(self.view)[1]
            modules = BackendManager.active_backend().module(project_name, file=self.current_filename)
            current_project = Utils.head_of(modules).location.project
            if not current_project:
                Common.show_status_message('File {0} is not in project'.format(self.current_filename), False)
                return

            decls = self.sorted_decls_name(BackendManager.active_backend().symbol(project=current_project))
            self.declarations = [[decl.brief(True, use_unicode=False), decl.module.name] for decl in decls]
        else:
            decls = self.sorted_decls_pos(BackendManager.active_backend().symbol(file=self.current_filename, local_names=True))
            self.declarations = [[(decl.position.column * ' ') + decl.brief(True, use_unicode=False)] for decl in decls]
        self.decls = decls[:]

        if decls:
            self.window.show_quick_panel(self.declarations,
                                         self.on_done, 0,
                                         self.closest_idx(decls),
                                         self.on_highlighted if not project else None)
Ejemplo n.º 30
0
 def on_err(self, err, _details):
     Common.show_status_message('Browse declarations: {0}'.format(err))