def handle_thread(self, thread):
		if thread.is_alive():
			sublime.set_timeout(lambda: self.handle_thread(thread), 100)
		elif thread.result == False:
			_status_print(ERR_NOT_EDITED)
		else:
			_status_print("issue edited")
Example #2
0
def _delay_queue(timeout, preemptive):
    global __signaled_, __queued_
    now = time.time()

    if not preemptive and now <= __queued_ + 0.01:
        return  # never delay queues too fast (except preemptively)

    __queued_ = now
    _timeout = float(timeout) / 1000

    if __signaled_first_:
        if MAX_DELAY > 0 and now - __signaled_first_ + _timeout > MAX_DELAY:
            _timeout -= now - __signaled_first_
            if _timeout < 0:
                _timeout = 0
            timeout = int(round(_timeout * 1000, 0))

    new__signaled_ = now + _timeout - 0.01

    if __signaled_ >= now - 0.01 and (preemptive or new__signaled_ >= __signaled_ - 0.01):
        __signaled_ = new__signaled_
        # print 'delayed to', (preemptive, __signaled_ - now)

        def _signal():
            if time.time() < __signaled_:
                return
            __semaphore_.release()

        sublime.set_timeout(_signal, timeout)
Example #3
0
def cmd_9(view, edit, args, wd, rkey):
	if len(args) == 0 or args[0] not in ('run', 'replay', 'build'):
		push_output(view, rkey, ('9: invalid args %s' % args))
		return

	subcmd = args[0]
	cid = ''
	if subcmd == 'replay':
		cid = '9replay-%s' % wd
	cid, cb = _9_begin_call(subcmd, view, edit, args, wd, rkey, cid)

	a = {
		'cid': cid,
		'env': sh.env(),
		'dir': wd,
		'args': args[1:],
		'build_only': (subcmd == 'build'),
	}

	win = view.window()
	if win is not None:
		av = win.active_view()
		if av is not None:
			fn = av.file_name()
			if fn:
				_save_all(win, wd)
			else:
				if gs.is_go_source_view(av, False):
					a['fn'] = gs.view_fn(av)
					a['src'] = av.substr(sublime.Region(0, av.size()))

	sublime.set_timeout(lambda: mg9.acall('play', a, cb), 0)
Example #4
0
def monitorDownloadThread(downloadThread):
    if downloadThread.is_alive():
        msg = downloadThread.getCurrentMessage()
        sublime.status_message(msg)
        sublime.set_timeout(lambda: monitorDownloadThread(downloadThread), CHECK_DOWNLOAD_THREAD_TIME_MS)
    else:
        downloadThread.showResultToPresenter()
Example #5
0
	def on_complete(self, *args, **kwargs):
		self.state = 'complete'

		if kwargs['progress'].is_background:
			return

		sublime.set_timeout(lambda: sublime.status_message('PyV8 binary successfully loaded'), 0)
Example #6
0
 def parse_file(self, line):
     if(len(self.file) >= self.file_size and line == ".\n"):
         self.in_file = False
         self.parse_done = True
         sublime.set_timeout(self.on_done, 0)
     else:
         self.file += line
    def on_done_filename(self, value):
        self.filename = value
        # get selected text, or the whole file if nothing selected
        if all([region.empty() for region in self.view.sel()]):
            text = self.view.substr(sublime.Region(0, self.view.size()))
        else:
            text = "\n".join([self.view.substr(region) for region in self.view.sel()])

        try:
            gist = self.gistapi.create_gist(description=self.description,
                                            filename=self.filename,
                                            content=text,
                                            public=self.public)
            self.view.settings().set('gist', gist)
            sublime.set_clipboard(gist["html_url"])
            sublime.status_message(self.MSG_SUCCESS)
        except GitHubApi.UnauthorizedException:
            # clear out the bad token so we can reset it
            self.settings.set("github_token", "")
            sublime.save_settings("GitHub.sublime-settings")
            sublime.error_message(self.ERR_UNAUTHORIZED_TOKEN)
            sublime.set_timeout(self.get_username, 50)
        except GitHubApi.UnknownException as e:
            sublime.error_message(e.message)
        except GitHubApi.ConnectionException as e:
            sublime.error_message(e.message)
	def run(self, edit, event):
		if self.symbol_details:
			view_path = self.symbol_details[0]
			focus_region = self.symbol_details[1]
			# collapse the region to a single point, the region start
			focus_region = sublime.Region(focus_region.begin(), focus_region.begin())

			# get the view with this path
			view = sublime.active_window().find_open_file(view_path)
			if view:
				self.showSymbol(view, focus_region)
			else:
				# weird issue, but unless we open the file with 'ENCODED_POSITION' it won't scroll afterwards
				# https://github.com/SublimeTextIssues/Core/issues/538
				view = sublime.active_window().open_file("%s:%d:%d" % (view_path, 1, 0), sublime.ENCODED_POSITION)

				def viewLoadedTimeout():
					# we can run methods only on loaded views
					if not view.is_loading():
						self.showSymbol(view, focus_region)
					else:
						sublime.set_timeout(viewLoadedTimeout, 100)
				
				# open is asynchronous, wait for a bit and then try to focus
				sublime.set_timeout(viewLoadedTimeout, 100)
    def defered_update(self, view):
        if not view.window():  # If view is not visible window() will be None.
            return

        if view.id() not in self.seen_views:
            self.seen_views.append(view.id())

        if view_is_widget(view):
            return

        if not self.is_enabled(view):
            return

        if view_is_too_big(view, self.max_size_setting,
                           self.default_max_file_size):
            self.view_is_too_big_callback(view)
            return

        def func():
            self.update(view)

        if self.delay:
            sublime.set_timeout(func, self.delay)
        else:
            func()
Example #10
0
 def run(self, edit, fn=None):
     point = self.view.sel()[0].begin()
     line = self.view.substr(self.view.line(point))
     match_link = self.LINK_PATTERN.search(line)
     match_md   = self.MD_LINK.search(line)
     match_wiki = self.WIKI_LINK.search(line)
     if match_link:
         fn, sym, line, col, text = match_link.group('fn', 'sym', 'line', 'col', 'text')
     elif match_md:
         fn, sym, line, col, text = match_md.group('fn', 'sym', 'line', 'col', 'text')
         # unescape some chars
         fn = (fn.replace('\\(', '(').replace('\\)', ')'))
     elif match_wiki:
         fn   = match_wiki.group('fn')
         sym  = match_wiki.group('sym') or match_wiki.group('symn')
         line = match_wiki.group('line') or match_wiki.group('linen')
         col  = match_wiki.group('col') or match_wiki.group('coln')
         text = match_wiki.group('text') or match_wiki.group('textn')
         # unescape some chars
         fn   = (fn.replace('\\[', '[').replace('\\]', ']'))
         if text:
             text = (text.replace('\\[', '[').replace('\\]', ']'))
     if fn:
         self.show_panel_or_open(fn, sym, line, col, text)
         if text:
             sublime.set_timeout(lambda: self.find_text(self.opened_file, text, line), 300)
     else:
         sublime.status_message('Line does not contain a valid link to file')
