Пример #1
0
    def format(self, s):
        self.code_blocks = []

        # first, temporarily remove any code blocks,
        # as we don't want them formatted
        s = self.FENCED_RE.sub(self._remove_code_block, s)
        s = self.CODE_RE.sub(self._remove_code_inline, s)
        s = self.INDENTED_RE.sub(self._remove_code_indented, s)

        # first find bold, and then italic, then the rest
        s = self.BOLD_RE.sub('\x02\x01\\g<text>\x03', s)
        s = self.ITALICS_RE.sub('\x02\x04\\g<text>\x03', s)
        s = self.HIGHLIGHT_RE.sub('\x02\x05\\g<text>\x03', s)
        s = self.UNDERLINE_RE.sub('\x02\x06\\g<text>\x03', s)
        s = self.STRIKETHROUGH_RE.sub('\x02\x07\\g<text>\x03', s)

        # Find and format headers
        s = self.HEADER_RE1.sub(ansi.with_codes(r'\g<start> \g<name> \g<end>',
                                1), s)
        s = self.HEADER_RE2.sub(ansi.with_codes('\\g<text>\n\\g<underline>',
                                1), s)

        # now return everything to normal, with the ANSI encoding
        s = self.AFTER_RE.sub(self._add_ansi_formatting, s)

        return s
Пример #2
0
    def _add_ansi_formatting(self, match):
        sub_code = match.group('code')
        multiline = False
        prefix = None

        if sub_code in ('\x1C', '\x1E'):
            # deal with the special code blocks thing
            block_num = int(match.group('text'))
            inner_text = self.code_blocks[block_num]
            if sub_code == '\x1E':
                multiline = True
                prefix = ''
        elif sub_code == '\x1D':
            block_num = int(match.group('text'))
            prefix, inner_text = self.code_blocks[block_num]
            multiline = True
        else:
            inner_text = match.group('text')

        if multiline:
            prefix_codes, codes = self.FORMAT_CODES[sub_code]
            if isinstance(prefix_codes, int):
                prefix_codes = [prefix_codes]
        else:
            codes = self.FORMAT_CODES[sub_code]

        if isinstance(codes, int):
            codes = [codes]

        if multiline:
            chars, line_chars = self.FORMAT_CHARS[sub_code]
        else:
            chars = self.FORMAT_CHARS[sub_code]

        text = chars + inner_text + chars

        if multiline:
            raw_lines = text.splitlines()
            max_len = max(len(line) for line in raw_lines)

            res_lines = [("{1}{0: <%s}{1}" % max_len).format(line, line_chars)
                         for line in raw_lines]

            res = '\n'.join(ansi.with_codes(line, *codes)
                            for line in res_lines)
        else:
            res = ansi.with_codes(text, *codes)

        if multiline and prefix is not None:
            prefix_raw = ('{1}{0: <%s}{1}' % max_len).format(prefix,
                                                             line_chars)
            res = '%s\n%s' % (ansi.with_codes(prefix_raw, *prefix_codes), res)

        return res
Пример #3
0
    def _process_code_line(self, line, res, more):
        if self._readline is not None:
            self._readline.add_history(line)

        if more:
            self.write(sys.ps2)
        else:
            self.write(sys.ps1)

        if self.use_ansi:
            self.write(ansi.with_codes(line, 38, 5, 0xdf))
        else:
            self.write(line)

        self.write("\n")
        with self._capture_output() as output:
            more = self.push(line)

            res += output.getvalue()
            output.truncate(0)

        exc = self.exc_msg
        self.exc_msg = None
        return (res, exc, more)
Пример #4
0
    def interact(self, lit_string, name, pause=True, interactive=True):
        self.name = name
        self.pause = pause
        self.interactive = interactive

        try:
            sys.ps1
        except AttributeError:
            sys.ps1 = ">>> "

        try:
            sys.ps2
        except AttributeError:
            sys.ps2 = "... "

        try:
            sys.ps3
        except AttributeError:
            sys.ps3 = '>>> '

        if self._env_driver is not None:
            extra_locals = self._env_driver.setup()
            self.locals.update(extra_locals)
            extra_banner = self._env_driver.banner
            driver_text = " ({0})".format(self._env_driver.DRIVER_NAME)
        else:
            extra_banner = ""
            driver_text = ""

        cprt = ('Type "help", "copyright", "credits" or "license" for '
                'more information about Python.')
        self.write("Literate Python Shell{driver_text}\nPython {ver} "
                   "on {platform}\n{cprt}\n"
                   "{extra_banner}\n\n".format(driver_text=driver_text,
                                               ver=sys.version,
                                               platform=sys.platform,
                                               cprt=cprt,
                                               extra_banner=extra_banner))

        if not interactive and pause:
            self.write('Press enter to continue after a code block\n\n')

        try:
            parser = self.code_parser
            start = True
            self.chunks = list(parser.parse(lit_string, name))
            for chunk_ind, chunk in enumerate(self.chunks):
                if isinstance(chunk, parsers.CodeChunk):
                    self._run_code(chunk, chunk_ind)
                elif not chunk:
                    continue
                else:
                    if not start and pause and interactive:
                        self.filename = "<stdin>"
                        more = False
                        blanks = 0
                        while blanks < 2:
                            blank, more = self._interact_once(more)

                            if blank:
                                blanks += 1
                            else:
                                blanks = 0

                            if more is None:
                                return

                        # reset exc_msg so it doesn't get
                        # raised after the next code block
                        self.exc_msg = None
                    elif not start and pause:
                        self.no_echo_input(sys.ps3)

                    self.write(self.text_formatter.format(chunk))

                start = False

            complete_msg = ("\n{file} complete! Continuing to interactive "
                            "console...\n\n".format(file=self.name))

            if self.use_ansi:
                self.write(ansi.with_codes(complete_msg, 1))
            else:
                self.write(complete_msg)

            self.filename = "<stdin>"
            self.locals['con'] = self
            more = False
            while more is not None:
                blank, more = self._interact_once(more)
        finally:
            if self._env_driver is not None:
                self._env_driver.teardown()