예제 #1
0
    def run(self, **kwargs):
        with self.chdir(kwargs.get('working_dir')):
            p = os.path.join(os.getcwd(), 'tests')
            patt = kwargs.get('loader_pattern', 'test*.py',)
            # TODO(guillermooo): I can't get $file to expand in the build
            # system. It should be possible to make the following code simpler
            # with it.
            if kwargs.get('active_file_only') is True:
                patt = os.path.basename(self.window.active_view().file_name())
            suite = unittest.TestLoader().discover(p, pattern=patt)

            file_regex = r'^\s*File\s*"([^.].*?)",\s*line\s*(\d+),.*$'
            display = OutputPanel('fs.tests', file_regex=file_regex)
            display.show()
            runner = unittest.TextTestRunner(stream=display, verbosity=1)

            def run_and_display():
                runner.run(suite)

            threading.Thread(target=run_and_display).start()
예제 #2
0
    def run(self, **kwargs):
        with self.chdir(kwargs.get('working_dir')):
            p = os.path.join(os.getcwd(), 'tests')
            patt = kwargs.get(
                'loader_pattern',
                'test*.py',
            )
            # TODO(guillermooo): I can't get $file to expand in the build
            # system. It should be possible to make the following code simpler
            # with it.
            if kwargs.get('active_file_only') is True:
                patt = os.path.basename(self.window.active_view().file_name())
            suite = unittest.TestLoader().discover(p, pattern=patt)

            file_regex = r'^\s*File\s*"([^.].*?)",\s*line\s*(\d+),.*$'
            display = OutputPanel('fs.tests', file_regex=file_regex)
            display.show()
            runner = unittest.TextTestRunner(stream=display, verbosity=1)

            def run_and_display():
                runner.run(suite)

            threading.Thread(target=run_and_display).start()
예제 #3
0
def process_resp(data):
    _logger.debug ('processing response data: %s', data)
    if data ['Kind'] == 'compilerlocation':
        r = CompilerLocationResponse (data)
        editor_context.compilers_path = r.compilers_path
        return

    if data['Kind'] == 'project':
        r = ProjectResponse(data)
        panel = OutputPanel (name='fs.out')
        panel.write ("Files in project:\n")
        panel.write ("\n")
        panel.write ('\n'.join(r.files))
        panel.show()
        return

    if data['Kind'] == 'errors' and data['Data']:
        panel = OutputPanel (name='fs.out')
        panel.write (str(data))
        panel.write ("\n")
        panel.show()
        return

    if data['Kind'] == 'INFO' and data['Data']:
        print(str(data))
        return

    if data['Kind'] == 'declarations' and data['Data']:
        decls = DeclarationsResponse(data)
        its = [decl.to_menu_data() for decl in decls.declarations]
        w = sublime.active_window()
        w.run_command ('fs_show_menu', {'items': its})
        return
예제 #4
0
    def run(
        self,
        cmd=None,
        shell_cmd=None,
        file_regex="",
        line_regex="",
        working_dir="",
        encoding="utf-8",
        env={},
        quiet=False,
        kill=False,
        word_wrap=True,
        syntax="Packages/Text/Plain text.tmLanguage",
        preamble="",
        panel_name="fs.out",
        # Catches "path" and "shell"
        **kwargs
    ):

        if kill:
            if hasattr(self, "proc") and self.proc:
                self.proc.kill()
                self.proc = None
                self.append_string(None, "[Cancelled]")
            return

        # TODO(guillermooo): We cannot have multiple processes running at the
        # same time, or processes that use separate output panels.
        if not hasattr(self, "out_panel"):
            # Try not to call get_output_panel until the regexes are assigned
            self.out_panel = OutputPanel(panel_name)

        # Default to the current files directory if no working directory was given
        if not working_dir and self.window.active_view() and self.window.active_view().file_name():
            working_dir = os.path.dirname(self.window.active_view().file_name())

        self.out_panel.set("result_file_regex", file_regex)
        self.out_panel.set("result_line_regex", line_regex)
        self.out_panel.set("result_base_dir", working_dir)
        self.out_panel.set("word_wrap", word_wrap)
        self.out_panel.set("line_numbers", False)
        self.out_panel.set("gutter", False)
        self.out_panel.set("scroll_past_end", False)
        self.out_panel.view.assign_syntax(syntax)

        self.encoding = encoding
        self.quiet = quiet

        self.proc = None
        if not self.quiet:
            if shell_cmd:
                print("Running " + shell_cmd)
            else:
                print("Running " + " ".join(cmd))
            sublime.status_message("Building")

        if preamble:
            self.append_string(self.proc, preamble)

        show_panel_on_build = sublime.load_settings("Dart - Plugin Settings.sublime-settings").get(
            "show_panel_on_build", True
        )
        if show_panel_on_build:
            self.out_panel.show()

        merged_env = env.copy()
        if self.window.active_view():
            user_env = self.window.active_view().settings().get("build_env")
            if user_env:
                merged_env.update(user_env)

        # Change to the working dir, rather than spawning the process with it,
        # so that emitted working dir relative path names make sense
        if working_dir:
            os.chdir(working_dir)

        self.debug_text = ""
        if shell_cmd:
            self.debug_text += "[shell_cmd: " + shell_cmd + "]\n"
        else:
            self.debug_text += "[cmd: " + str(cmd) + "]\n"
        self.debug_text += "[dir: " + str(os.getcwd()) + "]\n"
        if "PATH" in merged_env:
            self.debug_text += "[path: " + str(merged_env["PATH"]) + "]"
        else:
            self.debug_text += "[path: " + str(os.environ["PATH"]) + "]"

        try:
            # Forward kwargs to AsyncProcess
            self.proc = AsyncProcess(cmd, shell_cmd, merged_env, self, **kwargs)
        except Exception as e:
            self.append_string(None, str(e) + "\n")
            self.append_string(None, self.debug_text + "\n")
            if not self.quiet:
                self.append_string(None, "[Finished]")