Example #11
0
 def __init__(self, threads, message, success_message):
     self.threads = threads
     self.message = message
     self.success_message = success_message
     self.addend = 1
     self.size = 15
     sublime.set_timeout(lambda: self.run(0), 100)
Example #12
0
    def create_class_file(self, info):
        """
        Create a specified Java class and returns the status

        @param info: class informations
        """
        contents = self.get_file_contents(info)
        if contents is None:
            return False
        if os.path.exists(info["file"]):
            sublime.error_message(
                "{class_type} \"{class_name}\" already exists".format_map({
                    "class_type": self.args["create_type"],
                    "class_name": info["class_name"]
                })
            )
            return False
        open(info["file"], "w").close()
        view = sublime.active_window().open_file(info["file"])
        view.set_syntax_file("Packages/Java/Java.tmLanguage")
        # File Header override
        view.settings().set("enable_add_template_to_empty_file", False)
        sublime.set_timeout(
            lambda: self.insert_and_save(view, contents, info),
            100
        )
        return True
Example #13
0
    def on_done(self, text=""):
        """
        Create a class with informations from the input text

        @param text: text from input panel
        """
        self.hide_status()
        info = self.parse_create(text)
        if isinstance(info, str):
            sublime.error_message(info)
            return
        ActionHistory().add_action(
            "javatar.commands.create.create_class.on_done",
            "Create [info={info}]".format_map({
                "info": info
            })
        )
        if JavaUtils().create_package_path(
                info["directory"], True) == JavaUtils().CREATE_ERROR:
            return

        if self.create_class_file(info):
            sublime.set_timeout(lambda: StatusManager().show_status(
                "{class_type} \"{class_name}\" is created within".format_map({
                    "class_type": self.args["create_type"],
                    "class_name": info["class_name"]
                }) + " package \"{readable_package_path}\"".format_map({
                    "readable_package_path": JavaUtils().to_readable_class_path(
                        info["package"].as_class_path(),
                        as_class_path=True
                    )
                })
            ), 500)
    def on_select_action(self, selected_index):
        """Triggers on select from quick panel."""

        if selected_index == -1:
            return

        # Create new file
        elif selected_index == 0:
            # TODO: Set Syntax of the new file to be python
            view = self.view.window().new_file()

            # Append snippet to the view
            sublime.set_timeout(
                lambda: self._append_snippet(view, new=True), 10)

        # Select existing file
        else:
            # Subtract one to account for the "Create file" item
            directory_index = selected_index - 1

            current_root = self.view.window().folders()[0]

            # The paths are relative to the project root
            file_directory = os.path.join(
                current_root,
                self.step_file_paths[directory_index])
            view = self.view.window().open_file(file_directory)

            # Append snippet to the view
            sublime.set_timeout(lambda: self._append_snippet(view), 10)
Example #15
0
    def handle_threads(self, edit, threads, selections, offset = 0, i = 0, dir = 1):

        next_threads = []
        for thread in threads:
            if thread.is_alive():
                next_threads.append(thread)
                continue
            if thread.result == False:
                continue
            self.handle_result(edit, thread, selections, offset)
        threads = next_threads

        if len(threads):
            before = i % 8
            after = (7) - before

            dir = -1 if not after else dir
            dir = 1 if not before else dir

            i += dir

            self.view.set_status('minify', '[%s=%s]' % (' ' * before, ' ' * after))

            sublime.set_timeout(lambda: self.handle_threads(edit, threads, selections, offset, i, dir), 100)
            return

        self.view.erase_status('minify')
        sublime.status_message('Successfully minified')
Example #16
0
def open_file(file_path, view_settings, callback):
    """
    Open a file in Sublime Text, sets settings on the view and then executes
    the callback once the file is opened

    :param file_path:
        A unicode string of the path to the file to open

    :param view_settings:
        A dict of settings to set the "golang" key of the view's settings to

    :param callback:
        The callback to execute in the UI thread once the file is opened
    """

    result_queue = Queue()
    file_param = file_path
    if sys.platform == 'win32':
        file_param = re.sub('^([a-zA-Z]):', '/\\1', file_param)
        file_param = file_param.replace('\\', '/')

    def open_file_callback():
        window = sublime.active_window()

        window.run_command(
            'open_file',
            {
                'file': file_param
            }
        )

        when_file_opened(window, file_path, view_settings, callback, result_queue)
    sublime.set_timeout(open_file_callback, 50)
    return result_queue
Example #17
0
def when_file_opened(window, file_path, view_settings, callback, result_queue):
    """
    Periodic polling callback used by open_file() to find the newly-opened file

    :param window:
        The sublime.Window to look for the view in

    :param file_path:
        The file path of the file that was opened

    :param view_settings:
        A dict of settings to set to the view's "golang" setting key

    :param callback:
        The callback to execute when the file is opened

    :param result_queue:
        A Queue() object the callback can use to communicate with the test
    """

    view = window.active_view()
    if view and view.file_name() == file_path:
        view.settings().set('golang', view_settings)
        callback(view, result_queue)
        return
    # If the view was not ready, retry a short while later
    sublime.set_timeout(lambda: when_file_opened(window, file_path, view_settings, callback, result_queue), 50)
Example #18
0
        def _run_build(view, result_queue):
            view.window().run_command('golang_build')

            def _cancel_build():
                view.window().run_command('golang_build_cancel')

            sublime.set_timeout(_cancel_build, 50)
Example #19
0
    def test_build_reopen(self):
        ensure_not_ui_thread()

        file_path = path.join(TEST_GOPATH, 'src', 'good', 'rune_len.go')

        def _run_build(view, result_queue):
            view.window().run_command('golang_build')

        result_queue = open_file(file_path, VIEW_SETTINGS, _run_build)
        result = wait_build(result_queue)
        self.assertEqual('success', result)

        time.sleep(0.4)

        def _hide_panel():
            sublime.active_window().run_command('hide_panel')
        sublime.set_timeout(_hide_panel, 1)

        time.sleep(0.4)
        self.assertTrue(confirm_user('Was the build output hidden?'))

        def _reopen_panel():
            sublime.active_window().run_command('golang_build_reopen')
        sublime.set_timeout(_reopen_panel, 1)

        time.sleep(0.4)
        self.assertTrue(confirm_user('Was the build output reopened?'))
