Exemplo n.º 1
0
    def __init__(self, panel, cmdargs, tie_stderr=True, **popen_args):
        stderr_flag = subprocess.STDOUT if tie_stderr else subprocess.PIPE
        panel_settings = panel.settings()

        self.prochelp = ProcHelper.ProcHelper(cmdargs, stderr=stderr_flag, **popen_args)
        self.panel = panel
        self.lines = []
        self.exit_code = -1
        self.stdout_collector = None
        self.stderr_collector = None
        self.autoindent = panel_settings.get('auto_indent')
        self.roflag = self.panel.is_read_only()

        panel_settings.set('auto_indent', False)
        panel.set_read_only(False)

        if self.prochelp.process is not None:
            lines_lock = threading.RLock()
            self.stdout_collector = FileObjectCollector("stdout-collector", panel, lines_lock,
                                                        self.lines, self.prochelp.process.stdout)
            self.stdout_collector.start()
            if not tie_stderr:
                self.stderr_collector = FileObjectCollector("stderr-collector", panel, lines_lock,
                                                            self.lines, self.prochelp.process.stderr)
                self.stderr_collector.start()
        else:
            self.lines = self.prochelp.process_err
            self.panel.run_command('insert', {'characters': self.prochelp.process_err})

        panel_settings.set('auto_indent', self.autoindent)
        self.panel.set_read_only(self.roflag)
Exemplo n.º 2
0
    def exec_with_wrapper(exec_with, install_dir, cmd_list):
        '''Wrapper function for inserting the execution wrapper, e.g., 'cabal exec' or 'stack exec'

        :returns: Process object from ProcHelper.
        '''

        proc_args = {}
        if exec_with is not None:
            if exec_with == 'cabal':
                cmd_list = ['cabal', 'exec'] + cmd_list
                cmd_list.insert(3, '--')
            elif exec_with == 'stack':
                cmd_list = ['stack', 'exec'] + cmd_list
                cmd_list.insert(3, '--')
            else:
                errmsg = 'HsDevBackend.exec_with_wrapper: Unknown execution prefix \'{0}\''.format(
                    exec_with)
                raise RuntimeError(errmsg)

            if install_dir is not None:
                proc_args['cwd'] = Utils.normalize_path(install_dir)
        else:
            cmd = Which.which(cmd_list[0],
                              ProcHelper.ProcHelper.get_extended_path())
            if cmd is not None:
                cmd_list[0] = cmd

        Logging.log('HsDevBackend.exec_with_wrapper: {0}'.format(cmd_list),
                    Logging.LOG_DEBUG)
        return ProcHelper.ProcHelper(cmd_list, **proc_args)
Exemplo n.º 3
0
    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))
Exemplo n.º 4
0
    def run(self, edit):
        try:
            window = self.view.window()
            window.run_command('hide_panel', {
                'panel':
                'output.' + SublimeHaskellFilterCommand.OUTPUT_PANEL_NAME
            })
            regions = []
            for region in self.view.sel():
                regions.append(sublime.Region(region.a, region.b))
                if region.empty():
                    selection = sublime.Region(0, self.view.size())
                else:
                    selection = region

                # Newline conversion seems dubious here, but... leave it alone for the time being.
                sel_str = self.view.substr(selection).replace('\r\n', '\n')

                with ProcHelper.ProcHelper(self.indenter) as proc:
                    if proc.process is not None:
                        _, out, err = proc.wait(sel_str)
                        # stylish-haskell does not have a non-zero exit code if it errors out! (Surprise!)
                        # Not sure about hindent, but this seems like a safe enough test.
                        #
                        # Also test if the contents actually changed so break the save-indent-save-indent-... loop if
                        # the user enabled prettify_on_save.
                        #
                        # Yes, I like the explicitness of the 'err' test. It might be slower and less compact that
                        # 'if err and ...', but it does tell one what's going on.
                        if err is None or len(err) == 0:
                            if out not in [selection, sel_str]:
                                self.view.replace(edit, selection, out)
                        else:
                            indent_err = ' '.join(self.indenter)
                            stderr_out = '\n'.join([
                                "{0} failed, stderr contents:".format(
                                    indent_err), "-" * 40, ""
                            ]) + err
                            self.report_error(stderr_out)
                    else:
                        self.report_error(proc.process_err)

            # Questionable whether regions should be re-activated: stylish-haskell usually adds whitespace, which makes
            # the selection nonsensical.
            self.view.sel().clear()
            for region in regions:
                self.view.sel().add(region)

        except OSError:
            self.report_error('Exception executing {0}'.format(' '.join(
                self.indenter)))
            traceback.print_exc()