예제 #5
0
class fs_exec(sublime_plugin.WindowCommand, ProcessListener):
    def run(
        self,
        cmd=None,
        shell_cmd=None,
        file_regex="",
        line_regex="",
        working_dir="",
        encoding="utf-8",
        env={},
        quiet=False,
        kill=False,
        word_wrap=True,
        syntax="Packages/Text/Plain text.tmLanguage",
        preamble="",
        panel_name="fs.out",
        # Catches "path" and "shell"
        **kwargs
    ):

        if kill:
            if hasattr(self, "proc") and self.proc:
                self.proc.kill()
                self.proc = None
                self.append_string(None, "[Cancelled]")
            return

        # TODO(guillermooo): We cannot have multiple processes running at the
        # same time, or processes that use separate output panels.
        if not hasattr(self, "out_panel"):
            # Try not to call get_output_panel until the regexes are assigned
            self.out_panel = OutputPanel(panel_name)

        # Default to the current files directory if no working directory was given
        if not working_dir and self.window.active_view() and self.window.active_view().file_name():
            working_dir = os.path.dirname(self.window.active_view().file_name())

        self.out_panel.set("result_file_regex", file_regex)
        self.out_panel.set("result_line_regex", line_regex)
        self.out_panel.set("result_base_dir", working_dir)
        self.out_panel.set("word_wrap", word_wrap)
        self.out_panel.set("line_numbers", False)
        self.out_panel.set("gutter", False)
        self.out_panel.set("scroll_past_end", False)
        self.out_panel.view.assign_syntax(syntax)

        self.encoding = encoding
        self.quiet = quiet

        self.proc = None
        if not self.quiet:
            if shell_cmd:
                print("Running " + shell_cmd)
            else:
                print("Running " + " ".join(cmd))
            sublime.status_message("Building")

        if preamble:
            self.append_string(self.proc, preamble)

        show_panel_on_build = sublime.load_settings("Dart - Plugin Settings.sublime-settings").get(
            "show_panel_on_build", True
        )
        if show_panel_on_build:
            self.out_panel.show()

        merged_env = env.copy()
        if self.window.active_view():
            user_env = self.window.active_view().settings().get("build_env")
            if user_env:
                merged_env.update(user_env)

        # Change to the working dir, rather than spawning the process with it,
        # so that emitted working dir relative path names make sense
        if working_dir:
            os.chdir(working_dir)

        self.debug_text = ""
        if shell_cmd:
            self.debug_text += "[shell_cmd: " + shell_cmd + "]\n"
        else:
            self.debug_text += "[cmd: " + str(cmd) + "]\n"
        self.debug_text += "[dir: " + str(os.getcwd()) + "]\n"
        if "PATH" in merged_env:
            self.debug_text += "[path: " + str(merged_env["PATH"]) + "]"
        else:
            self.debug_text += "[path: " + str(os.environ["PATH"]) + "]"

        try:
            # Forward kwargs to AsyncProcess
            self.proc = AsyncProcess(cmd, shell_cmd, merged_env, self, **kwargs)
        except Exception as e:
            self.append_string(None, str(e) + "\n")
            self.append_string(None, self.debug_text + "\n")
            if not self.quiet:
                self.append_string(None, "[Finished]")

    def append_data(self, proc, data):
        if proc != self.proc:
            # a second call to exec has been made before the first one
            # finished, ignore it instead of intermingling the output.
            if proc:
                proc.kill()
            return

        try:
            str_ = data.decode(self.encoding)
        except UnicodeEncodeError:
            str_ = "[Decode error - output not " + self.encoding + "]\n"
            proc = None
            return

        # Normalize newlines, Sublime Text always uses a single \n separator
        # in memory.
        str_ = str_.replace("\r\n", "\n").replace("\r", "\n")

        self.out_panel.write(str_)

    def append_string(self, proc, str):
        self.append_data(proc, str.encode(self.encoding))

    def finish(self, proc):
        if not self.quiet:
            elapsed = time.time() - proc.start_time
            exit_code = proc.exit_code()
            if (exit_code == 0) or (exit_code == None):
                self.append_string(proc, "[Finished in %.1fs]" % (elapsed))
            else:
                self.append_string(proc, "[Finished in %.1fs with exit code %d]\n" % (elapsed, exit_code))
                self.append_string(proc, self.debug_text)

        if proc != self.proc:
            return

        # XXX: What's this for?
        errs = self.out_panel.view.find_all_results()
        if len(errs) == 0:
            sublime.status_message("Build finished")
        else:
            sublime.status_message(("Build finished with %d errors") % len(errs))

    def on_data(self, proc, data):
        after(0, functools.partial(self.append_data, proc, data))

    def on_finished(self, proc):
        after(0, functools.partial(self.finish, proc))