Example #20
0
  def handle_threads(self, edit, threads, offset=0, i=0, dir=1):
    next_threads = []
    for thread in threads:
      if thread.is_alive():
        next_threads.append(thread)
        continue
      if thread.result == False:
        continue
      offset = self.replace(edit, thread, offset)

    threads = next_threads

    if len(threads):
      # This animates a little activity indicator in the status area
      before = i % 8
      after = (7) - before
      if not after:
        dir = -1
      if not before:
        dir = 1
      i += dir
      self.view.set_status('bitly', 'Bitly [%s=%s]' % (' ' * before, ' ' * after))

      sublime.set_timeout(lambda: self.handle_threads(edit, threads, offset, i, dir), 100)
      return

    self.view.end_edit(edit)

    self.view.erase_status('bitly')
    matches = len(self.urls)
    sublime.status_message('Bitly successfully run on %s selection%s' % (matches, '' if matches == 1 else 's'))
    def run(self):
        user_settings = os.path.join(
            sublime.packages_path(),
            "User",
            "LaTeXTools.sublime-settings"
        )

        load_default = False
        if not os.path.exists(user_settings):
            migrate = sublime.ok_cancel_dialog(
                'You do not currently have a personalized '
                'LaTeXTools.sublime-settings file.\n\n'
                'Create a copy of the default settings file in '
                'your User directory?'
            )

            if migrate:
                sublime.active_window().run_command('latextools_migrate')
            else:
                load_default = True

        self.view = sublime.active_window().open_file(user_settings)

        if load_default:
            sublime.set_timeout(self.set_content, 1)
Example #22
0
	def cb(res, err):
		out = '\n'.join(s for s in (res.get('out'), res.get('err'), err) if s)
		def f():
			gs.end(tid)
			push_output(view, rkey, out, hourglass_repl='| done: %s' % res.get('dur', ''))

		sublime.set_timeout(f, 0)
Example #23
0
	def lint_view(cls, view_id, filename, code, sections, callback):
		if view_id in cls.linters:
			selectors = Linter.get_selectors(view_id)

			linters = tuple(cls.linters[view_id])
			for linter in linters:
				if not linter.selector:
					linter.filename = filename
					linter.pre_lint(code)

			for sel, linter in selectors:
				if sel in sections:
					highlight = Highlight(code, scope=linter.scope, outline=linter.outline)
					errors = {}

					for line_offset, left, right in sections[sel]:
						highlight.shift(line_offset, left)
						linter.pre_lint(code[left:right], highlight=highlight)

						for line, error in linter.errors.items():
							errors[line+line_offset] = error

					linter.errors = errors

			# merge our result back to the main thread
			sublime.set_timeout(lambda: callback(linters[0].view, linters), 0)
    def output(self, stdout, stderr, q):
        errs = []

        for line in iter(stdout.readline, b''):
            if len(errs) == 0 and ('error' not in line.lower().decode('utf-8')):
                q.put(line)
                print(line.decode('utf-8'))
            else:
                errs.append(line)

            # print(str(line))

        for line in iter(stderr.readline, b''):
            errs.append(line)

        if len(errs) != 0:
            message = ''
            sublime.set_timeout(lambda: self.show_status('Error'), 0)
            for line in errs:
                message += line.decode('utf-8')

            sublime.error_message(message)
        else:
            sublime.set_timeout(lambda: self.show_status('Success'), 0)

        stderr.close()
        stdout.close()
 def run(self, edit):
     for region in self.view.sel():
         self.view.insert(edit, region.end(), ".")
     caret = self.view.sel()[0].begin()
     line = self.view.substr(sublime.Region(self.view.word(caret-1).a, caret))
     if member_regex.search(line) != None:
         sublime.set_timeout(self.delayed_complete, 1)
    def set_status(self):
        global server, client

        if server or client:
            if server:
                server_status = "running"
            else:
                server_status = "off"

            if client:
                host = client.socket.host
                state = client.state
                client_status = "client:%(host)s...%(state)s" % locals()
            else:
                client_status = "disconnected"

            status_value = "Collab (server:%(server_status)s; %(client_status)s)" % locals()
        else:
            status_value = ""

        def _set_status():
            for window in sublime.windows():
                for view in window.views():
                    view.set_status("collab_server_status", status_value)

        sublime.set_timeout(_set_status, 0)
    def run(self, paths=[]):
        self.paths = paths

        if (sys.version_info > (3, 0)):
            q = Queue()
        else:
            q = Queue.Queue()

        for path in self.paths:
            proc = subprocess.Popen(
                self.build_cmd(path),
                bufsize=bufsize,
                cwd=os.path.dirname(path),
                shell=True,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                close_fds=ON_POSIX)

            thread = Thread(
                target=self.output,
                args=(proc.stdout, proc.stderr, q))
            thread.daemon = True
            thread.start()

        self.thread = thread
        self.message = 'Compiling'
        self.addend = 1
        self.size = 8
        sublime.set_timeout(lambda: self.show_progress(0), 100)
 def read_handle(self, handle):
     chunk_size = 2 ** 13
     out = b''
     while True:
         try:
             data = os.read(handle.fileno(), chunk_size)
             # If exactly the requested number of bytes was
             # read, there may be more data, and the current
             # data may contain part of a multibyte char
             out += data
             if len(data) == chunk_size:
                 continue
             if data == b'' and out == b'':
                 raise IOError('EOF')
             # We pass out to a function to ensure the
             # timeout gets the value of out right now,
             # rather than a future (mutated) version
             self.queue_write(out.decode(self.encoding))
             if data == b'':
                 raise IOError('EOF')
             out = b''
         except (UnicodeDecodeError) as e:
             msg = 'Error decoding output using %s - %s'
             self.queue_write(msg  % (self.encoding, str(e)))
             break
         except (IOError):
             if self.killed:
                 msg = 'Cancelled'
             else:
                 msg = 'Finished'
             sublime.set_timeout(self.finished, 1)
             self.queue_write('\n[%s]' % msg)
             break
 def on_load(self, view):
     DbgPrint("ReadOnly Protect: on_load of view %d" %(view.id()))
     global config
     UpdateViewModeStatus(view, config.protect_mode, isFileReadonly(view))
     if(config.protect_mode == 1):
         sublime.set_timeout(lambda: start_polling(), 1000)
     DumpAll()
 def on_load(self, view):
     Pref.time = time()
     Pref.modified = True
     view.settings().set('function_name_status_row', -1)
     sublime.set_timeout(
         lambda: self.display_current_class_and_function(view,
             'on_load'), 0)
Example #31
0
def main_thread(fn):
    "Run function in main thread"
    return lambda *args, **kwargs: sublime.set_timeout(
        lambda: fn(*args, **kwargs), 0)
