Skip to content

vtf iodata esccontainer

srccircumflex edited this page Apr 24, 2023 · 4 revisions

↑ vtf-iodata

esccontainer

This module contains the original data types for processing escape sequences. The essential properties of EscSegment and EscContainer are that the processing of the type is oriented to the eventual length of the character sequence after output to stdout (after removing the escape sequences).

Example:
>>> green_text = EscSegment.new(intro="\x1b[32m", string="green text", outro="\x1b[m")
>>> white_text = EscSegment.new(intro="\x1b[37m", string="white text", outro="\x1b[m")
>>> frame = EscSegment("%-12s|")
>>>
>>> green = green_text[:5]          # "\x1b[32mgreen\x1b[m"
>>> text = white_text[6:]           # "\x1b[37mtext\x1b[m"
>>>
>>> len(text)
4
>>> int(text)
8
>>> abs(text)
12
>>>
>>> frame % (green + white)
"\x1b[32mgreen\x1b[m\x1b[37mtext\x1b[m   |"

The properties are made possible by an internal shared memory allocation of printable sequences and escape sequences.

Note:

An automatic conversion of strings containing escape sequences into an EscSegment or EscContainer is NOT available or meant, the data type is to be understood as a tool.

WARNING:

The data type is fully implemented in Python, which, combined with the complexity of its properties, makes it a a "heavy object". Especially frequent concatenation and slicing can slow down the program significantly. To reduce the computational overhead of slicing or formatting, the EscSegment.assimilate()/ EscContainer.assimilate() method can be used for concatenation; this method attempts to concatenate the segments at the intersections and ignores irrelevant segments, which minimizes the likelihood of a high number of segments. (But also not recommended for concatenating many different sequences, as it is more computationally intensive than EscSegment.__add__()/EscContainer.__add__()). In practice, its use should be bypassed as much as possible.

A practical example:

The following code is part of the tab visualization within the buffer display in simplified and pseudo form.

raster = ["column 1", "column 2", "column 3", …]
tab_sizes = [4, 2, 7, …]
start_of_visible_string = 100

tab_visualisation = lambda n: EscSegment.new(intro="\x1b[32m", string=" " * n, outro="\x1b[m")
nbsp = chr(160)  # no breaking space

visualized = str()

def tab_visualisation():

    for col, tab in zip(raster, tab_sizes):
        visualized += col
        if len(visualized) + tab >=  start_of_visible_string:
            visualized = EscSegment(visualized) + tab_visualisation(tab)
            for col, tab in <remaining>:
                visualized += col + tab_visualisation(tab)
            break
        else:
            visualized += nbsp * tab
    else:
        visualized = EscSegment(visualized)

Because of the caching, the buffer display also involves the number of segments (EscSegment.n_segments()/ EscContainer.n_segments()) in the algorithm and removes an EscSegment/EscContainer from memory if a defined size is exceeded.

EscSegment and EscContainer are not related classes, but can be treated the same way because of Duck Typing.

New since version [v] 2023.04.24-2:
  • EscSegment and EscContainer both additionally inherit from type EscString.
  • (EscSegment | EscContainer).(__iter__ | __reversed__) behaves like str.(__iter__ | __reversed__), considering the fields of the escape sequences and creating an EscSegment for each printable character.

Module contents

Constants

NUL_SLC = EscSlice([EscSegment("")], [(0, 0)], None, None)

Assigned internally for a slice that is equivalent to "".

Functions

esccontainer.__ec_abs__(ec) -> int

Calculates the absolute data length of an EscContainer and stores the value in the EscContainer for repeated calls of __abs__(). (Is called internally)

esccontainer.__ec_int__(ec) -> int

Calculates the length of an EscContainer's escape sequences and stores the value in the EscContainer for repeated calls of __int__(). (Is called internally)

esccontainer.__ec_len__(ec) -> int

Calculates the length of the printable characters of an EscContainer and stores the value in the EscContainer for repeated calls of __len__(). (Is called internally)