예제 #6
0
def process_resp(data):
    _logger.debug('processing response data: %s', data)
    if data['Kind'] == 'compilerlocation':
        r = CompilerLocationResponse(data)
        raise_event(ON_COMPILER_PATH_AVAILABLE, {'response': r})
        return

    if data['Kind'] == 'project':
        r = ProjectResponse(data)
        _logger.debug('\n'.join(r.files))
        return

    if data['Kind'] == 'errors':
        # todo: enable error navigation via standard keys
        v = sublime.active_window().active_view()
        v.erase_regions('fs.errs')
        if not data['Data']:
            return
        v.add_regions(
            'fs.errs', [ErrorInfo(e).to_region(v) for e in data['Data']],
            'invalid.illegal', 'dot', sublime.DRAW_SQUIGGLY_UNDERLINE
            | sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE)
        return

    if data['Kind'] == 'ERROR':
        _logger.error(str(data))
        return

    if data['Kind'] == 'tooltip' and data['Data']:
        v = sublime.active_window().active_view()
        word = v.substr(v.word(v.sel()[0].b))
        panel = OutputPanel('fs.out')
        panel.write(data['Data'])
        panel.show()
        return

    if data['Kind'] == 'INFO' and data['Data']:
        _logger.info(str(data))
        print("FSharp:", data['Data'])
        return

    if data['Kind'] == 'finddecl' and data['Data']:
        fname = data['Data']['File']
        row = data['Data']['Line']
        col = data['Data']['Column'] + 1
        w = sublime.active_window()
        # todo: don't open file if we are looking at the requested file
        target = '{0}:{1}:{2}'.format(fname, row, col)
        w.open_file(target, sublime.ENCODED_POSITION)
        return

    if data['Kind'] == 'declarations' and data['Data']:
        decls = DeclarationsResponse(data)
        its = [decl.to_menu_data() for decl in decls.declarations]
        w = sublime.active_window()
        w.run_command('fs_show_menu', {'items': its})
        return

    if data['Kind'] == 'completion' and data['Data']:
        _logger.error(
            'unexpected "completion" results - should be handled elsewhere')
        return