Exemplo n.º 5
0
def do_prettify(view, edit, indenter, indenter_options):
    try:
        window = view.window()
        window.run_command('hide_panel',
                           {'panel': 'output.' + FILTER_OUTPUT_PANEL_NAME})
        regions = []
        for region in view.sel():
            regions.append(sublime.Region(region.a, region.b))
            selection = region if not region.empty() else sublime.Region(
                0, view.size())

            # Newline conversion seems dubious here, but... leave it alone for the time being.
            sel_str = view.substr(selection).replace('\r\n', '\n')

            with ProcHelper.ProcHelper(indenter + indenter_options) as proc:
                if proc.process is not None:
                    _, out, err = proc.wait(sel_str)
                    # stylish-haskell does not have a non-zero exit code if it errors out! (Surprise!)
                    # Not sure about hindent, but this seems like a safe enough test.
                    #
                    # Also test if the contents actually changed so break the save-indent-save-indent-... loop if
                    # the user enabled prettify_on_save.
                    if not err:
                        if out not in [selection, sel_str]:
                            view.replace(edit, selection, out)
                    else:
                        indent_err = ' '.join(indenter)
                        stderr_out = '\n'.join([
                            "{0} failed, stderr contents:".format(indent_err),
                            "-" * 40, ""
                        ]) + err
                        report_error(view, stderr_out)
                else:
                    report_error(view, proc.process_err)

        view.sel().clear()
        # Questionable whether regions should be re-activated: stylish-haskell usually adds whitespace, which makes
        # the selection nonsensical.
        #
        # However, there are other plugins that get fired after SublimeHaskell that don't like it when you kill all of the
        # selection regions from underneath their feet.
        for region in regions:
            view.sel().add(region)

    except OSError:
        report_error(view,
                     'Exception executing {0}'.format(' '.join(indenter)))
        traceback.print_exc()
Exemplo n.º 6
0
    def run(self):
        cmd = concat_args([(True, ["hsdev", "run"]),
                           (self.port, ["--port", str(self.port)]),
                           (self.cache, ["--cache", self.cache]),
                           (self.log_file, ["--log", self.log_file]),
                           (self.log_config, ["--log-config", self.log_config])])

        Logging.log('hsdev command: {0}'.format(cmd), Logging.LOG_DEBUG)

        while True:
            self.create_event.wait()
            self.create_event.clear()
            while not self.stop_event.is_set():
                Logging.log('Starting hsdev server', Logging.LOG_INFO)
                hsdev_proc = ProcHelper.ProcHelper(cmd)
                if hsdev_proc.process is None:
                    Logging.log('Failed to create hsdev process', Logging.LOG_ERROR)
                    return None

                # Use TextIOWrapper here because it combines decoding with newline handling,
                # which means less to maintain.
                hsdev_proc.process.stdout = io.TextIOWrapper(hsdev_proc.process.stdout, 'utf-8')
                hsdev_proc.process.stderr = io.TextIOWrapper(hsdev_proc.process.stderr, 'utf-8')

                while True:
                    srvout = hsdev_proc.process.stdout.readline().strip()
                    Logging.log('hsdev initial output: {0}'.format(srvout), Logging.LOG_DEBUG)
                    start_confirm = re.match(r'^.*?hsdev> Server started at port (?P<port>\d+)$', srvout)
                    if start_confirm:
                        Logging.log('hsdev server started at port {0}'.format(start_confirm.group('port')))
                        break

                self.process = hsdev_proc.process
                self.drain_stdout = OutputCollector.DescriptorDrain('hsdev stdout', self.process.stdout)
                self.drain_stderr = OutputCollector.DescriptorDrain('hsdev stderr', self.process.stderr)
                self.drain_stdout.start()
                self.drain_stderr.start()
                HsCallback.call_callback(self.on_start, name='HsDevProcess.on_start')

                self.process.wait()

                self.drain_stdout.stop()
                self.drain_stderr.stop()
                HsCallback.call_callback(self.on_exit, name='HsDevProcess.on_exit')
            self.stop_event.clear()
Exemplo n.º 7
0
    def __init__(self, project, project_dir, opt_args):
        Logging.log('Starting \'ghc-mod\' for project {0}'.format(project),
                    Logging.LOG_INFO)

        self.ghcmod = None
        self.action_lock = None
        self.stderr_drain = None
        self.cmd = []
        self.diag_prefix = 'ghc-mod ' + project

        # 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']

        Logging.log('ghc-mod command: {0}'.format(self.cmd), Logging.LOG_DEBUG)

        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 successfully.')
