Exemplo n.º 1
0
    def __init__(
        self, text, mark_sequence, text_plane=None, context=None, starting_point=None
    ):
        """
        Args:
          text (Sequence): the stream of characters to be rendered  - it can be a string or a list of 1-grapheme strings.
          mark_sequence (Mapping): A mappign with Mark objects. The keys either represent index positions on the text
            where the mark will be processed, or they can be at the special index "config" denoting marks
            that are to have their indexes processed according to other enviroment circunstances
            (like the current "tick" - and possibly 'current position')
            The value at each item can contain a single Mark or a of Markers.
          text_plane (terminedia.text.planes.TextPlane): area where the output is to be rendered
            on iterating. The Text object will be searched for aditional "Mark" objects that
            will compose the syle and position when encountered (they are less
            prioritary than the Marks passed in mark_sequence)
            If no Text object is given, the instance may still be iterated to retrieve
            a sequence of char, context and position - for example, when generating
            output directly to a tty.
          context (terminedia.Context): parent context. By default the context
          attached to the given text_plane is used
          starting_point: first position to be yielded when iteration starts (from which
            rules apply according to context.direction and others given by the matched
            "Mark" objects. Defaults to (0, 0)



        Helper class to render text that will both hold embedded style information,
        conveyed in "Mark" objects (with information like "at position 10, push foreground color 'red'"),
        and respect Mark objects embedded in the "text_plane" associanted rendering space.

        Style changes are all on top of a given "parent context"
        if any (otherwise, the text_plane context is used, or None)

        The rendering part include yielding the proper position of each
        rendering character,as contexts convey also
        text printing direction and marks can not only
        push a new printing direction, but also "teleport" the
        rendering point for the next character altogether.

        """
        self.text = text
        self.mark_sequence = mark_sequence
        self.parent_context = context
        self._last_index_processed = None
        self.context = Context()
        self.text_plane = text_plane
        self.starting_point = V2(starting_point) if starting_point else V2(0, 0)
        self.current_position = self.starting_point
        self._sanity_counter = 0
        self.locals = threading.local()
        if isinstance(text, GraphemeIter):
            self.cooked_text = text
        else:
            new_text = self.cooked_text = GraphemeIter(text)
            # adjust mark items to match graphemes instead of characters:
            sorted_old_keys = sorted(key for key in mark_sequence.keys() if isinstance(key, int))
            new_keys = {old_key: new_key for old_key, new_key in zip(
                sorted_old_keys, new_text.iter_cooked_indexes(sorted_old_keys)
            )}
            self.mark_sequence = {new_keys.get(old_key, old_key): value for old_key, value in mark_sequence.items()}
Exemplo n.º 2
0
    def __init__(self, size=(), clear_screen=True, backend="ansi"):
        if not size:
            #: Set in runtime to a method to retrieve the screen width, height.
            #: The class is **not** aware of terminal resizings while running, though.
            self.get_size = lambda: V2(os.get_terminal_size())
            try:
                size = self.get_size()
            except OSError as error:
                if error.errno == 25:
                    logger.error(
                        "This terminal type does not allow guessing screen size."
                        "Pass an explicit (cols, rows) size when instantiating {self.__class__}"
                    )
                raise
        else:
            self.get_size = lambda: V2(size)

        #: Namespace to configure drawing and printing color and other parameters.
        #: Currently, the attributes that are used from here are
        #: ``color``, ``background``, ``direction``, ``effects`` and ``char``.
        self.context = Context()

        #: Namespace for drawing methods, containing an instance of the :any:`Drawing` class
        self.draw = Drawing(self.set_at, self.reset_at, self.get_size,
                            self.context)
        self.width, self.height = self.size = size

        #: Namespace to allow high-resolution drawing using a :any:`HighRes` instance
        #: One should either use the public methods in HighRes or the methods on the
        #: :any:`Drawing` instance at ``Screen.high.draw`` to do 1/4 block pixel
        #: manipulation.
        self.high = HighRes(self)
        self.braille = HighRes(self,
                               block_class=BrailleChars,
                               block_width=2,
                               block_height=4)
        self.square = HighRes(self,
                              block_class=HalfChars,
                              block_width=1,
                              block_height=2)
        self.sextant = HighRes(self,
                               block_class=SextantChars,
                               block_width=2,
                               block_height=3)

        self.text = terminedia.text.TextPlane(self)

        self.backend = backend = backend.upper()
        if backend == "ANSI":
            from terminedia.terminal import JournalingScreenCommands as CommandsClass
        elif backend == "HTML":
            from terminedia.html import JournalingHTMLCommands as CommandsClass
        else:
            raise ValueError(f"Unrecognized backend: {backend!r}.")

        #: Namespace for low-level rendering commands, an instance of :any:`JournalingCommandsMixin`.
        #: This attribute can be used as a context manager to group
        #: various output operations in a single block that is rendered at once.
        self.commands = CommandsClass()
        self.clear_screen = clear_screen
        self.data = FullShape.new((self.width, self.height))
        # Synchronize context for data and screen painting.
        self.data.context = self.context
        from terminedia import context
        self.root_context = context
        self._last_setitem = 0
Exemplo n.º 3
0
 def _prepare_context(self):
     self.context = Context()
     source = self.text_plane.owner.context
     self._parent_context_data = {key:value for key, value in source}
     self._reset_context()
Exemplo n.º 4
0
 def context(self):
     return Context()