예제 #7
0
    def run(
            self,
            cmd=None,
            shell_cmd=None,
            file_regex="",
            line_regex="",
            working_dir="",
            encoding="utf-8",
            env={},
            quiet=False,
            kill=False,
            word_wrap=True,
            syntax="Packages/Text/Plain text.tmLanguage",
            preamble='',
            panel_name='fs.out',
            # Catches "path" and "shell"
            **kwargs):

        if kill:
            if hasattr(self, 'proc') and self.proc:
                self.proc.kill()
                self.proc = None
                self.append_string(None, "[Cancelled]")
            return

        # TODO(guillermooo): We cannot have multiple processes running at the
        # same time, or processes that use separate output panels.
        if not hasattr(self, 'out_panel'):
            # Try not to call get_output_panel until the regexes are assigned
            self.out_panel = OutputPanel(panel_name)

        # Default to the current files directory if no working directory was given
        if (not working_dir and self.window.active_view()
                and self.window.active_view().file_name()):
            working_dir = os.path.dirname(
                self.window.active_view().file_name())

        self.out_panel.set("result_file_regex", file_regex)
        self.out_panel.set("result_line_regex", line_regex)
        self.out_panel.set("result_base_dir", working_dir)
        self.out_panel.set("word_wrap", word_wrap)
        self.out_panel.set("line_numbers", False)
        self.out_panel.set("gutter", False)
        self.out_panel.set("scroll_past_end", False)
        self.out_panel.view.assign_syntax(syntax)

        self.encoding = encoding
        self.quiet = quiet

        self.proc = None
        if not self.quiet:
            if shell_cmd:
                print("Running " + shell_cmd)
            else:
                print("Running " + " ".join(cmd))
            sublime.status_message("Building")

        if preamble:
            self.append_string(self.proc, preamble)

        show_panel_on_build = sublime.load_settings(
            "Dart - Plugin Settings.sublime-settings").get(
                "show_panel_on_build", True)
        if show_panel_on_build:
            self.out_panel.show()

        merged_env = env.copy()
        if self.window.active_view():
            user_env = self.window.active_view().settings().get('build_env')
            if user_env:
                merged_env.update(user_env)

        # Change to the working dir, rather than spawning the process with it,
        # so that emitted working dir relative path names make sense
        if working_dir:
            os.chdir(working_dir)

        self.debug_text = ""
        if shell_cmd:
            self.debug_text += "[shell_cmd: " + shell_cmd + "]\n"
        else:
            self.debug_text += "[cmd: " + str(cmd) + "]\n"
        self.debug_text += "[dir: " + str(os.getcwd()) + "]\n"
        if "PATH" in merged_env:
            self.debug_text += "[path: " + str(merged_env["PATH"]) + "]"
        else:
            self.debug_text += "[path: " + str(os.environ["PATH"]) + "]"

        try:
            # Forward kwargs to AsyncProcess
            self.proc = AsyncProcess(cmd, shell_cmd, merged_env, self,
                                     **kwargs)
        except Exception as e:
            self.append_string(None, str(e) + "\n")
            self.append_string(None, self.debug_text + "\n")
            if not self.quiet:
                self.append_string(None, "[Finished]")
예제 #8
0
class fs_exec(sublime_plugin.WindowCommand, ProcessListener):
    def run(
            self,
            cmd=None,
            shell_cmd=None,
            file_regex="",
            line_regex="",
            working_dir="",
            encoding="utf-8",
            env={},
            quiet=False,
            kill=False,
            word_wrap=True,
            syntax="Packages/Text/Plain text.tmLanguage",
            preamble='',
            panel_name='fs.out',
            # Catches "path" and "shell"
            **kwargs):

        if kill:
            if hasattr(self, 'proc') and self.proc:
                self.proc.kill()
                self.proc = None
                self.append_string(None, "[Cancelled]")
            return

        # TODO(guillermooo): We cannot have multiple processes running at the
        # same time, or processes that use separate output panels.
        if not hasattr(self, 'out_panel'):
            # Try not to call get_output_panel until the regexes are assigned
            self.out_panel = OutputPanel(panel_name)

        # Default to the current files directory if no working directory was given
        if (not working_dir and self.window.active_view()
                and self.window.active_view().file_name()):
            working_dir = os.path.dirname(
                self.window.active_view().file_name())

        self.out_panel.set("result_file_regex", file_regex)
        self.out_panel.set("result_line_regex", line_regex)
        self.out_panel.set("result_base_dir", working_dir)
        self.out_panel.set("word_wrap", word_wrap)
        self.out_panel.set("line_numbers", False)
        self.out_panel.set("gutter", False)
        self.out_panel.set("scroll_past_end", False)
        self.out_panel.view.assign_syntax(syntax)

        self.encoding = encoding
        self.quiet = quiet

        self.proc = None
        if not self.quiet:
            if shell_cmd:
                print("Running " + shell_cmd)
            else:
                print("Running " + " ".join(cmd))
            sublime.status_message("Building")

        if preamble:
            self.append_string(self.proc, preamble)

        show_panel_on_build = sublime.load_settings(
            "Dart - Plugin Settings.sublime-settings").get(
                "show_panel_on_build", True)
        if show_panel_on_build:
            self.out_panel.show()

        merged_env = env.copy()
        if self.window.active_view():
            user_env = self.window.active_view().settings().get('build_env')
            if user_env:
                merged_env.update(user_env)

        # Change to the working dir, rather than spawning the process with it,
        # so that emitted working dir relative path names make sense
        if working_dir:
            os.chdir(working_dir)

        self.debug_text = ""
        if shell_cmd:
            self.debug_text += "[shell_cmd: " + shell_cmd + "]\n"
        else:
            self.debug_text += "[cmd: " + str(cmd) + "]\n"
        self.debug_text += "[dir: " + str(os.getcwd()) + "]\n"
        if "PATH" in merged_env:
            self.debug_text += "[path: " + str(merged_env["PATH"]) + "]"
        else:
            self.debug_text += "[path: " + str(os.environ["PATH"]) + "]"

        try:
            # Forward kwargs to AsyncProcess
            self.proc = AsyncProcess(cmd, shell_cmd, merged_env, self,
                                     **kwargs)
        except Exception as e:
            self.append_string(None, str(e) + "\n")
            self.append_string(None, self.debug_text + "\n")
            if not self.quiet:
                self.append_string(None, "[Finished]")

    def append_data(self, proc, data):
        if proc != self.proc:
            # a second call to exec has been made before the first one
            # finished, ignore it instead of intermingling the output.
            if proc:
                proc.kill()
            return

        try:
            str_ = data.decode(self.encoding)
        except UnicodeEncodeError:
            str_ = "[Decode error - output not " + self.encoding + "]\n"
            proc = None
            return

        # Normalize newlines, Sublime Text always uses a single \n separator
        # in memory.
        str_ = str_.replace('\r\n', '\n').replace('\r', '\n')

        self.out_panel.write(str_)

    def append_string(self, proc, str):
        self.append_data(proc, str.encode(self.encoding))

    def finish(self, proc):
        if not self.quiet:
            elapsed = time.time() - proc.start_time
            exit_code = proc.exit_code()
            if (exit_code == 0) or (exit_code == None):
                self.append_string(proc, "[Finished in %.1fs]" % (elapsed))
            else:
                self.append_string(
                    proc, "[Finished in %.1fs with exit code %d]\n" %
                    (elapsed, exit_code))
                self.append_string(proc, self.debug_text)

        if proc != self.proc:
            return

        # XXX: What's this for?
        errs = self.out_panel.view.find_all_results()
        if len(errs) == 0:
            sublime.status_message("Build finished")
        else:
            sublime.status_message(
                ("Build finished with %d errors") % len(errs))

    def on_data(self, proc, data):
        after(0, functools.partial(self.append_data, proc, data))

    def on_finished(self, proc):
        after(0, functools.partial(self.finish, proc))
