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')
def on_select(self, idx): if idx == -1: return package = self.packages[idx] Common.output_panel(self.window, package.detailed(), 'sublime_haskell_cabal_package')
def mark(self): (cur, corrs) = self.get_corrections() self.view.add_regions('autofix', [corr.to_region(self.view) for corr in corrs], 'warning', 'dot', sublime.DRAW_OUTLINED) rgns = [cur.to_region(self.view)] self.view.add_regions('autofix_current', rgns, 'warning', 'dot') self.view.show(sublime.Region(rgns[0].a, rgns[-1].b)) Common.output_panel(self.view.window(), 'Press {0}\n\n{1}'.format(self.keys(), self.message(cur)), 'sublime_haskell_auto_fix', syntax='HaskellAutoFix')
def wait_for_chain_to_complete(view, cabal_project_dir, msg, cmds, on_done): """Chains several commands, wait for them to complete, then parse and display the resulting errors.""" # First hide error panel to show that something is going on sublime.set_timeout(lambda: hide_output(view), 0) # run and wait commands, fail on first fail # stdout = '' collected_out = [] output_log = Common.output_panel(view.window(), '', panel_name=BUILD_LOG_PANEL_NAME, panel_display=Settings.PLUGIN.show_output_window) for cmd in cmds: Common.output_text(output_log, ' '.join(cmd) + '...\n') # Don't tie stderr to stdout, since we're interested in the error messages out = OutputCollector.OutputCollector(output_log, cmd, cwd=cabal_project_dir) exit_code, cmd_out = out.wait() collected_out.append(cmd_out) # Bail if the command failed... if exit_code != 0: break if len(collected_out) > 0: # We're going to show the errors in the output panel... Common.hide_panel(view.window(), panel_name=BUILD_LOG_PANEL_NAME) # Notify UI thread that commands are done sublime.set_timeout(on_done, 0) parse_output_messages_and_show(view, msg, cabal_project_dir, exit_code, ''.join(collected_out))
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)
def write_output(window, text, base_dir): "Write text to Sublime's output panel." output_view = Common.output_panel(window, text, panel_name=OUTPUT_PANEL_NAME, panel_display=True) output_view.settings().set("result_base_dir", base_dir)
def write_output(view, text, cabal_project_dir, panel_display=False): "Write text to Sublime's output panel." global ERROR_VIEW ERROR_VIEW = Common.output_panel(view.window(), text, panel_name=OUTPUT_PANEL_NAME, syntax='HaskellOutputPanel', panel_display=panel_display) ERROR_VIEW.settings().set("RESULT_FILE_REGEX", RESULT_FILE_REGEX) ERROR_VIEW.settings().set("result_base_dir", cabal_project_dir)
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)
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 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 report_error(view, errmsg): window = view.window() output_view = Common.output_panel(window, FILTER_OUTPUT_PANEL_NAME) output_view.run_command('sublime_haskell_output_text', { 'text': errmsg, 'clear': 'yes' }) Common.show_panel(window, FILTER_OUTPUT_PANEL_NAME) output_view.sel().clear() output_view.sel().add(sublime.Region(0, 0))
def make_message_panel(self, view, text, cabal_project_dir, panel_out): '''Create the message panel for error/warnings/hints/uncategorized errors''' self.message_panel = Common.output_panel(view.window(), text, panel_name=OUTPUT_PANEL_NAME, syntax='HaskellOutputPanel', panel_display=panel_out) self.message_panel.settings().set("result_file_regex", Regexes.RESULT_FILE_REGEX) self.message_panel.settings().set("result_base_dir", cabal_project_dir)
def __init__(self, project, project_dir, opt_args): if debug_any(): print('Starting \'ghc-mod\' for project {0}'.format(project)) self.ghcmod = None self.action_lock = None self.stderr_drain = None self.cmd = [] self.diag_prefix = 'ghc-mod: project ' + project win = sublime.active_window() msg = 'Error and diagnostic output from ' + self.diag_prefix banner = '~' * len(msg) self.output_panel = Common.output_panel( win, panel_name=self.diag_prefix, text='\n'.join([banner, msg, banner, '', ''])) panel_settings = self.output_panel.settings() panel_settings.set("auto_indent", False) panel_settings.set("smart_indent", False) # if self.exec_with is not None: # if self.exec_with == 'cabal': # cmd += ['cabal'] # elif self.exec_with == 'stack': # cmd += ['stack'] self.cmd += ['ghc-mod'] # if self.exec_with is not None: # cmd += ['--'] self.cmd += [ '-b', '\\n', '--line-prefix', self.GHCMOD_OUTPUT_MARKER + ',' + self.GHCMOD_ERROR_MARKER ] self.cmd += opt_args self.cmd += ['legacy-interactive'] if debug_any(): print('ghc-mod command: {0}'.format(self.cmd)) self.ghcmod = ProcHelper.ProcHelper(self.cmd, cwd=project_dir) if self.ghcmod.process is not None: self.ghcmod.process.stdin = io.TextIOWrapper( self.ghcmod.process.stdin, 'utf-8') self.ghcmod.process.stdout = io.TextIOWrapper( self.ghcmod.process.stdout, 'utf-8') self.action_lock = threading.Lock() self.stderr_drain = OutputCollector.DescriptorDrain( self.diag_prefix, self.ghcmod.process.stderr) self.stderr_drain.start() else: Logging.log('Did not start ghc-mod ({0}) successfully.'.format( self.diag_prefix))
def stack_exec(self, arg): args = shlex.split(arg) if any(map(lambda arg: arg.startswith('-'), args)) and '--' not in args: args.insert(0, '--') cmdargs = ['stack', 'exec'] + args window = self.view.window() runv = Common.output_panel(window, panel_name=SublimeHaskellStackExec.OUTPUT_PANEL_NAME) pretty_cmdargs = 'Running \'{0}\''.format(' '.join(cmdargs)) runv.run_command('insert', {'characters': '{0}\n{1}\n'.format(pretty_cmdargs, '-' * len(pretty_cmdargs))}) SublimeHaskellStackExec.SExecRunner(runv, cmdargs).start()
def show_declaration_info_panel(view, decl): info = decl.detailed() panel = Common.output_panel(view.window(), info, 'sublime_haskell_symbol_info_panel', syntax='HaskellSymbolInfo') panel.settings().set('result_file_regex', SYMBOL_FILE_REGEX) panel.settings().erase('location') panel.settings().erase('package') panel.settings().erase('module') if decl.has_source_location(): panel.settings().set('location', decl.get_source_location()) if decl.by_cabal(): panel.settings().set('package', decl.defined_module().location.package.package_id()) panel.settings().set('module', decl.defined_module().name)
def on_program_args(self, args): view = self.window.active_view() view_settings = view.settings() run_args = (view_settings or {}).get('subhask_run_args', {}) run_args[self.exec_name] = args view_settings.set('subhask_run_args', run_args) project_builder = Settings.get_project_setting(view, 'haskell_build_tool', Settings.PLUGIN.haskell_build_tool) cmd_list = ProcHelper.exec_wrapper_cmd(project_builder, [self.exec_name] + shlex.split(args)) Common.hide_panel(self.window, panel_name=OUTPUT_PANEL_NAME) outview = Common.output_panel(self.window, panel_name=OUTPUT_PANEL_NAME) pretty_cmdargs = 'Running \'{0}\' in {1}'.format(' '.join(cmd_list), self.exec_base_dir) outview.run_command('insert', {'characters': '{0}\n{1}\n'.format(pretty_cmdargs, '-' * len(pretty_cmdargs))}) self.ExecRunner(outview, cmd_list, self.exec_base_dir).start()
def wait_for_chain_to_complete(self, view, cabal_project_name, cabal_project_dir, banner, cmds): '''Chains several commands, wait for them to complete, then parse and display the resulting errors.''' # First hide error panel to show that something is going on sublime.set_timeout(lambda: hide_output(view), 0) # run and wait commands, fail on first fail # exit_code has scope outside of the loop collected_out = [] exit_code = 0 output_log = Common.output_panel( view.window(), '', panel_name=BUILD_LOG_PANEL_NAME, panel_display=Settings.PLUGIN.show_output_window) for cmd in cmds: if isinstance(cmd, list): Common.output_text(output_log, ' '.join(cmd) + '\u2026\n') # Don't tie stderr to stdout, since we're interested in the error messages out = OutputCollector.OutputCollector(output_log, cmd, cwd=cabal_project_dir) exit_code, cmd_out = out.wait() elif callable(cmd): Common.output_text( output_log, 'Function/method {0}\n'.format(cmd.__name__)) exit_code, cmd_out = cmd(cabal_project_dir) else: # Clearly something not a list or callable: pass collected_out.append(cmd_out) # Bail if the command failed... if exit_code != 0: break if collected_out or exit_code == 0: # We're going to show the errors in the output panel... Common.hide_panel(view.window(), panel_name=BUILD_LOG_PANEL_NAME) # Notify UI thread that commands are done self.PROJECTS_BEING_BUILT.remove(cabal_project_name) ParseOutput.MARKER_MANAGER.mark_compiler_output( view, banner, cabal_project_dir, ''.join(collected_out), exit_code)
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 wait_for_chain_to_complete(self, view, cabal_project_name, cabal_project_dir, banner, cmds): '''Chains several commands, wait for them to complete, then parse and display the resulting errors.''' # First hide error panel to show that something is going on Common.hide_panel(view.window(), panel_name=OUTPUT_PANEL_NAME) # run and wait commands, fail on first fail # exit_code has scope outside of the loop collected_out = [] exit_code = 0 output_log = Common.output_panel(view.window(), '', panel_name=BUILD_LOG_PANEL_NAME, panel_display=Settings.PLUGIN.show_output_window) try: for cmd in cmds: if isinstance(cmd, list): Common.output_text(output_log, ' '.join(cmd) + '\u2026\n') # Don't tie stderr to stdout, since we're interested in the error messages out = OutputCollector.OutputCollector(output_log, cmd, cwd=cabal_project_dir) exit_code, cmd_out = out.wait() elif callable(cmd): Common.output_text(output_log, 'Function/method {0}\n'.format(cmd.__name__)) exit_code, cmd_out = cmd(cabal_project_dir) else: # Clearly something not a list or callable: pass collected_out.append(cmd_out) # Bail if the command failed... if exit_code != 0: break if exit_code == 0: # Hide the build panel if successful Common.hide_panel(view.window(), panel_name=BUILD_LOG_PANEL_NAME) finally: self.PROJECTS_BEING_BUILT.remove(cabal_project_name) # Execute post-build steps in the UI thread (paranoia) sublime.set_timeout(functools.partial(self.post_build, banner, cabal_project_dir, collected_out, exit_code), 0)
def wait_for_chain_to_complete(self, view, cabal_project_dir, msg, cmds, on_done): '''Chains several commands, wait for them to complete, then parse and display the resulting errors.''' # First hide error panel to show that something is going on sublime.set_timeout(lambda: hide_output(view), 0) # run and wait commands, fail on first fail # exit_code has scope outside of the loop # stdout = '' collected_out = [] exit_code = 0 output_log = Common.output_panel( view.window(), '', panel_name=BUILD_LOG_PANEL_NAME, panel_display=Settings.PLUGIN.show_output_window) for cmd in cmds: Common.output_text(output_log, ' '.join(cmd) + '...\n') # Don't tie stderr to stdout, since we're interested in the error messages out = OutputCollector.OutputCollector(output_log, cmd, cwd=cabal_project_dir) exit_code, cmd_out = out.wait() collected_out.append(cmd_out) # Bail if the command failed... if exit_code != 0: break if collected_out or exit_code == 0: # We're going to show the errors in the output panel... Common.hide_panel(view.window(), panel_name=BUILD_LOG_PANEL_NAME) # Notify UI thread that commands are done sublime.set_timeout(on_done, 0) the_stderr = ''.join(collected_out) # The process has terminated; parse and display the output: parsed_messages = ParseOutput.parse_output_messages( view, cabal_project_dir, the_stderr) # The unparseable part (for other errors) unparsable = Regexes.OUTPUT_REGEX.sub('', the_stderr).strip() # Set global error list ParseOutput.set_global_error_messages(parsed_messages) # If we couldn't parse any messages, just show the stderr # Otherwise the parsed errors and the unparsable stderr remainder outputs = [] if parsed_messages: outputs += [ParseOutput.format_output_messages(parsed_messages)] if unparsable: outputs += ['', ''] if unparsable: outputs += ["Collected output:\n", unparsable] ParseOutput.show_output_result_text(view, msg, '\n'.join(outputs), exit_code, cabal_project_dir) sublime.set_timeout( lambda: ParseOutput.mark_messages_in_views(parsed_messages), 0)