Example #32
0
    def __handle_compile_response(self, **kwargs):
        debug("HANDLING COMPILE!")
        debug(self.result)

        #diffing with server
        if 'actions' in self.result and util.to_bool(
                self.result['success']) == False:
            diff_merge_settings = config.settings.get(
                'mm_diff_server_conflicts', False)
            if diff_merge_settings:
                if sublime.ok_cancel_dialog(self.result["body"],
                                            self.result["actions"][0].title()):
                    self.__print_to_panel("Diffing with server")
                    th = MavensMateDiffThread(self.thread.window,
                                              self.thread.view,
                                              self.result['tmp_file_path'])
                    th.start()
                else:
                    self.__print_to_panel(self.result["actions"][1].title())
            else:
                if sublime.ok_cancel_dialog(self.result["body"],
                                            "Overwrite Server Copy"):
                    self.__print_to_panel("Overwriting server copy")
                    self.thread.params['action'] = 'overwrite'
                    if kwargs.get("callback", None) != None:
                        sublime.set_timeout(
                            lambda: self.callback('compile',
                                                  params=self.thread.params),
                            100)
                else:
                    self.__print_to_panel(self.result["actions"][1].title())
        else:
            try:
                if 'State' in self.result and self.result[
                        'State'] == 'Error' and 'ErrorMsg' in self.result:
                    self.__print_to_panel(
                        "[OPERATION FAILED]: {0}\n\n{1}".format(
                            self.result['ErrorMsg'],
                            'If you are having difficulty compiling, try toggling the mm_compile_with_tooling_api setting to \'false\' or cleaning your project.'
                        ))
                elif 'State' in self.result and self.result[
                        'State'] == 'Failed' and (
                            'CompilerErrors' in self.result
                            or 'DeployDetails' in self.result):
                    #here we're parsing a response from the tooling endpoint
                    isLegacy = False  #pre 30.0

                    if 'DeployDetails' in self.result:  #31.0 and up
                        errors = self.result['DeployDetails'][
                            'componentFailures']
                        lineKey = 'lineNumber'
                        colKey = 'columnNumber'
                    else:
                        errors = json.loads(self.result['CompilerErrors'])
                        isLegacy = True
                        lineKey = 'line'
                        colKey = 'column'

                    if type(errors) is not list:
                        errors = [errors]
                    if len(errors) > 0:
                        for e in errors:
                            line_col = ""
                            line, col = 1, 1
                            if lineKey in e:
                                if type(e[lineKey]) is list:
                                    line = int(e[lineKey][0])
                                else:
                                    line = int(e[lineKey])
                                line_col = ' (Line: ' + str(line)
                            if colKey in e:
                                if type(e[colKey]) is list:
                                    line = int(e[colKey][0])
                                else:
                                    col = int(e[colKey])
                                line_col += ', Column: ' + str(col)
                            if len(line_col):
                                line_col += ')'

                            #scroll to the line and column of the exception
                            #if settings.get('mm_compile_scroll_to_error', True):
                            #open file, if already open it will bring it to focus
                            #view = sublime.active_window().open_file(self.thread.active_file)
                            view = self.thread.view
                            pt = view.text_point(line - 1, col - 1)
                            view.sel().clear()
                            view.sel().add(sublime.Region(pt))
                            view.show(pt)
                            problem = e['problem']
                            if type(problem) is list:
                                problem = problem[0]
                            problem = html_parser.unescape(problem)
                            if isLegacy:
                                file_base_name = e['name']
                            else:
                                file_base_name = e['fileName']
                            if type(file_base_name) is list:
                                file_base_name = file_base_name[0]
                            #if self.thread.window.active_view().name():
                            current_active_view = sublime.active_window(
                            ).active_view()
                            if current_active_view.file_name() != None:
                                current_active_view_file_name = os.path.basename(
                                    current_active_view.file_name())
                                if "." in current_active_view_file_name:
                                    current_active_view_file_name = current_active_view_file_name.split(
                                        ".")[0]
                                debug(current_active_view_file_name)
                                debug(file_base_name)
                                if current_active_view_file_name != file_base_name:
                                    #this is the tooling api throwing a compile error against a different file
                                    msg = "[COMPILE FAILED]: ({0}) {1} {2}".format(
                                        file_base_name, problem, line_col)
                                    msg += "\n\nThe Tooling API has failed to compile a separate element of metadata in your current MetadataContainer. You can either:"
                                    msg += "\n1. Fix the compilation error on " + file_base_name
                                    msg += "\n2. Reset your MetadataContainer to clear this error: MavensMate > Utilities > Reset MetadataContainer"
                                    self.__print_to_panel(msg)
                                elif current_active_view_file_name == file_base_name:
                                    util.mark_line_numbers(
                                        self.thread.view, [line], "bookmark")
                                    self.__print_to_panel(
                                        "[COMPILE FAILED]: ({0}) {1} {2}".
                                        format(file_base_name, problem,
                                               line_col))
                    elif "ErrorMsg" in self.result:
                        msg = ''
                        if 'object has been modified on server' in self.result[
                                'ErrorMsg']:
                            msg = self.result[
                                'ErrorMsg'] + '. You may try resetting your MetadataContainer to clear this error: MavensMate > Utilities > Reset MetadataContainer.'
                        else:
                            msg = self.result['ErrorMsg']
                        self.__print_to_panel(
                            "[COMPILE FAILED]: {0}".format(msg))

                elif 'success' in self.result and util.to_bool(
                        self.result['success']) == False and (
                            ('messages' in self.result or 'Messages'
                             in self.result) or 'details' in self.result):
                    if 'details' in self.result and 'componentFailures' in self.result[
                            'details']:
                        self.result['messages'] = self.result['details'].pop(
                            'componentFailures')
                    elif 'Messages' in self.result:
                        self.result['messages'] = self.result.pop('Messages')

                    #here we're parsing a response from the metadata endpoint
                    failures = None
                    messages = self.result['messages']
                    if type(messages) is not list:
                        messages = [messages]

                    problems = 0
                    for m in messages:
                        if 'problem' in m:
                            problems += 1
                            break

                    if problems == 0:  #must not have been a compile error, must be a test run error
                        if 'runTestResult' in self.result:
                            if 'runTestResult' in self.result and 'failures' in self.result[
                                    'runTestResult'] and type(
                                        self.result['runTestResult']
                                        ['failures']) == list:
                                failures = self.result['runTestResult'][
                                    'failures']
                            elif 'failures' in self.result['runTestResult']:
                                failures = [
                                    self.result['runTestResult']['failures']
                                ]

                            if failures != None:
                                msg = ' [DEPLOYMENT FAILED]:'
                                for f in failures:
                                    msg += f['name'] + ', ' + f[
                                        'methodName'] + ': ' + f[
                                            'message'] + '\n'
                                    self.__print_to_panel(msg)
                        elif 'run_test_result' in self.result:
                            if 'run_test_result' in self.result and 'failures' in self.result[
                                    'run_test_result'] and type(
                                        self.result['run_test_result']
                                        ['failures']) == list:
                                failures = self.result['run_test_result'][
                                    'failures']
                            elif 'failures' in self.result['run_test_result']:
                                failures = [
                                    self.result['run_test_result']['failures']
                                ]

                            if failures != None:
                                msg = ' [DEPLOYMENT FAILED]:'
                                for f in failures:
                                    msg += f['name'] + ', ' + f[
                                        'methodName'] + ': ' + f[
                                            'message'] + '\n'
                                self.__print_to_panel(msg)
                    else:  #compile error, build error message
                        msg = ""
                        for m in messages:
                            if "success" in m and m["success"] == False:
                                line_col = ""
                                if 'lineNumber' in m:
                                    line_col = ' (Line: ' + m['lineNumber']
                                    util.mark_line_numbers(
                                        self.thread.view,
                                        [int(float(m['lineNumber']))],
                                        "bookmark")
                                if 'columnNumber' in m:
                                    line_col += ', Column: ' + m['columnNumber']
                                if len(line_col) > 0:
                                    line_col += ')'
                                filename = m['fileName']
                                filename = re.sub(r'unpackaged/[A-Z,a-z]*/',
                                                  '', filename)
                                msg += filename + ': ' + m[
                                    'problem'] + line_col + "\n"

                        self.__print_to_panel('[DEPLOYMENT FAILED]: ' + msg)

                elif 'success' in self.result and self.result[
                        "success"] == False and 'line' in self.result:
                    #this is a response from the apex compile api
                    line_col = ""
                    line, col = 1, 1
                    if 'line' in self.result:
                        line = int(self.result['line'])
                        line_col = ' (Line: ' + str(line)
                        util.mark_line_numbers(self.thread.view, [line],
                                               "bookmark")
                    if 'column' in self.result:
                        col = int(self.result['column'])
                        line_col += ', Column: ' + str(col)
                    if len(line_col):
                        line_col += ')'

                    #scroll to the line and column of the exception
                    if settings.get('mm_compile_scroll_to_error', True):
                        #open file, if already open it will bring it to focus
                        #view = sublime.active_window().open_file(self.thread.active_file)
                        view = self.thread.view
                        pt = view.text_point(line - 1, col - 1)
                        view.sel().clear()
                        view.sel().add(sublime.Region(pt))
                        view.show(pt)

                        self.__print_to_panel('[COMPILE FAILED]: ' +
                                              self.result['problem'] +
                                              line_col)
                elif 'success' in self.result and util.to_bool(
                        self.result['success']
                ) == True and 'Messages' in self.result and len(
                        self.result['Messages']) > 0:
                    msg = ' [Operation completed Successfully - With Compile Errors]\n'
                    msg += '[COMPILE ERRORS] - Count:\n'
                    for m in self.result['Messages']:
                        msg += ' FileName: ' + m['fileName'] + ': ' + m[
                            'problem'] + 'Line: ' + m['lineNumber']
                    self.__print_to_panel(msg)
                elif 'success' in self.result and util.to_bool(
                        self.result['success']) == True:
                    self.__print_to_panel("Success")
                elif 'success' in self.result and util.to_bool(
                        self.result['success']
                ) == False and 'body' in self.result:
                    self.__print_to_panel('[OPERATION FAILED]: ' +
                                          self.result['body'])
                elif 'success' in self.result and util.to_bool(
                        self.result['success']) == False:
                    self.__print_to_panel('[OPERATION FAILED]')
                else:
                    self.__print_to_panel("Success")
            except Exception as e:
                debug(e)
                debug(traceback.print_exc())
                debug(type(self.result))
                msg = ""
                if type(self.result) is dict:
                    if 'body' in self.result:
                        msg = self.result["body"]
                    else:
                        msg = json.dumps(self.result)
                elif type(self.result) is str:
                    try:
                        m = json.loads(self.result)
                        msg = m["body"]
                    except:
                        msg = self.result
                else:
                    msg = "Check Sublime Text console for error and report issue to MavensMate-SublimeText GitHub project."
                self.__print_to_panel('[OPERATION FAILED]: ' + msg)