Objects

class esccontainer.EscContainer(str, EscString)

A container for EscSegment's. Subclass of string.

Structure:
sequence_segments
[EscSegment(...), ...]
print_index
[(0, print length), (previous segment print length, extended print length), ...]

The default EscContainer(EscSegment(...)) initialization expects the EscSegment as a parameter. [ ! ] IS NOT TYPE CHECKED. The class method new first creates an EscSegment and then creates EscContainer from it.

Unique features:
len(econt)
returns the length of the printable string (excl. escape sequences).
int(econt)
returns the length of the escape sequences.
abs(econt)
returns the real data length (including escape sequences).
econt + str | EscSegment | EscContainer
returns an EscContainer.
econt << str
appends the first intro escape sequence to str and returns a new EscContainer.
econt >> str
appends to the last outro escape sequence and returns a new EscContainer.
econt % eseg | econt2
considers the real length of eseg | econt2 when formatting fstring arguments like '%-4s' or '%+2s' and extends the parameterization. So the entered parameterization corresponds to the final one after printing. Also supports any other fstring parameterization and argumentation, and behaves similarly for exceptions. Differently, SyntaxError is raised if a fstring flag or conversion for an EscSegment/EscContainer is not supported (Supported flags: - and + only; Supported conversion: s only).
eseg[0] | eseg[1:4] | eseg[(4, 7)]
relates to and is oriented to the string field.
__iter__()
New since version [v] 2023.04.24-2:
(EscSegment | EscContainer).(__iter__ | __reversed__) behaves like str.(__iter__ | __reversed__), considering the fields of the escape sequences and creating an EscSegment for each printable character.

Note: The data type is fully implemented in Python, which combined with the complexity of its properties makes it a "heavy object". Especially frequently concatenation and slicing can slow down the program significantly. To reduce the computational cost of slicing or formatting, method EscContainer.assimilate() can be used for concatenation; this tries to merge the segments at the intersections and ignores irrelevant ones, minimizing the likelihood of a high number of segments (but also not recommended for concatenation of many diverse sequences, since it is more computationally intensive than EscContainer.__add__()). Practically, its use should be avoided as far as possible.

__abs__() -> int

Returns the real data length (including escape sequences).

__add__(__o) -> EscContainer

Extends the segment sequence and returns a new EscContainer.

__bool__() -> bool

Returns whether data is stored.

__getitem__(item) -> EscContainer

Works like str[...] but is oriented to the string fields.

__int__() -> int

Returns the length of the escape sequences

__iter__() -> Generator[EscSegment]

New since version [v] 2023.04.24-2:
Behaves like str.__iter__, considering the fields of the escape sequences and creating an EscSegment for each printable character.

__len__() -> int

Returns the length of the printable string (excl. escape sequences).

__lshift__(other) -> EscContainer

Appends the first intro escape sequence to str and returns a new EscContainer.

>>> <EscContainer(first_into_field="\x1b[32m", ...)> << "\x1b[47m"
>>> <EscContainer(first_into_field="\x1b[47m\x1b[32m"), ...>

__mod__(args) -> EscContainer

Format fstring (%) patterns in EscContainer. The arguments can be formulated as dict, tuple, or as a single.

When formatting pattern like "%-4s" or "%+2s" with EscSegment/EscContainer arguments, their real length is considered and the format parameters are extended with the length of the escape sequences. The entered parameterization thus corresponds to the value after printing.

Also supports any other fstring parameterization and argumentation, and behaves similarly for exceptions. Differently, SyntaxError is raised if a fstring flag or conversion for an EscSegment/EscContainer is not supported (Supported flags: - and + only; Supported conversion: s only).

Note: If EscSegment/EscContainer is formatted as an argument, its escape fields merge into the string field. Thus, in case of the presence of escape sequences, the EscSegment/EscContainer loses its typical properties. (The parameter extension property is created for a final operation).