예제 #9
0
def process_resp(data):
    _logger.debug ('processing response data: %s', data)
    if data ['Kind'] == 'compilerlocation':
        r = CompilerLocationResponse (data)
        raise_event(ON_COMPILER_PATH_AVAILABLE, {'response': r})
        return

    if data['Kind'] == 'project':
        r = ProjectResponse(data)
        _logger.debug('\n'.join(r.files))
        return

    if data['Kind'] == 'errors':
        # todo: enable error navigation via standard keys
        v = sublime.active_window().active_view()
        v.erase_regions ('fs.errs')
        if not data['Data']:
            return
        v.add_regions('fs.errs',
                      [ErrorInfo(e).to_region(v) for e in data['Data']],
                      'invalid.illegal',
                      'dot',
                      sublime.DRAW_SQUIGGLY_UNDERLINE |
                      sublime.DRAW_NO_FILL |
                      sublime.DRAW_NO_OUTLINE
                      )
        return

    if data['Kind'] == 'ERROR':
        _logger.error(str(data))
        return

    if data['Kind'] == 'tooltip' and data['Data']:
        v = sublime.active_window().active_view()
        word = v.substr(v.word(v.sel()[0].b))
        panel = OutputPanel('fs.out')
        panel.write(data['Data'])
        panel.show()
        return

    if data['Kind'] == 'INFO' and data['Data']:
        _logger.info(str(data))
        print("FSharp:", data['Data'])
        return

    if data['Kind'] == 'finddecl' and data['Data']:
        fname = data['Data']['File']
        row = data['Data']['Line']
        col = data['Data']['Column'] + 1
        w = sublime.active_window()
        # todo: don't open file if we are looking at the requested file
        target = '{0}:{1}:{2}'.format(fname, row, col)
        w.open_file(target, sublime.ENCODED_POSITION)
        return

    if data['Kind'] == 'declarations' and data['Data']:
        decls = DeclarationsResponse(data)
        its = [decl.to_menu_data() for decl in decls.declarations]
        w = sublime.active_window()
        w.run_command ('fs_show_menu', {'items': its})
        return

    if data['Kind'] == 'completion' and data['Data']:
        _logger.error('unexpected "completion" results - should be handled elsewhere')
        return