Example #1
0
    def start_backend(self):
        retval = True
        if self.is_local_hsdev:
            Logging.log('Starting local \'hsdev\' server', Logging.LOG_INFO)

            use_log_level = (self.version >= [0, 2, 3, 2])
            log_config = Settings.PLUGIN.hsdev_log_config
            log_level = Settings.PLUGIN.hsdev_log_level

            cmd = self.concat_args([(True, ["hsdev"]),
                                    (True, ["run"]),
                                    (self.port, ["--port", str(self.port)]),
                                    (self.cache, ["--cache", self.cache]),
                                    (self.log_file, ["--log", self.log_file]),
                                    (not use_log_level and log_config, ["--log-config", log_config]),
                                    (use_log_level, ["--log-level", log_level])])

            hsdev_proc = ProcHelper.exec_with_wrapper(self.exec_with, self.install_dir, cmd)
            if hsdev_proc.process is not 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')

                # Read and wait for hsdev's startup messge. 15 seconds should be enough time for the message to appear.
                # Otherwise, kill the thread because we don't want to get stuck waiting forever.
                startup_reader = HsDevStartupReader(hsdev_proc.process.stdout)
                startup_reader.start()
                startup_reader.wait_startup(15.0)
                if startup_reader.successful():
                    port = startup_reader.port()
                    if port != self.port:
                        Logging.log('hsdev: server port changed, was {0}, now {1}'.format(self.port, port), Logging.LOG_WARNING)
                        self.port = port
                    self.drain_stdout = OutputCollector.DescriptorDrain('hsdev stdout', hsdev_proc.process.stdout)
                    self.drain_stderr = OutputCollector.DescriptorDrain('hsdev stderr', hsdev_proc.process.stderr)
                    self.drain_stdout.start()
                    self.drain_stderr.start()
                    self.hsdev_process = hsdev_proc

                    Logging.log('Local \'hsdev\' server started successfully.', Logging.LOG_INFO)
                else:
                    # This is a bit of a "Hail Mary!" because readline() could just hang forever. Just to make sure,
                    # kill the process too!
                    startup_reader.stop()
                    hsdev_proc.process.kill()
                    if hsdev_proc.process_err is not None:
                        Logging.log('Possible reason for timeout: {0}'.format(hsdev_proc.process_err))
                    self.hsdev_process = None
                    retval = False

                    sublime.error_message('Timed out waiting for \'hsdev\' to start up.')
            else:
                errmsg = 'Could not start local \'hsdev\' server because:\n\n' + hsdev_proc.process_err
                sublime.error_message(errmsg)
                self.hsdev_process = None
                retval = False

        return retval
Example #2
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()
Example #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))
Example #4
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
Example #5
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.')
Example #6
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()