raises:
  • SyntaxError(unsupported flag or conversion for EscSegment | EscContainer)
  • TypeError(too many or too few arguments)
  • TypeError(format requires or does not require a mapping)
  • TypeError(by printf (str.__mod__) -> conversion not supported)
  • KeyError(by printf (str.__mod__) -> dictionary assignment not found)

__new__(seg) -> EscContainer

Creates a new EscContainer with an EscSegment.

__repr__() -> str

Representative string.

__reversed__() -> Generator[EscSegment]

New since version [v] 2023.04.24-2:
Behaves like str.__reversed__, considering the fields of the escape sequences and creating an EscSegment for each printable character.

__rshift__(other) -> EscContainer

Appends to the last outro escape sequence and returns a new EscContainer

>>> <EscContainer(..., last_outro_field="\x1b[m")> >> "\x1b[31m"
>>> <EscContainer(..., last_outro_field="\x1b[m\x1b[31m")>

assimilate(__o) -> EscContainer

Merge the segments at the intersection points if both parts do not contain any escape sequences or if they are identical. Otherwise, append the segment.

assimilate_string(__o) -> EscContainer

Gradation of assimilate().

Merge the segments at the intersection points if both parts do not contain any escape sequences. Otherwise, append the segment.

clean() -> EscContainer

Removes rudimentary segments (inplace).

endswith_esc() -> bool

Return whether an escape sequence field is assigned in the last segment in the container.

overload formatting(next_arg, /, *, as_str=False, as_str_if_esc=False) -> str | EscContainer

overload formatting(kw_args, /, *, as_str=False, as_str_if_esc=False) -> str | EscContainer

overload formatting(arg_tuple, /, *, as_str=False, as_str_if_esc=False) -> str | EscContainer

formatting(args, /, *, as_str=False, as_str_if_esc=False) -> str | EscContainer

Format fstring (%) patterns in EscContainer. The arguments can be formulated as dict, tuple, or callable.

When formatting pattern like "%-4s" or "%+2s" with EscSegment/EscContainer arguments, their real length is considered and the format parameters are extended with the length of the escape sequences. The entered parameterization thus corresponds to the value after printing. Also supports any other fstring parameterization and argumentation. SyntaxError is raised if a fstring flag or conversion for an EscSegment/EscContainer is not supported (Supported flags: - and + only; Supported conversion: s only).

Differing from the formatting by the modulo operator (% / EscContainer.__mod__() ), the complete formatting of the arguments is NOT checked and if there are too few arguments the IndexError is NOT converted to a TypeError.

Additionally, the return value can be optionally defined by one of the keyword arguments
as_str
Creates an ordinary string. (minimally less complex than %)
as_str_if_esc
Creates an ordinal string from the occurrence of EscSegment/EscContainer parameterization. (More complex than as_str but can be minimally less complex than %).

Note: If EscSegment/EscContainer is formatted as an argument, its escape fields merge into the string field. Thus, in case of the presence of escape sequences, the EscSegment/EscContainer loses its typical properties. (The parameter extension property is created for a final operation).

raises:
  • SyntaxError(unsupported flag or conversion for EscSegment | EscContainer)
  • IndexError(by callable_args -> too few arguments)
  • TypeError(format requires or does not require a mapping)
  • TypeError(by printf (str.__mod__) -> conversion not supported)
  • KeyError(by printf (str.__mod__) -> dictionary assignment not found)

classmethod fromattr(seq, idx) -> EscContainer

Create a new EscContainer from a list of EscSegments and an index of lengths of the total printable characters in relation to EscSegment positions.

classmethod fromslice(slc) -> EscContainer

Create a new EscContainer from a EscSlice object.

has_escape() -> bool

Return whether an escape sequence field is assigned.

join(__iterable) -> EscContainer | EscSegment

classmethod more(*i_s_o) -> EscContainer

Create a EscContainer from a sequence of