Example #33
0
    def __handle_test_result(self):
        responses = []
        if len(self.result) == 1:
            res = self.result[0]
            response_string = ""
            if 'detailed_results' in res:
                all_tests_passed = True
                for r in res['detailed_results']:
                    if r["Outcome"] != "Pass":
                        all_tests_passed = False
                        break

                if all_tests_passed:
                    response_string += '[TEST RESULT]: PASS'
                else:
                    response_string += '[TEST RESULT]: FAIL'

                for r in res['detailed_results']:
                    if r["Outcome"] == "Pass":
                        pass  #dont need to write anything here...
                    else:
                        response_string += '\n\n'
                        rstring = " METHOD RESULT "
                        rstring += "\n"
                        rstring += "{0} : {1}".format(r["MethodName"],
                                                      r["Outcome"])

                        if "StackTrace" in r and r["StackTrace"] != None:
                            rstring += "\n\n"
                            rstring += " STACK TRACE "
                            rstring += "\n"
                            rstring += r["StackTrace"]

                        if "Message" in r and r["Message"] != None:
                            rstring += "\n\n"
                            rstring += " MESSAGE "
                            rstring += "\n"
                            rstring += r["Message"]
                            rstring += "\n"
                        #responses.append("{0} | {1} | {2} | {3}\n".format(r["MethodName"], r["Outcome"], r["StackTrace"], r["Message"]))
                        responses.append(rstring)
                response_string += "\n\n".join(responses)
                self.__print_to_panel(response_string)
                self.printer.scroll_to_bottom()
            else:
                self.__print_to_panel(json.dumps(self.result))
        elif len(self.result) > 1:
            #run multiple tests
            response_string = ''
            for res in self.result:
                if 'detailed_results' in res:
                    all_tests_passed = True
                    for r in res['detailed_results']:
                        if r["Outcome"] != "Pass":
                            all_tests_passed = False
                            break

                    if all_tests_passed:
                        response_string += res['ApexClass'][
                            'Name'] + ':\n\tTEST RESULT: PASS'
                    else:
                        response_string += res['ApexClass'][
                            'Name'] + ':\n\tTEST RESULT: FAIL'

                    for r in res['detailed_results']:
                        if r["Outcome"] == "Pass":
                            pass  #dont need to write anything here...
                        else:
                            response_string += '\n\n'
                            response_string += "\t METHOD RESULT "
                            response_string += "\t\n"
                            response_string += "\t{0} : {1}".format(
                                r["MethodName"], r["Outcome"])

                            if "StackTrace" in r and r["StackTrace"] != None:
                                response_string += "\n\n"
                                response_string += "\t STACK TRACE "
                                response_string += "\t\n"
                                response_string += "\t" + r[
                                    "StackTrace"].replace("\n", "\t\n")

                            if "Message" in r and r["Message"] != None:
                                response_string += "\n\n"
                                response_string += "\t MESSAGE "
                                response_string += "\t\n"
                                response_string += "\t" + r["Message"].replace(
                                    "\n", "\t\n")
                                response_string += "\n"
                response_string += "\n\n"
            #self.__print_to_panel(response_string)
            #self.printer.scroll_to_bottom()

            self.__print_to_panel('Success')
            new_view = self.thread.window.new_file()
            new_view.set_scratch(True)
            new_view.set_name("Run All Tests Result")
            if "linux" in sys.platform or "darwin" in sys.platform:
                new_view.set_syntax_file(
                    os.path.join("Packages", "YAML", "YAML.tmLanguage"))
                new_view.set_syntax_file(
                    os.path.join("Packages", "MavensMate", "sublime", "panel",
                                 "MavensMate.hidden-tmLanguage"))
            else:
                new_view.set_syntax_file(
                    os.path.join(
                        "Packages/MavensMate/sublime/panel/MavensMate.hidden-tmLanguage"
                    ))

            sublime.set_timeout(
                new_view.run_command('generic_text',
                                     {'text': response_string}), 1)

        elif 'body' in self.result:
            self.__print_to_panel(json.dumps(self.result['body']))
