def run(self, edit, **_kwargs): 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.sublime_status_message( 'Unable to retrieve expand selection info') 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')
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: self.unique_candidates = set(self.candidates) self.select_candidate() else: if len(self.candidates) == 1: Common.sublime_status_message(self.candidates[0]) else: sublime.message_dialog('\n'.join(self.candidates)) else: self.add_import(edit, kw_module)
def show_types(self, types): if not types: Common.sublime_status_message("Can't infer type") return view_sel = self.view.sel()[0] types = sorted(filter(lambda t: t.region(self.view).contains(view_sel), 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)
def run(self, **_args): self.executables = [] projs = [] builder = Builder(self.window.active_view()) projects = builder.get_projects() for proj, info in projects.items(): if 'description' in info: for exes in info['description']['executables']: projs.append((proj + ': ' + exes['name'], {'dir': info['path'], 'name': exes['name']})) print('SublimeHaskellRunCommand: projects {0}'.format(projects)) if not projs: Common.sublime_status_message('No project or nothing to run') elif len(projs) == 1: # One project proj_info = projs[0][1] self.exec_name = proj_info['name'] self.exec_base_dir = proj_info['dir'] self.prompt_prog_args() else: # Multiple choices _, cabal_project_name = Common.locate_cabal_project_from_view(self.window.active_view()) # Show current project first projs.sort(key=lambda s: (not s[0].startswith(cabal_project_name + ': '), s[0])) self.executables = [p[1] for p in projs] self.window.show_quick_panel([p[0] for p in projs], self.on_project_selected)
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.sublime_status_message("No active projects found.") 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.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.view.window().show_quick_panel([[m[0], m[1].get('path', '??')] for m in projs], on_done, 0, current_project_idx)
def run(self): self.executables = [] projs = [] projects = self.get_projects() for proj, info in projects.items(): if 'description' in info: for exes in info['description']['executables']: projs.append((proj + ": " + exes['name'], { 'dir': info['path'], 'dist': project_dist_path(info['path']), 'name': exes['name'] })) # Nothing to run if not projs: _, cabal_project_name = Common.locate_cabal_project_from_view( self.window.active_view()) # Show current project first projs.sort( key=lambda s: (not s[0].startswith(cabal_project_name), s[0])) self.executables = list(map(lambda m: m[1], projs)) self.window.show_quick_panel(list(map(lambda m: m[0], projs)), self.on_done) else: Common.sublime_status_message('Nothing to run')
def run(self, **_args): self.executables = [] projs = [] builder = Builder(self.window.active_view()) projects = builder.get_projects() for proj, info in projects.items(): if 'description' in info: for exes in info['description']['executables']: projs.append((proj + ': ' + exes['name'], {'dir': info['path'], 'name': exes['name']})) print('SublimeHaskellRunCommand: projects {0}'.format(projects)) if not projs: Common.sublime_status_message('No project or nothing to run') elif len(projs) == 1: # One project proj_info = projs[0][1] self.exec_name = proj_info['name'] self.exec_base_dir = proj_info['dir'] self.prompt_prog_args() else: # Multiple choices _, cabal_project_name = Common.locate_cabal_project_from_view(self.window.active_view()) # Show current project first projs.sort(key=lambda s: (not s[0].startswith(cabal_project_name + ': '), s[0])) self.executables = [p[1] for p in projs] self.window.show_quick_panel([p[0] for p in projs], self.on_project_selected)
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.sublime_status_message(self.candidates[0]) else: sublime.message_dialog('\n'.join(self.candidates)) else: self.add_import(edit, kw_module)
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.sublime_status_message("No active projects found.") 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.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.view.window().show_quick_panel([[m[0], m[1].get('path', '??')] for m in projs], on_done, 0, current_project_idx)
def on_done(self, inp): self.packages = BackendMgr.active_backend().cabal_list(input) if not self.packages: Common.sublime_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)
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.sublime_status_message("Can't infer type")
def on_resp(self, resp): self.status_msg.result_ok() self.decls = resp if not self.decls: Common.sublime_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)
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.sublime_status_message("Can't infer type")
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.sublime_status_message("Can't get info for {0}.{1}".format(module_name, ident_name),)
def on_resp(self, resp): self.status_msg.result_ok() self.decls.extend(resp) if not self.decls: Common.sublime_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)
def run(self, **_kwargs): view = self.window.active_view() if not view: Common.sublime_status_message("No file active") else: opts = Settings.PLUGIN.ghci_opts or [] self.window.run_command("repl_open", repl_args(cmd=repl_command() + ["$file"] + opts, loaded=view.file_name(), caption="ghci: {0}".format(os.path.basename(view.file_name()))))
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.sublime_status_message("Nothing found for: {0}".format(sym))
def run(self, _edit, **_kwargs): qsymbol = Common.get_qualified_symbol_at_region(self.view, self.view.sel()[0]) if Common.view_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.sublime_status_message('Source location of {0} not found'.format(qsymbol.name)) 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.sublime_status_message('Declaration {0} not found'.format(qsymbol.name)) 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)
def run(self, **_kwargs): view = self.window.active_view() if not view: Common.sublime_status_message("No file active") 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", {})
def run(self, _edit, **_kwargs): errs = MARKER_MANAGER.marks_for_view(self.view) if not errs: Common.sublime_status_message("No errors or warnings!") 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)
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.sublime_status_message('No symbol selected') 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.sublime_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)
def run(self, _edit, **_kwargs): errs = MARKER_MANAGER.marks_for_view(self.view) if not errs: Common.sublime_status_message("No errors or warnings!") 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)
def add_import(self, edit, module_name): contents = self.view.substr(sublime.Region(0, self.view.size())) # Phase 2: Ask the backend to turn the contents into a list of Module objects: imp_module = self.backend.contents_to_module(self.view.file_name(), 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 after: # Insert before after[0] insert_line = after[0].position.line - 1 elif imports: # Insert after all imports insert_line = imports[-1].position.line else: declarations = self.backend.symbol(file=self.view.file_name()) if declarations: # Insert before first declaration # HOWTO: Detect signature? insert_line = min([d.position.line for d in declarations]) - 2 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 = self.view.rowcol(mod_decl.end())[0] 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.sublime_status_message( 'Import {0} added'.format(module_name))
def run_build(self, 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.sublime_status_message('Already building {0}'.format(project_name)) return # Set project as building self.PROJECTS_BEING_BUILT.add(project_name) Logging.log('project build tool: {0}'.format(Settings.get_project_setting(self.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(self.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_args = [] override_config = Settings.get_project_setting(self.view, 'active_stack_config') if tool_name == 'stack' else '' 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) # Run them ## banner = '{0} {1} with {2}\ncommands:\n{3}'.format(action_title, project_name, tool_title, commands) banner = '{0} {1} with {2}'.format(action_title, project_name, tool_title) Logging.log(banner, Logging.LOG_DEBUG) Utils.run_async('wait_for_chain_to_complete', self.wait_for_chain_to_complete, self.view, project_name, project_dir, banner, commands)
def run_build(self, 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.sublime_status_message('Already building {0}'.format(project_name)) return # Set project as building self.PROJECTS_BEING_BUILT.add(project_name) Logging.log('project build tool: {0}'.format(Settings.get_project_setting(self.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(self.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_args = [] override_config = Settings.get_project_setting(self.view, 'active_stack_config') if tool_name == 'stack' else '' 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) # Run them ## banner = '{0} {1} with {2}\ncommands:\n{3}'.format(action_title, project_name, tool_title, commands) banner = '{0} {1} with {2}'.format(action_title, project_name, tool_title) Logging.log(banner, Logging.LOG_DEBUG) Utils.run_async('wait_for_chain_to_complete', self.wait_for_chain_to_complete, self.view, project_name, project_dir, banner, commands)
def show_types(self, types): if not types: Common.sublime_status_message("Can't infer type") return self.types = types self.output_view = Common.output_panel(self.view.window(), '', panel_name=TYPES_PANEL_NAME, syntax='Haskell-SublimeHaskell', panel_display=False) regions = [] for typ in self.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)
def run(self, edit, **_kwargs): 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.sublime_status_message('Unable to retrieve expand selection info') 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')
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 imports_list: 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 after: # Insert before after[0] insert_line = after[0].position.line - 1 elif imports: # Insert after all imports insert_line = imports[-1].position.line elif imp_module.declarations: # 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.sublime_status_message('Import {0} added'.format(module_name))
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.sublime_status_message('Module {0} not found'.format(filename)) return elif module_name: cand_mods = self.candidate_modules(project_name, module_name, scope, symdb) if not cand_mods: Common.sublime_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)
def run(self, _edit, **_kwargs): if Common.view_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.sublime_status_message('Module for symbol {0} not found'.format(qsymbol.full_name())) return modules = [decl.defined_module() for decl in decls] if not modules: Common.sublime_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)
def run(self, _edit, **_kwargs): errs = MARKER_MANAGER.marks_for_view(self.view) if not errs: Common.sublime_status_message('No errors or warnings!') 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)
def run(self, _edit, **_kwargs): errs = MARKER_MANAGER.marks_for_view(self.view) if not errs: Common.sublime_status_message('No errors or warnings!') 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)
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.sublime_status_message('different number of imports: {0} and {1}'.format(len(imports), len(result))) else: if len(result) == 1: Common.sublime_status_message(result[0]) else: sublime.message_dialog('\n'.join(result)) else: Common.sublime_status_message('Clean Imports failed: module not scanned')
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.sublime_status_message('File {0} is not in project'.format(self.current_filename)) 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)
def run(self, **_kwargs): self.view = self.window.active_view() if self.view: self.targets = [] self.args = {} project_dir, project_name = Common.locate_cabal_project_from_view( self.view) Logging.log( 'repl: project_dir {0} project_name {1}'.format( project_dir, project_name), Logging.LOG_DEBUG) if project_dir: proj_info = BackendManager.active_backend().project( project_name) self.project_name = project_name self.project_dir = project_dir if proj_info: descrip = proj_info.get('description', {}) if descrip.get('library'): target = '{0} library'.format(project_name) self.targets.append(target) self.args[target] = (project_name, 'lib', '') for exe in descrip.get('executables', []): target = '{0} ({1} executable)'.format( exe['name'], project_name) self.targets.append(target) self.args[target] = (project_name, 'exe', exe['name']) for test in descrip.get('tests', []): target = '{0} ({1} test)'.format( test['name'], project_name) self.targets.append(target) self.args[target] = (project_name, 'test', test['name']) len_targets = len(self.targets) if len_targets == 1: self.on_done(0) elif len_targets > 1: self.window.show_quick_panel(self.targets, self.on_done) else: Common.sublime_status_message('No target found for REPL.') else: Common.sublime_status_message("Not in project") else: Common.sublime_status_message("No file active")
def on_err(err, _details): self.status_msg.result_fail() Common.sublime_status_message('Check & Lint: {0}'.format(err))
def run(self, **_kwargs): global TOGGLE_SYMBOL_INFO TOGGLE_SYMBOL_INFO = not TOGGLE_SYMBOL_INFO Common.sublime_status_message('continuous symbol info: {0}'.format('on' if TOGGLE_SYMBOL_INFO else 'off'))
def on_err(self, err, _details): self.status_msg.result_fail() Common.sublime_status_message("Search '{0}': {1}".format(self.search_str, err))
def on_err(self, err, _details): Common.sublime_status_message('Browse declarations: {0}'.format(err))