tuple( "<escape intro filed>", "<string field>", "<escape outro field>" ) | "<string field>" | EscSegment

n_segments() -> int

Return the number of segments in the container.

classmethod new(intro='', string='', outro='') -> EscContainer

Create a new EscSegment and from it a new EscContainer.

out() -> TextIO

Write the sequence to stdout, then flush and return stdout.

printable() -> str

Return the string fields as one string.

overload slicing(*, regard_string) -> EscSlice

overload slicing(*, regard_segments) -> EscSlice

slicing(*, regard_string=0, regard_segments=None) -> EscSlice

Create a EscSlice object with regard to the string or the sequence of EscSegment's.

startswith_esc() -> bool

Return whether an escape sequence field is assigned in the first segment in the container.

wrap(sufseq, preseq, *, inner=False, cellular=False) -> EscContainer

Executes the wrap method on each segment if cellular is True. Otherwise, extends the intro sequence of the first EscSegment and the outro sequence of the last EscSegment depending on inner:

wrap:
>>> <EscContainer(first EscSegment(intro="\x1b[32m", ...), ..., last EscSegment(..., outtro="\x1b[m"))>.wrap("\x1b[47m", "\x1b[31m")
>>> <EscContainer(first EscSegment(intro="\x1b[47m\x1b[32m", ...), ..., last EscSegment(..., outtro="\x1b[m\x1b[31m"))>
inner-wrap:
>>> <EscContainer(first EscSegment(intro="\x1b[32m", ...), ..., last EscSegment(..., outtro="\x1b[m"))>.wrap("\x1b[47m", "\x1b[31m", inner=True)
>>> <EscContainer(first EscSegment(intro="\x1b[32m\x1b[47m", ...), ..., last EscSegment(..., outtro="\x1b[31m\x1b[m"))>

class esccontainer.EscSegment(str, EscString)

Data type for escape sequences. Subclass of string.

Structure: "<introducing escape sequence><printable string><terminating escape sequence>"

The default EscSegment("string") initialization only provides for the creation of an EscSegment with the string field. Escape sequences can be assigned already with the creation via class methods with new -prefix.

Unique features:
len(eseg)
returns the length of the printable string (excl. escape sequences).
int(eseg)
returns the length of the escape sequences.
abs(eseg)
returns the real data length (including escape sequences).
eseg + str | EscSegment | EscContainer``
returns an EscContainer.
eseg & str
appends str to the printable string and returns a new EscSegment.
eseg << str
appends the intro escape sequence to str and returns a new EscSegment.
eseg >> str
appends to the outro escape sequence and returns a new EscSegment.
econt % eseg | econt2
considers the real length of eseg | econt2 when formatting fstring arguments like '%-4s' or '%+2s' and extends the parameterization. So the entered parameterization corresponds to the final one after printing. Also supports any other fstring parameterization and argumentation, and behaves similarly for exceptions. Differently, SyntaxError is raised if a fstring flag or conversion for an EscSegment/EscContainer is not supported (Supported flags: - and + only; Supported conversion: s only).
eseg[0] | eseg[1:4] | eseg[(4, 7)]
relates to and is oriented to the string field.
__iter__()
New since version [v] 2023.04.24-2:
(EscSegment | EscContainer).(__iter__ | __reversed__) behaves like str.(__iter__ | __reversed__), considering the fields of the escape sequences and creating an EscSegment for each printable character.

The base class for escape sequences.

Derivatives:

Note: The data type is fully implemented in Python, which combined with the complexity of its properties makes it a "heavy object". Especially frequently concatenation and slicing can slow down the program significantly. To reduce the computational cost of slicing or formatting, method EscSegment.assimilate() can be used for concatenation; this tries to merge the segments at the intersections and ignores irrelevant ones, minimizing the likelihood of a high number of segments (but also not recommended for concatenation of many diverse sequences, since it is more computationally intensive than EscSegment.__add__()). Practically, its use should be avoided as far as possible.

esc_len: int