Example #34
0
    def queue_request(self, worker, handler):
        log.debug('In queue_request for work scheduler')

        # Use nested functions to close over the worker and handler parameters

        def work_done(results):
            """ Called when the scheduled work item is complete

            This function does some bookkeeping before calling the completion
            handler provided when the job was queued.
            """
            log.debug('In work_done for work scheduler')
            end_time = time.time()
            canceled = False
            with self.lock:
                self.last_cost = end_time - self.last_time
                self.job_running = False
                canceled = self.canceled
            log.debug('Work took {0:d}ms'.format(int(self.last_cost * 1000)))
            if not canceled:
                # Post the response to the handler on the main thread
                sublime.set_timeout(lambda: handler(results), 0)

        def do_work():
            """ Called to execute the worker callback provided

            This function closes over the worker callback provided, and is
            stored in the slot for the queued work item (self.next_job).
            """
            log.debug('In do_work for work scheduler')
            start_time = time.time()
            canceled = False
            with self.lock:
                self.last_time = start_time
                canceled = self.canceled
                if canceled:
                    self.job_running = False
            if not canceled:
                worker(work_done)

        def on_scheduled():
            """ This function is called by the scheduler when the timeout fires

            This pulls the queued work-item from self.next_job, which is an
            instance of 'do_work' above, and executes it.
            """
            log.debug('In on_scheduled for work scheduler')
            job = None
            job_running = False
            with self.lock:
                if self.job_running:
                    job_running = True
                else:
                    # Get the job to run if not canceled, and reset timer state
                    if not self.canceled:
                        job = self.next_job
                    if job:
                        # There will be a job running when this function exits
                        self.job_running = True
                    self.timer_set = False
                    self.next_job = None
            if job_running:
                # Defer 50ms until current job completes.
                log.debug('Timer elapsed while prior job running.  Deferring')
                sublime.set_timeout(on_scheduled, 50)
            else:
                if job:
                    job()

        # When to set the timer for next.
        delta_ms = 0
        job_scheduled = False
        curr_time = time.time()

        with self.lock:
            # Ensure queued job is this job and state is not canceled
            self.next_job = do_work
            self.canceled = False
            job_scheduled = self.timer_set
            if not self.timer_set:
                # How long to defer execution. Use last cost as basis
                if self.last_cost:
                    min_delay = self.last_cost * 3
                    next_time = self.last_time + min_delay
                    delta_ms = int((next_time - curr_time) * 1000)
                else:
                    delta_ms = 33
            self.timer_set = True  # Will be before this function returns

        if not job_scheduled:
            # Ensure no less that 33ms, and no more than 500ms
            delta_ms = max(33, delta_ms)
            delta_ms = min(500, delta_ms)
            # Run whatever is the 'next_job' when scheduler is due
            log.debug('Scheduling job for {0}ms'.format(delta_ms))
            sublime.set_timeout(on_scheduled, delta_ms)
        else:
            log.debug('Job already scheduled')
 def setup_view(self, view):
     if not view.is_loading():
         view.set_read_only(False)
         view.run_command("save")
     else:
         sublime.set_timeout(lambda: self.setup_view(view), 15)
 def setup_view(self, view):
     if not view.is_loading():
         view.set_read_only(True)
         view.set_scratch(True)
     else:
         sublime.set_timeout(lambda: self.setup_view(view), 10)
 def insert_text(self, content, view):
     if not view.is_loading():
         view.run_command("insert_content", {"content": content})
         view.settings().set("buffer_empty", False)
     else:
         sublime.set_timeout(lambda: self.insert_text(content, view), 10)
 def go_to_kw(self, file_path, regex):
     new_view = self.view.window().open_file(file_path)
     sublime.set_timeout(lambda: self.select_keyword(new_view, regex), 10)
Example #39
0
def status_message(msg):
    """Workaround for osx run_on_main_thread problem"""
    sublime.set_timeout(functools.partial(sublime.status_message, msg), 0)
Example #40
0
def st_status_message(msg):
    sublime.set_timeout(
        lambda: sublime.status_message('{0}: {1}'.format('JsPretter', msg)), 0)
Example #41
0
 def _show_quick_panel(self, options, done):
     if is_st3():
         sublime.set_timeout(lambda: self.window.show_quick_panel(options, done), 10)
     else:
         self.window.show_quick_panel(options, done)
Example #42
0
def sched_sm_cb():
    sublime.set_timeout(sm_cb, 250)
Example #43
0
 def sent(self):
     sublime.set_timeout(self.set_status_bar, 0)
     sublime.set_timeout(self.set_last_heartbeat, 0)
 def show_quick_panel(self, options, done):
     sublime.set_timeout(
         lambda: self.window.show_quick_panel(options, done), 10)
Example #45
0
    ctx.load_user_data(json.dumps(payload))


# load settings
settings = sublime.load_settings('Emmet.sublime-settings')
settings.add_on_change('extensions_path', update_settings)

# provide some contributions to JS
contrib = {'sublime': sublime, 'sublimeReplaceSubstring': replace_substring}

# create JS environment
ctx = Context(['../editor.js'], settings.get('extensions_path', None), contrib)

update_settings()

sublime.set_timeout(cmpl.remove_html_completions, 2000)


class RunEmmetAction(sublime_plugin.TextCommand):
    def run(self, edit, action=None, **kw):
        run_action(lambda i, sel: ctx.js().locals.pyRunAction(action))
        # ctx.js().locals.pyRunAction(action)


def run_action(action, view=None):
    "Runs Emmet action in multiselection mode"
    if not view:
        view = active_view()

    region_key = '__emmet__'
    sels = list(view.sel())