Exemplo n.º 8
0
def admin(cmds, wait=False, **popen_kwargs):
    if not Settings.PLUGIN.enable_hdevtools:
        return None

    hdevtools_socket = Settings.PLUGIN.hdevtools_socket

    if hdevtools_socket:
        cmds.append('--socket={0}'.format(hdevtools_socket))

    command = ["hdevtools", "admin"] + cmds

    try:
        if wait:
            exit_code, stdout, stderr = ProcHelper.ProcHelper.run_process(
                command, **popen_kwargs)
            return stdout if exit_code == 0 else 'error running {0}: {1}'.format(
                command, stderr)
        else:
            proc = ProcHelper.ProcHelper(command, **popen_kwargs)
            OutputCollector.DescriptorDrain('hdevtools stdout',
                                            proc.process.stdout).start()
            OutputCollector.DescriptorDrain('hdevtools stderr',
                                            proc.process.stderr).start()
            return ''

    except OSError as os_exc:
        if os_exc.errno == errno.ENOENT:
            show_hdevtools_error_and_disable()

        Settings.PLUGIN.enable_hdevtools = False

        return None
    except Exception:
        Logging.log(
            'hdevtools.admin failed with exception, see console window traceback'
        )
        traceback.print_exc()
        return None
Exemplo n.º 9
0
    def run(self):
        new_simple_log = patch_simple_log(self.version)

        cmd = concat_args([
            (True, ["hsdev", "run"]),
            (self.port, ["--port", str(self.port)]),
            (self.cache, ["--cache", self.cache]),
            (self.log_file, ["--log", self.log_file]),
            # HACK! HACK! HACK! Alexandr changed simple-log's command line API.
            #
            # "--log-config" only applies to earlier hsdev versions that support 'log politics' (and for those
            # of us old enough to remember the Soviet era, 'log politics' is an incredibly Soviet notion that
            # makes us smile! :-)
            #
            # Versions 0.2.3.0 and later: Simplified argument -- just the log level, and only one log level,
            # Yvgeny! (With apologies to "The Hunt for Red October".)
            (not new_simple_log
             and self.log_config, ["--log-config", self.log_config]),
            (new_simple_log
             and self.log_config, ["--log-level", self.log_config])
        ])

        Logging.log('hsdev command: {0}'.format(cmd), Logging.LOG_DEBUG)

        while True:
            self.create_event.wait()
            self.create_event.clear()
            while not self.stop_event.is_set():
                Logging.log('Starting hsdev server', Logging.LOG_INFO)
                hsdev_proc = ProcHelper.ProcHelper(cmd)
                if hsdev_proc.process is None:
                    Logging.log('Failed to create hsdev process',
                                Logging.LOG_ERROR)
                    return

                # Use TextIOWrapper here because it combines decoding with newline handling,
                # which means less to maintain.
                hsdev_proc.process.stdout = io.TextIOWrapper(
                    hsdev_proc.process.stdout, 'utf-8')
                hsdev_proc.process.stderr = io.TextIOWrapper(
                    hsdev_proc.process.stderr, 'utf-8')

                while True:
                    srvout = hsdev_proc.process.stdout.readline().strip()
                    if srvout != '':
                        Logging.log('hsdev initial output: {0}'.format(srvout),
                                    Logging.LOG_DEBUG)
                        start_confirm = re.search(
                            r'[Ss]erver started at port (?P<port>\d+)$',
                            srvout)
                        if start_confirm:
                            Logging.log(
                                'hsdev server started at port {0}'.format(
                                    start_confirm.group('port')))
                            break
                    else:
                        Logging.log(
                            'hsdev initial output: Got EOF. Server not started successfully.'
                        )
                        return

                self.process = hsdev_proc.process
                self.drain_stdout = OutputCollector.DescriptorDrain(
                    'hsdev stdout', self.process.stdout)
                self.drain_stderr = OutputCollector.DescriptorDrain(
                    'hsdev stderr', self.process.stderr)
                self.drain_stdout.start()
                self.drain_stderr.start()
                HsCallback.call_callback(self.on_start,
                                         name='HsDevProcess.on_start')

                self.process.wait()

                self.drain_stdout.stop()
                self.drain_stderr.stop()
                HsCallback.call_callback(self.on_exit,
                                         name='HsDevProcess.on_exit')

            self.stop_event.clear()