intro: str

len: int

outro: str

string: str

__abs__() -> int

Returns the real data length (including escape sequences).

__add__(__o) -> EscContainer

Extends the sequence and creates an EscContainer.

__and__(string) -> EscSegment

Appends string to the string field and returns a new EscSegment

__bool__() -> bool

Returns whether data is stored.

__getitem__(item) -> EscSegment

Works like str[...] but is oriented to the string fields.

__int__() -> int

Returns the length of the escape sequences

__iter__() -> Generator[EscSegment]

New since version [v] 2023.04.24-2:
Behaves like str.__iter__, considering the fields of the escape sequences and creating an EscSegment for each printable character.

__len__() -> int

Returns the length of the printable string (excl. escape sequences)

__lshift__(other) -> EscSegment

Appends the intro escape sequence to str and returns a new EscSegment.

>>> <EscSegment(intro="\x1b[32m", ...)> << "\x1b[47m"
>>> <EscSegment(intro="\x1b[47m\x1b[32m"), ...>

__mod__(args) -> EscSegment

Format fstring (%) patterns in EscSegment. The arguments can be formulated as dict, tuple, or as a single.

When formatting pattern like "%-4s" or "%+2s" with EscSegment/EscContainer arguments, their real length is considered and the format parameters are extended with the length of the escape sequences. The entered parameterization thus corresponds to the value after printing.

Also supports any other fstring parameterization and argumentation, and behaves similarly for exceptions. Differently, SyntaxError is raised if a fstring flag or conversion for an EscSegment/EscContainer is not supported (Supported flags: - and + only; Supported conversion: s only).

Note: If EscSegment/EscContainer is formatted as an argument, its escape fields merge into the string field. Thus, in case of the presence of escape sequences, the EscSegment/EscContainer loses its typical properties. (The parameter extension property is created for a final operation).

raises:
  • SyntaxError(unsupported flag or conversion for EscSegment | EscContainer)
  • TypeError(too many or too few arguments)
  • TypeError(format requires or does not require a mapping)
  • TypeError(by printf (str.__mod__) -> conversion not supported)
  • KeyError(by printf (str.__mod__) -> dictionary assignment not found)

__new__(string) -> EscSegment

Creates a new EscContainer with string in the string field.

__reduce__() -> tuple[Callable[ [str, str, str], EscSegment], tuple[str, str, str]]

Pickler support

__repr__() -> str

Representative string.

__reversed__() -> Generator[EscSegment]

New since version [v] 2023.04.24-2:
Behaves like str.__reversed__, considering the fields of the escape sequences and creating an EscSegment for each printable character.

__rshift__(other) -> EscSegment

Appends to the outro escape sequence and returns a new EscSegment.

>>> <EscSegment(..., outro="\x1b[m")> >> "\x1b[31m"
>>> <EscSegment(..., outro="\x1b[m\x1b[31m")>

assimilate(__o) -> EscSegment | EscContainer

Merge the segments at the intersection points if both parts do not contain any escape sequences or if they are identical. Otherwise, append the segment.

assimilate_string(__o) -> EscSegment | EscContainer

Gradation of assimilate().

Merge the segments at the intersection points if both parts do not contain any escape sequences. Otherwise, append the segment.

endswith_esc() -> bool

Return whether an escape sequence field is assigned in the last segment in the container. (Duck typing method; alias to has_escape()).

overload formatting(next_arg, /, *, as_str=False, as_str_if_esc=False) -> str | EscSegment

overload formatting(kw_args, /, *, as_str=False, as_str_if_esc=False) -> str | EscSegment

overload formatting(arg_tuple, /, *, as_str=False, as_str_if_esc=False) -> str | EscSegment

formatting(args, /, *, as_str=False, as_str_if_esc=False) -> str | EscSegment

Format fstring (%) patterns in EscSegment. The arguments can be formulated as dict, tuple, or callable.