Example #46
0
def after_loaded():
    if not prompt_api_key():
        sublime.set_timeout(after_loaded, 500)
Example #47
0
 def add_callback(self, view, error, doc):
     if error:
         sublime.error_message("Error adding document: {0}".format(error))
     else:
         sublime.set_timeout(lambda: self.add_editor(view, doc), 0)
Example #48
0
 def undo(self):
     if self.erase:
         sublime.set_timeout(lambda: self.view.run_command('undo'), 0)
Example #49
0
 def _on_doc_remoteop(self, op, old_snapshot):
     sublime.set_timeout(lambda: self._apply_remoteop(op), 0)
Example #50
0
 def focus(self):
     sublime.set_timeout(lambda: sublime.active_window().focus_view(self.view), 0)
 def handle_file_open_go_to(self, line):
     if not self.active_view().is_loading():
         self.active_view().run_command('goto_line', {'line': line})
     else:
         sublime.set_timeout(lambda: self.handle_file_open_go_to(line), 100)
Example #52
0
 def open_callback(self, error, doc):
     if error:
         sublime.error_message("Error opening document: {0}".format(error))
     else:
         sublime.set_timeout(lambda: self.create_editor(doc), 0)
Example #53
0
def get_real_path(uri, server=False):
    """
    Get real path

    Keyword arguments:
    uri -- Uri of file that needs to be mapped and located
    server -- Map local path to server path

    TODO: Fix mapping for root (/) and drive letters (P:/)
    """
    if uri is None:
        return uri

    # URLdecode uri
    uri = H.url_decode(uri)

    # Split scheme from uri to get absolute path
    try:
        # scheme:///path/file => scheme, /path/file
        # scheme:///C:/path/file => scheme, C:/path/file
        transport, filename = uri.split(':///', 1)
    except:
        filename = uri

    # Normalize path for comparison and remove duplicate/trailing slashes
    uri = os.path.normpath(filename)

    # Pattern for checking if uri is a windows path
    drive_pattern = re.compile(r'^[a-zA-Z]:[\\/]')

    # Append leading slash if filesystem is not Windows
    if not drive_pattern.match(uri) and not os.path.isabs(uri):
        uri = os.path.normpath('/' + uri)

    path_mapping = get_value(S.KEY_PATH_MAPPING)
    if isinstance(path_mapping, dict):
        # Go through path mappings
        for server_path, local_path in path_mapping.items():
            server_path = os.path.normpath(server_path)
            local_path = os.path.normpath(local_path)
            # Replace path if mapping available
            if server:
                # Map local path to server path
                if local_path in uri:
                    uri = uri.replace(local_path, server_path)
                    break
            else:
                # Map server path to local path
                if server_path in uri:
                    uri = uri.replace(server_path, local_path)
                    break
    else:
        sublime.set_timeout(
            lambda: sublime.status_message(
                "Xdebug: No path mapping defined, returning given path."), 100)

    # Replace slashes
    if not drive_pattern.match(uri):
        uri = uri.replace("\\", "/")

    # Append scheme
    if server:
        return H.url_encode("file://" + uri)

    return uri
Example #54
0
 def poll_copy(self):
     # FIXME HACK: Stop polling after one minute
     if self.active_for < 60000:
         self.active_for += 50
         sublime.set_timeout(self.copy_stuff, 50)
Example #55
0
 def show_panel(self):
     folder_name_list = app.fileutil.getFolderNameList(self.folder_list)
     sublime.set_timeout(
         lambda: self.window.show_quick_panel(folder_name_list, self.on_done
                                              ), 10)
Example #56
0
 def handle_runer(self):
     if (self.runner.is_alive()):
         sublime.set_timeout(lambda: self.handle_runer(), 100)
     else:
         self.handel_output(self.runner.output, self.temp_file_path)
 def finish(self, can_switch_to_pdf):
     sublime.set_timeout(
         functools.partial(self.do_finish, can_switch_to_pdf), 0)
 def run(self):
     sublime.set_timeout(
         lambda: self.method(self.view, self.results, self.action), 50)
 def output(self, data):
     sublime.set_timeout(functools.partial(self.do_output, data), 0)
    def run(self):
        print("Welcome to thread " + self.getName())
        self.caller.output("[Compiling " + self.caller.file_name + "]")

        # Handle custom env variables
        if self.caller.env:
            old_env = os.environ
            if not _ST3:
                os.environ.update(
                    dict((k.encode(sys.getfilesystemencoding()), v)
                         for (k, v) in self.caller.env.items()))
            else:
                os.environ.update(self.caller.env.items())

        # Handle path; copied from exec.py
        if self.caller.path:
            # if we had an env, the old path is already backuped in the env
            if not self.caller.env:
                old_path = os.environ["PATH"]
            # The user decides in the build system  whether he wants to append $PATH
            # or tuck it at the front: "$PATH;C:\\new\\path", "C:\\new\\path;$PATH"
            # Handle differently in Python 2 and 3, to be safe:
            if not _ST3:
                os.environ["PATH"] = os.path.expandvars(
                    self.caller.path).encode(sys.getfilesystemencoding())
            else:
                os.environ["PATH"] = os.path.expandvars(self.caller.path)

        # Set up Windows-specific parameters
        if self.caller.plat == "windows":
            # make sure console does not come up
            startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW

        # Now, iteratively call the builder iterator
        #
        cmd_iterator = self.caller.builder.commands()
        try:
            for (cmd, msg) in cmd_iterator:

                # If there is a message, display it
                if msg:
                    self.caller.output(msg)

                # If there is nothing to be done, exit loop
                # (Avoids error with empty cmd_iterator)
                if cmd == "":
                    break

                if isinstance(cmd, strbase) or isinstance(cmd, list):
                    print(cmd)
                    # Now create a Popen object
                    try:
                        if self.caller.plat == "windows":
                            proc = subprocess.Popen(cmd,
                                                    startupinfo=startupinfo,
                                                    stderr=subprocess.STDOUT,
                                                    stdout=subprocess.PIPE,
                                                    cwd=self.caller.tex_dir)
                        elif self.caller.plat == "osx":
                            proc = subprocess.Popen(cmd,
                                                    stderr=subprocess.STDOUT,
                                                    stdout=subprocess.PIPE,
                                                    env=os.environ,
                                                    preexec_fn=os.setsid,
                                                    cwd=self.caller.tex_dir)
                        else:  # Must be linux
                            proc = subprocess.Popen(cmd,
                                                    stderr=subprocess.STDOUT,
                                                    stdout=subprocess.PIPE,
                                                    preexec_fn=os.setsid,
                                                    cwd=self.caller.tex_dir)
                    except:
                        self.caller.output("\n\nCOULD NOT COMPILE!\n\n")
                        self.caller.output("Attempted command:")
                        self.caller.output(" ".join(cmd))
                        self.caller.output("\nBuild engine: " +
                                           self.caller.builder.name)
                        self.caller.proc = None
                        print(traceback.format_exc())
                        return
                # Abundance of caution / for possible future extensions:
                elif isinstance(cmd, subprocess.Popen):
                    proc = cmd
                else:
                    # don't know what the command is
                    continue

                # Now actually invoke the command, making sure we allow for killing
                # First, save process handle into caller; then communicate (which blocks)
                with self.caller.proc_lock:
                    self.caller.proc = proc
                out, err = proc.communicate()
                self.caller.builder.set_output(
                    out.decode(self.caller.encoding, "ignore"))

                # Here the process terminated, but it may have been killed. If so, stop and don't read log
                # Since we set self.caller.proc above, if it is None, the process must have been killed.
                # TODO: clean up?
                with self.caller.proc_lock:
                    if not self.caller.proc:
                        print(proc.returncode)
                        self.caller.output(
                            "\n\n[User terminated compilation process]\n")
                        self.caller.finish(
                            False)  # We kill, so won't switch to PDF anyway
                        return
                # Here we are done cleanly:
                with self.caller.proc_lock:
                    self.caller.proc = None
                print("Finished normally")
                print(proc.returncode)
                # At this point, out contains the output from the current command;
                # we pass it to the cmd_iterator and get the next command, until completion
        except:
            self.caller.output("\n\nCOULD NOT COMPILE!\n\n")
            self.caller.output("\nBuild engine: " + self.caller.builder.name)
            self.caller.proc = None
            print(traceback.format_exc())
            return
        finally:
            # restore environment
            if self.caller.env:
                os.environ = old_env
            elif self.caller.path:
                os.environ['PATH'] = old_path

        # Clean up
        cmd_iterator.close()

        try:
            # Here we try to find the log file...
            # 1. Check the aux_directory if there is one
            # 2. Check the output_directory if there is one
            # 3. Assume the log file is in the same folder as the main file
            log_file_base = self.caller.tex_base + ".log"
            if self.caller.aux_directory is None:
                if self.caller.output_directory is None:
                    log_file = os.path.join(self.caller.tex_dir, log_file_base)
                else:
                    log_file = os.path.join(self.caller.output_directory,
                                            log_file_base)

                    if not os.path.exists(log_file):
                        log_file = os.path.join(self.caller.tex_dir,
                                                log_file_base)
            else:
                log_file = os.path.join(self.caller.aux_directory,
                                        log_file_base)

                if not os.path.exists(log_file):
                    if (self.caller.output_directory is not None
                            and self.caller.output_directory !=
                            self.caller.aux_directory):
                        log_file = os.path.join(self.caller.output_directory,
                                                log_file_base)

                    if not os.path.exists(log_file):
                        log_file = os.path.join(self.caller.tex_dir,
                                                log_file_base)

            # CHANGED 12-10-27. OK, here's the deal. We must open in binary mode
            # on Windows because silly MiKTeX inserts ASCII control characters in
            # over/underfull warnings. In particular it inserts EOFs, which
            # stop reading altogether; reading in binary prevents that. However,
            # that's not the whole story: if a FS character is encountered,
            # AND if we invoke splitlines on a STRING, it sadly breaks the line
            # in two. This messes up line numbers in error reports. If, on the
            # other hand, we invoke splitlines on a byte array (? whatever read()
            # returns), this does not happen---we only break at \n, etc.
            # However, we must still decode the resulting lines using the relevant
            # encoding.

            # Note to self: need to think whether we don't want to codecs.open
            # this, too... Also, we may want to move part of this logic to the
            # builder...
            with open(log_file, 'rb') as f:
                data = f.read()
        except IOError:
            self.caller.output([
                "",
                ""
                "Could not find log file {0}!".format(log_file_base),
            ])
            try:
                self.handle_std_outputs(out, err)
            except:
                # if out or err don't yet exist
                self.caller.finish(False)
        else:
            errors = []
            warnings = []
            badboxes = []

            try:
                (errors, warnings, badboxes) = parseTeXlog.parse_tex_log(data)
                content = [""]
                if errors:
                    content.append("Errors:")
                    content.append("")
                    content.extend(errors)
                else:
                    content.append("No errors.")
                if warnings:
                    if errors:
                        content.extend(["", "Warnings:"])
                    else:
                        content[-1] = content[-1] + " Warnings:"
                    content.append("")
                    content.extend(warnings)
                else:
                    if errors:
                        content.append("")
                    content.append("No warnings.")

                if badboxes and self.caller.display_bad_boxes:
                    if warnings or errors:
                        content.extend(["", "Bad Boxes:"])
                    else:
                        content[-1] = content[-1] + " Bad Boxes:"
                    content.append("")
                    content.extend(badboxes)
                else:
                    if self.caller.display_bad_boxes:
                        if errors or warnings:
                            content.append("")
                        content.append("No bad boxes.")

                hide_panel = {
                 "always": True,
                 "no_errors": not errors,
                 "no_warnings": not errors and not warnings,
                 "no_badboxes": not errors and not warnings and \
                  (not self.caller.display_bad_boxes or not badboxes),
                 "never": False
                }.get(self.caller.hide_panel_level, False)

                if hide_panel:
                    # hide the build panel (ST2 api is not thread save)
                    if _ST3:
                        self.caller.window.run_command(
                            "hide_panel", {"panel": "output.latextools"})
                    else:
                        sublime.set_timeout(
                            lambda: self.caller.window.run_command(
                                "hide_panel", {"panel": "output.latextools"}),
                            10)
                    message = "build completed"
                    if errors:
                        message += " with errors"
                    if warnings:
                        if errors:
                            if badboxes and self.caller.display_bad_boxes:
                                message += ","
                            else:
                                message += " and"
                        else:
                            message += " with"
                        message += " warnings"
                    if badboxes and self.caller.display_bad_boxes:
                        if errors or warnings:
                            message += " and"
                        else:
                            message += " with"
                        message += " bad boxes"

                    if _ST3:
                        sublime.status_message(message)
                    else:
                        sublime.set_timeout(
                            lambda: sublime.status_message(message), 10)
            except Exception as e:
                # dumpt exception to console
                traceback.print_exc()

                content = ["", ""]
                content.append(
                    "LaTeXTools could not parse the TeX log file {0}".format(
                        log_file))
                content.append("(actually, we never should have gotten here)")
                content.append("")
                content.append("Python exception: {0!r}".format(e))
                content.append("")
                content.append(
                    "The full error description can be found on the console.")
                content.append("Please let us know on GitHub. Thanks!")

            self.caller.output(content)
            self.caller.output("\n\n[Done!]\n")
            self.caller.finish(len(errors) == 0)