When formatting pattern like "%-4s" or "%+2s" with EscSegment/EscContainer arguments, their real length is considered and the format parameters are extended with the length of the escape sequences. The entered parameterization thus corresponds to the value after printing. Also supports any other fstring parameterization and argumentation. SyntaxError is raised if a fstring flag or conversion for an EscSegment/EscContainer is not supported (Supported flags: - and + only; Supported conversion: s only).

Differing from the formatting by the modulo operator (% / EscSegment.__mod__() ), the complete formatting of the arguments is not checked and if there are too few arguments the IndexError is not converted to a TypeError.

Additionally, the return value can be optionally defined by one of the keyword arguments
as_str
Creates an ordinary string. (minimally less complex than %)
as_str_if_esc
Creates an ordinal string from the occurrence of EscSegment/EscContainer parameterization. (More complex than as_str but can be minimally less complex than %).

Note: If EscSegment/EscContainer is formatted as an argument, its escape fields merge into the string field. Thus, in case of the presence of escape sequences, the EscSegment/EscContainer loses its typical properties. (The parameter extension property is created for a final operation).

raises:
  • SyntaxError(unsupported flag or conversion for EscSegment | EscContainer)
  • IndexError(by callable_args -> too few arguments)
  • TypeError(format requires or does not require a mapping)
  • TypeError(by printf (str.__mod__) -> conversion not supported)
  • KeyError(by printf (str.__mod__) -> dictionary assignment not found)

has_escape() -> bool

Return whether an escape sequence field is assigned.

join(__iterable) -> EscContainer | EscSegment

n_segments() -> int

Return the number of segments in the container (Duck typing method; returns 1).

classmethod new(intro='', string='', outro='') -> EscSegment

Creates a new EscSegment. Each field can be assigned.

classmethod new_esc(*params, string='', outro='') -> EscSegment

Creates an escape sequence from params (puts ESC in front of it) and puts it into the intro field.

staticmethod new_nul(*_, **__) -> EscSegment

Creates an EscSegment(intro='', string='', outro='').

classmethod new_pur(esc='', esc_string='', term='') -> EscSegment

Intended for terminated string escapes. Ignores the length of the string. (Unstable)

staticmethod new_raw(*params) -> str

Creates a new escape sequence (type str) from params. Prepends the ESC character.

out() -> TextIO

Write the sequence to stdout, then flush and return stdout.

printable() -> str

Return the string field.

startswith_esc() -> bool

Return whether an escape sequence field is assigned in the first segment in the container. (Duck

wrap(sufseq, preseq, *, inner=False, cellular=False) -> EscSegment

Extends the intro and outro sequence depending on inner:

wrap:
>>> <EscSegment(intro=sufseq + self.intro, self.string, outro=self.outro + preseq)>
inner-wrap:
>>> <EscSegment(intro=self.intro + sufseq, self.string, outro=preseq + self.outro)>

cellular is duck typing, takes effect only in EscContainer.warp().

class esccontainer.EscSlice(NamedTuple)

Slice object for EscContainer.

Is in the first instance the rough area of the EscSegment's, only by exact() the exact slice is created.

By make() and makeexact() the sliced EscContainer can be created analogous from it.

print_index: list[tuple[int, int]]

sequence_segments: list[EscSegment]

start: int | None

stop: int | None

exact() -> EscSlice

make() -> EscContainer

makeexact() -> EscContainer

class esccontainer.EscString

Parent class of EscSegment and EscContainer. Cannot be initialized, returns an EscSegment on creation and does not support escape sequences. Via the static method new can be checked whether the passed object is an EscSegment or EscContainer, if this is true this is returned, otherwise an EscSegment is created from the input.

__new__(string="") -> EscSegment

staticmethod new(s) -> EscSegment | EscContainer


Date: 07 Nov 2022
Version: 0.1
Author: Adrian Hoefflin [srccircumflex]
Doc-Generator: "pyiStructure-RSTGenerator" <prototype>
Clone this wiki locally