diff --git a/Makefile b/Makefile index 6e323d9d..d3c9f235 100644 --- a/Makefile +++ b/Makefile @@ -256,7 +256,7 @@ docs-all: depends demolish-docs docs docs-pdf docs-man open-docs-html: ## Open HTML docs in browser @$(call _ensure_x11) || return - @[ -d localhost ] && xdg-open ${LOCALHOST_URL}/docs/pages || xdg-open ${DOCS_IN_PATH}/_build/index.html + @[ -d localhost ] && xdg-open ${LOCALHOST_URL}/docs/pages || xdg-open ${DOCS_IN_PATH}/_build/pages/index.html open-docs-pdf: ## Open PDF docs in reader @$(call _ensure_x11) || return diff --git a/docs-build/2.106.3.pdf b/docs-build/2.106.3.pdf new file mode 100644 index 00000000..df230079 Binary files /dev/null and b/docs-build/2.106.3.pdf differ diff --git a/docs-build/2.106.4.1 b/docs-build/2.106.4.1 new file mode 100644 index 00000000..5aa3e130 --- /dev/null +++ b/docs-build/2.106.4.1 @@ -0,0 +1,16984 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "PYTERMOR" "1" "Oct 17, 2023" "2.106.4" "pytermor" +.SH NAME +pytermor \- pytermor 2.106.4 +.sp +(yet another) Python library initially designed for formatting +terminal output using ANSI escape codes. +.sp +Provides \fI\%high\-level\fP methods for working with text sections, colors, +formats, alignment and wrapping, as well as \fI\%low\-level\fP modules which +allow to operate with \fI\%ANSI\fP sequences directly and also implement +automatic format termination. Depending on the context and technical +requirements either approach can be used. Also includes a set of additional +number/string/time formatters for pretty output, filters, templating engine, +escape sequence parser and provides support for several color spaces, which is +also used for fluent color approximation if terminal capabilities do not +allow to work in True Color mode. See \fI\%Features\fP page for the details. +.sp +No dependencies required, only Python Standard Library (although there +are some for testing and docs building). +.sp +The library is extendable and supports a variety of formatters (called +\fI\%renderers\fP), which determine the output syntax: +.INDENT 0.0 +.IP \(bu 2 +\fI\%SgrRenderer\fP, global default; formats the text with ANSI escape sequences for +terminal emulators; +.IP \(bu 2 +\fI\%TmuxRenderer\fP, suitable for integration with tmux (terminal multiplexer); +.IP \(bu 2 +\fI\%HtmlRenderer\fP, which makes a HTML page with all the formatting composed by +CSS styles; +.IP \(bu 2 +\fI\%SgrDebugger\fP, same as \fBSgrRenderer\fP, but control bytes are replaced with a +regular letter, therefore all the sequences are no longer sequences and can be +seen as a text, for SGR debugging; +.IP \(bu 2 +etc. +.UNINDENT +.sp +Contents +.SH INSTALLATION +.sp +Python 3.8 or later should be installed and available in \fB$PATH\fP; that\(aqs +basically it if intended usage of the package is as a library. +.sp +Installing into a project +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ python \-m pip install pytermor +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +Standalone installation (for developing or experimenting) +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ git clone git@github.com:delameter/pytermor.git . +$ python \-m venv venv +$ PYTHONPATH=. venv/bin/python \-m pytermor +v2.41.1\-dev1:Feb\-23 +.ft P +.fi +.UNINDENT +.UNINDENT +.SH FEATURES +.SS Flexible input formats +.sp +\fI\%fargs syntax\fP allows to compose formatted text parts much faster and keeps the code +compact: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +import pytermor as pt + +ex_st = pt.Style(bg=\(aq#ffff00\(aq, fg=\(aqblack\(aq) +text = pt.FrozenText( + \(aqThis is red \(aq, pt.cv.RED, + \(dqThis is white \(dq, + \(dqThis is black on yellow\(dq, ex_st, +) +pt.echo(text) +.ft P +.fi +.UNINDENT +.UNINDENT +This is red\ This is white\ This is black on yellow +.SS Content\-aware format nesting +.sp +Template tags and non\-closing \fI\%Fragments\fP allow to build complex formats: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +import pytermor as pt + +s = \(dq:[fg=red]fg :[bg=blue]and bg :[fg=black]formatting with:[\-] overlap:[\-] support\(dq +pt.echo(pt.TemplateEngine().substitute(s)) +.ft P +.fi +.UNINDENT +.UNINDENT +fg and bg\ formatting with\ overlap support +.SS 256 colors / True Color support +.sp +The library supports extended color modes: +.INDENT 0.0 +.IP \(bu 2 +XTerm 256 colors indexed mode +.IP \(bu 2 +True Color RGB mode (16M colors) +.UNINDENT +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +import pytermor as pt + +for outm in [\(aqxterm_16\(aq, \(aqxterm_256\(aq, \(aqtrue_color\(aq]: + print(\(aq \(aq+outm.ljust(12), end=\(dq\(dq) + for c in range((W := 80) + 1): + b = pt.RGB.from_ratios(1 \- (p := c / W), 2 * min(p, 1 \- p), p).int + f = pt.Fragment(\(dq ·\(dq[c & 1], pt.Style(fg=(1 << 24) \- b, bg=b, bold=True)) + print(f.render(pt.SgrRenderer(outm)), end=[\(dq\(dq, 2*\(dq\en\(dq][c >= W], flush=True) +.ft P +.fi +.UNINDENT +.UNINDENT +[image] +.SS Different color spaces +.sp +Currently supported spaces: \fI\%RGB\fP, \fI\%HSV\fP, \fI\%XYZ\fP, \fI\%LAB\fP\&. A color defined +in any of these can be transparently translated into any other: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +import pytermor as pt + +col = pt.RGB(0xDA9AC4) +st = pt.Style(fg=col) +for v in [col.rgb, col.hsv, col.xyz, col.lab]: + pt.echo(repr(v), st) +.ft P +.fi +.UNINDENT +.UNINDENT +.nf +RGB[#DA9AC4][R=218 G=154 B=196] +HSV[H=321° S=29% V=85%] +XYZ[X=50.43 Y=42.00% Z=57.66] +LAB[L=70.872% a=30.339 b=\-12.031] +.fi +.sp +.SS Named colors collection +.sp +Registry containing more than 2400 named colors, in addition to +default 256 from \fBxterm\fP palette. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ /run\-cli examples/list_named_rgb.py +.ft P +.fi +.UNINDENT +.UNINDENT +[image] +.SS Extendable renderers +.sp +\fI\%Renderers\fP is a family of classes responsible for creating +formatted strings from \fI\%IRenderable\fP instances, which, in general, consist of +a text piece and a \fI\%Style\fP \-\- a set of formatting rules. Concrete implementation +of the renderer determines the target format and/or platform. +.sp +This is how \fI\%SgrRenderer\fP, \fI\%HtmlRenderer\fP, \fI\%TmuxRenderer\fP, \fI\%SgrDebugger\fP (from top +to bottom) output can be seen in a terminal emulator: +.nf +This is red\ This is white\ This is black on yellow + +This is red This is white This is black on yellow + +#[fg=red]This is red #[fg=default]This is white #[fg=black bg=#ffff00]This is black on yellow#[fg=default bg=default] + +(·[31m)This is red (·[39m)This is white (·[30;48;5;11m)This is black on yellow(·[39;49m) +.fi +.sp +.SS Number formatters +.sp +Set of highly customizable helpers, see \fI\%numfmt\fP\&. +\fI\%format_si()\fP output sample +[image] +\fI\%format_time_ns()\fP output samples +[image] +\fI\%format_time_delta()\fP output sample +[image] +.SS Data dumps +.sp +Special formatters for raw binary/string data. +.sp +These examples were composed for a terminal 80\-chars wide; tracers +dynamically change the amount of elements per line at each \fI\%dump()\fP +call. +.sp +Input data for all examples below was the same. +.sp +Decomposition into separate bytes by \fI\%BytesTracer\fP\&. Note the hexadecimal offset format. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C + 0x00 | 3D 90 39 05 B9 54 BA 89 90 A8 86 4C A3 99 75 DD BC 02 0D 0A + 0x14 | 7A E8 E6 40 76 4B 36 1C 00 AD 02 E2 61 45 FD 92 CD B6 71 02 + 0x28 | 4F 52 EC 39 64 22 68 6A 2E 4E 80 1E 67 07 31 0D 83 55 4D F2 + 0x3C | D0 D5 D9 41 72 54 6D 2B 03 80 FE 95 B3 28 C4 3E FC BC 4E 30 + 0x50 | 5C 6B 5C C3 99 B3 A4 93 24 E9 43 E9 30 B8 6A BC 74 F9 EA 4A + 0x64 | 30 4F 9A 38 71 DF B2 39 19 30 56 7C 73 91 56 6E B8 38 48 F5 + 0x78 | B7 5B 08 BD 96 B5 4F 6E +\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-(0x80) + +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +Decomposition into UTF\-8 sequences by \fI\%StringTracer\fP +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C + 0 | 3d efbfbd 39 05 efbfbd 54 efbfbd efbfbd |=�9·�T�� + 8 | efbfbd efbfbd efbfbd 4c efbfbd efbfbd 75 ddbc |���L��uݼ + 16 | 02 0d 0a 7a efbfbd efbfbd 40 76 |·⇤↵z��@v + 24 | 4b 36 1c 00 efbfbd 02 efbfbd 61 |K6··�·�a + 32 | 45 efbfbd efbfbd cdb6 71 02 4f 52 |E��Ͷq·OR + 40 | efbfbd 39 64 22 68 6a 2e 4e |�9d\(dqhj.N + 48 | efbfbd 1e 67 07 31 0d efbfbd 55 |�·g·1⇤�U + 56 | 4d efbfbd efbfbd efbfbd efbfbd 41 72 54 |M����ArT + 64 | 6d 2b 03 efbfbd efbfbd efbfbd efbfbd 28 |m+·����( + 72 | efbfbd 3e efbfbd efbfbd 4e 30 5c 6b |�>��N0\ek + 80 | 5c c399 efbfbd efbfbd efbfbd 24 efbfbd 43 |\eÙ���$�C + 88 | efbfbd 30 efbfbd 6a efbfbd 74 efbfbd efbfbd |�0�j�t�� + 96 | 4a 30 4f efbfbd 38 71 dfb2 39 |J0O�8q߲9 + 104 | 19 30 56 7c 73 efbfbd 56 6e |·0V|s�Vn + 112 | efbfbd 38 48 efbfbd efbfbd 5b 08 efbfbd |�8H��[·� + 120 | efbfbd efbfbd 4f 6e |��On +\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-(124) + +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +Decomposition into Unicode codepoints by \fI\%StringUcpTracer\fP +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C + 0 |U+ 3D FFFD 39 05 FFFD 54 FFFD FFFD FFFD FFFD FFFD |=�9·�T����� + 11 |U+ 4C FFFD FFFD 75 77C 02 0D 0A 7A FFFD FFFD |L��uݼ·⇤↵z�� + 22 |U+ 40 76 4B 36 1C 00 FFFD 02 FFFD 61 45 |@vK6··�·�aE + 33 |U+ FFFD FFFD 376 71 02 4F 52 FFFD 39 64 22 |��Ͷq·OR�9d\(dq + 44 |U+ 68 6A 2E 4E FFFD 1E 67 07 31 0D FFFD |hj.N�·g·1⇤� + 55 |U+ 55 4D FFFD FFFD FFFD FFFD 41 72 54 6D 2B |UM����ArTm+ + 66 |U+ 03 FFFD FFFD FFFD FFFD 28 FFFD 3E FFFD FFFD 4E |·����(�>��N + 77 |U+ 30 5C 6B 5C D9 FFFD FFFD FFFD 24 FFFD 43 |0\ek\eÙ���$�C + 88 |U+ FFFD 30 FFFD 6A FFFD 74 FFFD FFFD 4A 30 4F |�0�j�t��J0O + 99 |U+ FFFD 38 71 7F2 39 19 30 56 7C 73 FFFD |�8q߲9·0V|s� + 110 |U+ 56 6E FFFD 38 48 FFFD FFFD 5B 08 FFFD FFFD |Vn�8H��[·�� + 121 |U+ FFFD 4F 6E |�On +\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-(124) + +.ft P +.fi +.UNINDENT +.UNINDENT +.SH EXAMPLES +.sp +Most basic example: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C + import pytermor as pt + + pt.force_ansi_rendering() + pt.echo(\(aqRED\(aq, \(aqred\(aq) + pt.echo(\(aqGREEN\(aq, pt.cv.GREEN) + pt.echo(\(dqThis is warning, be warned\(dq, pt.Styles.WARNING) +.ft P +.fi +.UNINDENT +.UNINDENT +.nf +red text +green text +This is warning, be warned +.fi +.sp +.sp +For more advanced ones proceed to the next section. +.SS Rendering +.sp +The library can be split into two domains, the first one being \(dq\fBhigh\fP\-level\(dq +domain, which includes templating, style abstractions, text implementations +which support aligning, wrapping, padding, etc., as well as number formatting +helpers and a registry of preset colors. +.sp +The second one is \(dq\fBlow\fP\-level\(dq, containing colors and color spaces +definitions, helpers for composing various terminal escape sequences, the escape +sequence abstractions themselves, as well as a large set of filters for +chain\-like application. +.SS High\-level +.sp +Imagine we want to colorize \fBgit \-\-help\fP output \fImanually\fP, i.e., we will not +pipe an output of \fBgit\fP and apply filters to do the job (yet), instead we +copy\-paste the output to python source code files as string literals and will try +to add a formatting using all primary approaches. +.sp +Part of the input +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C + These are common Git commands used in various situations: + + start a working area (see also: git help tutorial) + clone Clone a repository into a new directory + init Create an empty Git repository or reinitialize an existing one + [..] +.ft P +.fi +.UNINDENT +.UNINDENT +Part of the output +.nf +These are common Git commands used in various situations: + +start a working area (see also: git help tutorial) +\ \ \ clone\ \ \ \ \ \ \ \ \ \ \ \ \ Clone a repository into a new directory +\ \ \ init\ \ \ \ \ \ \ \ \ \ \ \ \ \ Create an empty Git repository or reinitialize an existing one +\ \ \ [..] +.fi +.sp +.sp +The examples in this part are sorted from simple ones at the beginning to +complicated ones at the end. +.SS Isolated pre\-rendering +.sp +Use \fI\%render()\fP method to apply a \fI\%style\fP to a string part individually for +each of them: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +import pytermor as pt + +subtitle = pt.render(\(dqstart a working area\(dq, pt.Style(fg=pt.cv.YELLOW, bold=True)) +subtitle += \(dq (see also: \(dq +subtitle += pt.render(\(dqgit help tutorial\(dq, pt.cv.GREEN) +subtitle += \(dq)\(dq + +pt.echo(subtitle) +.ft P +.fi +.UNINDENT +.UNINDENT +start a working area (see also: git help tutorial) +.sp +\fI\%render()\fP method uses \fI\%SgrRenderer\fP by default, which is set up automatically +depending on output device characteristics and environment setup. +.sp +Note that \fBrender()\fP accepts \fI\%FT\fP as format argument, which can be \fI\%Style\fP or +\fI\%Color\fP or \fIstr\fP or \fIint\fP (there are a few ways to define a color). +.SS Fragments +.sp +\fI\%Fragment\fP is a basic class implementing \fI\%IRenderable\fP interface and contains a +text string along with a \fI\%Style\fP instance and that\(aqs it. +.sp +\fBFragment\fP instances can be safely concatenated with a regular \fIstr\fP (but not +with another \fI\%Fragment\fP) from the left side as well as from the right side +(highlighted line). If you attempt to add one \fBFragment\fP to another +\fBFragment\fP, you\(aqll end +up with a \fI\%Text\fP instance (see the example after next). +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C + from collections.abc import Iterable + import pytermor as pt + + data = [ + (\(dqclone\(dq, \(dqClone a repository into a new directory\(dq), + (\(dqinit\(dq, \(dqCreate an empty Git repository or reinitialize an existing one\(dq), + ] + + st = pt.Style(fg=pt.cv.GREEN) + for name, desc in data: + frag = pt.Fragment(name.ljust(16), st) + pt.echo(\(aq \(aq + frag + desc) +.ft P +.fi +.UNINDENT +.UNINDENT +.nf +\ \ \ clone\ \ \ \ \ \ \ \ \ \ \ \ \ Clone a repository into a new directory +\ \ \ init\ \ \ \ \ \ \ \ \ \ \ \ \ \ Create an empty Git repository or reinitialize an existing one +.fi +.sp +.SS Fragments in f\-strings +.sp +Another approach to align a formatted text is to combine Python\(aqs \fIf\-strings\fP +with \fI\%Fragment\fP instances: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +import pytermor as pt + +data = [ + (\(dqbisect\(dq, \(dqUse binary search to find the commit that introduced a bug\(dq), + (\(dqdiff\(dq, \(dqShow changes between commits, commit and working tree, etc\(dq), + (\(dqgrep\(dq, \(dqPrint lines matching a pattern\(dq), +] + +st = pt.Style(fg=pt.cv.GREEN) +for name, desc in data: + frag = pt.Fragment(name, st) + pt.echo(f\(dq {frag:<16s} {desc}\(dq) +.ft P +.fi +.UNINDENT +.UNINDENT +.nf +\ \ \ bisect\ \ \ \ \ \ \ \ \ \ \ \ Use binary search to find the commit that introduced a bug +\ \ \ diff\ \ \ \ \ \ \ \ \ \ \ \ \ \ Show changes between commits, commit and working tree, etc +\ \ \ grep\ \ \ \ \ \ \ \ \ \ \ \ \ \ Print lines matching a pattern +.fi +.sp +.SS Texts & FrozenTexts +.sp +\fI\%Text\fP is a general\-purpose composite \fI\%IRenderable\fP implementation, which can +contain any amount of strings linked with styles (i.e. \fI\%Fragment\fP instances). +.sp +\fBText\fP also supports aligning, padding with specified chars to specified width, +but most importantly it supports fargs syntax (for the details see \fI\%fargs syntax\fP), +which allows to compose formatted text parts much faster and keeps the code compact. Generally +speaking, the basic input parameter is either a tuple of string and \fI\%Style\fP or \fI\%Color\fP, +which then will be applied to preceeding string, or a standalone string. Usually +explicit definition of a tuple is not neccessary, but there are cases, when it is: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +import pytermor as pt + +subtitle_st = pt.Style(fg=pt.cv.YELLOW, bold=True) +command_st = pt.Style(fg=pt.cv.GREEN) +text = pt.FrozenText( + (\(dqwork on the current change \(dq, subtitle_st), + \(dq(see also: \(dq, + \(dqgit help everyday\(dq, command_st, + \(dq)\(dq +) +pt.echo(text) +.ft P +.fi +.UNINDENT +.UNINDENT +work on the current change (see also: git help everyday) +.sp +\fI\%FrozenText\fP is an immutable version of \fI\%Text\fP (to be precise, its quite the +opposite: \fBText\fP is a child of \fBFrozenText\fP). +.sp +We will utilize aligning capabilities of \fBFrozenText\fP class in a following +code fragment: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C + import pytermor as pt + + data = [ + (\(dqadd\(dq, \(dqAdd file contents to the index\(dq), + (\(dqmv\(dq, \(dqMove or rename a file, a directory, or a symlink\(dq), + (\(dqrestore\(dq, \(dqRestore working tree files\(dq), + ] + st = pt.Style(fg=pt.cv.GREEN) + + for name, desc in data: + pt.echo([pt.FrozenText(\(dq \(dq, name, st, width=18, pad=4), desc]) +.ft P +.fi +.UNINDENT +.UNINDENT +.nf +\ \ \ add\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Add file contents to the index +\ \ \ mv\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Move or rename a file, a directory, or a symlink +\ \ \ restore\ \ \ \ \ \ \ \ \ \ \ Restore working tree files +.fi +.sp +.sp +At highlighted line we compose a \fI\%FrozenText\fP instance with command +name and set up desired width (18=16+2 for right margin), and explicitly set up +left padding with \fBpad\fP argument. Padding chars and regular spaces originating +from the alignment process are always applied to the opposite sides of text. +.sp +Note that although \fI\%text.echo()\fP accepts a single \fI\%RT\fP as a first argument, +it also accepts a sequence of them, which allows us to call \fBecho\fP just +once. \fI\%common.RT\fP is a type var including \fIstr\fP type and all \fI\%IRenderable\fP +implementations. +.SS Template tags +.sp +There is a support of library\(aqs internal tag format, which allows to inline +formatting into the original string, and get the final result by calling just +one method: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +import pytermor as pt + +s = \(dq\(dq\(dq@st:[fg=yellow bold] @cmd:[fg=green] +:[st]grow, mark and tweak your common history:[\-] + :[cmd]branch:[\-] List, create, or delete branches + :[cmd]commit:[\-] Record changes to the repository + :[cmd]merge:[\-] Join two or more development histories together +\(dq\(dq\(dq +pt.echo(pt.TemplateEngine().substitute(s)) +.ft P +.fi +.UNINDENT +.UNINDENT +.nf +\ \ \ branch\ \ \ \ \ \ \ \ \ \ \ \ List, create, or delete branches +\ \ \ commit\ \ \ \ \ \ \ \ \ \ \ \ Record changes to the repository +\ \ \ merge\ \ \ \ \ \ \ \ \ \ \ \ \ Join two or more development histories together +.fi +.sp +.sp +Here \fB\(dq@st:[fg=yellow bold]\(dq\fP is a definition of a custom user style named \fI\(dqst\(dq\fP, +\fB\(dq:[st]\(dq\fP is a opening tag for that style, and \fB\(dq:[\-]\(dq\fP is a closing tag matching +the most recently opened one. See \fI\%Templates\fP for the details. +.INDENT 0.0 +.INDENT 3.5 +.UNINDENT +.UNINDENT +.SS Regexp group substitution +.sp +A little bit artificial example, but this method can be applied to +solve real tasks nevertheless. The trick is to apply the desired style +to a string containing special characters like \fBr\(dq\e1\(dq\fP, which +will represent regexp group 1 after passing it into \fBre.sub()\fP\&. The actual +string being passed as 2nd argument will be \fB\(dq ESC [ 32m \e1 ESC [ m\(dq\fP\&. Regexp +substitution function will replace all \fB\(dq\e1\(dq\fP with a matching group in every +line of the input, therefore the match will end up being surrounded with +(already rendered) SGRs responsible for green text color, ???, PROFIT: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +import re +import pytermor as pt + +s = \(dq\(dq\(dq + fetch Download objects and refs from another repository + pull Fetch from and integrate with another repository or a local branch + push Update remote refs along with associated objects +\(dq\(dq\(dq + +regex = re.compile(r\(dq^(\es+)(\eS+)(.+)$\(dq) +for line in s.splitlines(): + pt.echo( + regex.sub( + pt.render(r\(dq\e1\(dq + pt.Fragment(r\(dq\e2\(dq, pt.cv.GREEN) + r\(dq\e3\(dq), + line, + ) + ) +.ft P +.fi +.UNINDENT +.UNINDENT +.nf +\ \ \ fetch\ \ \ \ \ \ \ \ \ \ \ \ \ Download objects and refs from another repository +\ \ \ pull\ \ \ \ \ \ \ \ \ \ \ \ \ \ Fetch from and integrate with another repository or a local branch +\ \ \ push\ \ \ \ \ \ \ \ \ \ \ \ \ \ Update remote refs along with associated objects +.fi +.sp +.sp +For more complex logic it\(aqs usually better to extract it into separate function: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +def replace_expand(m: re.Match) \-> str: + tpl = pt.render(r\(dq\e1\(dq + pt.Fragment(r\(dq\e2\(dq, pt.cv.GREEN) + r\(dq\e3\(dq) + return m.expand(tpl) +regex.sub(replace_expand, \(dq...\(dq) +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +Another approach: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +def replace_manual(m: re.Match) \-> str: + return pt.render(m.group(1) + pt.Fragment(m.group(2), pt.cv.GREEN) + m.group(3)) +regex.sub(replace_manual, \(dq...\(dq) +.ft P +.fi +.UNINDENT +.UNINDENT +.SS Refilters +.sp +Refilters (\fBRe\fPndering \fBfilter\fPs) are usually applied in sequences, where +each of those matches one or two named regexp groups and applies the specified +styles accordingly. +.sp +In the example below we first (#10\-12) implement \fB_render()\fP method in a new +class inherited from \fI\%AbstractNamedGroupsRefilter\fP, then (#14\-16) the refilter +is created (note regexp group name \fB\(aqcmd\(aq\fP and matching dictionary key, which +value is a \fI\%FT\fP), then (#19) the refilter is applied and result is printed. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +Although filters in general are classified as \fBlow\fP\-level, this example +is placed into \fBhigh\fP\-level group, because no manipulation at byte level +or at color channel level is performed. +.UNINDENT +.UNINDENT +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +import re +import pytermor as pt + +s = \(dq\(dq\(dq + reset Reset current HEAD to the specified state + switch Switch branches + tag Create, list, delete or verify a tag object signed with GPG +\(dq\(dq\(dq + +class SgrNamedGroupsRefilter(pt.AbstractNamedGroupsRefilter): + def _render(self, v: pt.IT, st: pt.FT) \-> str: + return pt.render(v, st, pt.SgrRenderer) + +f = SgrNamedGroupsRefilter( + re.compile(r\(dq(\es+)(?P\eS+)(.+)\(dq), + {\(dqcmd\(dq: pt.cv.GREEN}, +) + +pt.echo(pt.apply_filters(s, f)) +.ft P +.fi +.UNINDENT +.UNINDENT +.nf +\ \ \ reset\ \ \ \ \ \ \ \ \ \ \ \ \ Reset current HEAD to the specified state +\ \ \ switch\ \ \ \ \ \ \ \ \ \ \ \ Switch branches +\ \ \ tag\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Create, list, delete or verify a tag object signed with GPG +.fi +.sp +.SS Low\-level +.sp +The examples in this part are sorted from simple (for the developer) ones at the beginning to +complicated (for the developer) ones at the end. But after you change the point of view, the +results are reversed: first ones are most complicated for the interpreter to run, while the +ones at the end are simplest (roughly one robust method per instance is invoked). Therefore, +the answer to the question \(dqwhich method is most suitable\(dq should always be evaluated on the +individual basis. +.SS Preset compositions +.sp +Preset composition methods produce sequence instances or ready\-to\-print +strings as if they were rendered by \fI\%SgrRenderer\fP\&. Methods with +names starting with \fBmake_\fP return single sequence instance each, while +methods named \fBcompose_*\fP return \fIstr\fPings which are several sequences +rendered and concatenated. +.sp +In the next example we create an SGR which sets background color to +@#008787 (highlighted line) by specifying xterm\-256 +code 30 (see \fI\%xterm\-256 palette\fP), then compose a string which includes: +.INDENT 0.0 +.INDENT 3.5 +.INDENT 0.0 +.IP \(bu 2 +CUP instruction: \fBESC [1;1H\fP; +.IP \(bu 2 +SGR instruction with our color: \fBESC [48;5;30m\fP; +.IP \(bu 2 +EL instruction: \fBESC [0K\fP\&. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +Effectively this results in a whole terminal line colored with a specified color, +and note that we did not fill the line with spaces or something like that \-\- +this method is (in theory) faster, because the tty needs to process only ~10\-20 +characters of input instead of 120+ (average terminal width). +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C + import pytermor as pt + + col_sgr = pt.make_color_256(30, pt.ColorTarget.BG) + seq = pt.compose_clear_line_fill_bg(col_sgr) + pt.echo(seq + \(aqAAAA BBBB\(aq) +.ft P +.fi +.UNINDENT +.UNINDENT +AAA BBBB +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +\fBcompose_*\fP methods do not belong to any \fI\%renderer\fP, so the decision of using +or not using these depending on a terminal settings should be made by the developer +on a higher level. The suggested implementation of conditional composite sequences +would be to request current renderer setup and ensure \fI\%is_format_allowed\fP returns +\fITrue\fP, in which case it\(aqs ok to write composite sequences (as the default renderer +already uses them): +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +seq = \(dq\(dq +if pt.RendererManager.get_default().is_format_allowed: + seq = pt.compose_clear_line_fill_bg(pt.cv.NAVY_BLUE) +pt.echo(seq + \(aqAAAA BBBB\(aq) +.ft P +.fi +.UNINDENT +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.INDENT 3.5 +.SS Todo +.sp +More consistent way of working with composite sequences would be to merge +classes from \fI\%ansi\fP module with classes from \fI\%text\fP module, i.e. make +\fI\%ISequence\fP children also inherit \fI\%IRenderable\fP interface and therefore be +rendered using the same mechanism as for \fI\%Text\fP or \fI\%Fragment\fP, but that would +require quite a bit of refactoring and, considering relatively rare usage of +pre\-rendered composites, was deferred for a time. +.UNINDENT +.UNINDENT +.SS Assisted wrapping +.sp +Similar to the next one, but here we call helper method \fI\%ansi.enclose()\fP, which +automatically builds the closing sequence complement to specified opening one, +while there we pick and insert a closing sequence manually: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +import pytermor as pt + +pt.echo(pt.enclose(pt.SeqIndex.CYAN, \(dqimported\(dq) + \(dq rich.inspect\(dq) +.ft P +.fi +.UNINDENT +.UNINDENT +imported rich.inspect +.SS Manual wrapping +.sp +Pretty straightforward wrapping of target string into a format which, for +example, colors the text with a specified color, can be performed with +f\-stings. All inheritors of \fI\%ISequence\fP class implement \fB__str__()\fP method, +which ensures that they can be safely evaluated in f\-strings even without +format specifying. +.sp +Resetter, of closing sequence, in this case can vary; for example, it can +be \(dqhard\-reset\(dq sequence, which resets the terminal format stack completely (\fBESC +[m\fP), or it can be text color reset sequence (\fBESC [39m\fP), or even more exotic +ones. +.sp +\fI\%SeqIndex\fP class contains prepared sequences which can be inserted into f\-string +directly without any modifications: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +import pytermor as pt + +print(f\(dq{pt.SeqIndex.CYAN}imported{pt.SeqIndex.RESET} rich.inspect\(dq, end=\(dq\(dq) +.ft P +.fi +.UNINDENT +.UNINDENT +imported rich.inspect +.SS Manual instantiating +.sp +In case of necessity of some non\-standard sequence types or \(dqillegal\(dq parameter +values there is also a possibility to build the sequence from the scratch, +instantiating one of the base sequence classes and providing required parameters +values: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +import pytermor as pt + +print(pt.SequenceCSI(\(dqJ\(dq, 2).assemble(), end=\(dq\(dq) +# which is equivalent to: +print(pt.make_erase_in_display(2).assemble(), end=\(dq\(dq) +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +If your case is covered with an existing helper method in \fI\%term\fP package, use it +instead of making new instance directly. This approach will make it easier to +maintain the code, if something in internal logic of sequence base classes changes +in the future. +.SS Manual assembling \s-2\u(don\(aqt do this)\d\s0 +.sp +The last resort method which works in 100% is to assemble the sequence char by char +manually, contain it as a string in source code and just print it when there is a +necessity to do that. The only problem with this approach is an empirical rule, +which says: +.INDENT 0.0 +.INDENT 3.5 +Each raw ANSI escape sequence in the source code reduces +the readability of the whole file by 50%. +.UNINDENT +.UNINDENT +.sp +This means that even 2 SGRs would give 25% readability of the original, while 4 +SGRs give ≈6% (this rule is a joke I made up just now, but the key +idea should be true)\&. +.INDENT 0.0 +.TP +.B In short: +.INDENT 7.0 +.IP \(bu 2 +they are hard to modify, +.IP \(bu 2 +they are hard to maintain, +.IP \(bu 2 +they are hard to debug. +.UNINDENT +.UNINDENT +.sp +Even if it seems OK for a while: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +print(\(aq\ex1b[41m\(aq, end=\(dq(;¬_¬)\(dq) +print(\(aq\ex1b[1;1H\ex1b[41m\ex1b[0K\(aq, end=\(dq(O∆O)\(dq) +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +\&...things get worse pretty fast: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +print(\(aq\ex1b[1;1H\ex1b[38;2;232;232;22m\ex1b[1;41m\ex1b[0K\(aq, end=\(dq(╯°□°)╯\(dq) +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +Compare with the next fragment, which does literally the same as the line +from the example above, but is much easier to read thanks to low\-level abstractions: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +import pytermor as pt +print( + pt.make_reset_cursor(), + pt.make_color_rgb(232, 232, 22), + pt.ansi.SeqIndex.BOLD, + pt.ansi.SeqIndex.BG_RED, + pt.make_erase_in_line(), + sep=\(dq\(dq, end=\(dq(°~°)\(dq, +) +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +Or doing the same with high\-level abstractions instead: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +import pytermor as pt +st = pt.Style(fg=0xe8e816, bg=\(aqred\(aq, bold=True) +fill = pt.compose_clear_line_fill_bg(st.fg.to_sgr()) +pt.echo(fill + \(dq(°v°♡)\(dq, st) +.ft P +.fi +.UNINDENT +.UNINDENT +(°v°♡) +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +The last example also automatically resets the terminal back to normal +state, so that the text that is printed afterwards doesn\(aqt have any formatting, +in contrast with other examples requiring to assemble and print \fI\%SeqIndex.COLOR_OFF\fP +and \fI\%SeqIndex.BG_COLOR_OFF\fP (or just \fI\%SeqIndex.RESET\fP) at the end (which is omitted). +.UNINDENT +.UNINDENT +.SH LIBRARY STRUCTURE +.TS +center; +|l|l|. +_ +T{ +\fI\%ansi\fP +T} T{ +Classes for working with ANSI escape sequences on a lower level. +T} +_ +T{ +\fI\%color\fP +T} T{ +Abstractions for color definitions in three primary modes: 4\-bit, 8\-bit and 24\-bit (\fBxterm\-16\fP, \fBxterm\-256\fP and \fBTrue Color/RGB\fP, respectively). +T} +_ +T{ +\fI\%common\fP +T} T{ +T} +_ +T{ +\fI\%config\fP +T} T{ +Library fine tuning module. +T} +_ +T{ +\fI\%cval\fP +T} T{ +Color preset list: +T} +_ +T{ +\fI\%exception\fP +T} T{ +T} +_ +T{ +\fI\%filter\fP +T} T{ +Formatters for prettier output and utility classes to avoid writing boilerplate code when dealing with escape sequences. +T} +_ +T{ +\fI\%numfmt\fP +T} T{ +utilnum +T} +_ +T{ +\fI\%renderer\fP +T} T{ +Renderers transform \fI\%Style\fP instances into lower\-level abstractions like \fI\%SGR sequences\fP, tmux\-compatible directives, HTML markup etc., depending on renderer type. +T} +_ +T{ +\fI\%style\fP +T} T{ +Reusable data classes that control the appearance of the output \-\- colors (text/background/underline) and attributes (\fIbold\fP, \fIunderlined\fP, \fIitalic\fP, etc.). +T} +_ +T{ +\fI\%template\fP +T} T{ +T} +_ +T{ +\fI\%term\fP +T} T{ +A +T} +_ +T{ +\fI\%text\fP +T} T{ +\(dqFront\-end\(dq module of the library. +T} +_ +.TE +.SH GUIDE · HIGH-LEVEL +.SS Core API I +.SS Glossary +.INDENT 0.0 +.TP +.B rendering +A process of transforming text\-describing instances into specified +output format, e.g. instance of \fI\%Fragment\fP class with content and +\fI\%Style\fP class containing colors and other text formatting can be +rendered into terminal\-compatible string with \fI\%SgrRenderer\fP, or into +HTML markup with \fI\%HtmlRenderer\fP, etc. +.TP +.B style +Class describing text format options: text color, background color, +boldness, underlining, etc. Styles can be inherited and merged +with each other. See \fI\%Style\fP constructor description for the details. +.TP +.B color +Three different classes describing the color options: \fI\%Color16\fP, \fI\%Color256\fP +and \fI\%ColorRGB\fP\&. The first one corresponds to 16\-color terminal mode, the +second \-\- to 256\-color mode, and the last one represents full RGB color +space rather than color index palette. The first two also contain terminal +\fI\%SGR\fP bindings. +.UNINDENT +.SS Core methods +.TS +center; +|l|l|. +_ +T{ +\fI\%text.render\fP([string, fmt, renderer]) +T} T{ +\&. +T} +_ +T{ +\fI\%text.echo\fP([string, fmt, renderer, nl, file, ...]) +T} T{ +\&. +T} +_ +T{ +\fI\%color.resolve_color\fP(subject[, color_type, ...]) +T} T{ +Suggested usage is to transform the user input in a free form in an attempt to find any matching color. +T} +_ +T{ +\fI\%style.make_style\fP([fmt]) +T} T{ +General \fI\%Style\fP constructor. +T} +_ +T{ +\fI\%style.merge_styles\fP([origin, fallbacks, ...]) +T} T{ +Bulk style merging method. +T} +_ +.TE +.SS Text fragments +.SS Renderable class hierarchy +.INDENT 0.0 +.INDENT 2.5 +\fI\%IRenderable\fP inheritance diagram.UNINDENT +.UNINDENT +.SS Styles +.SS Colors +.SS Color mode fallbacks +.SS Color class hierarchy +.IP "System Message: ERROR/3 (/home/a.shavykin/dl/pytermor/docs/pages/guide-hi/colors.rst:, line 35)" +Unknown directive type \(dqgrid\(dq. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +\&.. grid:: 1 + :class\-container: inheritance\-columns + + .. grid\-item:: + + .. inheritance\-diagram:: pytermor.color + :parts: 1 + :top\-classes: pytermor.color.IColorValue, + pytermor.color.NamedColor, + pytermor.color.IndexedColor, + pytermor.color.RenderColor, + pytermor.color.ResolvableColor + :caption: \(ga\(gaColor\(ga\(ga inheritance diagram +.ft P +.fi +.UNINDENT +.UNINDENT +.SS fargs syntax +.INDENT 0.0 +.INDENT 3.5 +.SS Todo +.sp +@TODO +.UNINDENT +.UNINDENT +.SS Renderers +.SS Renderer setup +.sp +The library provides options to select the output format, and that option +comes in the form of \fI\%renderers\fP . +.sp +Selecting the renderer can be accomplished in several ways: +.INDENT 0.0 +.INDENT 3.5 +.INDENT 0.0 +.IP a. 3 +By using general\-purpose functions \fI\%render()\fP and +\fI\%echo()\fP \-\- both have an argument \fBrenderer\fP (preferrable; +\fIintroduced in v2.x\fP). +.IP b. 3 +Method \fI\%RendererManager.set_default()\fP sets the default renderer globally. +After that calling \fI\%render()\fP will automatically invoke a +said renderer and apply the required formatting (but only if \fBrenderer\fP +argument of \fBrender()\fP method is left empty). +.IP c. 3 +Set up the config variable \fI\%Config.renderer_class\fP directly or +via environment variable. +.IP d. 3 +Use renderer\(aqs instance method \fI\%IRenderer.render()\fP directly, +but that\(aqs not recommended and possibly will be deprecated in the future. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +Generally speaking, if you need to invoke a custom renderer just once, it\(aqs +convenient to use the first method for this matter, and use the second one +in all the other cases. +.sp +On the contrary, if there is a necessity to use more than one renderer +alternatingly, it\(aqs better to avoid using the global one at all, and just +instantiate and invoke both renderers independently. +.sp +TL;DR +.sp +To unconditionally print formatted message to standard output, call +\fI\%force_ansi_rendering()\fP and then \fI\%render()\fP\&. +.SS Default renderers priority +.sp +When it comes to the rendering, \fI\%RendererManager\fP will use the first non\-empty +renderer from the list below, skipping the undefined elements: +.INDENT 0.0 +.INDENT 3.5 +.INDENT 0.0 +.IP 1. 3 +Explicitly specified as argument \fBrenderer\fP in methods +\fI\%render()\fP, \fI\%echo()\fP, \fI\%echoi()\fP\&. +.IP 2. 3 +Default renderer in global \fI\%RendererManager\fP class (see +\fI\%RendererManager.set_default()\fP) +.IP 3. 3 +Renderer class in the current loaded library config: +\fI\%Config.renderer_class\fP\&. +.IP 4. 3 +Value from environment variable PYTERMOR_RENDERER_CLASS\&. +.IP 5. 3 +Default library renderer \fI\%SgrRenderer\fP\&. +.UNINDENT +.sp +Argument > RendererManager > Config > Environment > Library\(aqs default +.UNINDENT +.UNINDENT +.SS Output mode auto\-selection +.sp +\fI\%SgrRenderer\fP can be set up with automatic output mode \fI\%OutputMode.AUTO\fP\&. +In that case the renderer will return \fI\%OutputMode.NO_ANSI\fP for any output device +other than terminal emulator, or try to find a matching rule from this list: +.SS Auto output mode parameters and results +.TS +center; +|l|l|l|l|. +_ +T{ +Is a +tty? +T} T{ +\fBTERM\fP +env. var +T} T{ +\fBCOLORTERM\fP +env. var [1] +T} T{ +Result +output mode +T} +_ +T{ + +T} T{ +\fI\%Config.force_output_mode\fP [2] +T} +_ +T{ +No +T} T{ + +T} T{ +\fI\%NO_ANSI\fP +T} +_ +T{ +Yes +T} T{ +\fBxterm\-256color\fP +T} T{ +\fB24bit\fP, +\fBtruecolor\fP +T} T{ +\fI\%TRUE_COLOR\fP +T} +_ +T{ +\fB*\-256color\fP [3] +T} T{ + +T} T{ +\fI\%XTERM_256\fP +T} +_ +T{ +\fBxterm\-color\fP +T} T{ + +T} T{ +\fI\%XTERM_16\fP +T} +_ +T{ +\fBxterm\fP +T} T{ + +T} T{ +\fI\%NO_ANSI\fP +T} +_ +T{ + +T} T{ + +T} T{ +\fI\%Config.default_output_mode\fP [4] +T} +_ +.TE +.INDENT 0.0 +.INDENT 3.5 +.IP [1] 5 +should both env. var requirements be present, they both must be true +as well (i.e. logical AND is applied). +.IP [2] 5 +empty by default and thus ignored +.IP [3] 5 +\fB*\fP represents any string; that\(aqs how e.g. \fIbash 5\fP +determines the color support. +.IP [4] 5 +\fI\%XTERM_256\fP by default, but can be customized. +.UNINDENT +.UNINDENT +.INDENT 0.0 +.INDENT 2.5 +[graph]Auto output mode algorithm.UNINDENT +.UNINDENT +.SS Renderer class hierarchy +.INDENT 0.0 +.INDENT 2.5 +\fI\%IRenderer\fP inheritance tree.UNINDENT +.UNINDENT +.SS Templates +.SS Number formatters +.INDENT 0.0 +.INDENT 3.5 +.SS Todo +.sp +The library contains @TODO +.UNINDENT +.UNINDENT +.SS Auto\-float formatter +.SS Prefixed\-unit formatter +.SS Time delta formatter +[image] +.SS NumFormatter class hierarchy +.IP "System Message: ERROR/3 (/home/a.shavykin/dl/pytermor/docs/pages/guide-hi/num-formatters.rst:, line 38)" +Unknown directive type \(dqgrid\(dq. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +\&.. grid:: 1 + :class\-container: inheritance\-columns + + .. grid\-item:: + + .. inheritance\-diagram:: pytermor.numfmt + :parts: 1 + :top\-classes: pytermor.numfmt.NumFormatter + :caption: \(gaNumFormatter\(ga inheritance tree +.ft P +.fi +.UNINDENT +.UNINDENT +.SS Named colors collection +.INDENT 0.0 +.INDENT 3.5 +.SS Todo +.sp +@TODO +.UNINDENT +.UNINDENT +.SS Dynamic/deferred colors +.INDENT 0.0 +.INDENT 3.5 +.SS Todo +.sp +@TODO +.UNINDENT +.UNINDENT +.SH GUIDE · LOW-LEVEL +.SS Core API II +.sp +So, what\(aqs happening under the hood? +.SS Glossary +.INDENT 0.0 +.TP +.B ASCII +Basic charset developed back in 1960s, consisting of 128 code points. +Nevertheless it is still used nowadays as a part of Unicode character +set. +.TP +.B ANSI +\&..escape sequence is a standard for in\-band signaling to control cursor +location, color, font styling, and other options on video text terminals +and terminal emulators. Certain sequences of bytes, most starting with an +\fI\%ASCII\fP escape character (\fBESC\fP 0x1B) and a bracket +character (\fB[\fP 0x5B), are embedded into text. The terminal +interprets these sequences as commands, rather than text to display +verbatim. [1] +.TP +.B SGR +\&..sequence is a subtype of \fI\%ANSI\fP escape sequences with a varying +amount of parameters. SGR sequences used for changing the color of text or/and +terminal background (in 3 different color modes), as well as for +decorating text with italic font, underline, overline, cross\-line, making +it bold or blinking etc. Represented by \fI\%SequenceSGR\fP class. +.UNINDENT +.IP [1] 5 +\fI\%https://en.wikipedia.org/wiki/ANSI_escape_code\fP +.SS Core methods +.TS +center; +|l|l|. +_ +T{ +\fI\%ansi.SequenceSGR\fP(*params) +T} T{ +Class representing SGR\-type escape sequence with varying amount of parameters. +T} +_ +T{ +\fI\%term.make_color_256\fP(code[, target]) +T} T{ +Wrapper for creation of \fI\%SequenceSGR\fP that sets foreground (or background) to one of 256\-color palette value.: +T} +_ +T{ +\fI\%term.make_color_rgb\fP(r, g, b[, target]) +T} T{ +Wrapper for creation of \fI\%SequenceSGR\fP operating in True Color mode (16M). Valid values for \fBr\fP, \fBg\fP and \fBb\fP are in range of [0; 255]. This range linearly translates into [0x00; 0xFF] for each channel. The result value is composed as \(dq#RRGGBB\(dq. For example, a sequence with color of #ff3300 can be created with::. +T} +_ +T{ +\fI\%color.Color256.to_sgr\fP([target, upper_bound]) +T} T{ +Make an \fI\%SGR sequence\fP out of \fBColor\fP\&. +T} +_ +.TE +.sp +Sources +.INDENT 0.0 +.IP 1. 3 +\fI\%XTerm Control Sequences\fP +.IP 2. 3 +\fI\%ECMA\-48 specification\fP +.UNINDENT +.SS SGR sequences +.SS Format soft reset +.INDENT 0.0 +.INDENT 3.5 +.SS Todo +.sp +This is how you \fBshould\fP format examples: +.UNINDENT +.UNINDENT +.INDENT 0.0 +.INDENT 2.5 +[image] +\fI\%https://chrisyeh96.github.io/2020/03/28/terminal\-colors.html#color\-schemes\fP.UNINDENT +.UNINDENT +.sp +There are two ways to manage color and attribute termination: +.INDENT 0.0 +.IP \(bu 2 +hard reset (SGR\-0 or \fBESC [0m\fP) +.IP \(bu 2 +soft reset (SGR\-22, 23, 24 etc.) +.UNINDENT +.sp +The main difference between them is that \fIhard\fP reset disables all formatting after itself, while \fIsoft\fP +reset disables only actually necessary attributes (i.e. used as opening sequence in \fBSpan\fP instance\(aqs context) +and keeps the other. +.sp +That\(aqs what \fBSpan\fP class is designed for: to simplify creation of soft\-resetting text spans, so that developer +doesn\(aqt have to restore all previously applied formats after every closing sequence. +.sp +Example +.sp +We are given a text span which is initially \fIbold\fP and \fIunderlined\fP\&. We want to recolor a few words inside of this +span. By default this will result in losing all the formatting to the right of updated text span (because +\fI\%RESET\fP, or \fBESC [0m\fP, clears all text attributes). +.sp +However, there is an option to specify what attributes should be disabled or let the library do that for you: +[image] +.sp +As you can see, the update went well \-\- we kept all the previously applied formatting. Of course, this method +cannot be 100% applicable; for example, imagine that original text was colored blue. After the update \(dqstring\(dq +word won\(aqt be blue anymore, as we used \fBSeqIndex.COLOR_OFF\fP escape sequence to neutralize our own yellow color. +But it still can be helpful for a majority of cases (especially when text is generated and formatted by the same +program and in one go). +.SS Working with Spans +.sp +Use \fBSpan\fP constructor to create new instance with specified control sequence(s) as a opening/starter sequence +and \fBautomatically composed\fP closing sequence that will terminate attributes defined in opening sequence while +keeping the others (soft reset). +.sp +Resulting sequence params\(aq order is the same as argument\(aqs order. +.sp +Each sequence param can be specified as: +.INDENT 0.0 +.IP \(bu 2 +string key (see \fBansi\-presets\fP); +.IP \(bu 2 +integer param value; +.IP \(bu 2 +existing \fI\%SequenceSGR\fP instance (params will be extracted). +.UNINDENT +.sp +It\(aqs also possible to avoid auto\-composing mechanism and create \fBSpan\fP with +explicitly set parameters using \fBSpan.init_explicit()\fP\&. +.SS Creating and applying SGRs +.sp +You can use any of predefined sequences from \fI\%SeqIndex\fP registry or create your own via standard constructor. Valid +argument values as well as preset constants are described in \fBansi\-presets\fP page. +.sp +\fBIMPORTANT:\fP +.INDENT 0.0 +.INDENT 3.5 +\fI\%SequenceSGR\fP with zero params \fBESC [m\fP is interpreted by terminal emulators as \fBESC [0m\fP, which is \fIhard\fP reset sequence. +.UNINDENT +.UNINDENT +.sp +There is also a set of methods for dynamic \fI\%SequenceSGR\fP creation: +.INDENT 0.0 +.IP \(bu 2 +\fI\%make_color_256()\fP will produce sequence operating in 256\-colors mode (for a complete list +see \fBansi\-presets\fP); +.IP \(bu 2 +\fI\%make_color_rgb()\fP will create a sequence capable of setting the colors in True Color 16M mode (however, some terminal emulators doesn\(aqt +support it). +.UNINDENT +.sp +To get the resulting sequence chars use \fBassemble()\fP method or cast instance to \fIstr\fP\&. +[image] +.INDENT 0.0 +.IP \(bu 2 +First line is the string with encoded escape sequence; +.IP \(bu 2 +Second line shows up the string in raw mode, as if sequences were ignored by the terminal; +.IP \(bu 2 +Third line is hexadecimal string representation. +.UNINDENT +.SS \fI\%SGR\fP sequence structure +.INDENT 0.0 +.IP 1. 3 +\fBESC\fP is escape \fIcontrol character\fP, which opens a control sequence (can also be +written as \fB\ex1b\fP, \fB\e033\fP or \fB\ee\fP). +.IP 2. 3 +\fB[\fP is sequence \fIclassifier\fP; it determines the type of control sequence (in this case +it\(aqs CSI). +.IP 3. 3 +\fB4\fP and \fB7\fP are \fIparameters\fP of the escape sequence; they mean \(dqunderlined\(dq and \(dqinversed\(dq +attributes respectively. Those parameters must be separated by \fB;\fP\&. +.IP 4. 3 +\fBm\fP is sequence \fIterminator\fP; it also determines the sub\-type of sequence, in our +case SGR\&. Sequences of this kind are most commonly encountered. +.UNINDENT +.SS Combining SGRs +.sp +One instance of \fI\%SequenceSGR\fP can be added to another. This will result in a new \fBSequenceSGR\fP with combined params. +.SS Sequence class hierarchy +.INDENT 0.0 +.INDENT 2.5 +\fI\%ISequence\fP inheritance tree.UNINDENT +.UNINDENT +.SS Sequence presets +.sp +Preset lists are omitted from API docs to avoid unnesessary duplication; +summary list of all presets defined in the library (excluding \fButil*\fP) +is displayed here. +.INDENT 0.0 +.INDENT 3.5 +.SS Todo +.sp +USAGE \- list all memthods that accept string keys of those prsets. +.UNINDENT +.UNINDENT +.sp +There are two types of color palettes used in modern terminals \-\- first one +containing 16 colors (\fI\%Color16\fP), and second one consisting of 256 colors +(\fI\%Color256\fP). There is also True Color mode (referenced as \fIRGB\fP mode), +but it is not palette\-based. +.SS Meta, attributes, resetters +.TS +center; +|l|l|l|l|l|. +_ +T{ +T} T{ +\fBName\fP +T} T{ +int +T} T{ +sty +T} T{ +\fBDescription\fP +T} +_ +T{ +Meta +T} +_ +T{ +T} T{ +\fBNOOP\fP +T} T{ +T} T{ +\fBV\fP +T} T{ +No\-operation; always assembled as empty string +T} +_ +T{ +T} T{ +\fBRESET\fP +T} T{ +\fB0\fP +T} T{ +T} T{ +Reset all attributes and colors +T} +_ +T{ +Attributes +T} +_ +T{ +T} T{ +\fBBOLD\fP +T} T{ +\fB1\fP +T} T{ +\fBV\fP\ [1] +T} T{ +Bold or increased intensity +T} +_ +T{ +T} T{ +\fBDIM\fP +T} T{ +\fB2\fP +T} T{ +\fBV\fP +T} T{ +Faint, decreased intensity +T} +_ +T{ +T} T{ +\fBITALIC\fP +T} T{ +\fB3\fP +T} T{ +\fBV\fP +T} T{ +Italic; \fInot widely supported\fP +T} +_ +T{ +T} T{ +\fBUNDERLINED\fP +T} T{ +\fB4\fP +T} T{ +\fBV\fP +T} T{ +Underline +T} +_ +T{ +T} T{ +\fBBLINK_SLOW\fP +T} T{ +\fB5\fP +T} T{ +\fBV\fP\ [2] +T} T{ +Set blinking to < 150 cpm +T} +_ +T{ +T} T{ +\fBBLINK_FAST\fP +T} T{ +\fB6\fP +T} T{ +T} T{ +Set blinking to 150+ cpm; \fInot widely supported\fP +T} +_ +T{ +T} T{ +\fBINVERSED\fP +T} T{ +\fB7\fP +T} T{ +\fBV\fP +T} T{ +Swap foreground and background colors +T} +_ +T{ +T} T{ +\fBHIDDEN\fP +T} T{ +\fB8\fP +T} T{ +T} T{ +Conceal characters; \fInot widely supported\fP +T} +_ +T{ +T} T{ +\fBCROSSLINED\fP +T} T{ +\fB9\fP +T} T{ +\fBV\fP +T} T{ +Strikethrough +T} +_ +T{ +T} T{ +\fBDOUBLE_UNDERLINED\fP +T} T{ +\fB21\fP +T} T{ +T} T{ +Double\-underline; \fIon several terminals disables\fP \fBBOLD\fP \fIinstead\fP +T} +_ +T{ +T} T{ +\fBCOLOR_EXTENDED\fP +T} T{ +\fB38\fP +T} T{ +T} T{ +Set foreground color [\fIindexed\fP/\fIRGB\fP mode]; +\fIuse\fP \fI\%make_color_256\fP \fIand\fP \fI\%make_color_rgb\fP \fIinstead\fP +T} +_ +T{ +T} T{ +\fBBG_COLOR_EXTENDED\fP +T} T{ +\fB48\fP +T} T{ +T} T{ +Set background color [\fIindexed\fP/\fIRGB\fP mode]; +\fIuse\fP \fI\%make_color_256\fP \fIand\fP \fI\%make_color_rgb\fP \fIinstead\fP +T} +_ +T{ +T} T{ +\fBOVERLINED\fP +T} T{ +\fB53\fP +T} T{ +\fBV\fP +T} T{ +Overline; \fInot widely supported\fP +T} +_ +T{ +Resetters +T} +_ +T{ +T} T{ +\fBBOLD_DIM_OFF\fP +T} T{ +\fB22\fP +T} T{ +T} T{ +Disable \fBBOLD\fP and \fBDIM\fP attributes. \fISpecial aspects... It\(aqs +impossible to reliably disable them on a separate basis.\fP +T} +_ +T{ +T} T{ +\fBITALIC_OFF\fP +T} T{ +\fB23\fP +T} T{ +T} T{ +Disable italic +T} +_ +T{ +T} T{ +\fBUNDERLINED_OFF\fP +T} T{ +\fB24\fP +T} T{ +T} T{ +Disable underlining +T} +_ +T{ +T} T{ +\fBBLINK_OFF\fP +T} T{ +\fB25\fP +T} T{ +T} T{ +Disable blinking +T} +_ +T{ +T} T{ +\fBINVERSED_OFF\fP +T} T{ +\fB27\fP +T} T{ +T} T{ +Disable inversing +T} +_ +T{ +T} T{ +\fBHIDDEN_OFF\fP +T} T{ +\fB28\fP +T} T{ +T} T{ +Disable conecaling +T} +_ +T{ +T} T{ +\fBCROSSLINED_OFF\fP +T} T{ +\fB29\fP +T} T{ +T} T{ +Disable strikethrough +T} +_ +T{ +T} T{ +\fBCOLOR_OFF\fP +T} T{ +\fB39\fP +T} T{ +T} T{ +Reset foreground color +T} +_ +T{ +T} T{ +\fBBG_COLOR_OFF\fP +T} T{ +\fB49\fP +T} T{ +T} T{ +Reset background color +T} +_ +T{ +T} T{ +\fBOVERLINED_OFF\fP +T} T{ +\fB55\fP +T} T{ +T} T{ +Disable overlining +T} +_ +T{ +.IP [1] 5 +for this and subsequent items in \(dqAttributes\(dq section: as boolean flags. +.IP [2] 5 +as \fBblink\fP\&. +T} +_ +.TE +.SS Color16 presets +.TS +center; +|l|l|l|l|l|l|. +_ +T{ +T} T{ +\fBName\fP +T} T{ +int +T} T{ +sty +T} T{ +\fBRGB code\fP +T} T{ +\fBXTerm name\fP +T} +_ +T{ +Foreground \fIdefault\fP colors +T} +_ +T{ +[image] +T} T{ +\fBBLACK\fP +T} T{ +\fB30\fP +T} T{ +T} T{ +\fB#000000\fP +T} T{ +Black +T} +_ +T{ +[image] +T} T{ +\fBRED\fP +T} T{ +\fB31\fP +T} T{ +T} T{ +\fB#800000\fP +T} T{ +Maroon +T} +_ +T{ +[image] +T} T{ +\fBGREEN\fP +T} T{ +\fB32\fP +T} T{ +T} T{ +\fB#008000\fP +T} T{ +Green +T} +_ +T{ +[image] +T} T{ +\fBYELLOW\fP +T} T{ +\fB33\fP +T} T{ +T} T{ +\fB#808000\fP +T} T{ +Olive +T} +_ +T{ +[image] +T} T{ +\fBBLUE\fP +T} T{ +\fB34\fP +T} T{ +T} T{ +\fB#000080\fP +T} T{ +Navy +T} +_ +T{ +[image] +T} T{ +\fBMAGENTA\fP +T} T{ +\fB35\fP +T} T{ +T} T{ +\fB#800080\fP +T} T{ +Purple +T} +_ +T{ +[image] +T} T{ +\fBCYAN\fP +T} T{ +\fB36\fP +T} T{ +T} T{ +\fB#008080\fP +T} T{ +Teal +T} +_ +T{ +[image] +T} T{ +\fBWHITE\fP +T} T{ +\fB37\fP +T} T{ +T} T{ +\fB#c0c0c0\fP +T} T{ +Silver +T} +_ +T{ +Background \fIdefault\fP colors +T} +_ +T{ +[image] +T} T{ +\fBBG_BLACK\fP +T} T{ +\fB40\fP +T} T{ +T} T{ +\fB#000000\fP +T} T{ +Black +T} +_ +T{ +[image] +T} T{ +\fBBG_RED\fP +T} T{ +\fB41\fP +T} T{ +T} T{ +\fB#800000\fP +T} T{ +Maroon +T} +_ +T{ +[image] +T} T{ +\fBBG_GREEN\fP +T} T{ +\fB42\fP +T} T{ +T} T{ +\fB#008000\fP +T} T{ +Green +T} +_ +T{ +[image] +T} T{ +\fBBG_YELLOW\fP +T} T{ +\fB43\fP +T} T{ +T} T{ +\fB#808000\fP +T} T{ +Olive +T} +_ +T{ +[image] +T} T{ +\fBBG_BLUE\fP +T} T{ +\fB44\fP +T} T{ +T} T{ +\fB#000080\fP +T} T{ +Navy +T} +_ +T{ +[image] +T} T{ +\fBBG_MAGENTA\fP +T} T{ +\fB45\fP +T} T{ +T} T{ +\fB#800080\fP +T} T{ +Purple +T} +_ +T{ +[image] +T} T{ +\fBBG_CYAN\fP +T} T{ +\fB46\fP +T} T{ +T} T{ +\fB#008080\fP +T} T{ +Teal +T} +_ +T{ +[image] +T} T{ +\fBBG_WHITE\fP +T} T{ +\fB47\fP +T} T{ +T} T{ +\fB#c0c0c0\fP +T} T{ +Silver +T} +_ +T{ +High\-intensity foreground \fIdefault\fP colors +T} +_ +T{ +[image] +T} T{ +\fBGRAY\fP +T} T{ +\fB90\fP +T} T{ +T} T{ +\fB#808080\fP +T} T{ +Grey +T} +_ +T{ +[image] +T} T{ +\fBHI_RED\fP +T} T{ +\fB91\fP +T} T{ +T} T{ +\fB#ff0000\fP +T} T{ +Red +T} +_ +T{ +[image] +T} T{ +\fBHI_GREEN\fP +T} T{ +\fB92\fP +T} T{ +T} T{ +\fB#00ff00\fP +T} T{ +Lime +T} +_ +T{ +[image] +T} T{ +\fBHI_YELLOW\fP +T} T{ +\fB93\fP +T} T{ +T} T{ +\fB#ffff00\fP +T} T{ +Yellow +T} +_ +T{ +[image] +T} T{ +\fBHI_BLUE\fP +T} T{ +\fB94\fP +T} T{ +T} T{ +\fB#0000ff\fP +T} T{ +Blue +T} +_ +T{ +[image] +T} T{ +\fBHI_MAGENTA\fP +T} T{ +\fB95\fP +T} T{ +T} T{ +\fB#ff00ff\fP +T} T{ +Fuchsia +T} +_ +T{ +[image] +T} T{ +\fBHI_CYAN\fP +T} T{ +\fB96\fP +T} T{ +T} T{ +\fB#00ffff\fP +T} T{ +Aqua +T} +_ +T{ +[image] +T} T{ +\fBHI_WHITE\fP +T} T{ +\fB97\fP +T} T{ +T} T{ +\fB#ffffff\fP +T} T{ +White +T} +_ +T{ +High\-intensity background \fIdefault\fP colors +T} +_ +T{ +[image] +T} T{ +\fBBG_GRAY\fP +T} T{ +\fB100\fP +T} T{ +T} T{ +\fB#808080\fP +T} T{ +Grey +T} +_ +T{ +[image] +T} T{ +\fBBG_HI_RED\fP +T} T{ +\fB101\fP +T} T{ +T} T{ +\fB#ff0000\fP +T} T{ +Red +T} +_ +T{ +[image] +T} T{ +\fBBG_HI_GREEN\fP +T} T{ +\fB102\fP +T} T{ +T} T{ +\fB#00ff00\fP +T} T{ +Lime +T} +_ +T{ +[image] +T} T{ +\fBBG_HI_YELLOW\fP +T} T{ +\fB103\fP +T} T{ +T} T{ +\fB#ffff00\fP +T} T{ +Yellow +T} +_ +T{ +[image] +T} T{ +\fBBG_HI_BLUE\fP +T} T{ +\fB104\fP +T} T{ +T} T{ +\fB#0000ff\fP +T} T{ +Blue +T} +_ +T{ +[image] +T} T{ +\fBBG_HI_MAGENTA\fP +T} T{ +\fB105\fP +T} T{ +T} T{ +\fB#ff00ff\fP +T} T{ +Fuchsia +T} +_ +T{ +[image] +T} T{ +\fBBG_HI_CYAN\fP +T} T{ +\fB106\fP +T} T{ +T} T{ +\fB#00ffff\fP +T} T{ +Aqua +T} +_ +T{ +[image] +T} T{ +\fBBG_HI_WHITE\fP +T} T{ +\fB107\fP +T} T{ +T} T{ +\fB#ffffff\fP +T} T{ +White +T} +_ +.TE +.SS Color256 presets +.TS +center; +|l|l|l|l|l|l|. +_ +T{ +T} T{ +\fBName\fP +T} T{ +int +T} T{ +sty +T} T{ +\fBRGB code\fP +T} T{ +\fBXTerm name\fP +T} +_ +T{ +T} T{ +\fBXTERM_BLACK\fP [3] +T} T{ +\fB0\fP +T} T{ +T} T{ +\fB#000000\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_MAROON\fP +T} T{ +\fB1\fP +T} T{ +T} T{ +\fB#800000\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREEN\fP +T} T{ +\fB2\fP +T} T{ +T} T{ +\fB#008000\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_OLIVE\fP +T} T{ +\fB3\fP +T} T{ +T} T{ +\fB#808000\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_NAVY\fP +T} T{ +\fB4\fP +T} T{ +T} T{ +\fB#000080\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_PURPLE_5\fP +T} T{ +\fB5\fP +T} T{ +T} T{ +\fB#800080\fP +T} T{ +\fBPurple\fP [4] +T} +_ +T{ +T} T{ +\fBXTERM_TEAL\fP +T} T{ +\fB6\fP +T} T{ +T} T{ +\fB#008080\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_SILVER\fP +T} T{ +\fB7\fP +T} T{ +T} T{ +\fB#c0c0c0\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY\fP +T} T{ +\fB8\fP +T} T{ +T} T{ +\fB#808080\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_RED\fP +T} T{ +\fB9\fP +T} T{ +T} T{ +\fB#ff0000\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_LIME\fP +T} T{ +\fB10\fP +T} T{ +T} T{ +\fB#00ff00\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_YELLOW\fP +T} T{ +\fB11\fP +T} T{ +T} T{ +\fB#ffff00\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_BLUE\fP +T} T{ +\fB12\fP +T} T{ +T} T{ +\fB#0000ff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_FUCHSIA\fP +T} T{ +\fB13\fP +T} T{ +T} T{ +\fB#ff00ff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_AQUA\fP +T} T{ +\fB14\fP +T} T{ +T} T{ +\fB#00ffff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_WHITE\fP +T} T{ +\fB15\fP +T} T{ +T} T{ +\fB#ffffff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_0\fP +T} T{ +\fB16\fP +T} T{ +T} T{ +\fB#000000\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_NAVY_BLUE\fP +T} T{ +\fB17\fP +T} T{ +T} T{ +\fB#00005f\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DARK_BLUE\fP +T} T{ +\fB18\fP +T} T{ +T} T{ +\fB#000087\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_BLUE_3\fP +T} T{ +\fB19\fP +T} T{ +T} T{ +\fB#0000af\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_BLUE_2\fP +T} T{ +\fB20\fP +T} T{ +T} T{ +\fB#0000d7\fP +T} T{ +\fBBlue3\fP +T} +_ +T{ +T} T{ +\fBXTERM_BLUE_1\fP +T} T{ +\fB21\fP +T} T{ +T} T{ +\fB#0000ff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DARK_GREEN\fP +T} T{ +\fB22\fP +T} T{ +T} T{ +\fB#005f00\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DEEP_SKY_BLUE_7\fP +T} T{ +\fB23\fP +T} T{ +T} T{ +\fB#005f5f\fP +T} T{ +\fBDeepSkyBlue4\fP +T} +_ +T{ +T} T{ +\fBXTERM_DEEP_SKY_BLUE_6\fP +T} T{ +\fB24\fP +T} T{ +T} T{ +\fB#005f87\fP +T} T{ +\fBDeepSkyBlue4\fP +T} +_ +T{ +T} T{ +\fBXTERM_DEEP_SKY_BLUE_5\fP +T} T{ +\fB25\fP +T} T{ +T} T{ +\fB#005faf\fP +T} T{ +\fBDeepSkyBlue4\fP +T} +_ +T{ +T} T{ +\fBXTERM_DODGER_BLUE_3\fP +T} T{ +\fB26\fP +T} T{ +T} T{ +\fB#005fd7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DODGER_BLUE_2\fP +T} T{ +\fB27\fP +T} T{ +T} T{ +\fB#005fff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREEN_5\fP +T} T{ +\fB28\fP +T} T{ +T} T{ +\fB#008700\fP +T} T{ +\fBGreen4\fP +T} +_ +T{ +T} T{ +\fBXTERM_SPRING_GREEN_4\fP +T} T{ +\fB29\fP +T} T{ +T} T{ +\fB#00875f\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_TURQUOISE_4\fP +T} T{ +\fB30\fP +T} T{ +T} T{ +\fB#008787\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DEEP_SKY_BLUE_4\fP +T} T{ +\fB31\fP +T} T{ +T} T{ +\fB#0087af\fP +T} T{ +\fBDeepSkyBlue3\fP +T} +_ +T{ +T} T{ +\fBXTERM_DEEP_SKY_BLUE_3\fP +T} T{ +\fB32\fP +T} T{ +T} T{ +\fB#0087d7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DODGER_BLUE_1\fP +T} T{ +\fB33\fP +T} T{ +T} T{ +\fB#0087ff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREEN_4\fP +T} T{ +\fB34\fP +T} T{ +T} T{ +\fB#00af00\fP +T} T{ +\fBGreen3\fP +T} +_ +T{ +T} T{ +\fBXTERM_SPRING_GREEN_5\fP +T} T{ +\fB35\fP +T} T{ +T} T{ +\fB#00af5f\fP +T} T{ +\fBSpringGreen3\fP +T} +_ +T{ +T} T{ +\fBXTERM_DARK_CYAN\fP +T} T{ +\fB36\fP +T} T{ +T} T{ +\fB#00af87\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_SEA_GREEN\fP +T} T{ +\fB37\fP +T} T{ +T} T{ +\fB#00afaf\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DEEP_SKY_BLUE_2\fP +T} T{ +\fB38\fP +T} T{ +T} T{ +\fB#00afd7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DEEP_SKY_BLUE_1\fP +T} T{ +\fB39\fP +T} T{ +T} T{ +\fB#00afff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREEN_3\fP +T} T{ +\fB40\fP +T} T{ +T} T{ +\fB#00d700\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_SPRING_GREEN_3\fP +T} T{ +\fB41\fP +T} T{ +T} T{ +\fB#00d75f\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_SPRING_GREEN_6\fP +T} T{ +\fB42\fP +T} T{ +T} T{ +\fB#00d787\fP +T} T{ +\fBSpringGreen2\fP +T} +_ +T{ +T} T{ +\fBXTERM_CYAN_3\fP +T} T{ +\fB43\fP +T} T{ +T} T{ +\fB#00d7af\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DARK_TURQUOISE\fP +T} T{ +\fB44\fP +T} T{ +T} T{ +\fB#00d7d7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_TURQUOISE_2\fP +T} T{ +\fB45\fP +T} T{ +T} T{ +\fB#00d7ff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREEN_2\fP +T} T{ +\fB46\fP +T} T{ +T} T{ +\fB#00ff00\fP +T} T{ +\fBGreen1\fP +T} +_ +T{ +T} T{ +\fBXTERM_SPRING_GREEN_2\fP +T} T{ +\fB47\fP +T} T{ +T} T{ +\fB#00ff5f\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_SPRING_GREEN_1\fP +T} T{ +\fB48\fP +T} T{ +T} T{ +\fB#00ff87\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_MEDIUM_SPRING_GREEN\fP +T} T{ +\fB49\fP +T} T{ +T} T{ +\fB#00ffaf\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_CYAN_2\fP +T} T{ +\fB50\fP +T} T{ +T} T{ +\fB#00ffd7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_CYAN_1\fP +T} T{ +\fB51\fP +T} T{ +T} T{ +\fB#00ffff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DARK_RED_2\fP +T} T{ +\fB52\fP +T} T{ +T} T{ +\fB#5f0000\fP +T} T{ +\fBDarkRed\fP +T} +_ +T{ +T} T{ +\fBXTERM_DEEP_PINK_8\fP +T} T{ +\fB53\fP +T} T{ +T} T{ +\fB#5f005f\fP +T} T{ +\fBDeepPink4\fP +T} +_ +T{ +T} T{ +\fBXTERM_PURPLE_6\fP +T} T{ +\fB54\fP +T} T{ +T} T{ +\fB#5f0087\fP +T} T{ +\fBPurple4\fP +T} +_ +T{ +T} T{ +\fBXTERM_PURPLE_4\fP +T} T{ +\fB55\fP +T} T{ +T} T{ +\fB#5f00af\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_PURPLE_3\fP +T} T{ +\fB56\fP +T} T{ +T} T{ +\fB#5f00d7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_BLUE_VIOLET\fP +T} T{ +\fB57\fP +T} T{ +T} T{ +\fB#5f00ff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_ORANGE_4\fP +T} T{ +\fB58\fP +T} T{ +T} T{ +\fB#5f5f00\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_37\fP +T} T{ +\fB59\fP +T} T{ +T} T{ +\fB#5f5f5f\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_MEDIUM_PURPLE_7\fP +T} T{ +\fB60\fP +T} T{ +T} T{ +\fB#5f5f87\fP +T} T{ +\fBMediumPurple4\fP +T} +_ +T{ +T} T{ +\fBXTERM_SLATE_BLUE_3\fP +T} T{ +\fB61\fP +T} T{ +T} T{ +\fB#5f5faf\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_SLATE_BLUE_2\fP +T} T{ +\fB62\fP +T} T{ +T} T{ +\fB#5f5fd7\fP +T} T{ +\fBSlateBlue3\fP +T} +_ +T{ +T} T{ +\fBXTERM_ROYAL_BLUE_1\fP +T} T{ +\fB63\fP +T} T{ +T} T{ +\fB#5f5fff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_CHARTREUSE_6\fP +T} T{ +\fB64\fP +T} T{ +T} T{ +\fB#5f8700\fP +T} T{ +\fBChartreuse4\fP +T} +_ +T{ +T} T{ +\fBXTERM_DARK_SEA_GREEN_9\fP +T} T{ +\fB65\fP +T} T{ +T} T{ +\fB#5f875f\fP +T} T{ +\fBDarkSeaGreen4\fP +T} +_ +T{ +T} T{ +\fBXTERM_PALE_TURQUOISE_4\fP +T} T{ +\fB66\fP +T} T{ +T} T{ +\fB#5f8787\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_STEEL_BLUE\fP +T} T{ +\fB67\fP +T} T{ +T} T{ +\fB#5f87af\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_STEEL_BLUE_3\fP +T} T{ +\fB68\fP +T} T{ +T} T{ +\fB#5f87d7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_CORNFLOWER_BLUE\fP +T} T{ +\fB69\fP +T} T{ +T} T{ +\fB#5f87ff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_CHARTREUSE_5\fP +T} T{ +\fB70\fP +T} T{ +T} T{ +\fB#5faf00\fP +T} T{ +\fBChartreuse3\fP +T} +_ +T{ +T} T{ +\fBXTERM_DARK_SEA_GREEN_8\fP +T} T{ +\fB71\fP +T} T{ +T} T{ +\fB#5faf5f\fP +T} T{ +\fBDarkSeaGreen4\fP +T} +_ +T{ +T} T{ +\fBXTERM_CADET_BLUE_2\fP +T} T{ +\fB72\fP +T} T{ +T} T{ +\fB#5faf87\fP +T} T{ +\fBCadetBlue\fP +T} +_ +T{ +T} T{ +\fBXTERM_CADET_BLUE\fP +T} T{ +\fB73\fP +T} T{ +T} T{ +\fB#5fafaf\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_SKY_BLUE_3\fP +T} T{ +\fB74\fP +T} T{ +T} T{ +\fB#5fafd7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_STEEL_BLUE_2\fP +T} T{ +\fB75\fP +T} T{ +T} T{ +\fB#5fafff\fP +T} T{ +\fBSteelBlue1\fP +T} +_ +T{ +T} T{ +\fBXTERM_CHARTREUSE_4\fP +T} T{ +\fB76\fP +T} T{ +T} T{ +\fB#5fd700\fP +T} T{ +\fBChartreuse3\fP +T} +_ +T{ +T} T{ +\fBXTERM_PALE_GREEN_4\fP +T} T{ +\fB77\fP +T} T{ +T} T{ +\fB#5fd75f\fP +T} T{ +\fBPaleGreen3\fP +T} +_ +T{ +T} T{ +\fBXTERM_SEA_GREEN_3\fP +T} T{ +\fB78\fP +T} T{ +T} T{ +\fB#5fd787\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_AQUAMARINE_3\fP +T} T{ +\fB79\fP +T} T{ +T} T{ +\fB#5fd7af\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_MEDIUM_TURQUOISE\fP +T} T{ +\fB80\fP +T} T{ +T} T{ +\fB#5fd7d7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_STEEL_BLUE_1\fP +T} T{ +\fB81\fP +T} T{ +T} T{ +\fB#5fd7ff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_CHARTREUSE_2\fP +T} T{ +\fB82\fP +T} T{ +T} T{ +\fB#5fff00\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_SEA_GREEN_4\fP +T} T{ +\fB83\fP +T} T{ +T} T{ +\fB#5fff5f\fP +T} T{ +\fBSeaGreen2\fP +T} +_ +T{ +T} T{ +\fBXTERM_SEA_GREEN_2\fP +T} T{ +\fB84\fP +T} T{ +T} T{ +\fB#5fff87\fP +T} T{ +\fBSeaGreen1\fP +T} +_ +T{ +T} T{ +\fBXTERM_SEA_GREEN_1\fP +T} T{ +\fB85\fP +T} T{ +T} T{ +\fB#5fffaf\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_AQUAMARINE_2\fP +T} T{ +\fB86\fP +T} T{ +T} T{ +\fB#5fffd7\fP +T} T{ +\fBAquamarine1\fP +T} +_ +T{ +T} T{ +\fBXTERM_DARK_SLATE_GRAY_2\fP +T} T{ +\fB87\fP +T} T{ +T} T{ +\fB#5fffff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DARK_RED\fP +T} T{ +\fB88\fP +T} T{ +T} T{ +\fB#870000\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DEEP_PINK_7\fP +T} T{ +\fB89\fP +T} T{ +T} T{ +\fB#87005f\fP +T} T{ +\fBDeepPink4\fP +T} +_ +T{ +T} T{ +\fBXTERM_DARK_MAGENTA_2\fP +T} T{ +\fB90\fP +T} T{ +T} T{ +\fB#870087\fP +T} T{ +\fBDarkMagenta\fP +T} +_ +T{ +T} T{ +\fBXTERM_DARK_MAGENTA\fP +T} T{ +\fB91\fP +T} T{ +T} T{ +\fB#8700af\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DARK_VIOLET_2\fP +T} T{ +\fB92\fP +T} T{ +T} T{ +\fB#8700d7\fP +T} T{ +\fBDarkViolet\fP +T} +_ +T{ +T} T{ +\fBXTERM_PURPLE_2\fP +T} T{ +\fB93\fP +T} T{ +T} T{ +\fB#8700ff\fP +T} T{ +\fBPurple\fP +T} +_ +T{ +T} T{ +\fBXTERM_ORANGE_3\fP +T} T{ +\fB94\fP +T} T{ +T} T{ +\fB#875f00\fP +T} T{ +\fBOrange4\fP +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_PINK_3\fP +T} T{ +\fB95\fP +T} T{ +T} T{ +\fB#875f5f\fP +T} T{ +\fBLightPink4\fP +T} +_ +T{ +T} T{ +\fBXTERM_PLUM_4\fP +T} T{ +\fB96\fP +T} T{ +T} T{ +\fB#875f87\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_MEDIUM_PURPLE_6\fP +T} T{ +\fB97\fP +T} T{ +T} T{ +\fB#875faf\fP +T} T{ +\fBMediumPurple3\fP +T} +_ +T{ +T} T{ +\fBXTERM_MEDIUM_PURPLE_5\fP +T} T{ +\fB98\fP +T} T{ +T} T{ +\fB#875fd7\fP +T} T{ +\fBMediumPurple3\fP +T} +_ +T{ +T} T{ +\fBXTERM_SLATE_BLUE_1\fP +T} T{ +\fB99\fP +T} T{ +T} T{ +\fB#875fff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_YELLOW_6\fP +T} T{ +\fB100\fP +T} T{ +T} T{ +\fB#878700\fP +T} T{ +\fBYellow4\fP +T} +_ +T{ +T} T{ +\fBXTERM_WHEAT_4\fP +T} T{ +\fB101\fP +T} T{ +T} T{ +\fB#87875f\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_53\fP +T} T{ +\fB102\fP +T} T{ +T} T{ +\fB#878787\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_SLATE_GREY\fP +T} T{ +\fB103\fP +T} T{ +T} T{ +\fB#8787af\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_MEDIUM_PURPLE_4\fP +T} T{ +\fB104\fP +T} T{ +T} T{ +\fB#8787d7\fP +T} T{ +\fBMediumPurple\fP +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_SLATE_BLUE\fP +T} T{ +\fB105\fP +T} T{ +T} T{ +\fB#8787ff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_YELLOW_4\fP +T} T{ +\fB106\fP +T} T{ +T} T{ +\fB#87af00\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DARK_OLIVE_GREEN_6\fP +T} T{ +\fB107\fP +T} T{ +T} T{ +\fB#87af5f\fP +T} T{ +\fBDarkOliveGreen3\fP +T} +_ +T{ +T} T{ +\fBXTERM_DARK_SEA_GREEN_7\fP +T} T{ +\fB108\fP +T} T{ +T} T{ +\fB#87af87\fP +T} T{ +\fBDarkSeaGreen\fP +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_SKY_BLUE_3\fP +T} T{ +\fB109\fP +T} T{ +T} T{ +\fB#87afaf\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_SKY_BLUE_2\fP +T} T{ +\fB110\fP +T} T{ +T} T{ +\fB#87afd7\fP +T} T{ +\fBLightSkyBlue3\fP +T} +_ +T{ +T} T{ +\fBXTERM_SKY_BLUE_2\fP +T} T{ +\fB111\fP +T} T{ +T} T{ +\fB#87afff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_CHARTREUSE_3\fP +T} T{ +\fB112\fP +T} T{ +T} T{ +\fB#87d700\fP +T} T{ +\fBChartreuse2\fP +T} +_ +T{ +T} T{ +\fBXTERM_DARK_OLIVE_GREEN_4\fP +T} T{ +\fB113\fP +T} T{ +T} T{ +\fB#87d75f\fP +T} T{ +\fBDarkOliveGreen3\fP +T} +_ +T{ +T} T{ +\fBXTERM_PALE_GREEN_3\fP +T} T{ +\fB114\fP +T} T{ +T} T{ +\fB#87d787\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DARK_SEA_GREEN_5\fP +T} T{ +\fB115\fP +T} T{ +T} T{ +\fB#87d7af\fP +T} T{ +\fBDarkSeaGreen3\fP +T} +_ +T{ +T} T{ +\fBXTERM_DARK_SLATE_GRAY_3\fP +T} T{ +\fB116\fP +T} T{ +T} T{ +\fB#87d7d7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_SKY_BLUE_1\fP +T} T{ +\fB117\fP +T} T{ +T} T{ +\fB#87d7ff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_CHARTREUSE_1\fP +T} T{ +\fB118\fP +T} T{ +T} T{ +\fB#87ff00\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_GREEN_2\fP +T} T{ +\fB119\fP +T} T{ +T} T{ +\fB#87ff5f\fP +T} T{ +\fBLightGreen\fP +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_GREEN\fP +T} T{ +\fB120\fP +T} T{ +T} T{ +\fB#87ff87\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_PALE_GREEN_1\fP +T} T{ +\fB121\fP +T} T{ +T} T{ +\fB#87ffaf\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_AQUAMARINE_1\fP +T} T{ +\fB122\fP +T} T{ +T} T{ +\fB#87ffd7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DARK_SLATE_GRAY_1\fP +T} T{ +\fB123\fP +T} T{ +T} T{ +\fB#87ffff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_RED_4\fP +T} T{ +\fB124\fP +T} T{ +T} T{ +\fB#af0000\fP +T} T{ +\fBRed3\fP +T} +_ +T{ +T} T{ +\fBXTERM_DEEP_PINK_6\fP +T} T{ +\fB125\fP +T} T{ +T} T{ +\fB#af005f\fP +T} T{ +\fBDeepPink4\fP +T} +_ +T{ +T} T{ +\fBXTERM_MEDIUM_VIOLET_RED\fP +T} T{ +\fB126\fP +T} T{ +T} T{ +\fB#af0087\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_MAGENTA_6\fP +T} T{ +\fB127\fP +T} T{ +T} T{ +\fB#af00af\fP +T} T{ +\fBMagenta3\fP +T} +_ +T{ +T} T{ +\fBXTERM_DARK_VIOLET\fP +T} T{ +\fB128\fP +T} T{ +T} T{ +\fB#af00d7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_PURPLE\fP +T} T{ +\fB129\fP +T} T{ +T} T{ +\fB#af00ff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DARK_ORANGE_3\fP +T} T{ +\fB130\fP +T} T{ +T} T{ +\fB#af5f00\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_INDIAN_RED_4\fP +T} T{ +\fB131\fP +T} T{ +T} T{ +\fB#af5f5f\fP +T} T{ +\fBIndianRed\fP +T} +_ +T{ +T} T{ +\fBXTERM_HOT_PINK_5\fP +T} T{ +\fB132\fP +T} T{ +T} T{ +\fB#af5f87\fP +T} T{ +\fBHotPink3\fP +T} +_ +T{ +T} T{ +\fBXTERM_MEDIUM_ORCHID_4\fP +T} T{ +\fB133\fP +T} T{ +T} T{ +\fB#af5faf\fP +T} T{ +\fBMediumOrchid3\fP +T} +_ +T{ +T} T{ +\fBXTERM_MEDIUM_ORCHID_3\fP +T} T{ +\fB134\fP +T} T{ +T} T{ +\fB#af5fd7\fP +T} T{ +\fBMediumOrchid\fP +T} +_ +T{ +T} T{ +\fBXTERM_MEDIUM_PURPLE_2\fP +T} T{ +\fB135\fP +T} T{ +T} T{ +\fB#af5fff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DARK_GOLDENROD\fP +T} T{ +\fB136\fP +T} T{ +T} T{ +\fB#af8700\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_SALMON_3\fP +T} T{ +\fB137\fP +T} T{ +T} T{ +\fB#af875f\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_ROSY_BROWN\fP +T} T{ +\fB138\fP +T} T{ +T} T{ +\fB#af8787\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_63\fP +T} T{ +\fB139\fP +T} T{ +T} T{ +\fB#af87af\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_MEDIUM_PURPLE_3\fP +T} T{ +\fB140\fP +T} T{ +T} T{ +\fB#af87d7\fP +T} T{ +\fBMediumPurple2\fP +T} +_ +T{ +T} T{ +\fBXTERM_MEDIUM_PURPLE_1\fP +T} T{ +\fB141\fP +T} T{ +T} T{ +\fB#af87ff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GOLD_3\fP +T} T{ +\fB142\fP +T} T{ +T} T{ +\fB#afaf00\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DARK_KHAKI\fP +T} T{ +\fB143\fP +T} T{ +T} T{ +\fB#afaf5f\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_NAVAJO_WHITE_3\fP +T} T{ +\fB144\fP +T} T{ +T} T{ +\fB#afaf87\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_69\fP +T} T{ +\fB145\fP +T} T{ +T} T{ +\fB#afafaf\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_STEEL_BLUE_3\fP +T} T{ +\fB146\fP +T} T{ +T} T{ +\fB#afafd7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_STEEL_BLUE_2\fP +T} T{ +\fB147\fP +T} T{ +T} T{ +\fB#afafff\fP +T} T{ +\fBLightSteelBlue\fP +T} +_ +T{ +T} T{ +\fBXTERM_YELLOW_5\fP +T} T{ +\fB148\fP +T} T{ +T} T{ +\fB#afd700\fP +T} T{ +\fBYellow3\fP +T} +_ +T{ +T} T{ +\fBXTERM_DARK_OLIVE_GREEN_5\fP +T} T{ +\fB149\fP +T} T{ +T} T{ +\fB#afd75f\fP +T} T{ +\fBDarkOliveGreen3\fP +T} +_ +T{ +T} T{ +\fBXTERM_DARK_SEA_GREEN_6\fP +T} T{ +\fB150\fP +T} T{ +T} T{ +\fB#afd787\fP +T} T{ +\fBDarkSeaGreen3\fP +T} +_ +T{ +T} T{ +\fBXTERM_DARK_SEA_GREEN_4\fP +T} T{ +\fB151\fP +T} T{ +T} T{ +\fB#afd7af\fP +T} T{ +\fBDarkSeaGreen2\fP +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_CYAN_3\fP +T} T{ +\fB152\fP +T} T{ +T} T{ +\fB#afd7d7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_SKY_BLUE_1\fP +T} T{ +\fB153\fP +T} T{ +T} T{ +\fB#afd7ff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREEN_YELLOW\fP +T} T{ +\fB154\fP +T} T{ +T} T{ +\fB#afff00\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DARK_OLIVE_GREEN_3\fP +T} T{ +\fB155\fP +T} T{ +T} T{ +\fB#afff5f\fP +T} T{ +\fBDarkOliveGreen2\fP +T} +_ +T{ +T} T{ +\fBXTERM_PALE_GREEN_2\fP +T} T{ +\fB156\fP +T} T{ +T} T{ +\fB#afff87\fP +T} T{ +\fBPaleGreen1\fP +T} +_ +T{ +T} T{ +\fBXTERM_DARK_SEA_GREEN_3\fP +T} T{ +\fB157\fP +T} T{ +T} T{ +\fB#afffaf\fP +T} T{ +\fBDarkSeaGreen2\fP +T} +_ +T{ +T} T{ +\fBXTERM_DARK_SEA_GREEN_1\fP +T} T{ +\fB158\fP +T} T{ +T} T{ +\fB#afffd7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_PALE_TURQUOISE_1\fP +T} T{ +\fB159\fP +T} T{ +T} T{ +\fB#afffff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_RED_3\fP +T} T{ +\fB160\fP +T} T{ +T} T{ +\fB#d70000\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DEEP_PINK_5\fP +T} T{ +\fB161\fP +T} T{ +T} T{ +\fB#d7005f\fP +T} T{ +\fBDeepPink3\fP +T} +_ +T{ +T} T{ +\fBXTERM_DEEP_PINK_3\fP +T} T{ +\fB162\fP +T} T{ +T} T{ +\fB#d70087\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_MAGENTA_3\fP +T} T{ +\fB163\fP +T} T{ +T} T{ +\fB#d700af\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_MAGENTA_5\fP +T} T{ +\fB164\fP +T} T{ +T} T{ +\fB#d700d7\fP +T} T{ +\fBMagenta3\fP +T} +_ +T{ +T} T{ +\fBXTERM_MAGENTA_4\fP +T} T{ +\fB165\fP +T} T{ +T} T{ +\fB#d700ff\fP +T} T{ +\fBMagenta2\fP +T} +_ +T{ +T} T{ +\fBXTERM_DARK_ORANGE_2\fP +T} T{ +\fB166\fP +T} T{ +T} T{ +\fB#d75f00\fP +T} T{ +\fBDarkOrange3\fP +T} +_ +T{ +T} T{ +\fBXTERM_INDIAN_RED_3\fP +T} T{ +\fB167\fP +T} T{ +T} T{ +\fB#d75f5f\fP +T} T{ +\fBIndianRed\fP +T} +_ +T{ +T} T{ +\fBXTERM_HOT_PINK_4\fP +T} T{ +\fB168\fP +T} T{ +T} T{ +\fB#d75f87\fP +T} T{ +\fBHotPink3\fP +T} +_ +T{ +T} T{ +\fBXTERM_HOT_PINK_3\fP +T} T{ +\fB169\fP +T} T{ +T} T{ +\fB#d75faf\fP +T} T{ +\fBHotPink2\fP +T} +_ +T{ +T} T{ +\fBXTERM_ORCHID_3\fP +T} T{ +\fB170\fP +T} T{ +T} T{ +\fB#d75fd7\fP +T} T{ +\fBOrchid\fP +T} +_ +T{ +T} T{ +\fBXTERM_MEDIUM_ORCHID_2\fP +T} T{ +\fB171\fP +T} T{ +T} T{ +\fB#d75fff\fP +T} T{ +\fBMediumOrchid1\fP +T} +_ +T{ +T} T{ +\fBXTERM_ORANGE_2\fP +T} T{ +\fB172\fP +T} T{ +T} T{ +\fB#d78700\fP +T} T{ +\fBOrange3\fP +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_SALMON_2\fP +T} T{ +\fB173\fP +T} T{ +T} T{ +\fB#d7875f\fP +T} T{ +\fBLightSalmon3\fP +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_PINK_2\fP +T} T{ +\fB174\fP +T} T{ +T} T{ +\fB#d78787\fP +T} T{ +\fBLightPink3\fP +T} +_ +T{ +T} T{ +\fBXTERM_PINK_3\fP +T} T{ +\fB175\fP +T} T{ +T} T{ +\fB#d787af\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_PLUM_3\fP +T} T{ +\fB176\fP +T} T{ +T} T{ +\fB#d787d7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_VIOLET\fP +T} T{ +\fB177\fP +T} T{ +T} T{ +\fB#d787ff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GOLD_2\fP +T} T{ +\fB178\fP +T} T{ +T} T{ +\fB#d7af00\fP +T} T{ +\fBGold3\fP +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_GOLDENROD_5\fP +T} T{ +\fB179\fP +T} T{ +T} T{ +\fB#d7af5f\fP +T} T{ +\fBLightGoldenrod3\fP +T} +_ +T{ +T} T{ +\fBXTERM_TAN\fP +T} T{ +\fB180\fP +T} T{ +T} T{ +\fB#d7af87\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_MISTY_ROSE_3\fP +T} T{ +\fB181\fP +T} T{ +T} T{ +\fB#d7afaf\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_THISTLE_3\fP +T} T{ +\fB182\fP +T} T{ +T} T{ +\fB#d7afd7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_PLUM_2\fP +T} T{ +\fB183\fP +T} T{ +T} T{ +\fB#d7afff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_YELLOW_3\fP +T} T{ +\fB184\fP +T} T{ +T} T{ +\fB#d7d700\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_KHAKI_3\fP +T} T{ +\fB185\fP +T} T{ +T} T{ +\fB#d7d75f\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_GOLDENROD_3\fP +T} T{ +\fB186\fP +T} T{ +T} T{ +\fB#d7d787\fP +T} T{ +\fBLightGoldenrod2\fP +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_YELLOW_3\fP +T} T{ +\fB187\fP +T} T{ +T} T{ +\fB#d7d7af\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_84\fP +T} T{ +\fB188\fP +T} T{ +T} T{ +\fB#d7d7d7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_STEEL_BLUE_1\fP +T} T{ +\fB189\fP +T} T{ +T} T{ +\fB#d7d7ff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_YELLOW_2\fP +T} T{ +\fB190\fP +T} T{ +T} T{ +\fB#d7ff00\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DARK_OLIVE_GREEN_2\fP +T} T{ +\fB191\fP +T} T{ +T} T{ +\fB#d7ff5f\fP +T} T{ +\fBDarkOliveGreen1\fP +T} +_ +T{ +T} T{ +\fBXTERM_DARK_OLIVE_GREEN_1\fP +T} T{ +\fB192\fP +T} T{ +T} T{ +\fB#d7ff87\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DARK_SEA_GREEN_2\fP +T} T{ +\fB193\fP +T} T{ +T} T{ +\fB#d7ffaf\fP +T} T{ +\fBDarkSeaGreen1\fP +T} +_ +T{ +T} T{ +\fBXTERM_HONEYDEW_2\fP +T} T{ +\fB194\fP +T} T{ +T} T{ +\fB#d7ffd7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_CYAN_1\fP +T} T{ +\fB195\fP +T} T{ +T} T{ +\fB#d7ffff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_RED_1\fP +T} T{ +\fB196\fP +T} T{ +T} T{ +\fB#ff0000\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DEEP_PINK_4\fP +T} T{ +\fB197\fP +T} T{ +T} T{ +\fB#ff005f\fP +T} T{ +\fBDeepPink2\fP +T} +_ +T{ +T} T{ +\fBXTERM_DEEP_PINK_2\fP +T} T{ +\fB198\fP +T} T{ +T} T{ +\fB#ff0087\fP +T} T{ +\fBDeepPink1\fP +T} +_ +T{ +T} T{ +\fBXTERM_DEEP_PINK_1\fP +T} T{ +\fB199\fP +T} T{ +T} T{ +\fB#ff00af\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_MAGENTA_2\fP +T} T{ +\fB200\fP +T} T{ +T} T{ +\fB#ff00d7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_MAGENTA_1\fP +T} T{ +\fB201\fP +T} T{ +T} T{ +\fB#ff00ff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_ORANGE_RED_1\fP +T} T{ +\fB202\fP +T} T{ +T} T{ +\fB#ff5f00\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_INDIAN_RED_1\fP +T} T{ +\fB203\fP +T} T{ +T} T{ +\fB#ff5f5f\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_INDIAN_RED_2\fP +T} T{ +\fB204\fP +T} T{ +T} T{ +\fB#ff5f87\fP +T} T{ +\fBIndianRed1\fP +T} +_ +T{ +T} T{ +\fBXTERM_HOT_PINK_2\fP +T} T{ +\fB205\fP +T} T{ +T} T{ +\fB#ff5faf\fP +T} T{ +\fBHotPink\fP +T} +_ +T{ +T} T{ +\fBXTERM_HOT_PINK\fP +T} T{ +\fB206\fP +T} T{ +T} T{ +\fB#ff5fd7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_MEDIUM_ORCHID_1\fP +T} T{ +\fB207\fP +T} T{ +T} T{ +\fB#ff5fff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_DARK_ORANGE\fP +T} T{ +\fB208\fP +T} T{ +T} T{ +\fB#ff8700\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_SALMON_1\fP +T} T{ +\fB209\fP +T} T{ +T} T{ +\fB#ff875f\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_CORAL\fP +T} T{ +\fB210\fP +T} T{ +T} T{ +\fB#ff8787\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_PALE_VIOLET_RED_1\fP +T} T{ +\fB211\fP +T} T{ +T} T{ +\fB#ff87af\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_ORCHID_2\fP +T} T{ +\fB212\fP +T} T{ +T} T{ +\fB#ff87d7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_ORCHID_1\fP +T} T{ +\fB213\fP +T} T{ +T} T{ +\fB#ff87ff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_ORANGE_1\fP +T} T{ +\fB214\fP +T} T{ +T} T{ +\fB#ffaf00\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_SANDY_BROWN\fP +T} T{ +\fB215\fP +T} T{ +T} T{ +\fB#ffaf5f\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_SALMON_1\fP +T} T{ +\fB216\fP +T} T{ +T} T{ +\fB#ffaf87\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_PINK_1\fP +T} T{ +\fB217\fP +T} T{ +T} T{ +\fB#ffafaf\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_PINK_1\fP +T} T{ +\fB218\fP +T} T{ +T} T{ +\fB#ffafd7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_PLUM_1\fP +T} T{ +\fB219\fP +T} T{ +T} T{ +\fB#ffafff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GOLD_1\fP +T} T{ +\fB220\fP +T} T{ +T} T{ +\fB#ffd700\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_GOLDENROD_4\fP +T} T{ +\fB221\fP +T} T{ +T} T{ +\fB#ffd75f\fP +T} T{ +\fBLightGoldenrod2\fP +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_GOLDENROD_2\fP +T} T{ +\fB222\fP +T} T{ +T} T{ +\fB#ffd787\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_NAVAJO_WHITE_1\fP +T} T{ +\fB223\fP +T} T{ +T} T{ +\fB#ffd7af\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_MISTY_ROSE_1\fP +T} T{ +\fB224\fP +T} T{ +T} T{ +\fB#ffd7d7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_THISTLE_1\fP +T} T{ +\fB225\fP +T} T{ +T} T{ +\fB#ffd7ff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_YELLOW_1\fP +T} T{ +\fB226\fP +T} T{ +T} T{ +\fB#ffff00\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_LIGHT_GOLDENROD_1\fP +T} T{ +\fB227\fP +T} T{ +T} T{ +\fB#ffff5f\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_KHAKI_1\fP +T} T{ +\fB228\fP +T} T{ +T} T{ +\fB#ffff87\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_WHEAT_1\fP +T} T{ +\fB229\fP +T} T{ +T} T{ +\fB#ffffaf\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_CORNSILK_1\fP +T} T{ +\fB230\fP +T} T{ +T} T{ +\fB#ffffd7\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_100\fP +T} T{ +\fB231\fP +T} T{ +T} T{ +\fB#ffffff\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_3\fP +T} T{ +\fB232\fP +T} T{ +T} T{ +\fB#080808\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_7\fP +T} T{ +\fB233\fP +T} T{ +T} T{ +\fB#121212\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_11\fP +T} T{ +\fB234\fP +T} T{ +T} T{ +\fB#1c1c1c\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_15\fP +T} T{ +\fB235\fP +T} T{ +T} T{ +\fB#262626\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_19\fP +T} T{ +\fB236\fP +T} T{ +T} T{ +\fB#303030\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_23\fP +T} T{ +\fB237\fP +T} T{ +T} T{ +\fB#3a3a3a\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_27\fP +T} T{ +\fB238\fP +T} T{ +T} T{ +\fB#444444\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_30\fP +T} T{ +\fB239\fP +T} T{ +T} T{ +\fB#4e4e4e\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_35\fP +T} T{ +\fB240\fP +T} T{ +T} T{ +\fB#585858\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_39\fP +T} T{ +\fB241\fP +T} T{ +T} T{ +\fB#626262\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_42\fP +T} T{ +\fB242\fP +T} T{ +T} T{ +\fB#6c6c6c\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_46\fP +T} T{ +\fB243\fP +T} T{ +T} T{ +\fB#767676\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_50\fP +T} T{ +\fB244\fP +T} T{ +T} T{ +\fB#808080\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_54\fP +T} T{ +\fB245\fP +T} T{ +T} T{ +\fB#8a8a8a\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_58\fP +T} T{ +\fB246\fP +T} T{ +T} T{ +\fB#949494\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_62\fP +T} T{ +\fB247\fP +T} T{ +T} T{ +\fB#9e9e9e\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_66\fP +T} T{ +\fB248\fP +T} T{ +T} T{ +\fB#a8a8a8\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_70\fP +T} T{ +\fB249\fP +T} T{ +T} T{ +\fB#b2b2b2\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_74\fP +T} T{ +\fB250\fP +T} T{ +T} T{ +\fB#bcbcbc\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_78\fP +T} T{ +\fB251\fP +T} T{ +T} T{ +\fB#c6c6c6\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_82\fP +T} T{ +\fB252\fP +T} T{ +T} T{ +\fB#d0d0d0\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_85\fP +T} T{ +\fB253\fP +T} T{ +T} T{ +\fB#dadada\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_89\fP +T} T{ +\fB254\fP +T} T{ +T} T{ +\fB#e4e4e4\fP +T} T{ +T} +_ +T{ +T} T{ +\fBXTERM_GREY_93\fP +T} T{ +\fB255\fP +T} T{ +T} T{ +\fB#eeeeee\fP +T} T{ +T} +_ +T{ +.IP [3] 5 +First 16 colors are effectively the same as colors in \fIdefault\fP 16\-color mode and share with them the same color values (and +depend on terminal color scheme as well). +.IP [4] 5 +XTerm name list contains duplicates; variable names for these were slightly modified (different numbers at the end) to avoid +namespace conflicts. Every changed name is displayed with \fBbold\fP font. +T} +_ +.TE + +.sp +.ce +---- + +.ce 0 +.sp +.sp +Sources +.INDENT 0.0 +.IP 1. 3 +\fI\%https://en.wikipedia.org/wiki/ANSI_escape_code\fP +.IP 2. 3 +\fI\%https://www.ditig.com/256\-colors\-cheat\-sheet\fP +.UNINDENT +.SS xterm indexed colors +.SS Color16 and Color256 equivalents +.sp +\fI\%Color16\fP palette consists of 16 base colors which are listed +below. At the same time, they are part of \fI\%Color256\fP palette +(the first 16 ones). Actual colors of \fI\%Color16\fP palette depend on user\(aqs +terminal settings, i.e. the result color of \fI\%Color16\fP is not guaranteed to +exactly match the corresponding color. That\(aqs why using this color type is +discouraged, if you want to be sure that the result will match the expectations. +.sp +However, it doesn\(aqt mean that \fBColor16\fP is useless. Just the opposite \-\- it\(aqs +ideal for situations when you don\(aqt actually \fBneed\fP to set exact values and +it\(aqs easier to specify estimation of desired color. I.e. setting color to \fB\(aqred\(aq\fP +is usually more than enough for displaying an error message \-\- we don\(aqt really care +about precise values of hue or brightness that will be used to display it. +.sp +The instances of \fBColor256\fP with an exact \fBColor16\fP counterpart have a private +property \fB_color16_equiv\fP, which is used to determine the result of comparison +between two colors \-\- i.e., \fB==\fP opeartor will return \fITrue\fP for pairs of +equivalent colors: +.sp +.nf +.ft C +>>> col1, col2 = pt.Color256.get_by_code(1), pt.Color16.get_by_code(31) +(, ) +>>> col1 == col2 +True +.ft P +.fi +.sp +At the same time, colors which share the color value, but behave differently due +to equivalence mechanics are considered different: +.sp +.nf +.ft C +>>> col1, col2 = pt.Color256.get_by_code(9), pt.Color256.get_by_code(196) +(, ) +>>> col1 == col2 +False +.ft P +.fi +.SS Approximation algorithm +.sp +The approximation algorithm was explicitly made to ignore these colors because +otherwise the results of transforming \fI\%RGB\fP values into e.g. \fBColor256\fP, would +be unpredictable, in addition to different results for different users, depending +on their terminal emulator setup. +.INDENT 0.0 +.INDENT 3.5 +.SS Todo +.sp +Approximation algorithm is as simple as iterating through all colors in the +\fIlookup table\fP (which contains all possible ... +.UNINDENT +.UNINDENT +.SS xterm\-256 palette + +.sp +.ce +---- + +.ce 0 +.sp +.sp +Sources +.INDENT 0.0 +.IP 1. 3 +\fI\%https://www.tweaking4all.com/software/linux\-software/xterm\-color\-cheat\-sheet/\fP +.UNINDENT +.SS ANSI sequences review +.SS Sequence classes +.sp +Sequences can be divided to 4 different classes depending on their classifier +byte(s); a class indicates the application domain the purpose of the sequence +in general. According to \fI\%ECMA\-48\fP specification the classes are: \fBnF\fP, +\fBFp\fP, \fBFe\fP, \fBFs\fP\&. +.INDENT 0.0 +.IP \(bu 2 +\fBnF\fP escape sequences are mostly used for ANSI/ISO code\-switching +mechanisms. All \fBnF\fP\-class sequences start with \fBESC\fP plus ASCII byte +from the range 0x20\-0x2F: ( \fB!\(dq#$%&\(aq()*+\e\-./\fP and space ). +.sp +They are represented by \fI\%SequenceNf\fP class without any specific implementations. +.IP \(bu 2 +\fBfP\fP\-class sequences can be used for invoking private control functions. +The characteristic property is that the first byte after \fBESC\fP is always +in range 0x30\-0x3F (\fB0123456789:;<=>?\fP). +.sp +They are represented by \fI\%SequenceFp\fP class, which, for example, +assembles DECSC and DECRC +sequence types. +.IP \(bu 2 +\fBFe\fP\-class sequences are the most common ones and 99% of the sequences +you will ever encounter will be of \fBFe\fP class. ECMA\-48 names them +\(dqC1 set sequences\(dq, and their \fIclassifier\fP byte (the one right after +escape byte) is from 0x40 to 0x5F range (\fB@[\e\e]_^ABCDEFGHIJKLMNOPQRSTUVWXYZ\fP). +.sp +These sequences are implemented in \fI\%SequenceFe\fP parent class, which is then +subclassed by even more specific classes \fI\%SequenceST\fP, \fI\%SequenceOSC\fP, +\fI\%SequenceCSI\fP and \fI(drums)\fP \fI\%SequenceSGR\fP \-\- the one responsible for +setting the terminal colors and formats (or at least the majority of them), +and also the one that\(aqs going to be encountered most of the time. The examples +include CUP, ED, +aforementioned SGR and much more. +.IP \(bu 2 +\fBFs\fP\-class sequences ... +.INDENT 2.0 +.INDENT 3.5 +.INDENT 0.0 +.INDENT 3.5 +.SS Todo +.sp +This +.UNINDENT +.UNINDENT +.UNINDENT +.UNINDENT +.UNINDENT +.SS Sequence types +.sp +\fI\%ECMA\-48\fP introduces a list of terminal control functions and contains the +implementation details and formats. Each of these usually has a 3+ letters +abbreviation (SGR, CSI, EL, etc.) which determines the action that will be +performed after the terminal receives control sequence of this function. +Let\(aqs identify these abbreviations as sequence types\&. +.sp +At the time of writing (v2.75) \fI\%ansi\fP module contains the implementations of +about 25 control sequence types (that should be read as \(dqhas seperated classes +and/or factory methods and is also documented). However, ECMA\-48 standard +mentions about 160 sequence types. +.sp +The main principle of \fI\%pytermor\fP development was the rule \fI\(dqif I don\(aqt see it, +it doesn\(aqt exist\(dq\fP, which should be read as \(dqDon\(aqt waste days and nights on +specs comprehension and implementation of the features no one ever will use\(dq. +.sp +That\(aqs why the only types of sequences implemented are the ones that I personally +encountered in the modern environment (and having a practical application, of +course). +.sp +However, the library was designed to provide an easy way to extend the control +sequences class hierarchy; what\(aqs more, this includes not only the extendability +of the library itself (i.e., improvements in the context of library source code), +but also the extra logic in the client code referencing the library classes. In +case something important is missed \-\- there is an \fI\%Issues\fP page on the GitHub, +you are welcome to make a feature request. +.INDENT 0.0 +.INDENT 3.5 +.UNINDENT +.UNINDENT +.SS Parser +.SS Filters +.SS Filter class hierarchy +.IP "System Message: ERROR/3 (/home/a.shavykin/dl/pytermor/docs/pages/guide-lo/filters.rst:, line 11)" +Unknown directive type \(dqgrid\(dq. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +\&.. grid:: 1 + :class\-container: inheritance\-columns + + .. grid\-item:: + + .. inheritance\-diagram:: pytermor.filter + :parts: 1 + :top\-classes: pytermor.filter.IFilter + :caption: \(gaIFilter\(ga inheritance tree +.ft P +.fi +.UNINDENT +.UNINDENT +.SS Color spaces and transformations +.INDENT 0.0 +.INDENT 2.5 +[graph]Supported color spaces and transformations.UNINDENT +.UNINDENT +.SH API REFERENCE +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +Almost all public classes are imported into the first package level +on its initialization, which makes kind of a contract on library\(aqs API. +The exceptions include some abstract superclasses or metaclasses, which +generally should not be used outside of the library, but still can be +imported directly using a full module path. +.UNINDENT +.UNINDENT +.TS +center; +|l|l|. +_ +T{ +\fI\%ansi\fP +T} T{ +Classes for working with ANSI escape sequences on a lower level. +T} +_ +T{ +\fI\%color\fP +T} T{ +Abstractions for color definitions in three primary modes: 4\-bit, 8\-bit and 24\-bit (\fBxterm\-16\fP, \fBxterm\-256\fP and \fBTrue Color/RGB\fP, respectively). +T} +_ +T{ +\fI\%common\fP +T} T{ +T} +_ +T{ +\fI\%config\fP +T} T{ +Library fine tuning module. +T} +_ +T{ +\fI\%cval\fP +T} T{ +Color preset list: +T} +_ +T{ +\fI\%exception\fP +T} T{ +T} +_ +T{ +\fI\%filter\fP +T} T{ +Formatters for prettier output and utility classes to avoid writing boilerplate code when dealing with escape sequences. +T} +_ +T{ +\fI\%numfmt\fP +T} T{ +utilnum +T} +_ +T{ +\fI\%renderer\fP +T} T{ +Renderers transform \fI\%Style\fP instances into lower\-level abstractions like \fI\%SGR sequences\fP, tmux\-compatible directives, HTML markup etc., depending on renderer type. +T} +_ +T{ +\fI\%style\fP +T} T{ +Reusable data classes that control the appearance of the output \-\- colors (text/background/underline) and attributes (\fIbold\fP, \fIunderlined\fP, \fIitalic\fP, etc.). +T} +_ +T{ +\fI\%template\fP +T} T{ +T} +_ +T{ +\fI\%term\fP +T} T{ +A +T} +_ +T{ +\fI\%text\fP +T} T{ +\(dqFront\-end\(dq module of the library. +T} +_ +.TE +.SS pytermor.ansi +.sp +Classes for working with ANSI escape sequences on a lower level. +Can be used for creating a variety of sequences including: +.INDENT 0.0 +.INDENT 3.5 +.INDENT 0.0 +.IP \(bu 2 +SGR sequences (text and background +coloring, other text formatting and effects); +.IP \(bu 2 +CSI sequences (cursor management, +selective screen clearing); +.IP \(bu 2 +OSC sequences (various system commands). +.UNINDENT +.UNINDENT +.UNINDENT +.sp +Provides a bunch of ready\-to\-use sequence makers, as well as core method +\fI\%get_closing_seq()\fP that queries SGR pairs registry and composes \(dqcounterpart\(dq +sequence for a specified one: every attribute that the latter modifies, will be +changed back by the one that\(aqs being created, while keeping the other attributes +untouched. This method is used by \fI\%SgrRenderer\fP and is essential for nested style +processing, as regular \fI\%RESET\fP sequence cancels all the formatting applied to +the output at the moment it\(aqs getting introduced to a terminal emulator, and +is near to impossible to use because of that (at least when there is a need to +perform partial attribute termination, e.g. for overlapping styles rendering). +.sp +Module Attributes +.TS +center; +|l|l|. +_ +T{ +\fI\%NOOP_SEQ\fP +T} T{ +Special sequence in case one \fIhas to\fP provide one or another SGR, but does not want any control sequences to be actually included in the output. +T} +_ +T{ +\fI\%ESCAPE_SEQ_REGEX\fP +T} T{ +Regular expression that matches all classes of escape sequences. +T} +_ +.TE +.sp +Functions +.TS +center; +|l|l|. +_ +T{ +\fI\%contains_sgr\fP(string, *codes) +T} T{ +Return the first match of \fI\%SGR\fP sequence in \fBstring\fP with specified \fBcodes\fP as params, strictly inside a single sequence in specified order, or \fINone\fP if nothing was found. +T} +_ +T{ +\fI\%enclose\fP(opening_seq, string) +T} T{ +.INDENT 0.0 +.TP +.B param opening_seq +.UNINDENT +T} +_ +T{ +\fI\%get_closing_seq\fP(opening_seq) +T} T{ +.INDENT 0.0 +.TP +.B param opening_seq +.UNINDENT +T} +_ +T{ +\fBget_resetter_codes\fP() +T} T{ +T} +_ +T{ +\fI\%parse\fP(string) +T} T{ +.INDENT 0.0 +.TP +.B param string +.UNINDENT +T} +_ +T{ +\fBseq_from_dict\fP(groupdict) +T} T{ +T} +_ +.TE +.sp +Classes +.TS +center; +|l|l|. +_ +T{ +\fI\%ColorTarget\fP(value) +T} T{ +An enumeration. +T} +_ +T{ +\fI\%ISequence\fP(classifier[, interm, final, abbr]) +T} T{ +Abstract ancestor of all escape sequences. +T} +_ +T{ +\fI\%IntCode\fP(value) +T} T{ +Complete or almost complete list of reliably working SGR param integer codes. +T} +_ +T{ +\fI\%SeqIndex\fP() +T} T{ +Registry of static sequences that can be utilized without implementing an extra logic. +T} +_ +T{ +\fI\%SequenceCSI\fP([final, interm, abbr]) +T} T{ +Class representing CSI\-type ANSI escape sequence. +T} +_ +T{ +\fI\%SequenceFe\fP(classifier, *params[, interm, ...]) +T} T{ +C1 set sequences \-\- a wide range of sequences that includes \fI\%CSI\fP, \fI\%OSC\fP and more. +T} +_ +T{ +\fI\%SequenceFp\fP(classifier[, abbr]) +T} T{ +Sequence class representing private control functions. +T} +_ +T{ +\fI\%SequenceFs\fP(classifier[, abbr]) +T} T{ +Sequences referred by ECMA\-48 as \(dqindependent control functions\(dq. +T} +_ +T{ +\fI\%SequenceNf\fP(classifier, final[, interm, abbr]) +T} T{ +Escape sequences mostly used for ANSI/ISO code\-switching mechanisms. +T} +_ +T{ +\fI\%SequenceOSC\fP(*params) +T} T{ +OSC\-type sequence. +T} +_ +T{ +\fI\%SequenceSGR\fP(*params) +T} T{ +Class representing SGR\-type escape sequence with varying amount of parameters. +T} +_ +T{ +\fI\%SequenceST\fP() +T} T{ +String Terminator sequence (ST). +T} +_ +T{ +\fBSubtypedParam\fP(value, subtype) +T} T{ +T} +_ +.TE +.INDENT 0.0 +.TP +.B class pytermor.ansi.ISequence(classifier, interm=None, final=None, abbr=\(aqESC*\(aq) +Bases: \fBSized\fP +.sp +Abstract ancestor of all escape sequences. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBclassifier\fP (\fIstr\fP) \-\- Classifier char, see \fI\%ANSI sequences review\fP\&. +.IP \(bu 2 +\fBinterm\fP (\fIstr\fP) \-\- Intermediate chars. +.IP \(bu 2 +\fBfinal\fP (\fIstr\fP) \-\- Final char. +.IP \(bu 2 +\fBabbr\fP (\fIstr\fP) \-\- Abbreviation for debug purposes. +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.ansi.SequenceNf(classifier, final, interm=None, abbr=\(aqnF\(aq) +Bases: \fI\%ISequence\fP +.sp +Escape sequences mostly used for ANSI/ISO code\-switching mechanisms. +.sp +All \fBnF\fP\-class sequences start with \fBESC\fP plus ASCII byte from +the range 0x20\-0x2F (space, \fB!\fP, \fB\(dq\fP, \fB#\fP, \fB$\fP, \fB%\fP, +\fB&\fP, \fB\(aq\fP, \fB(\fP, \fB)\fP, \fB*\fP, \fB+\fP, \fB,\fP, \fB\-\fP, \fB\&.\fP, \fB/\fP). +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBclassifier\fP (\fIstr\fP) \-\- Classifier char (0x20\-0x2F) +.IP \(bu 2 +\fBfinal\fP (\fIstr\fP) \-\- Final char (0x30\-0x7E) +.IP \(bu 2 +\fBinterm\fP (\fIstr\fP) \-\- intermediate chars (0x20\-0x2F) +.IP \(bu 2 +\fBabbr\fP \-\- Abbreviation for debug purposes. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B assemble() +Build up actual byte sequence and return as an ASCII\-encoded string. +.INDENT 7.0 +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.ansi.SequenceFp(classifier, abbr=\(aqFp\(aq) +Bases: \fI\%ISequence\fP +.sp +Sequence class representing private control functions. +.sp +All \fBFp\fP\-class sequences start with \fBESC\fP plus ASCII byte in the +range 0x30\-0x3F (\fB0\fP\-\fB9\fP, \fB:\fP, \fB;\fP, \fB<\fP, \fB=\fP, \fB>\fP, +\fB?\fP). +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBclassifier\fP (\fIstr\fP) \-\- Classifier char (0x30\-0x3F) +.IP \(bu 2 +\fBabbr\fP \-\- Abbreviation for debug purposes. +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.ansi.SequenceFs(classifier, abbr=\(aqFs\(aq) +Bases: \fI\%ISequence\fP +.sp +Sequences referred by ECMA\-48 as \(dqindependent control functions\(dq. +.sp +All \fBFs\fP\-class sequences start with \fBESC\fP plus a byte in the range +0x60\-0x7E (\fB\(ga\fP, \fBa\fP\-\fBz\fP, \fB{\fP, \fB|\fP, \fB}\fP). +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBclassifier\fP (\fIstr\fP) \-\- Classifier char (0x60\-0x7E) +.IP \(bu 2 +\fBabbr\fP \-\- Abbreviation for debug purposes. +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.ansi.SequenceFe(classifier, *params, interm=None, final=None, abbr=\(aqFe\(aq) +Bases: \fI\%ISequence\fP +.sp +C1 set sequences \-\- a wide range of sequences that includes +\fI\%CSI\fP, \fI\%OSC\fP and more. +.sp +All \fBFe\fP\-class sequences start with \fBESC\fP plus ASCII byte +from 0x40 to 0x5F (\fB@\fP, \fB[\fP, \fB\e\fP, \fB]\fP, \fB_\fP, \fB^\fP +and capital letters \fBA\fP\-\fBZ\fP). +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBclassifier\fP (\fIstr\fP) \-\- Classifier char (0x40\-0x5F) +.IP \(bu 2 +\fBparams\fP (\fIint\fP\fI | \fP\fIstr\fP) \-\- Parameter chars (0x30\-0x3F) +.IP \(bu 2 +\fBinterm\fP (\fIstr\fP) \-\- Intermediate chars (0x20\-0x2F) +.IP \(bu 2 +\fBfinal\fP (\fIstr\fP) \-\- Final char (0x40\-0x7E) +.IP \(bu 2 +\fBabbr\fP \-\- Abbreviation for debug purposes. +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.ansi.SequenceST +Bases: \fI\%SequenceFe\fP +.sp +String Terminator sequence (ST). Terminates strings in other control +sequences. Encoded as \fBESC \e\fP (0x1B 0x5C). +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.ansi.SequenceOSC(*params) +Bases: \fI\%SequenceFe\fP +.sp +OSC\-type sequence. Starts a control +string for the operating system to use. Encoded as \fBESC ]\fP, plus params +separated by \fB;\fP\&. The control string can contain bytes from ranges +0x08\-0x0D, \fB0x20\-0x7E\fP and is usually terminated by +\fI\%ST\fP\&. +.INDENT 7.0 +.TP +.B Parameters +\fBparams\fP (\fIint\fP\fI | \fP\fIstr\fP) \-\- Parameter chars (0x30\-0x3F) +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.ansi.SequenceCSI(final=None, *params, interm=None, abbr=\(aqCSI\(aq) +Bases: \fI\%SequenceFe\fP +.sp +Class representing CSI\-type ANSI +escape sequence. All subtypes of this sequence start with \fBESC [\fP\&. +.sp +Sequences of this type are used to control text formatting, +change cursor position, erase screen and more. +.sp +.nf +.ft C +>>> from pytermor import * +>>> make_clear_line().assemble() +\(aq\(aq +.ft P +.fi +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBfinal\fP (\fIstr\fP) \-\- Final char (0x40\-0x7E) +.IP \(bu 2 +\fBparams\fP (\fIint\fP) \-\- Parameter chars (0x30\-0x3F) +.IP \(bu 2 +\fBinterm\fP (\fIstr\fP) \-\- Intermediate chars. (0x21/0x3F) +.IP \(bu 2 +\fBabbr\fP (\fIstr\fP) \-\- Abbreviation for debug purposes. +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.ansi.SequenceSGR(*params) +Bases: \fI\%SequenceCSI\fP +.sp +Class representing SGR\-type escape sequence +with varying amount of parameters. SGR sequences allow to change the color +of text or/and terminal background (in 3 different color spaces) as well +as set decorate text with italic style, underlining, overlining, cross\-lining, +making it bold or blinking etc. +.sp +.nf +.ft C +>>> SequenceSGR(IntCode.HI_CYAN, \(aqunderlined\(aq, 1) + +.ft P +.fi +.sp +To encode into control sequence byte\-string invoke \fI\%assemble()\fP method or cast +the instance to \fIstr\fP, which internally does the same (this actually applies +to all children of \fI\%ISequence\fP): +.sp +.nf +.ft C +>>> SequenceSGR(\(aqblue\(aq, \(aqitalic\(aq).assemble() +\(aq\(aq +>>> str(SequenceSGR(\(aqblue\(aq, \(aqitalic\(aq)) +\(aq\(aq +.ft P +.fi +.sp +The latter also allows fluent usage in f\-strings: +.sp +.nf +.ft C +>>> f\(aq{SeqIndex.RED}should be red{SeqIndex.RESET}\(aq +\(aqshould be red\(aq +.ft P +.fi +.sp +\fBNOTE:\fP +.INDENT 7.0 +.INDENT 3.5 +\fI\%SequenceSGR\fP with zero params \fBESC [m\fP is interpreted by terminal emulators +as \fBESC [0m\fP, which is \fIhard\fP reset sequence. The empty\-string\-sequence is +predefined at module level as \fI\%NOOP_SEQ\fP\&. +.UNINDENT +.UNINDENT +.sp +\fBNOTE:\fP +.INDENT 7.0 +.INDENT 3.5 +The module doesn\(aqt distinguish \(dqsingle\-instruction\(dq sequences from several +ones merged together, e.g. \fBStyle(fg=\(aqred\(aq, bold=True)\fP produces only one +opening SequenceSGR instance: +.sp +.nf +.ft C +>>> SequenceSGR(IntCode.BOLD, IntCode.RED).assemble() +\(aq\(aq +.ft P +.fi +.sp +\&...although generally speaking it is two of them (\fBESC [1m\fP and +\fBESC [31m\fP). However, the module can automatically match terminating +sequences for any form of input SGRs and translate it to specified format. +.UNINDENT +.UNINDENT +.sp +It is possible to add of one SGR sequence to another, resulting in a new one +with merged params: +.sp +.nf +.ft C +>>> SequenceSGR(\(aqblue\(aq) + SequenceSGR(\(aqitalic\(aq) + +.ft P +.fi +.INDENT 7.0 +.TP +.B Parameters +\fBparams\fP (\fIstr\fP\fI | \fP\fIint\fP\fI | \fP\fISubtypedParam\fP\fI | \fP\fI\%SequenceSGR\fP) \-\- +.sp +Sequence params. Resulting param order is the same as an +argument order. Each argument can be specified as: +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.IP \(bu 2 +\fIstr\fP \-\- any of \fI\%IntCode\fP names, case\-insensitive; +.IP \(bu 2 +\fIint\fP \-\- \fI\%IntCode\fP instance or plain integer; +.IP \(bu 2 +\fISubtypeParam\fP +.IP \(bu 2 +another \fI\%SequenceSGR\fP instance (params will be extracted). +.UNINDENT +.UNINDENT +.UNINDENT + +.UNINDENT +.INDENT 7.0 +.TP +.B property params: List[int | pytermor.ansi.SubtypedParam] +.INDENT 7.0 +.TP +.B Returns +Sequence params as integers. +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.ansi.IntCode(value) +Bases: \fBIntEnum\fP +.sp +Complete or almost complete list of reliably working SGR param integer codes. +Fully interchangeable with plain \fIint\fP\&. Suitable for \fI\%SequenceSGR\fP +default constructor. +.sp +\fBNOTE:\fP +.INDENT 7.0 +.INDENT 3.5 +\fI\%IntCode\fP predefined constants are omitted from documentation to avoid +useless repeats and save space, as most of the time \(dqhigher\-level\(dq class +\fI\%SeqIndex\fP will be more appropriate, and on top of that, the constant +names are literally the same for \fI\%SeqIndex\fP and \fI\%IntCode\fP\&. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod resolve(name) +.INDENT 7.0 +.TP +.B Parameters +\fBname\fP (\fIstr\fP) \-\- +.TP +.B Return type +\fI\%IntCode\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.ansi.SeqIndex +Registry of static sequences that can be utilized without implementing +an extra logic. +.INDENT 7.0 +.TP +.B RESET = +Hard reset sequence. +.UNINDENT +.INDENT 7.0 +.TP +.B BOLD = +Bold or increased intensity. +.UNINDENT +.INDENT 7.0 +.TP +.B DIM = +Faint, decreased intensity. +.UNINDENT +.INDENT 7.0 +.TP +.B ITALIC = +Italic \fI(not widely supported)\fP\&. +.UNINDENT +.INDENT 7.0 +.TP +.B UNDERLINED = +Underline. +.UNINDENT +.INDENT 7.0 +.TP +.B CURLY_UNDERLINED = +Curly underline. +.UNINDENT +.INDENT 7.0 +.TP +.B BLINK_SLOW = +Set blinking to < 150 cpm. +.UNINDENT +.INDENT 7.0 +.TP +.B BLINK_FAST = +Set blinking to 150+ cpm \fI(not widely supported)\fP\&. +.UNINDENT +.INDENT 7.0 +.TP +.B INVERSED = +Swap foreground and background colors. +.UNINDENT +.INDENT 7.0 +.TP +.B HIDDEN = +Conceal characters \fI(not widely supported)\fP\&. +.UNINDENT +.INDENT 7.0 +.TP +.B CROSSLINED = +Strikethrough. +.UNINDENT +.INDENT 7.0 +.TP +.B DOUBLE_UNDERLINED = +Double\-underline. \fIOn several terminals disables\fP \fI\%BOLD\fP \fIinstead\fP\&. +.UNINDENT +.INDENT 7.0 +.TP +.B FRAMED = +Rectangular border \fI(not widely supported, to say the least)\fP\&. +.UNINDENT +.INDENT 7.0 +.TP +.B OVERLINED = +Overline \fI(not widely supported)\fP\&. +.UNINDENT +.INDENT 7.0 +.TP +.B BOLD_DIM_OFF = +Disable \fBBOLD\fP and \fBDIM\fP attributes. +.sp +\fISpecial aspects... It\(aqs impossible to reliably disable them on a separate basis.\fP +.UNINDENT +.INDENT 7.0 +.TP +.B ITALIC_OFF = +Disable italic. +.UNINDENT +.INDENT 7.0 +.TP +.B UNDERLINED_OFF = +Disable underlining. +.UNINDENT +.INDENT 7.0 +.TP +.B BLINK_OFF = +Disable blinking. +.UNINDENT +.INDENT 7.0 +.TP +.B INVERSED_OFF = +Disable inversing. +.UNINDENT +.INDENT 7.0 +.TP +.B HIDDEN_OFF = +Disable conecaling. +.UNINDENT +.INDENT 7.0 +.TP +.B CROSSLINED_OFF = +Disable strikethrough. +.UNINDENT +.INDENT 7.0 +.TP +.B FRAMED_OFF = +Disable border. +.UNINDENT +.INDENT 7.0 +.TP +.B OVERLINED_OFF = +Disable overlining. +.UNINDENT +.INDENT 7.0 +.TP +.B UNDERLINE_COLOR_OFF = +Reset underline color. +.UNINDENT +.INDENT 7.0 +.TP +.B BLACK = +Set text color to 0x000000\&. +.UNINDENT +.INDENT 7.0 +.TP +.B RED = +Set text color to 0x800000\&. +.UNINDENT +.INDENT 7.0 +.TP +.B GREEN = +Set text color to 0x008000\&. +.UNINDENT +.INDENT 7.0 +.TP +.B YELLOW = +Set text color to 0x808000\&. +.UNINDENT +.INDENT 7.0 +.TP +.B BLUE = +Set text color to 0x000080\&. +.UNINDENT +.INDENT 7.0 +.TP +.B MAGENTA = +Set text color to 0x800080\&. +.UNINDENT +.INDENT 7.0 +.TP +.B CYAN = +Set text color to 0x008080\&. +.UNINDENT +.INDENT 7.0 +.TP +.B WHITE = +Set text color to 0xc0c0c0\&. +.UNINDENT +.INDENT 7.0 +.TP +.B COLOR_OFF = +Reset foreground color. +.UNINDENT +.INDENT 7.0 +.TP +.B BG_BLACK = +Set background color to 0x000000\&. +.UNINDENT +.INDENT 7.0 +.TP +.B BG_RED = +Set background color to 0x800000\&. +.UNINDENT +.INDENT 7.0 +.TP +.B BG_GREEN = +Set background color to 0x008000\&. +.UNINDENT +.INDENT 7.0 +.TP +.B BG_YELLOW = +Set background color to 0x808000\&. +.UNINDENT +.INDENT 7.0 +.TP +.B BG_BLUE = +Set background color to 0x000080\&. +.UNINDENT +.INDENT 7.0 +.TP +.B BG_MAGENTA = +Set background color to 0x800080\&. +.UNINDENT +.INDENT 7.0 +.TP +.B BG_CYAN = +Set background color to 0x008080\&. +.UNINDENT +.INDENT 7.0 +.TP +.B BG_WHITE = +Set background color to 0xc0c0c0\&. +.UNINDENT +.INDENT 7.0 +.TP +.B BG_COLOR_OFF = +Reset background color. +.UNINDENT +.INDENT 7.0 +.TP +.B GRAY = +Set text color to 0x808080\&. +.UNINDENT +.INDENT 7.0 +.TP +.B HI_RED = +Set text color to 0xff0000\&. +.UNINDENT +.INDENT 7.0 +.TP +.B HI_GREEN = +Set text color to 0x00ff00\&. +.UNINDENT +.INDENT 7.0 +.TP +.B HI_YELLOW = +Set text color to 0xffff00\&. +.UNINDENT +.INDENT 7.0 +.TP +.B HI_BLUE = +Set text color to 0x0000ff\&. +.UNINDENT +.INDENT 7.0 +.TP +.B HI_MAGENTA = +Set text color to 0xff00ff\&. +.UNINDENT +.INDENT 7.0 +.TP +.B HI_CYAN = +Set text color to 0x00ffff\&. +.UNINDENT +.INDENT 7.0 +.TP +.B HI_WHITE = +Set text color to 0xffffff\&. +.UNINDENT +.INDENT 7.0 +.TP +.B BG_GRAY = +Set background color to 0x808080\&. +.UNINDENT +.INDENT 7.0 +.TP +.B BG_HI_RED = +Set background color to 0xff0000\&. +.UNINDENT +.INDENT 7.0 +.TP +.B BG_HI_GREEN = +Set background color to 0x00ff00\&. +.UNINDENT +.INDENT 7.0 +.TP +.B BG_HI_YELLOW = +Set background color to 0xffff00\&. +.UNINDENT +.INDENT 7.0 +.TP +.B BG_HI_BLUE = +Set background color to 0x0000ff\&. +.UNINDENT +.INDENT 7.0 +.TP +.B BG_HI_MAGENTA = +Set background color to 0xff00ff\&. +.UNINDENT +.INDENT 7.0 +.TP +.B BG_HI_CYAN = +Set background color to 0x00ffff\&. +.UNINDENT +.INDENT 7.0 +.TP +.B BG_HI_WHITE = +Set background color to 0xffffff\&. +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.ansi.ColorTarget(value) +Bases: \fBEnum\fP +.sp +An enumeration. +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.ansi.get_closing_seq(opening_seq) +.INDENT 7.0 +.TP +.B Parameters +\fBopening_seq\fP (\fI\%SequenceSGR\fP) \-\- +.TP +.B Returns + +.TP +.B Return type +\fI\%SequenceSGR\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.ansi.enclose(opening_seq, string) +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBopening_seq\fP (\fI\%SequenceSGR\fP) \-\- +.IP \(bu 2 +\fBstring\fP (\fIstr\fP) \-\- +.UNINDENT +.TP +.B Returns + +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.ansi.NOOP_SEQ = +Special sequence in case one \fIhas to\fP provide one or another SGR, but does +not want any control sequences to be actually included in the output. +.sp +\fBNOOP_SEQ.assemble()\fP returns empty string, \fBNOOP_SEQ.params\fP +returns empty list: +.sp +.nf +.ft C +>>> NOOP_SEQ.assemble() +\(aq\(aq +>>> NOOP_SEQ.params +[] +.ft P +.fi +.sp +\fBIMPORTANT:\fP +.INDENT 7.0 +.INDENT 3.5 +Casting to \fIbool\fP results in \fBFalse\fP for all \fBNOOP\fP instances in the +library (\fI\%NOOP_SEQ\fP, \fBNOOP_COLOR\fP and \fI\%NOOP_STYLE\fP). This is intended. +.UNINDENT +.UNINDENT +.sp +Can be safely added to regular \fI\%SequenceSGR\fP from any side, as internally +\fI\%SequenceSGR\fP always makes a new instance with concatenated params from both +items, rather than modifies state of either of them: +.sp +.nf +.ft C +>>> NOOP_SEQ + SequenceSGR(1) + +>>> SequenceSGR(3) + NOOP_SEQ + +.ft P +.fi +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.ansi.ESCAPE_SEQ_REGEX +Regular expression that matches all classes of escape sequences. +.sp +More specifically, it recognizes \fBnF\fP, \fBFp\fP, \fBFe\fP and \fBFs\fP [1] +classes. Useful for removing the sequences as well as for granular search +thanks to named match groups, which include: +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.TP +.B \fBescape_byte\fP +first byte of every sequence \-\- \fBESC\fP, or 0x1B\&. +.TP +.B \fBdata\fP +remaining bytes of the sequence (without escape byte) represented as +one of the following groups: \fBnf_class_seq\fP, \fBfp_class_seq\fP, +\fBfe_class_seq\fP or \fBfs_class_seq\fP; each of these splits further to +even more specific subgroups: +.INDENT 7.0 +.IP \(bu 2 +\fBnf_classifier\fP, \fBnf_interm\fP and \fBnf_final\fP as parts of +\fBnF\fP\-class sequences, +.IP \(bu 2 +\fBfp_classifier\fP for \fBFp\fP\-class sequences, +.IP \(bu 2 +\fBst_classifier\fP, \fBosc_classifier\fP, \fBosc_param\fP, \fBcsi_classifier\fP, +\fBcsi_interm\fP, \fBcsi_param\fP, \fBcsi_final\fP, \fBfe_classifier\fP, \fBfe_param\fP, +\fBfe_interm\fP and \fBfe_final\fP for \fBFe\fP\-class generic sequences and +subtypes (including \fI\%SGRs\fP), +.IP \(bu 2 +\fBfs_classifier\fP for \fBFs\fP\-class sequences. +.UNINDENT +.UNINDENT +.UNINDENT +.UNINDENT +.IP [1] 5 +\fI\%ECMA\-35 specification\fP +.INDENT 7.0 +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.ansi.contains_sgr(string, *codes) +Return the first match of \fI\%SGR\fP sequence in \fBstring\fP with specified +\fBcodes\fP as params, strictly inside a single sequence in specified order, +or \fINone\fP if nothing was found. +.sp +The match object has one group (or, technically, two): +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.IP \(bu 2 +Group #0: the whole matched SGR sequence; +.IP \(bu 2 +Group #1: the requested params bytes only. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +Example regex used for searching: \fBx1b[(?:|[d;]*;)(48;5)(?:|;[d;]*)m\fP\&. +.sp +.nf +.ft C +>>> contains_sgr(make_color_256(128).assemble(), 38) + +>>> contains_sgr(make_color_256(84, ColorTarget.BG).assemble(), 48, 5) + +.ft P +.fi +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBstring\fP (\fIstr\fP) \-\- String to search the SGR in. +.IP \(bu 2 +\fBcodes\fP (\fIint\fP) \-\- Integer SGR codes to find. +.UNINDENT +.TP +.B Return type +re.Match | None +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.ansi.parse(string) +.INDENT 7.0 +.TP +.B Parameters +\fBstring\fP (\fIstr\fP) \-\- +.TP +.B Return type +\fIIterable\fP[\fI\%pytermor.ansi.ISequence\fP | str] +.UNINDENT +.UNINDENT +.SS pytermor.color +.sp +Abstractions for color definitions in three primary modes: 4\-bit, 8\-bit and +24\-bit (\fBxterm\-16\fP, \fBxterm\-256\fP and \fBTrue Color/RGB\fP, respectively). +Provides a global registry for color searching by names and codes, as well as +approximation algorithms, which are used for output devices with limited +advanced color modes support. Renderers do that automatically and transparently +for the developer, but the manual control over this process is also an option. +.sp +Supports 4 different color spaces: \fI\%RGB\fP, \fI\%HSV\fP, \fI\%XYZ\fP and \fI\%LAB\fP, and also +provides methods to covert colors from any space to any other. +.sp +Functions +.TS +center; +|l|l|. +_ +T{ +\fI\%approximate\fP(value[, color_type, max_results]) +T} T{ +Search for nearest to \fBvalue\fP colors of specified \fBcolor_type\fP and return the first \fBmax_results\fP of them. +T} +_ +T{ +\fI\%find_closest\fP(value[, color_type]) +T} T{ +Search and return nearest to \fBvalue\fP instance of specified \fBcolor_type\fP\&. +T} +_ +T{ +\fI\%resolve_color\fP(subject[, color_type, ...]) +T} T{ +Suggested usage is to transform the user input in a free form in an attempt to find any matching color. +T} +_ +.TE +.sp +Classes +.TS +center; +|l|l|. +_ +T{ +\fI\%ApxResult\fP(color, distance) +T} T{ +Approximation result. +T} +_ +T{ +\fI\%Color16\fP(*args, **kwargs) +T} T{ +Variant of a \fBColor\fP operating within the most basic color set \-\- \fBxterm\-16\fP\&. +T} +_ +T{ +\fI\%Color256\fP(*args, **kwargs) +T} T{ +Variant of a \fBColor\fP operating within relatively modern \fBxterm\-256\fP indexed color table. +T} +_ +T{ +\fI\%ColorRGB\fP(*args, **kwargs) +T} T{ +Variant of a \fBColor\fP operating within RGB color space. +T} +_ +T{ +\fI\%DefaultColor\fP() +T} T{ +Special \fBColor\fP instance rendering to SGR sequence telling the terminal to reset fg or bg color; same for \fI\%TmuxRenderer\fP\&. Useful when you inherit some \fI\%Style\fP with fg or bg color that you don\(aqt need, but at the same time you don\(aqt actually want to set up any color whatsoever::. +T} +_ +T{ +\fI\%DynamicColor\fP(*args, **kwargs) +T} T{ +Color that returns different values depending on internal class\-level state that can be altered globally for all instances of a concrete implementation. +T} +_ +T{ +\fI\%HSV\fP(hue, saturation, value) +T} T{ +Initially HSV is a transformation of RGB color space; color is stored as 3 floats representing Hue channel, Saturation channel and Value channel correspondingly. +T} +_ +T{ +\fBIColorValue\fP() +T} T{ +T} +_ +T{ +\fI\%LAB\fP(lum, a, b) +T} T{ +Color value in a \fIuniform\fP color space, CIELAB, which expresses color as three values: L* for perceptual lightness and a* and b* for the four unique colors of human vision: red, green, blue and yellow. +T} +_ +T{ +\fI\%NoopColor\fP() +T} T{ +Special \fBColor\fP class always rendering into empty string. +T} +_ +T{ +\fI\%RGB\fP(value) +T} T{ +Color value stored internally as an 24\-bit integer. +T} +_ +T{ +\fBRealColor\fP(value) +T} T{ +T} +_ +T{ +\fI\%RenderColor\fP() +T} T{ +Abstract superclass for other \fBColors\fP\&. +T} +_ +T{ +\fI\%ResolvableColor\fP(*args, **kwargs) +T} T{ +Mixin for other \fBColors\fP\&. +T} +_ +T{ +\fI\%XYZ\fP(x, y, z) +T} T{ +Color in XYZ space is represented by three floats: Y is the luminance, Z is quasi\-equal to blue (of CIE RGB), and X is a mix of the three CIE RGB curves chosen to be nonnegative. +T} +_ +.TE +.INDENT 0.0 +.TP +.B class pytermor.color.RGB(value) +Bases: \fBIColorValue\fP +.sp +Color value stored internally as an 24\-bit integer. +Base for more complex color classes. +.INDENT 7.0 +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod diff(c1, c2) +RGB euclidean distance. +.INDENT 7.0 +.TP +.B Return type +float +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod from_channels(red, green, blue) +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBred\fP \-\- +.IP \(bu 2 +\fBgreen\fP \-\- +.IP \(bu 2 +\fBblue\fP \-\- +.UNINDENT +.TP +.B Returns + +.TP +.B Return type + +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod from_ratios(rr, gr, br) +d +:param rr: +:param gr: +:param br: +.INDENT 7.0 +.TP +.B Return type +\fI\%RGB\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property red: int +Red channel value [0;255] +.UNINDENT +.INDENT 7.0 +.TP +.B property green: int +Green channel value [0;255] +.UNINDENT +.INDENT 7.0 +.TP +.B property blue: int +Blue channel value [0;255] +.UNINDENT +.INDENT 7.0 +.TP +.B property int: int +Color value in RGB space (24\-bit integer within +[0; 0xFFFFFF] range) +.UNINDENT +.INDENT 7.0 +.TP +.B property rgb: \fI\%RGB\fP +Color value in RGB space (3 × 8\-bit ints) +.UNINDENT +.INDENT 7.0 +.TP +.B property hsv: \fI\%HSV\fP +Color value in HSV space (three floats) +.UNINDENT +.INDENT 7.0 +.TP +.B property xyz: \fI\%XYZ\fP +Color value in XYZ space (three floats) +.UNINDENT +.INDENT 7.0 +.TP +.B property lab: \fI\%LAB\fP +Color value in LAB space (three floats) +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.color.HSV(hue, saturation, value) +Bases: \fBIColorValue\fP +.sp +Initially HSV is a transformation of RGB color space; color is stored as 3 +floats representing Hue channel, Saturation channel and Value channel +correspondingly. Supports direct (fast) transformation to RGB and indirect +(=slow) to all other spaces through using more than one conversion with +HSV → RGB being the first one. +.INDENT 7.0 +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod diff(c1, c2) +HSV euclidean distance. +.INDENT 7.0 +.TP +.B Return type +float +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property hue: float +Hue channel value [0;360] +.UNINDENT +.INDENT 7.0 +.TP +.B property saturation: float +Saturation channel value [0;1] +.UNINDENT +.INDENT 7.0 +.TP +.B property value: float +Value channel value [0;1] +.UNINDENT +.INDENT 7.0 +.TP +.B property int: int +Color value in RGB space (24\-bit integer within +[0; 0xFFFFFF] range) +.UNINDENT +.INDENT 7.0 +.TP +.B property rgb: \fI\%RGB\fP +Color value in RGB space (3 × 8\-bit ints) +.UNINDENT +.INDENT 7.0 +.TP +.B property hsv: \fI\%HSV\fP +Color value in HSV space (three floats) +.UNINDENT +.INDENT 7.0 +.TP +.B property xyz: \fI\%XYZ\fP +Color value in XYZ space (three floats) +.UNINDENT +.INDENT 7.0 +.TP +.B property lab: \fI\%LAB\fP +Color value in LAB space (three floats) +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.color.XYZ(x, y, z) +Bases: \fBIColorValue\fP +.sp +Color in XYZ space is represented by three floats: Y is the luminance, Z is +quasi\-equal to blue (of CIE RGB), and X is a mix of the three CIE RGB curves +chosen to be nonnegative. CIE 1931 XYZ color space was one of the first +attempts to produce a color space based on measurements of human color +perception. Setting Y as luminance has the useful result that for any given +Y value, the XZ plane will contain all possible chromaticities at that +luminance. +.sp +\fBNOTE:\fP +.INDENT 7.0 +.INDENT 3.5 +\fI\%x\fP and \fI\%z\fP values can be above 100. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod diff(c1, c2) +.sp +\fBNOTE:\fP +.INDENT 7.0 +.INDENT 3.5 +This one is written on the analogy of other diffs, therefore +it can be actually a little bit incorrect or outright wrong. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Return type +float +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property x: float +X channel value [0;100) +.UNINDENT +.INDENT 7.0 +.TP +.B property y: float +Luminance [0;100] +.UNINDENT +.INDENT 7.0 +.TP +.B property z: float +Quasi\-equal to blue [0;100) +.UNINDENT +.INDENT 7.0 +.TP +.B property int: int +Color value in RGB space (24\-bit integer within +[0; 0xFFFFFF] range) +.UNINDENT +.INDENT 7.0 +.TP +.B property rgb: \fI\%RGB\fP +Color value in RGB space (3 × 8\-bit ints) +.UNINDENT +.INDENT 7.0 +.TP +.B property hsv: \fI\%HSV\fP +Color value in HSV space (three floats) +.UNINDENT +.INDENT 7.0 +.TP +.B property xyz: \fI\%XYZ\fP +Color value in XYZ space (three floats) +.UNINDENT +.INDENT 7.0 +.TP +.B property lab: \fI\%LAB\fP +Color value in LAB space (three floats) +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.color.LAB(lum, a, b) +Bases: \fBIColorValue\fP +.sp +Color value in a \fIuniform\fP color space, CIELAB, which expresses color as +three values: L* for perceptual lightness and a* and b* for the four unique +colors of human vision: red, green, blue and yellow. CIELAB was intended as +a perceptually uniform space, where a given numerical change corresponds to +a similar perceived change in color. Like the CIEXYZ space it derives from, +CIELAB color space is a device\-independent, \(dqstandard observer\(dq model. +.INDENT 7.0 +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod diff(c1, c2) +CIE76 ΔE* color difference. +.INDENT 7.0 +.TP +.B Return type +float +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property lum: float +Luminance [0;100] +.UNINDENT +.INDENT 7.0 +.TP +.B property a: float +Green–magenta axis, [\-100;100] in general, but can be less/more +.UNINDENT +.INDENT 7.0 +.TP +.B property b: float +Blue–yellow axis, [\-100;100] in general, but can be less/more +.UNINDENT +.INDENT 7.0 +.TP +.B property int: int +Color value in RGB space (24\-bit integer within +[0; 0xFFFFFF] range) +.UNINDENT +.INDENT 7.0 +.TP +.B property rgb: \fI\%RGB\fP +Color value in RGB space (3 × 8\-bit ints) +.UNINDENT +.INDENT 7.0 +.TP +.B property hsv: \fI\%HSV\fP +Color value in HSV space (three floats) +.UNINDENT +.INDENT 7.0 +.TP +.B property xyz: \fI\%XYZ\fP +Color value in XYZ space (three floats) +.UNINDENT +.INDENT 7.0 +.TP +.B property lab: \fI\%LAB\fP +Color value in LAB space (three floats) +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.color.RenderColor +Abstract superclass for other \fBColors\fP\&. Provides interfaces for +transforming RGB values to SGRs for different terminal modes. +.INDENT 7.0 +.TP +.B abstract to_sgr(target=ColorTarget.FG, upper_bound=None) +Make an \fI\%SGR sequence\fP out of \fBColor\fP\&. Used by \fI\%SgrRenderer\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBtarget\fP (\fI\%ColorTarget\fP) \-\- Sequence context (FG, BG, UNDERLINE). +.IP \(bu 2 +\fBupper_bound\fP (\fIOptional\fP\fI[\fP\fIType\fP\fI[\fP\fIColor\fP\fI]\fP\fI]\fP) \-\- Required result \fBColor\fP type upper boundary, i.e., the +maximum acceptable color class, which will be the basis for +SGR being made. See \fI\%Color256.to_sgr()\fP for the details. +.UNINDENT +.TP +.B Return type +\fI\%SequenceSGR\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B abstract to_tmux(target=ColorTarget.FG) +Make a tmux markup directive, which will change the output color to +this color\(aqs value (after tmux processes and prints it). Used by \fI\%TmuxRenderer\fP\&. +.INDENT 7.0 +.TP +.B Parameters +\fBtarget\fP (\fI\%ColorTarget\fP) \-\- Sequence context (FG, BG, UNDERLINE). +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.color.ResolvableColor(*args, **kwargs) +Bases: \fBGeneric\fP[\fB_RCT\fP] +.sp +Mixin for other \fBColors\fP\&. Implements color search by name. +.INDENT 7.0 +.TP +.B Return type +_RCT +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod names() +All registried colors\(aq names of this type. +.INDENT 7.0 +.TP +.B Return type +\fIIterable\fP[\fITuple\fP[str]] +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod find_by_name(name) +Case\-insensitive search through registry contents. +.sp +\fBSEE ALSO:\fP +.INDENT 7.0 +.INDENT 3.5 +\fI\%resolve_color()\fP for the details +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +\fBname\fP (\fIstr\fP) \-\- Name to search for. +.TP +.B Return type +\fI_RCT\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod find_closest(value) +Search and return color instance nearest to \fBvalue\fP\&. +.sp +\fBSEE ALSO:\fP +.INDENT 7.0 +.INDENT 3.5 +\fI\%color.find_closest()\fP for the details +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +\fBvalue\fP (\fIpytermor.color.IColorValue\fP\fI | \fP\fIint\fP) \-\- Target color/color value. +.TP +.B Return type +\fI_RCT\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod approximate(value, max_results=1) +Search for the colors nearest to \fBvalue\fP and return the first \fBmax_results\fP\&. +.sp +\fBSEE ALSO:\fP +.INDENT 7.0 +.INDENT 3.5 +\fI\%color.approximate()\fP for the details +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBvalue\fP (\fIpytermor.color.IColorValue\fP\fI | \fP\fIint\fP) \-\- Target color/color value. +.IP \(bu 2 +\fBmax_results\fP (\fIint\fP) \-\- Result limit. +.UNINDENT +.TP +.B Return type +\fIList\fP[\fI\%ApxResult\fP[\fI_RCT\fP]] +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property name: str | None +Color name, e.g. \(dqnavy\-blue\(dq. +.UNINDENT +.INDENT 7.0 +.TP +.B property available_for_approximation: bool +All colors should be available for approximations, but there is one +exception \-\- \fI\%Color256\fP instances who have a \fI\%Color16\fP counterpart +with the same value. Details described in \fI\%Color16 and Color256 equivalents\fP\&. +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.color.ApxResult(color, distance) +Bases: \fBGeneric\fP[\fB_RCT\fP] +.sp +Approximation result. +.INDENT 7.0 +.UNINDENT +.INDENT 7.0 +.TP +.B color: _RCT +Found \fBColor\fP instance. +.UNINDENT +.INDENT 7.0 +.TP +.B distance: float +Color difference between this instance and the approximation target. +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B final class pytermor.color.Color16(*args, **kwargs) +Bases: \fBRealColor\fP, \fI\%RenderColor\fP, \fI\%ResolvableColor\fP[\fI\%Color16\fP] +.sp +Variant of a \fBColor\fP operating within the most basic color set +\-\- \fBxterm\-16\fP\&. Represents basic color\-setting SGRs with primary codes +30\-37, 40\-47, 90\-97 and 100\-107 (see \fBguide.ansi\-presets.color16\fP). +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBvalue\fP (\fIint\fP\fI|\fP\fIIColorValue\fP) \-\- Color value as 24\-bit integer in RGB space, or any +instance implementing color value interface (e.g. \fI\%HSV\fP). +.IP \(bu 2 +\fBcode_fg\fP (\fIint\fP) \-\- Int code for a foreground color setup, e.g. 30. +.IP \(bu 2 +\fBcode_bg\fP (\fIint\fP) \-\- Int code for a background color setup. e.g. 40. +.IP \(bu 2 +\fBname\fP (\fIstr\fP) \-\- Name of the color, e.g. \(dqred\(dq. +.IP \(bu 2 +\fBregister\fP (\fIbool\fP) \-\- If \fITrue\fP, add color to registry for resolving by name +and approximation. +.IP \(bu 2 +\fBaliases\fP (\fIlist\fP\fI[\fP\fIstr\fP\fI]\fP) \-\- Alternative color names (used in \fI\%resolve_color()\fP). +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property code_fg: int +Int code for a foreground color setup, e.g. 30. +.UNINDENT +.INDENT 7.0 +.TP +.B property code_bg: int +Int code for a background color setup. e.g. 40. +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod get_by_code(code) +Get a \fI\%Color16\fP instance with specified code. Only \fIforeground\fP (=text) +colors are indexed, therefore it is not possible to look up for a +\fI\%Color16\fP with given background color (on second thought, it \fIis\fP +actually possible using \fI\%find_closest()\fP). +.INDENT 7.0 +.TP +.B Parameters +\fBcode\fP (\fIint\fP) \-\- Foreground integer code to look up for (see +\fBguide.ansi\-presets.color16\fP). +.TP +.B Raises +\fBLookupError\fP \-\- If no color with specified code is found. +.TP +.B Return type +\fI\%Color16\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B to_sgr(target=ColorTarget.FG, upper_bound=None) +Make an \fI\%SGR sequence\fP out of \fBColor\fP\&. Used by \fI\%SgrRenderer\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBtarget\fP (\fI\%ColorTarget\fP) \-\- Sequence context (FG, BG, UNDERLINE). +.IP \(bu 2 +\fBupper_bound\fP (\fIOptional\fP\fI[\fP\fIType\fP\fI[\fP\fIColor\fP\fI]\fP\fI]\fP) \-\- Required result \fBColor\fP type upper boundary, i.e., the +maximum acceptable color class, which will be the basis for +SGR being made. See \fI\%Color256.to_sgr()\fP for the details. +.UNINDENT +.TP +.B Return type +\fI\%SequenceSGR\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B to_tmux(target=ColorTarget.FG) +Make a tmux markup directive, which will change the output color to +this color\(aqs value (after tmux processes and prints it). Used by \fI\%TmuxRenderer\fP\&. +.INDENT 7.0 +.TP +.B Parameters +\fBtarget\fP (\fI\%ColorTarget\fP) \-\- Sequence context (FG, BG, UNDERLINE). +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod approximate(value, max_results=1) +Search for the colors nearest to \fBvalue\fP and return the first \fBmax_results\fP\&. +.sp +\fBSEE ALSO:\fP +.INDENT 7.0 +.INDENT 3.5 +\fI\%color.approximate()\fP for the details +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBvalue\fP (\fIpytermor.color.IColorValue\fP\fI | \fP\fIint\fP) \-\- Target color/color value. +.IP \(bu 2 +\fBmax_results\fP (\fIint\fP) \-\- Result limit. +.UNINDENT +.TP +.B Return type +\fIList\fP[\fI\%ApxResult\fP[\fI_RCT\fP]] +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property available_for_approximation: bool +All colors should be available for approximations, but there is one +exception \-\- \fI\%Color256\fP instances who have a \fI\%Color16\fP counterpart +with the same value. Details described in \fI\%Color16 and Color256 equivalents\fP\&. +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod find_by_name(name) +Case\-insensitive search through registry contents. +.sp +\fBSEE ALSO:\fP +.INDENT 7.0 +.INDENT 3.5 +\fI\%resolve_color()\fP for the details +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +\fBname\fP (\fIstr\fP) \-\- Name to search for. +.TP +.B Return type +\fI_RCT\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod find_closest(value) +Search and return color instance nearest to \fBvalue\fP\&. +.sp +\fBSEE ALSO:\fP +.INDENT 7.0 +.INDENT 3.5 +\fI\%color.find_closest()\fP for the details +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +\fBvalue\fP (\fIpytermor.color.IColorValue\fP\fI | \fP\fIint\fP) \-\- Target color/color value. +.TP +.B Return type +\fI_RCT\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B format_value(prefix=\(aq0x\(aq) +Format color value as \(dq0xRRGGBB\(dq. +.INDENT 7.0 +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property hsv: \fI\%HSV\fP +Color value in HSV space (three floats) +.UNINDENT +.INDENT 7.0 +.TP +.B property int: int +Color value in RGB space (24\-bit integer within +[0; 0xFFFFFF] range) +.UNINDENT +.INDENT 7.0 +.TP +.B property lab: \fI\%LAB\fP +Color value in LAB space (three floats) +.UNINDENT +.INDENT 7.0 +.TP +.B property name: str | None +Color name, e.g. \(dqnavy\-blue\(dq. +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod names() +All registried colors\(aq names of this type. +.INDENT 7.0 +.TP +.B Return type +\fIIterable\fP[\fITuple\fP[str]] +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property rgb: \fI\%RGB\fP +Color value in RGB space (3 × 8\-bit ints) +.UNINDENT +.INDENT 7.0 +.TP +.B property xyz: \fI\%XYZ\fP +Color value in XYZ space (three floats) +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B final class pytermor.color.Color256(*args, **kwargs) +Bases: \fBRealColor\fP, \fI\%RenderColor\fP, \fI\%ResolvableColor\fP[\fI\%Color256\fP] +.sp +Variant of a \fBColor\fP operating within relatively modern \fBxterm\-256\fP +indexed color table. Represents SGR complex codes \fB38;5;*\fP and \fB48;5;*\fP +(see \fI\%Color256 presets\fP). +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBvalue\fP (\fIint\fP\fI|\fP\fIIColorValue\fP) \-\- Color value as 24\-bit integer in RGB space, or any +instance implementing color value interface (e.g. \fI\%HSV\fP). +.IP \(bu 2 +\fBcode\fP (\fIint\fP) \-\- Int code for a color setup, e.g. 52. +.IP \(bu 2 +\fBname\fP (\fIstr\fP) \-\- Name of the color, e.g. \(dqdark\-red\(dq. +.IP \(bu 2 +\fBregister\fP (\fIbool\fP) \-\- If \fITrue\fP, add color to registry for resolving by name. +.IP \(bu 2 +\fBaliases\fP (\fIt.List\fP\fI[\fP\fIstr\fP\fI]\fP) \-\- Alternative color names (used in \fI\%resolve_color()\fP). +.IP \(bu 2 +\fBcolor16_equiv\fP (\fI\%Color16\fP) \-\- \fI\%Color16\fP counterpart (applies only to codes 0\-15). +For the details see \fI\%Color16 and Color256 equivalents\fP\&. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B to_sgr(target=ColorTarget.FG, upper_bound=None) +Make an \fI\%SGR sequence\fP out of \fBColor\fP\&. Used by \fI\%SgrRenderer\fP\&. +.sp +Each \fBColor\fP type represents one SGR type in the context of colors. For +example, if \fBupper_bound\fP is set to \fI\%Color16\fP, the resulting SGR will always +be one of 16\-color index table, even if the original color was of different +type \-\- it will be approximated just before the SGR assembling. +.sp +The reason for this is the necessity to provide a similar look for all users +with different terminal settings/ capabilities. When the library sees that +user\(aqs output device supports 256 colors only, it cannot assemble True Color +SGRs, because they will be ignored (if we are lucky), or displayed in a +glitchy way, or mess up the output completely. The good news is that the +process is automatic and in most cases the library will manage the +transformations by itself. If it\(aqs not the case, the developer can correct the +behaviour by overriding the renderers\(aq output mode. See \fI\%SgrRenderer\fP and +\fI\%OutputMode\fP docs. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBtarget\fP (\fI\%ColorTarget\fP) \-\- +.IP \(bu 2 +\fBupper_bound\fP (\fIOptional\fP\fI[\fP\fIType\fP\fI[\fP\fIColor\fP\fI]\fP\fI]\fP) \-\- Required result \fBColor\fP type upper boundary, i.e., the +maximum acceptable color class, which will be the basis for +SGR being made. +.UNINDENT +.TP +.B Return type +\fI\%SequenceSGR\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B to_tmux(target=ColorTarget.FG) +Make a tmux markup directive, which will change the output color to +this color\(aqs value (after tmux processes and prints it). Used by \fI\%TmuxRenderer\fP\&. +.INDENT 7.0 +.TP +.B Parameters +\fBtarget\fP (\fI\%ColorTarget\fP) \-\- Sequence context (FG, BG, UNDERLINE). +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property code: int +Int code for a color setup, e.g. 52. +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod get_by_code(code) +Get a \fI\%Color256\fP instance with specified code (=position in the index). +.INDENT 7.0 +.TP +.B Parameters +\fBcode\fP (\fIint\fP) \-\- Color code to look up for (see \fI\%Color256 presets\fP). +.TP +.B Raises +\fBLookupError\fP \-\- If no color with specified code is found. +.TP +.B Return type +\fI\%Color256\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property available_for_approximation: bool +All colors should be available for approximations, but there is one +exception \-\- \fI\%Color256\fP instances who have a \fI\%Color16\fP counterpart +with the same value. Details described in \fI\%Color16 and Color256 equivalents\fP\&. +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod approximate(value, max_results=1) +Search for the colors nearest to \fBvalue\fP and return the first \fBmax_results\fP\&. +.sp +\fBSEE ALSO:\fP +.INDENT 7.0 +.INDENT 3.5 +\fI\%color.approximate()\fP for the details +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBvalue\fP (\fIpytermor.color.IColorValue\fP\fI | \fP\fIint\fP) \-\- Target color/color value. +.IP \(bu 2 +\fBmax_results\fP (\fIint\fP) \-\- Result limit. +.UNINDENT +.TP +.B Return type +\fIList\fP[\fI\%ApxResult\fP[\fI_RCT\fP]] +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod find_by_name(name) +Case\-insensitive search through registry contents. +.sp +\fBSEE ALSO:\fP +.INDENT 7.0 +.INDENT 3.5 +\fI\%resolve_color()\fP for the details +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +\fBname\fP (\fIstr\fP) \-\- Name to search for. +.TP +.B Return type +\fI_RCT\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod find_closest(value) +Search and return color instance nearest to \fBvalue\fP\&. +.sp +\fBSEE ALSO:\fP +.INDENT 7.0 +.INDENT 3.5 +\fI\%color.find_closest()\fP for the details +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +\fBvalue\fP (\fIpytermor.color.IColorValue\fP\fI | \fP\fIint\fP) \-\- Target color/color value. +.TP +.B Return type +\fI_RCT\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B format_value(prefix=\(aq0x\(aq) +Format color value as \(dq0xRRGGBB\(dq. +.INDENT 7.0 +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property hsv: \fI\%HSV\fP +Color value in HSV space (three floats) +.UNINDENT +.INDENT 7.0 +.TP +.B property int: int +Color value in RGB space (24\-bit integer within +[0; 0xFFFFFF] range) +.UNINDENT +.INDENT 7.0 +.TP +.B property lab: \fI\%LAB\fP +Color value in LAB space (three floats) +.UNINDENT +.INDENT 7.0 +.TP +.B property name: str | None +Color name, e.g. \(dqnavy\-blue\(dq. +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod names() +All registried colors\(aq names of this type. +.INDENT 7.0 +.TP +.B Return type +\fIIterable\fP[\fITuple\fP[str]] +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property rgb: \fI\%RGB\fP +Color value in RGB space (3 × 8\-bit ints) +.UNINDENT +.INDENT 7.0 +.TP +.B property xyz: \fI\%XYZ\fP +Color value in XYZ space (three floats) +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B final class pytermor.color.ColorRGB(*args, **kwargs) +Bases: \fBRealColor\fP, \fI\%RenderColor\fP, \fI\%ResolvableColor\fP[\fI\%ColorRGB\fP] +.sp +Variant of a \fBColor\fP operating within RGB color space. Presets include +\fBes7s named colors\fP, a unique collection of colors +compiled from several known sources after careful selection. However, +it\(aqs not limited to aforementioned color list and can be easily extended. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBvalue\fP (\fIint\fP\fI|\fP\fIIColorValue\fP) \-\- Color value as 24\-bit integer in RGB space (e.g. +0x73a9c2), or any instance implementing color value +interface (e.g. \fI\%HSV\fP). +.IP \(bu 2 +\fBname\fP (\fIstr\fP) \-\- Name of the color, e.g. \(dqmoonstone\-blue\(dq. +.IP \(bu 2 +\fBregister\fP (\fIbool\fP) \-\- If \fITrue\fP, add color to registry for resolving by name. +.IP \(bu 2 +\fBaliases\fP (\fIt.List\fP\fI[\fP\fIstr\fP\fI]\fP) \-\- Alternative color names (used in \fI\%resolve_color()\fP). +.IP \(bu 2 +\fBvariation_map\fP (\fIt.Dict\fP\fI[\fP\fIint\fP\fI, \fP\fIstr\fP\fI]\fP) \-\- Mapping {\fIint\fP: \fIstr\fP}, where keys are hex values, +and values are variation names. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B to_sgr(target=ColorTarget.FG, upper_bound=None) +Make an \fI\%SGR sequence\fP out of \fBColor\fP\&. Used by \fI\%SgrRenderer\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBtarget\fP (\fI\%ColorTarget\fP) \-\- Sequence context (FG, BG, UNDERLINE). +.IP \(bu 2 +\fBupper_bound\fP (\fIOptional\fP\fI[\fP\fIType\fP\fI[\fP\fIColor\fP\fI]\fP\fI]\fP) \-\- Required result \fBColor\fP type upper boundary, i.e., the +maximum acceptable color class, which will be the basis for +SGR being made. See \fI\%Color256.to_sgr()\fP for the details. +.UNINDENT +.TP +.B Return type +\fI\%SequenceSGR\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B to_tmux(target=ColorTarget.FG) +Make a tmux markup directive, which will change the output color to +this color\(aqs value (after tmux processes and prints it). Used by \fI\%TmuxRenderer\fP\&. +.INDENT 7.0 +.TP +.B Parameters +\fBtarget\fP (\fI\%ColorTarget\fP) \-\- Sequence context (FG, BG, UNDERLINE). +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property base: Optional[_RCT] +Parent color for color variations. Empty for regular colors. +.UNINDENT +.INDENT 7.0 +.TP +.B property variations: Dict[str, _RCT] +List of color variations. \fIVariation\fP of a color is a similar color with +almost the same name, but with differing suffix. The main idea of +variations is to provide a basis for fuzzy searching, which will return +several results for one query; i.e., when the query matches a color with +variations, the whole color family can be considered a match, which +should increase searching speed. +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod approximate(value, max_results=1) +Search for the colors nearest to \fBvalue\fP and return the first \fBmax_results\fP\&. +.sp +\fBSEE ALSO:\fP +.INDENT 7.0 +.INDENT 3.5 +\fI\%color.approximate()\fP for the details +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBvalue\fP (\fIpytermor.color.IColorValue\fP\fI | \fP\fIint\fP) \-\- Target color/color value. +.IP \(bu 2 +\fBmax_results\fP (\fIint\fP) \-\- Result limit. +.UNINDENT +.TP +.B Return type +\fIList\fP[\fI\%ApxResult\fP[\fI_RCT\fP]] +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property available_for_approximation: bool +All colors should be available for approximations, but there is one +exception \-\- \fI\%Color256\fP instances who have a \fI\%Color16\fP counterpart +with the same value. Details described in \fI\%Color16 and Color256 equivalents\fP\&. +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod find_by_name(name) +Case\-insensitive search through registry contents. +.sp +\fBSEE ALSO:\fP +.INDENT 7.0 +.INDENT 3.5 +\fI\%resolve_color()\fP for the details +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +\fBname\fP (\fIstr\fP) \-\- Name to search for. +.TP +.B Return type +\fI_RCT\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod find_closest(value) +Search and return color instance nearest to \fBvalue\fP\&. +.sp +\fBSEE ALSO:\fP +.INDENT 7.0 +.INDENT 3.5 +\fI\%color.find_closest()\fP for the details +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +\fBvalue\fP (\fIpytermor.color.IColorValue\fP\fI | \fP\fIint\fP) \-\- Target color/color value. +.TP +.B Return type +\fI_RCT\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B format_value(prefix=\(aq0x\(aq) +Format color value as \(dq0xRRGGBB\(dq. +.INDENT 7.0 +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property hsv: \fI\%HSV\fP +Color value in HSV space (three floats) +.UNINDENT +.INDENT 7.0 +.TP +.B property int: int +Color value in RGB space (24\-bit integer within +[0; 0xFFFFFF] range) +.UNINDENT +.INDENT 7.0 +.TP +.B property lab: \fI\%LAB\fP +Color value in LAB space (three floats) +.UNINDENT +.INDENT 7.0 +.TP +.B property name: str | None +Color name, e.g. \(dqnavy\-blue\(dq. +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod names() +All registried colors\(aq names of this type. +.INDENT 7.0 +.TP +.B Return type +\fIIterable\fP[\fITuple\fP[str]] +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property rgb: \fI\%RGB\fP +Color value in RGB space (3 × 8\-bit ints) +.UNINDENT +.INDENT 7.0 +.TP +.B property xyz: \fI\%XYZ\fP +Color value in XYZ space (three floats) +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.color.NoopColor +Bases: \fI\%RenderColor\fP +.sp +Special \fBColor\fP class always rendering into empty string. +.sp +\fBIMPORTANT:\fP +.INDENT 7.0 +.INDENT 3.5 +Casting to \fIbool\fP results in \fBFalse\fP for all \fBNOOP\fP instances in the +library (\fI\%NOOP_SEQ\fP, \fBNOOP_COLOR\fP and \fI\%NOOP_STYLE\fP). This is intended. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B to_sgr(target=ColorTarget.FG, upper_bound=None) +Make an \fI\%SGR sequence\fP out of \fBColor\fP\&. Used by \fI\%SgrRenderer\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBtarget\fP (\fI\%ColorTarget\fP) \-\- Sequence context (FG, BG, UNDERLINE). +.IP \(bu 2 +\fBupper_bound\fP (\fIOptional\fP\fI[\fP\fIType\fP\fI[\fP\fIColor\fP\fI]\fP\fI]\fP) \-\- Required result \fBColor\fP type upper boundary, i.e., the +maximum acceptable color class, which will be the basis for +SGR being made. See \fI\%Color256.to_sgr()\fP for the details. +.UNINDENT +.TP +.B Return type +\fI\%SequenceSGR\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B to_tmux(target=ColorTarget.FG) +Make a tmux markup directive, which will change the output color to +this color\(aqs value (after tmux processes and prints it). Used by \fI\%TmuxRenderer\fP\&. +.INDENT 7.0 +.TP +.B Parameters +\fBtarget\fP (\fI\%ColorTarget\fP) \-\- Sequence context (FG, BG, UNDERLINE). +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.color.DefaultColor +Bases: \fI\%RenderColor\fP +.sp +Special \fBColor\fP instance rendering to SGR sequence telling the terminal +to reset fg or bg color; same for \fI\%TmuxRenderer\fP\&. Useful when you inherit +some \fI\%Style\fP with fg or bg color that you don\(aqt need, but at the same +time you don\(aqt actually want to set up any color whatsoever: +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +>>> from pytermor import * +>>> DEFAULT_COLOR.to_sgr(target=ColorTarget.BG) + +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +\fBNOOP_COLOR\fP is treated like a placeholder for parent\(aqs attribute value and +doesn\(aqt change the result: +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +>>> from pytermor import SgrRenderer, render +>>> sgr_renderer = SgrRenderer(OutputMode.XTERM_16) +>>> render(\(dqMISMATCH\(dq, Style(Styles.INCONSISTENCY, fg=NOOP_COLOR), sgr_renderer) +\(aqMISMATCH\(aq +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +While \fBDEFAULT_COLOR\fP is actually resetting the color to default (terminal) value: +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +>>> render(\(dqMISMATCH\(dq, Style(Styles.INCONSISTENCY, fg=DEFAULT_COLOR), sgr_renderer) +\(aqMISMATCH\(aq +.ft P +.fi +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B to_sgr(target=ColorTarget.FG, upper_bound=None) +Make an \fI\%SGR sequence\fP out of \fBColor\fP\&. Used by \fI\%SgrRenderer\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBtarget\fP (\fI\%ColorTarget\fP) \-\- Sequence context (FG, BG, UNDERLINE). +.IP \(bu 2 +\fBupper_bound\fP (\fIOptional\fP\fI[\fP\fIType\fP\fI[\fP\fIColor\fP\fI]\fP\fI]\fP) \-\- Required result \fBColor\fP type upper boundary, i.e., the +maximum acceptable color class, which will be the basis for +SGR being made. See \fI\%Color256.to_sgr()\fP for the details. +.UNINDENT +.TP +.B Return type +\fI\%SequenceSGR\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B to_tmux(target=ColorTarget.FG) +Make a tmux markup directive, which will change the output color to +this color\(aqs value (after tmux processes and prints it). Used by \fI\%TmuxRenderer\fP\&. +.INDENT 7.0 +.TP +.B Parameters +\fBtarget\fP (\fI\%ColorTarget\fP) \-\- Sequence context (FG, BG, UNDERLINE). +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.color.DynamicColor(*args, **kwargs) +Bases: \fI\%RenderColor\fP, \fBGeneric\fP[\fB_T\fP] +.sp +Color that returns different values depending on internal class\-level +state that can be altered globally for all instances of a concrete +implementation. Supposed usage is to make a subclass of \fI\%DynamicColor\fP +and define state type, which will be shared between all instances of a +new class. Also concrete implementation of \fI\%update()\fP method is required, +which should contain logic for transforming some external parameters into +the state. State can be of any type, from plain \fI\%RGB\fP value to complex +dictionaries or custom classes. +.sp +There is also an \fBextractor\fP parameter, which is not shared between +instances of same subclass, rather being an instance attribute. This +parameter represents the logic of transforming one shared state into +several different colors, which therefore can be used as is, or be +included as a \fI\%fg\fP/\fI\%bg\fP attributes of \fI\%Style\fP instances. +.sp +Full usage example can be found at \fI\%Dynamic/deferred colors\fP docs page. +.INDENT 7.0 +.TP +.B Parameters +\fBextractor\fP \-\- Concrete implementation of \(dqstate\(dq \-> \(dqcolor\(dq +transformation logic. Can be a callable, which will be +invoked with a state variable as a first argument, or +can be a string, in which case it will be used to +extract the color value from the instance itself, with +this string as an attribute name, or it can be \fINone\fP, +in which case it implies that state variable is +instance of \fI\%Color\fP or it descendant and it can be +returned on extraction without transformation, as is. +.UNINDENT +.INDENT 7.0 +.TP +.B _DEFERRED: ClassVar[bool] = False +Class variable responsible for enabling deferred mode. In this +mode there is a possibility to delay an initialization of the state of +a concrete class and to create all dependant entities regardless. When +state is still uninitialized, the return color will be \fBNOOP_COLOR\fP, which +automatically updates to an actual color after state creation. See +\fI\%Dynamic/deferred colors\fP for the details. +.INDENT 7.0 +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod update(**kwargs) +Set new internal state for all instances of this class. +.INDENT 7.0 +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B to_sgr(target=ColorTarget.FG, upper_bound=None) +Make an \fI\%SGR sequence\fP out of \fBColor\fP\&. Used by \fI\%SgrRenderer\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBtarget\fP (\fI\%ColorTarget\fP) \-\- Sequence context (FG, BG, UNDERLINE). +.IP \(bu 2 +\fBupper_bound\fP (\fIOptional\fP\fI[\fP\fIType\fP\fI[\fP\fIColor\fP\fI]\fP\fI]\fP) \-\- Required result \fBColor\fP type upper boundary, i.e., the +maximum acceptable color class, which will be the basis for +SGR being made. See \fI\%Color256.to_sgr()\fP for the details. +.UNINDENT +.TP +.B Return type +\fI\%SequenceSGR\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B to_tmux(target=ColorTarget.FG) +Make a tmux markup directive, which will change the output color to +this color\(aqs value (after tmux processes and prints it). Used by \fI\%TmuxRenderer\fP\&. +.INDENT 7.0 +.TP +.B Parameters +\fBtarget\fP (\fI\%ColorTarget\fP) \-\- Sequence context (FG, BG, UNDERLINE). +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.color.resolve_color(subject, color_type=None, approx_cache=True) +Suggested usage is to transform the user input in a free form in an attempt +to find any matching color. The method operates in three different modes depending +on arguments: resolving by name, resolving by value and instantiating. +.sp +\fBResolving by name\fP: If \fBsubject\fP is a \fIstr\fP starting with any character +except \fB#\fP, case\-insensitive search through the registry of \fBcolor_type\fP colors +is performed. In this mode the algorithm looks for the instance which has all the +words from \fBsubject\fP as parts of its name (the order must be the same). Color +names are stored in registries as sets of tokens, which allows to use any form +of input and get the correct result regardless. The only requirement is to +separate the words in any matter (see the example below), so that they could be +split to tokens which will be matched with the registry keys. +.sp +If \fBcolor_type\fP is omitted, all the registries will be requested in this order: +[\fI\%Color16\fP, \fI\%Color256\fP, \fI\%ColorRGB\fP]. Should any registry find a full match, the +resolving is stopped and the result is returned. +.sp +.nf +.ft C +>>> resolve_color(\(aqdeep\-sky\-blue\-7\(aq) + +>>> resolve_color(\(aqDEEP SKY BLUE 7\(aq) + +>>> resolve_color(\(aqDeepSkyBlue7\(aq) + +.ft P +.fi +.sp +.nf +.ft C +>>> resolve_color(\(aqdeepskyblue7\(aq) +Traceback (most recent call last): +LookupError: Color \(aqdeepskyblue7\(aq was not found in any registry +.ft P +.fi +.sp +\fBResolving by value\fP or \fBinstantiating\fP: if \fBsubject\fP is specified as: +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.IP 1. 3 +\fIint\fP in [0x000000; 0xffffff] range, or +.IP 2. 3 +\fIstr\fP in full hexadecimal form: \(dq#RRGGBB\(dq, or +.IP 3. 3 +\fIstr\fP in short hexadecimal form: \(dq#RGB\(dq, +.UNINDENT +.UNINDENT +.UNINDENT +.sp +and \fBcolor_type\fP is \fBpresent\fP , the result will be the best \fBsubject\fP +approximation to corresponding color index. Note that this value is expected +to differ from the requested one (and sometimes differs a lot). If \fBcolor_type\fP +is \fBmissing\fP, no searching is performed; instead a new nameless \fI\%ColorRGB\fP +is instantiated and returned. +.sp +\fBNOTE:\fP +.INDENT 7.0 +.INDENT 3.5 +The instance created this way is an \(dqunbound\(dq color, i.e. it does +not end up in a registry or an index bound to its type, thus the resolver +and approximation algorithms are unaware of its existence. The rationale +for this is to keep the registries clean and stateless to ensure that +the same input always resolves to the same output. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +>>> resolve_color(\(dq#333\(dq) + +>>> resolve_color(0xfafef0) + +.ft P +.fi +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBsubject\fP (\fIstr\fP\fI|\fP\fIint\fP) \-\- \fBColor\fP name or hex value to search for. See \fI\%CDT\fP\&. +.IP \(bu 2 +\fBcolor_type\fP (\fIOptional\fP\fI[\fP\fIType\fP\fI[\fP\fI_RCT\fP\fI]\fP\fI]\fP) \-\- Target color type (\fI\%Color16\fP, \fI\%Color256\fP or \fI\%ColorRGB\fP). +.IP \(bu 2 +\fBapprox_cache\fP \-\- Use the approximation cache for \fBresolving by value\fP +mode or ignore it. For the details see \fI\%find_closest\fP and +\fI\%approximate\fP which are actually invoked by this method +under the hood. +.UNINDENT +.TP +.B Raises +\fBLookupError\fP \-\- If nothing was found in either of registries. +.TP +.B Returns +\fBColor\fP instance with specified name or value. +.TP +.B Return type +\fI_RCT\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.color.find_closest(value, color_type=None) +Search and return nearest to \fBvalue\fP instance of specified \fBcolor_type\fP\&. +If \fBcolor_type\fP is omitted, search for the closest \fI\%Color256\fP element. +.sp +\fBNOTE:\fP +.INDENT 7.0 +.INDENT 3.5 +Distance between two colors is calculated using CIE76 ΔE* color +difference formula in LAB color space. This method is considered to be +an acceptable tradeoff between sRGB euclidean distance, which doesn\(aqt +account for differences in human color perception, and CIE94/CIEDE2000, +which are more complex and in general excessive for this task. +.UNINDENT +.UNINDENT +.sp +Method is useful for finding applicable color alternatives if user\(aqs +terminal is incapable of operating in more advanced mode. Usually it is +done by the library automatically and transparently for both the developer +and the end\-user. +.sp +\fBIMPORTANT:\fP +.INDENT 7.0 +.INDENT 3.5 +This method caches the results, i.e., the same search query will from then +onward result in the same return value without the necessity of iterating +through the color index. If that\(aqs not applicable, use similar method +\fI\%approximate()\fP, which is unaware of caching mechanism altogether. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBvalue\fP (\fIpytermor.color.IColorValue\fP\fI | \fP\fIint\fP) \-\- Target color/color value. +.IP \(bu 2 +\fBcolor_type\fP (\fIOptional\fP\fI[\fP\fIType\fP\fI[\fP\fI_RCT\fP\fI]\fP\fI]\fP) \-\- Target color type (\fI\%Color16\fP, \fI\%Color256\fP or \fI\%ColorRGB\fP). +.UNINDENT +.TP +.B Returns +Nearest to \fBvalue\fP color instance of specified type. +.TP +.B Return type +\fI_RCT\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.color.approximate(value, color_type=None, max_results=1) +Search for nearest to \fBvalue\fP colors of specified \fBcolor_type\fP and +return the first \fBmax_results\fP of them. If \fBcolor_type\fP is omitted, search +for the closest \fI\%Color256\fP instances. This method is similar to the +\fI\%find_closest()\fP, although they differ in some aspects: +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.IP \(bu 2 +\fI\%approximate()\fP can return more than one result; +.IP \(bu 2 +\fI\%approximate()\fP returns not just a \fBColor\fP instance(s), but also a +number equal to squared distance to the target color for each of them; +.IP \(bu 2 +\fI\%find_closest()\fP caches the results, while \fI\%approximate()\fP ignores +the cache completely. +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBvalue\fP (\fIpytermor.color.IColorValue\fP\fI | \fP\fIint\fP) \-\- Target color/color value. +.IP \(bu 2 +\fBcolor_type\fP (\fIOptional\fP\fI[\fP\fIType\fP\fI[\fP\fI_RCT\fP\fI]\fP\fI]\fP) \-\- Target color type (\fI\%Color16\fP, \fI\%Color256\fP or \fI\%ColorRGB\fP). +.IP \(bu 2 +\fBmax_results\fP (\fIint\fP) \-\- Return no more than \fBmax_results\fP items. +.UNINDENT +.TP +.B Returns +Pairs of closest \fBColor\fP instance(s) found with their distances +to the target color, sorted by distance descending, i.e., element +at index 0 is the closest color found, paired with its distance +to the target; element with index 1 is second\-closest color +(if any) and corresponding distance value, etc. +.TP +.B Return type +\fIList\fP[\fI\%ApxResult\fP[\fI_RCT\fP]] +.UNINDENT +.UNINDENT +.SS pytermor.common +.sp +Module Attributes +.TS +center; +|l|l|. +_ +T{ +\fI\%CDT\fP +T} T{ +CDT represents a RGB color value. +T} +_ +T{ +\fI\%CXT\fP +T} T{ + +.nf +:todo:\(gaTODO\(ga +.fi +T} +_ +T{ +\fI\%FT\fP +T} T{ +FT is a style descriptor. +T} +_ +T{ +\fI\%RT\fP +T} T{ +RT includes regular \fIstr\fPs as well as \fI\%IRenderable\fP implementations. +T} +_ +T{ +\fI\%filterf\fP +T} T{ +Shortcut for filtering out falsy values from sequences +T} +_ +T{ +\fI\%filtern\fP +T} T{ +Shortcut for filtering out Nones from sequences +T} +_ +.TE +.sp +Functions +.TS +center; +|l|l|. +_ +T{ +\fI\%but\fP(cls, inp) +T} T{ +Return all elements from \fBinp\fP \fIexcept\fP instances of \fBcls\fP\&. +T} +_ +T{ +\fI\%char_range\fP(start, stop) +T} T{ +Yields all the characters from range of [\fBc1\fP; \fBc2\fP], inclusive (end character \fBc2\fP is \fBalso present\fP, in contrast with classic \fBrange()\fP, which excludes \fBstop\fP value from the results). +T} +_ +T{ +\fI\%chunk\fP(items, size) +T} T{ +Split item list into chunks of size \fBsize\fP and return these +T} +_ +T{ +\fI\%cut\fP(s, max_len[, align, overflow]) +T} T{ +.INDENT 0.0 +.TP +.B param s +.UNINDENT +T} +_ +T{ +\fI\%filterfv\fP(mapping) +T} T{ +Shortcut for filtering out falsy values from mappings +T} +_ +T{ +\fI\%filternv\fP(mapping) +T} T{ +Shortcut for filtering out None values from mappings +T} +_ +T{ +\fI\%fit\fP(s, max_len[, align, overflow, fill]) +T} T{ +.INDENT 0.0 +.TP +.B param s +.UNINDENT +T} +_ +T{ +\fI\%flatten\fP(items[, level_limit]) +T} T{ +Unpack a list consisting of any amount of nested lists to 1d\-array, or flat list, eliminating all the nesting. +T} +_ +T{ +\fI\%flatten1\fP(items) +T} T{ +Take a list of nested lists and unpack all nested elements one level up. +T} +_ +T{ +\fI\%get_qname\fP(obj) +T} T{ +Convenient method for getting a class name for the instances as well as for the classes themselves, in case where a variable in question can be both. +T} +_ +T{ +\fI\%get_subclasses\fP(target) +T} T{ +Traverse the inheritance tree and return a flat list of all descendants of \fBcls\fP (full hierarchy). +T} +_ +T{ +\fBisiterable\fP(arg) +T} T{ +T} +_ +T{ +\fI\%only\fP(cls, inp) +T} T{ +Return all elements from \fBinp\fP that \fIare\fP instances of \fBcls\fP +T} +_ +T{ +\fI\%others\fP(cls, inp) +T} T{ +Return all elements from \fBinp\fP \fIexcept\fP instances of \fBcls\fP and its children classes. +T} +_ +T{ +\fI\%ours\fP(cls, inp) +T} T{ +Return all elements from \fBinp\fP that \fIare\fP instances of \fBcls\fP or its children classes. +T} +_ +T{ +\fI\%pad\fP(n) +T} T{ +Convenient method to use instead of \fB\(dq\(dq.ljust(n)\fP\&. +T} +_ +T{ +\fI\%padv\fP(n) +T} T{ +Convenient method to use instead of \fB\(dq\en\(dq * n\fP\&. +T} +_ +.TE +.sp +Classes +.TS +center; +|l|l|. +_ +T{ +\fI\%Align\fP(value) +T} T{ +Align type. +T} +_ +T{ +\fI\%ExtendedEnum\fP(value) +T} T{ +Standard \fBEnum\fP with a few additional methods on top. +T} +_ +.TE +.INDENT 0.0 +.TP +.B pytermor.common.CDT +CDT represents a RGB color value. Primary handler +is \fI\%resolve_color()\fP\&. Valid values include: +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.IP \(bu 2 +\fIstr\fP with a color name in any form distinguishable by the color resolver; +the color lists can be found at: \fBguide.ansi\-presets\fP and \fBguide.es7s\-colors\fP; +.IP \(bu 2 +\fIstr\fP starting with a \(dq#\(dq and consisting of 6 more hexadecimal characters, case +insensitive (RGB regular form), e.g. \(dq#0b0cca\(dq; +.IP \(bu 2 +\fIstr\fP starting with a \(dq#\(dq and consisting of 3 more hexadecimal characters, case +insensitive (RGB short form), e.g. \(dq#666\(dq; +.IP \(bu 2 +\fIint\fP in a [0; 0xffffff] range. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +alias of TypeVar(\(aqCDT\(aq, int, str) +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.common.CXT + +.nf +:todo:\(gaTODO\(ga +.fi + +.IP "System Message: ERROR/3 (/home/a.shavykin/dl/pytermor/pytermor/common.py:docstring of pytermor.common:, line 1)" +Unknown interpreted text role \(dqtodo\(dq. +.sp +alias of TypeVar(\(aqCXT\(aq, int, str, IColorValue, RenderColor, None) +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.common.FT +FT is a style descriptor. Used as a shortcut precursor for actual +styles. Primary handler is \fI\%make_style()\fP\&. +.sp +alias of TypeVar(\(aqFT\(aq, int, str, IColorValue, Style, None) +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.common.RT +RT includes regular \fIstr\fPs as well as \fI\%IRenderable\fP +implementations. +.sp +alias of TypeVar(\(aqRT\(aq, str, IRenderable) +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.common.ExtendedEnum(value) +Bases: \fBEnum\fP +.sp +Standard \fBEnum\fP with a few additional methods on top. +.INDENT 7.0 +.TP +.B classmethod list() +Return all enum values as list. +.INDENT 7.0 +.TP +.B Example +[1, 10] +.TP +.B Return type +\fIList\fP[\fI_T\fP] +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod dict() +Return mapping of all enum keys to corresponding enum values. +.INDENT 7.0 +.TP +.B Example +{: 1, : 10} +.TP +.B Return type +\fIDict\fP[str, \fI_T\fP] +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.common.Align(value) +Bases: \fBstr\fP, \fI\%ExtendedEnum\fP +.sp +Align type. +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.common.pad(n) +Convenient method to use instead of \fB\(dq\(dq.ljust(n)\fP\&. +.INDENT 7.0 +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.common.padv(n) +Convenient method to use instead of \fB\(dq\en\(dq * n\fP\&. +.INDENT 7.0 +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.common.cut(s, max_len, align=Align.LEFT, overflow=\(aq‥\(aq) +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBs\fP (\fIstr\fP) \-\- +.IP \(bu 2 +\fBmax_len\fP (\fIint\fP) \-\- +.IP \(bu 2 +\fBalign\fP (\fI\%pytermor.common.Align\fP\fI | \fP\fIstr\fP) \-\- +.IP \(bu 2 +\fBoverflow\fP \-\- +.UNINDENT +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.common.fit(s, max_len, align=Align.LEFT, overflow=\(aq‥\(aq, fill=\(aq \(aq) +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBs\fP (\fIstr\fP) \-\- +.IP \(bu 2 +\fBmax_len\fP (\fIint\fP) \-\- +.IP \(bu 2 +\fBalign\fP (\fI\%pytermor.common.Align\fP\fI | \fP\fIstr\fP) \-\- +.IP \(bu 2 +\fBoverflow\fP (\fIstr\fP) \-\- +.IP \(bu 2 +\fBfill\fP (\fIstr\fP) \-\- +.UNINDENT +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.common.get_qname(obj) +Convenient method for getting a class name for the instances as well as +for the classes themselves, in case where a variable in question can be both. +.sp +.nf +.ft C +>>> get_qname(\(dqaaa\(dq) +\(aqstr\(aq +>>> get_qname(ExtendedEnum) +\(aq\(aq +.ft P +.fi +.INDENT 7.0 +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.common.only(cls, inp) +Return all elements from \fBinp\fP that \fIare\fP instances of \fBcls\fP +.INDENT 7.0 +.TP +.B Return type +\fIList\fP[\fI_T\fP] +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.common.but(cls, inp) +Return all elements from \fBinp\fP \fIexcept\fP instances of \fBcls\fP\&. +.INDENT 7.0 +.TP +.B Return type +\fIList\fP[\fI_T\fP] +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.common.ours(cls, inp) +Return all elements from \fBinp\fP that \fIare\fP instances of \fBcls\fP or its children classes. +.INDENT 7.0 +.TP +.B Return type +\fIList\fP[\fI_T\fP] +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.common.others(cls, inp) +Return all elements from \fBinp\fP \fIexcept\fP instances of \fBcls\fP and its children classes. +.INDENT 7.0 +.TP +.B Return type +\fIList\fP[\fI_T\fP] +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.common.chunk(items, size) +.INDENT 7.0 +.INDENT 3.5 +Split item list into chunks of size \fBsize\fP and return these +chunks as \fItuples\fP\&. +.sp +.nf +.ft C +>>> print(*chunk(range(10), 3), sep=\(aq\(aq\(aq +.ft P +.fi +.UNINDENT +.UNINDENT +.IP "System Message: WARNING/2 (/home/a.shavykin/dl/pytermor/docs/pages/apidoc/pytermor.common.rst:, line 9)" +Block quote ends without a blank line; unexpected unindent. +.INDENT 7.0 +.TP +.B \(aq\(aq\(aq) +(0, 1, 2) +(3, 4, 5) +(6, 7, 8) +(9,) +.INDENT 7.0 +.TP +.B param items +Input elements. +.TP +.B param size +Chunk size. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Return type +\fIIterator\fP[\fITuple\fP[\fI_T\fP, \&...]] +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.common.get_subclasses(target) +Traverse the inheritance tree and return a flat list of +all descendants of \fBcls\fP (full hierarchy). +.sp +.nf +.ft C +>>> from pytermor import SequenceCSI, Color16 +>>> get_subclasses(SequenceCSI()) +[, ] +.ft P +.fi +.sp +.nf +.ft C +>>> get_subclasses(Color16) +[] +.ft P +.fi +.INDENT 7.0 +.TP +.B Return type +\fIIterable\fP[\fIType\fP[\fI_T\fP]] +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.common.flatten1(items) +Take a list of nested lists and unpack all nested elements one level up. +.sp +.nf +.ft C +>>> flatten1([1, 2, [3, 4], [[5, 6]]]) +[1, 2, 3, 4, [5, 6]] +.ft P +.fi +.INDENT 7.0 +.TP +.B Return type +\fIList\fP[\fI_T\fP] +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.common.flatten(items, level_limit=None) +Unpack a list consisting of any amount of nested lists to 1d\-array, or flat list, +eliminating all the nesting. Note that nesting can be irregular, i.e. one part +of initial list can have deepest elemenets on 3rd level, while the other \-\- +on 5th level. +.sp +\fBATTENTION:\fP +.INDENT 7.0 +.INDENT 3.5 +Tracking of visited objects is not performed, i.e., circular references +and self\-references will be unpacked again and again endlessly, until +max recursion depth limit exceeds with a \fBRecursionError\fP or until the +program eats up all the available RAM (in theory, that is; in practice +I personally didn\(aqt enconuter that outcome even once). That was the +reason of adding \fBlevel_limit\fP parameter (see below). +.UNINDENT +.UNINDENT +.sp +.nf +.ft C +>>> flatten([1, 2, [3, [4, [[5]], [6, 7, [8]]]]]) +[1, 2, 3, 4, 5, 6, 7, 8] +.ft P +.fi +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBitems\fP (\fIIterable\fP\fI[\fP\fIUnion\fP\fI[\fP\fI_T\fP\fI, \fP\fIIterable\fP\fI[\fP\fI_T\fP\fI]\fP\fI]\fP\fI]\fP) \-\- N\-dimensional iterable to unpack. +.IP \(bu 2 +\fBlevel_limit\fP (\fIOptional\fP\fI[\fP\fIint\fP\fI]\fP) \-\- +.sp +Adjust how many levels deep can unpacking proceed, e.g. +if set to 1, only 2nd\-level elements will be raised up +to level 1, but not the deeper ones. If set to 2, the +first two levels will be unpacked, while keeping the 3rd +and others. 0 disables the limit. \fINone\fP is treated like +a default value, which is set to 50 empirically. +.sp +Note that altering/disabling this limit doesn\(aqt affect +max recursion depth limiting mechanism, which will (sooner +or later) interrupt the attempt to descent on hierarchy +with a self\-referencing object or several objects forming +a circular reference. + +.UNINDENT +.TP +.B Return type +\fIList\fP[\fI_T\fP] +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.common.char_range(start, stop) +Yields all the characters from range of [\fBc1\fP; \fBc2\fP], inclusive +(end character \fBc2\fP is \fBalso present\fP, in contrast with classic +\fBrange()\fP, which excludes \fBstop\fP value from the results). +.sp +.nf +.ft C +>>> \(aq\(aq.join(char_range(\(aq₁\(aq, \(aq₉\(aq)) +\(aq₁₂₃₄₅₆₇₈₉\(aq +.ft P +.fi +.sp +\fBNOTE:\fP +.INDENT 7.0 +.INDENT 3.5 +In some cases the result will seem to be incorrent, i.e. this: +\fBpt.char_range(\(aq¹\(aq, \(aq⁴\(aq)\fP yields 8124 characters total. The reason +is that the algoritm works with input characters as Unicode codepoints, +and \(aq¹\(aq, \(aq⁴\(aq are relatively distant from each other: \(dq¹\(dq U+B9, +\(dq⁴\(dq Ux2074, which leads to an unexpected results. Character +ranges in regular expessetions, e.g. \fB[A\-Z0\-9]\fP work the same way. +.UNINDENT +.UNINDENT +.sp +:param start; Character to start from (inclusive) +:param stop; Character to stop at (\fBinclusive\fP) +.INDENT 7.0 +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.common.filterf = functools.partial(, None) +Shortcut for filtering out falsy values from sequences +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.common.filtern = functools.partial(, >) +Shortcut for filtering out Nones from sequences +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.common.filterfv(mapping) +Shortcut for filtering out falsy values from mappings +.INDENT 7.0 +.TP +.B Return type +dict +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.common.filternv(mapping) +Shortcut for filtering out None values from mappings +.INDENT 7.0 +.TP +.B Return type +dict +.UNINDENT +.UNINDENT +.SS pytermor.config +.sp +Library fine tuning module. +.sp +Classes +.TS +center; +|l|l|. +_ +T{ +\fI\%Config\fP([renderer_class, force_output_mode, ...]) +T} T{ +Configuration variables container. +T} +_ +T{ +\fBConfigManager\fP() +T} T{ +T} +_ +.TE +.INDENT 0.0 +.TP +.B class pytermor.config.Config(renderer_class=, force_output_mode=, default_output_mode=, trace_renders=, prefer_rgb=) +Configuration variables container. Values can be modified in two ways: +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.IP 1. 3 +create new \fI\%Config\fP instance from scratch and activate with +\fBreplace_config()\fP; +.IP 2. 3 +or preliminarily set the corresponding environment variables to intended values, +and the default config instance will catch them up on initialization. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +\fBSEE ALSO:\fP +.INDENT 7.0 +.INDENT 3.5 +Environment variable list is located in \fI\%Configuration\fP guide section. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBrenderer_class\fP (\fIstr\fP) \-\- Explicitly set renderer class (e.g. \fI\%TmuxRenderer\fP). +See \fI\%Config.renderer_class\fP\&. +.IP \(bu 2 +\fBforce_output_mode\fP (\fIstr\fP) \-\- Explicitly set output mode (e.g. \fBxterm_16\fP; any \fIvalue\fP +from \fI\%OutputMode\fP enum is valid). +See \fI\%Config.force_output_mode\fP\&. +.IP \(bu 2 +\fBdefault_output_mode\fP (\fIstr\fP) \-\- Output mode to use as a fallback value when renderer is +unsure about user\(aqs terminal capabilities (e.g. \fBxterm_16\fP; +any \fIvalue\fP from \fI\%OutputMode\fP enum is valid). Initial value +is \fBxterm_256\fP\&. See \fI\%Config.default_output_mode\fP\&. +.IP \(bu 2 +\fBprefer_rgb\fP (\fIbool\fP) \-\- By default SGR renderer uses 8\-bit color mode sequences +for \fI\%Color256\fP instances (as it should), even when the +output device supports more advanced 24\-bit/True Color +mode. With this option set to \fITrue\fP \fI\%Color256\fP will be +rendered using True Color sequences instead, provided the +terminal emulator supports them. Most of the time the +results from different color modes are indistinguishable from +each other, however, there \fIare\fP rare cases, when it does +matter. See \fI\%Config.prefer_rgb\fP\&. +.IP \(bu 2 +\fBtrace_renders\fP (\fIbool\fP) \-\- Set to \fITrue\fP to log hex dumps of rendered strings. +Note that default handler is \fBlogging.NullHandler\fP +with \fBWARNING\fP level, so in order to see the traces +attached handler is required. See +\fI\%Config.trace_renders\fP\&. +.UNINDENT +.UNINDENT +.UNINDENT +.SS pytermor.cval +.sp +Color preset list: +.INDENT 0.0 +.INDENT 3.5 +.INDENT 0.0 +.IP \(bu 2 +16x \fI\%Color16\fP (16 unique) +.IP \(bu 2 +256x \fI\%Color256\fP (247 unique) +.IP \(bu 2 +2304x \fI\%ColorRGB\fP (2297 unique) +.UNINDENT +.UNINDENT +.UNINDENT +.SS pytermor.exception +.sp +Exceptions +.TS +center; +|l|l|. +_ +T{ +\fI\%ArgCountError\fP(actual, *expected) +T} T{ +T} +_ +T{ +\fI\%ArgTypeError\fP(arg_value, arg_name, *expected_type) +T} T{ +\&. +T} +_ +T{ +\fI\%ColorCodeConflictError\fP(code, existing_color, ...) +T} T{ +T} +_ +T{ +\fI\%ColorNameConflictError\fP(key, existing_color, ...) +T} T{ +T} +_ +T{ +\fI\%ConflictError\fP +T} T{ +T} +_ +T{ +\fI\%LogicError\fP +T} T{ +T} +_ +T{ +\fI\%NotInitializedError\fP +T} T{ +T} +_ +T{ +\fI\%ParseError\fP(groupdict) +T} T{ +T} +_ +T{ +\fI\%UserAbort\fP +T} T{ +T} +_ +T{ +\fI\%UserCancel\fP +T} T{ +T} +_ +.TE +.INDENT 0.0 +.TP +.B exception pytermor.exception.LogicError +Bases: \fBException\fP +.INDENT 7.0 +.TP +.B with_traceback() +Exception.with_traceback(tb) \-\- +set self.__traceback__ to tb and return self. +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B exception pytermor.exception.ParseError(groupdict) +Bases: \fBException\fP +.INDENT 7.0 +.UNINDENT +.INDENT 7.0 +.TP +.B with_traceback() +Exception.with_traceback(tb) \-\- +set self.__traceback__ to tb and return self. +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B exception pytermor.exception.ConflictError +Bases: \fBException\fP +.INDENT 7.0 +.TP +.B with_traceback() +Exception.with_traceback(tb) \-\- +set self.__traceback__ to tb and return self. +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B exception pytermor.exception.NotInitializedError +Bases: \fBException\fP +.INDENT 7.0 +.TP +.B with_traceback() +Exception.with_traceback(tb) \-\- +set self.__traceback__ to tb and return self. +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B exception pytermor.exception.ArgTypeError(arg_value, arg_name, *expected_type, suggestion=None) +Bases: \fBException\fP +.sp +\&. +.INDENT 7.0 +.UNINDENT +.INDENT 7.0 +.TP +.B with_traceback() +Exception.with_traceback(tb) \-\- +set self.__traceback__ to tb and return self. +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B exception pytermor.exception.ArgCountError(actual, *expected) +Bases: \fBException\fP +.INDENT 7.0 +.UNINDENT +.INDENT 7.0 +.TP +.B with_traceback() +Exception.with_traceback(tb) \-\- +set self.__traceback__ to tb and return self. +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B exception pytermor.exception.UserCancel +Bases: \fBException\fP +.INDENT 7.0 +.TP +.B with_traceback() +Exception.with_traceback(tb) \-\- +set self.__traceback__ to tb and return self. +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B exception pytermor.exception.UserAbort +Bases: \fBException\fP +.INDENT 7.0 +.TP +.B with_traceback() +Exception.with_traceback(tb) \-\- +set self.__traceback__ to tb and return self. +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B exception pytermor.exception.ColorNameConflictError(key, existing_color, new_color) +Bases: \fBException\fP +.INDENT 7.0 +.UNINDENT +.INDENT 7.0 +.TP +.B with_traceback() +Exception.with_traceback(tb) \-\- +set self.__traceback__ to tb and return self. +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B exception pytermor.exception.ColorCodeConflictError(code, existing_color, new_color) +Bases: \fBException\fP +.INDENT 7.0 +.UNINDENT +.INDENT 7.0 +.TP +.B with_traceback() +Exception.with_traceback(tb) \-\- +set self.__traceback__ to tb and return self. +.UNINDENT +.UNINDENT +.SS pytermor.filter +.sp +Formatters for prettier output and utility classes to avoid writing boilerplate +code when dealing with escape sequences. Also includes several Python Standard +Library methods rewritten for correct work with strings containing control sequences. +.sp +Module Attributes +.TS +center; +|l|l|. +_ +T{ +\fI\%SGR_SEQ_REGEX\fP +T} T{ +Regular expression that matches \fI\%SGR\fP sequences. +T} +_ +T{ +\fI\%CSI_SEQ_REGEX\fP +T} T{ +Regular expression that matches CSI sequences (a superset which includes \fI\%SGRs\fP). +T} +_ +T{ +\fI\%CONTROL_CHARS\fP +T} T{ +Set of ASCII control characters: 0x00\-0x08, 0x0E\-0x1F and 0x7F\&. +T} +_ +T{ +\fI\%WHITESPACE_CHARS\fP +T} T{ +Set of ASCII whitespace characters: 0x09\-0x0D and 0x20\&. +T} +_ +T{ +\fI\%PRINTABLE_CHARS\fP +T} T{ +Set of ASCII \(dqnormal\(dq characters, i.e. non\-control and non\-space ones: letters, digits and punctuation (0x21\-0x7E). +T} +_ +T{ +\fI\%NON_ASCII_CHARS\fP +T} T{ +Set of bytes that are invalid in ASCII\-7 context: 0x80\-0xFF\&. +T} +_ +T{ +\fI\%IT\fP +T} T{ +input\-type +T} +_ +T{ +\fI\%OT\fP +T} T{ +output\-type +T} +_ +T{ +\fI\%PTT\fP +T} T{ +pattern type +T} +_ +T{ +\fI\%RPT\fP +T} T{ +replacer type +T} +_ +T{ +\fI\%MPT\fP +T} T{ +# map +T} +_ +.TE +.sp +Functions +.TS +center; +|l|l|. +_ +T{ +\fI\%apply_filters\fP(inp, *args) +T} T{ +Method for applying dynamic filter list to a target string/bytes. +T} +_ +T{ +\fI\%center_sgr\fP(string, width[, fillchar]) +T} T{ +SGR\-formatting\-aware implementation of \fBstr.center\fP\&. +T} +_ +T{ +\fI\%dump\fP(data[, tracer_cls, extra, force_width]) +T} T{ +\&. +T} +_ +T{ +\fI\%get_max_ucs_chars_cp_length\fP(string) +T} T{ +\&. +T} +_ +T{ +\fI\%get_max_utf8_bytes_char_length\fP(string) +T} T{ +cc +T} +_ +T{ +\fI\%ljust_sgr\fP(string, width[, fillchar]) +T} T{ +SGR\-formatting\-aware implementation of \fBstr.ljust\fP\&. +T} +_ +T{ +\fI\%rjust_sgr\fP(string, width[, fillchar]) +T} T{ +SGR\-formatting\-aware implementation of \fBstr.rjust\fP\&. +T} +_ +.TE +.sp +Classes +.TS +center; +|l|l|. +_ +T{ +\fI\%AbstractNamedGroupsRefilter\fP(*args, **kwargs) +T} T{ +Substitute the input by applying following rules: +T} +_ +T{ +\fI\%AbstractStringTracer\fP(*args, **kwargs) +T} T{ +T} +_ +T{ +\fI\%AbstractTracer\fP(*args, **kwargs) +T} T{ +T} +_ +T{ +\fI\%BytesTracer\fP(*args, **kwargs) +T} T{ +str/bytes as byte hex codes, grouped by 4 +T} +_ +T{ +\fI\%CsiStringReplacer\fP(*args, **kwargs) +T} T{ +Find all \fI\%CSI\fP seqs (i.e., starting with \fBESC [\fP) and replace with given string. +T} +_ +T{ +\fI\%EscSeqStringReplacer\fP(*args, **kwargs) +T} T{ +, +T} +_ +T{ +\fI\%IFilter\fP(*args, **kwargs) +T} T{ +Main idea is to provide a common interface for string filtering, that can make possible working with filters like with objects rather than with functions/lambdas. +T} +_ +T{ +\fI\%IRefilter\fP(*args, **kwargs) +T} T{ +\fIRefilters\fP are rendering filters (output is \fIstr\fP with SGRs). +T} +_ +T{ +\fI\%NonPrintsOmniVisualizer\fP(*args, **kwargs) +T} T{ +Input type: \fIstr\fP, \fIbytes\fP\&. +T} +_ +T{ +\fI\%NonPrintsStringVisualizer\fP(*args, **kwargs) +T} T{ +Input type: \fIstr\fP\&. +T} +_ +T{ +\fBNoopFilter\fP(*args, **kwargs) +T} T{ +T} +_ +T{ +\fBOmniDecoder\fP(*args, **kwargs) +T} T{ +T} +_ +T{ +\fBOmniEncoder\fP(*args, **kwargs) +T} T{ +T} +_ +T{ +\fI\%OmniMapper\fP(*args, **kwargs) +T} T{ +Input type: \fIstr\fP, \fIbytes\fP\&. +T} +_ +T{ +\fI\%OmniPadder\fP(*args, **kwargs) +T} T{ +T} +_ +T{ +\fI\%OmniSanitizer\fP(*args, **kwargs) +T} T{ +Input type: \fIstr\fP, \fIbytes\fP\&. +T} +_ +T{ +\fI\%SgrStringReplacer\fP(*args, **kwargs) +T} T{ +Find all \fI\%SGR\fP seqs (e.g., \fBESC [1;4m\fP) and replace with given string. +T} +_ +T{ +\fI\%StringLinearizer\fP(*args, **kwargs) +T} T{ +Filter transforms all whitespace sequences in the input string into a single space character, or into a specified string. +T} +_ +T{ +\fI\%StringMapper\fP(*args, **kwargs) +T} T{ +a +T} +_ +T{ +\fI\%StringReplacer\fP(*args, **kwargs) +T} T{ +\&. +T} +_ +T{ +\fI\%StringReplacerChain\fP(*args, **kwargs) +T} T{ +\&. +T} +_ +T{ +\fI\%StringTracer\fP(*args, **kwargs) +T} T{ +str as byte hex codes (UTF\-8), grouped by characters +T} +_ +T{ +\fI\%StringUcpTracer\fP(*args, **kwargs) +T} T{ +str as Unicode codepoints +T} +_ +T{ +\fI\%TracerExtra\fP([label, addr_shift, hash]) +T} T{ +T} +_ +T{ +\fI\%WhitespaceRemover\fP(*args, **kwargs) +T} T{ +Special case of \fI\%StringLinearizer\fP\&. +T} +_ +.TE +.INDENT 0.0 +.TP +.B pytermor.filter.SGR_SEQ_REGEX +Regular expression that matches \fI\%SGR\fP sequences. Group 3 can be used for +sequence params extraction. +.INDENT 7.0 +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.filter.CSI_SEQ_REGEX +Regular expression that matches CSI sequences (a superset which includes +\fI\%SGRs\fP). +.INDENT 7.0 +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.filter.CONTROL_CHARS +Set of ASCII control characters: 0x00\-0x08, 0x0E\-0x1F and +0x7F\&. +.INDENT 7.0 +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.filter.WHITESPACE_CHARS +Set of ASCII whitespace characters: 0x09\-0x0D and 0x20\&. +.INDENT 7.0 +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.filter.PRINTABLE_CHARS +Set of ASCII \(dqnormal\(dq characters, i.e. non\-control and non\-space ones: +letters, digits and punctuation (0x21\-0x7E). +.INDENT 7.0 +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.filter.NON_ASCII_CHARS +Set of bytes that are invalid in ASCII\-7 context: 0x80\-0xFF\&. +.INDENT 7.0 +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.filter.IT +input\-type +.sp +alias of TypeVar(\(aqIT\(aq, str, bytes) +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.filter.OT +output\-type +.sp +alias of TypeVar(\(aqOT\(aq, str, bytes) +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.filter.PTT +pattern type +.sp +alias of \fBUnion\fP[\fI\%IT\fP, \fBPattern\fP[\fI\%IT\fP]] +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.filter.RPT +replacer type +.sp +alias of \fBUnion\fP[\fI\%OT\fP, \fBCallable\fP[[\fBMatch\fP[\fI\%OT\fP]], \fI\%OT\fP]] +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.filter.MPT +# map +.sp +alias of \fBDict\fP[\fBint\fP, \fI\%IT\fP] +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.filter.IFilter(*args, **kwargs) +Bases: \fBGeneric\fP[\fI\%IT\fP, \fI\%OT\fP] +.sp +Main idea is to provide a common interface for string filtering, that can make +possible working with filters like with objects rather than with functions/lambdas. +.INDENT 7.0 +.TP +.B Return type +\fI\%IFilter\fP +.UNINDENT +.INDENT 7.0 +.TP +.B apply(inp, extra=None) +Apply the filter to input \fIstr\fP or \fIbytes\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIIT\fP) \-\- input string +.IP \(bu 2 +\fBextra\fP (\fIOptional\fP\fI[\fP\fIAny\fP\fI]\fP) \-\- additional options +.UNINDENT +.TP +.B Returns +transformed string; the type can match the input type, +as well as be different \-\- that depends on filter type. +.TP +.B Return type +\fIOT\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.filter.IRefilter(*args, **kwargs) +Bases: \fI\%IFilter\fP[\fI\%IT\fP, \fBstr\fP] +.sp +\fIRefilters\fP are rendering filters (output is \fIstr\fP with SGRs). +.INDENT 7.0 +.TP +.B Return type +\fI\%IFilter\fP +.UNINDENT +.INDENT 7.0 +.TP +.B apply(inp, extra=None) +Apply the filter to input \fIstr\fP or \fIbytes\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIIT\fP) \-\- input string +.IP \(bu 2 +\fBextra\fP (\fIOptional\fP\fI[\fP\fIAny\fP\fI]\fP) \-\- additional options +.UNINDENT +.TP +.B Returns +transformed string; the type can match the input type, +as well as be different \-\- that depends on filter type. +.TP +.B Return type +\fIOT\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.filter.OmniPadder(*args, **kwargs) +Bases: \fI\%IFilter\fP[\fI\%IT\fP, \fI\%IT\fP] +.INDENT 7.0 +.UNINDENT +.INDENT 7.0 +.TP +.B apply(inp, extra=None) +Apply the filter to input \fIstr\fP or \fIbytes\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIIT\fP) \-\- input string +.IP \(bu 2 +\fBextra\fP (\fIOptional\fP\fI[\fP\fIAny\fP\fI]\fP) \-\- additional options +.UNINDENT +.TP +.B Returns +transformed string; the type can match the input type, +as well as be different \-\- that depends on filter type. +.TP +.B Return type +\fIOT\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.filter.StringReplacer(*args, **kwargs) +Bases: \fI\%IFilter\fP[\fBstr\fP, \fBstr\fP] +.sp +\&. +.INDENT 7.0 +.UNINDENT +.INDENT 7.0 +.TP +.B apply(inp, extra=None) +Apply the filter to input \fIstr\fP or \fIbytes\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIIT\fP) \-\- input string +.IP \(bu 2 +\fBextra\fP (\fIOptional\fP\fI[\fP\fIAny\fP\fI]\fP) \-\- additional options +.UNINDENT +.TP +.B Returns +transformed string; the type can match the input type, +as well as be different \-\- that depends on filter type. +.TP +.B Return type +\fIOT\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.filter.StringReplacerChain(*args, **kwargs) +Bases: \fI\%StringReplacer\fP +.sp +\&. +.INDENT 7.0 +.UNINDENT +.INDENT 7.0 +.TP +.B apply(inp, extra=None) +Apply the filter to input \fIstr\fP or \fIbytes\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIIT\fP) \-\- input string +.IP \(bu 2 +\fBextra\fP (\fIOptional\fP\fI[\fP\fIAny\fP\fI]\fP) \-\- additional options +.UNINDENT +.TP +.B Returns +transformed string; the type can match the input type, +as well as be different \-\- that depends on filter type. +.TP +.B Return type +\fIOT\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.filter.EscSeqStringReplacer(*args, **kwargs) +Bases: \fI\%StringReplacer\fP +.sp +, +.INDENT 7.0 +.UNINDENT +.INDENT 7.0 +.TP +.B apply(inp, extra=None) +Apply the filter to input \fIstr\fP or \fIbytes\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIIT\fP) \-\- input string +.IP \(bu 2 +\fBextra\fP (\fIOptional\fP\fI[\fP\fIAny\fP\fI]\fP) \-\- additional options +.UNINDENT +.TP +.B Returns +transformed string; the type can match the input type, +as well as be different \-\- that depends on filter type. +.TP +.B Return type +\fIOT\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.filter.SgrStringReplacer(*args, **kwargs) +Bases: \fI\%StringReplacer\fP +.sp +Find all \fI\%SGR\fP seqs (e.g., \fBESC [1;4m\fP) and replace with +given string. More specific version of \fBCsiReplacer\fP\&. +.INDENT 7.0 +.TP +.B Parameters +\fBrepl\fP (\fIRPT\fP\fI[\fP\fIstr\fP\fI]\fP) \-\- Replacement, can contain regexp groups (see \fI\%apply_filters()\fP). +.UNINDENT +.INDENT 7.0 +.TP +.B apply(inp, extra=None) +Apply the filter to input \fIstr\fP or \fIbytes\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIIT\fP) \-\- input string +.IP \(bu 2 +\fBextra\fP (\fIOptional\fP\fI[\fP\fIAny\fP\fI]\fP) \-\- additional options +.UNINDENT +.TP +.B Returns +transformed string; the type can match the input type, +as well as be different \-\- that depends on filter type. +.TP +.B Return type +\fIOT\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.filter.CsiStringReplacer(*args, **kwargs) +Bases: \fI\%StringReplacer\fP +.sp +Find all \fI\%CSI\fP seqs (i.e., starting with \fBESC [\fP) and replace +with given string. Less specific version of \fBSgrReplacer\fP, as CSI +consists of SGR and many other sequence subtypes. +.INDENT 7.0 +.TP +.B Parameters +\fBrepl\fP (\fIRPT\fP\fI[\fP\fIstr\fP\fI]\fP) \-\- Replacement, can contain regexp groups (see \fI\%apply_filters()\fP). +.UNINDENT +.INDENT 7.0 +.TP +.B apply(inp, extra=None) +Apply the filter to input \fIstr\fP or \fIbytes\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIIT\fP) \-\- input string +.IP \(bu 2 +\fBextra\fP (\fIOptional\fP\fI[\fP\fIAny\fP\fI]\fP) \-\- additional options +.UNINDENT +.TP +.B Returns +transformed string; the type can match the input type, +as well as be different \-\- that depends on filter type. +.TP +.B Return type +\fIOT\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.filter.StringLinearizer(*args, **kwargs) +Bases: \fI\%StringReplacer\fP +.sp +Filter transforms all whitespace sequences in the input string +into a single space character, or into a specified string. Most obvious +application is pre\-formatting strings for log output in order to keep +the messages one\-lined. +.INDENT 7.0 +.TP +.B Parameters +\fBrepl\fP (\fIRPT\fP\fI[\fP\fIstr\fP\fI]\fP) \-\- Replacement character(s). +.UNINDENT +.INDENT 7.0 +.TP +.B apply(inp, extra=None) +Apply the filter to input \fIstr\fP or \fIbytes\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIIT\fP) \-\- input string +.IP \(bu 2 +\fBextra\fP (\fIOptional\fP\fI[\fP\fIAny\fP\fI]\fP) \-\- additional options +.UNINDENT +.TP +.B Returns +transformed string; the type can match the input type, +as well as be different \-\- that depends on filter type. +.TP +.B Return type +\fIOT\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.filter.WhitespaceRemover(*args, **kwargs) +Bases: \fI\%StringReplacer\fP +.sp +Special case of \fI\%StringLinearizer\fP\&. Removes all the whitespaces from the +input string. +.INDENT 7.0 +.TP +.B apply(inp, extra=None) +Apply the filter to input \fIstr\fP or \fIbytes\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIIT\fP) \-\- input string +.IP \(bu 2 +\fBextra\fP (\fIOptional\fP\fI[\fP\fIAny\fP\fI]\fP) \-\- additional options +.UNINDENT +.TP +.B Returns +transformed string; the type can match the input type, +as well as be different \-\- that depends on filter type. +.TP +.B Return type +\fIOT\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.filter.AbstractNamedGroupsRefilter(*args, **kwargs) +Bases: \fI\%IRefilter\fP[\fBstr\fP], \fI\%StringReplacer\fP +.sp +Substitute the input by applying following rules: +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.IP \(bu 2 +Named groups which name is found in \fBgroup_st_map\fP keys are replaced with +themselves styled as specified in a corresponding map values. +.IP \(bu 2 +Regular/unnamed groups are kept as is, unless there is an \(dq\(dq (empty string) key +in \fBgroup_st_map\fP, in which case a style corresponding to such key is applied +to all these groups. +.IP \(bu 2 +Groups with names not present in the map, as well as lookaheads and lookbehinds, +are kept as is (unstyled). +.IP \(bu 2 +Non\-capturing groups\(aq contents and matched characters not belonging to any group +are thrown away. +.IP \(bu 2 +Not matched parts of the input are kept as is. +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +>>> import pytermor as pt +>>> class SgrNamedGroupsRefilter(AbstractNamedGroupsRefilter): +\&... def _render(self, v: IT, st: FT) \-> str: +\&... return pt.render(v, st, pt.SgrRenderer(pt.OutputMode.XTERM_16)) +\&... +>>> SgrNamedGroupsRefilter( +\&... re.compile(r\(aq.+?)(>)>?\(aq), +\&... {\(dqval\(dq: pt.cv.GREEN}, +\&... ).apply(\(dqtext <> text\(dq) +\(aqtext <link> text\(aq +.ft P +.fi +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +\fBgroup_st_map\fP (\fIdict\fP\fI[\fP\fIstr\fP\fI, \fP\fIFT\fP\fI]\fP) \-\- +.UNINDENT +.INDENT 7.0 +.TP +.B apply(inp, extra=None) +Apply the filter to input \fIstr\fP or \fIbytes\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIIT\fP) \-\- input string +.IP \(bu 2 +\fBextra\fP (\fIOptional\fP\fI[\fP\fIAny\fP\fI]\fP) \-\- additional options +.UNINDENT +.TP +.B Returns +transformed string; the type can match the input type, +as well as be different \-\- that depends on filter type. +.TP +.B Return type +\fIOT\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.filter.OmniMapper(*args, **kwargs) +Bases: \fI\%IFilter\fP[\fI\%IT\fP, \fI\%IT\fP] +.sp +Input type: \fIstr\fP, \fIbytes\fP\&. Abstract mapper. Replaces every character found in +map keys to corresponding map value. Map should be a dictionary of this type: +\fBdict[int, str|bytes]\fP; moreover, length of \fIstr\fP/\fIbytes\fP must be strictly 1 +character (ASCII codepage). If there is a necessity to map Unicode characters, +\fI\%StringMapper\fP should be used instead. +.sp +.nf +.ft C +>>> OmniMapper({0x20: \(aq.\(aq}).apply(b\(aqabc def ghi\(aq) +b\(aqabc.def.ghi\(aq +.ft P +.fi +.sp +For mass mapping it is better to subclass \fI\%OmniMapper\fP and override two methods \-\- +\fB_get_default_keys\fP and \fB_get_default_replacer\fP\&. In this case you don\(aqt have to +manually compose a replacement map with every character you want to replace. +.INDENT 7.0 +.TP +.B Parameters +\fBoverride\fP (\fIMPT\fP) \-\- a dictionary with mappings: keys must be \fIints\fP, values must be +either a single\-char \fIstrs\fP or \fIbytes\fP\&. +.TP +.B See +\fI\%NonPrintsOmniVisualizer\fP +.UNINDENT +.INDENT 7.0 +.TP +.B apply(inp, extra=None) +Apply the filter to input \fIstr\fP or \fIbytes\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIIT\fP) \-\- input string +.IP \(bu 2 +\fBextra\fP (\fIOptional\fP\fI[\fP\fIAny\fP\fI]\fP) \-\- additional options +.UNINDENT +.TP +.B Returns +transformed string; the type can match the input type, +as well as be different \-\- that depends on filter type. +.TP +.B Return type +\fIOT\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.filter.StringMapper(*args, **kwargs) +Bases: \fI\%OmniMapper\fP[\fBstr\fP] +.sp +a +.INDENT 7.0 +.TP +.B Return type +\fI\%IFilter\fP +.UNINDENT +.INDENT 7.0 +.TP +.B apply(inp, extra=None) +Apply the filter to input \fIstr\fP or \fIbytes\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIIT\fP) \-\- input string +.IP \(bu 2 +\fBextra\fP (\fIOptional\fP\fI[\fP\fIAny\fP\fI]\fP) \-\- additional options +.UNINDENT +.TP +.B Returns +transformed string; the type can match the input type, +as well as be different \-\- that depends on filter type. +.TP +.B Return type +\fIOT\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.filter.NonPrintsOmniVisualizer(*args, **kwargs) +Bases: \fI\%OmniMapper\fP +.sp +Input type: \fIstr\fP, \fIbytes\fP\&. Replace every whitespace character with \fB\&.\fP\&. +.INDENT 7.0 +.TP +.B Return type +\fI\%IFilter\fP +.UNINDENT +.INDENT 7.0 +.TP +.B apply(inp, extra=None) +Apply the filter to input \fIstr\fP or \fIbytes\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIIT\fP) \-\- input string +.IP \(bu 2 +\fBextra\fP (\fIOptional\fP\fI[\fP\fIAny\fP\fI]\fP) \-\- additional options +.UNINDENT +.TP +.B Returns +transformed string; the type can match the input type, +as well as be different \-\- that depends on filter type. +.TP +.B Return type +\fIOT\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.filter.NonPrintsStringVisualizer(*args, **kwargs) +Bases: \fI\%StringMapper\fP +.sp +Input type: \fIstr\fP\&. Replace every whitespace character with \(dq·\(dq, except +newlines. Newlines are kept and get prepneded with same char by default, +but this behaviour can be disabled with \fBkeep_newlines\fP = \fIFalse\fP\&. +.sp +.nf +.ft C +>>> NonPrintsStringVisualizer(keep_newlines=False).apply(\(dqS\(dq+os.linesep+\(dqK\(dq) +\(aqS↵K\(aq +.ft P +.fi +.INDENT 7.0 +.TP +.B Parameters +\fBkeep_newlines\fP (\fIbool\fP) \-\- When \fITrue\fP, transform newline characters into \(dq↵\en\(dq, or +into just \(dq↵\(dq otherwise. +.UNINDENT +.INDENT 7.0 +.TP +.B apply(inp, extra=None) +Apply the filter to input \fIstr\fP or \fIbytes\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIIT\fP) \-\- input string +.IP \(bu 2 +\fBextra\fP (\fIOptional\fP\fI[\fP\fIAny\fP\fI]\fP) \-\- additional options +.UNINDENT +.TP +.B Returns +transformed string; the type can match the input type, +as well as be different \-\- that depends on filter type. +.TP +.B Return type +\fIOT\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.filter.OmniSanitizer(*args, **kwargs) +Bases: \fI\%OmniMapper\fP +.sp +Input type: \fIstr\fP, \fIbytes\fP\&. Replace every control character and every non\-ASCII +character (0x80\-0xFF) with \(dq.\(dq, or with specified char. Note that the replacement +should be a single ASCII character, because \fBOmni\-\fP filters are designed to work +with \fIstr\fP inputs and \fIbytes\fP inputs on equal terms. +.INDENT 7.0 +.TP +.B Parameters +\fBrepl\fP (\fIIT\fP) \-\- Value to replace control/non\-ascii characters with. Should be strictly 1 +character long. +.UNINDENT +.INDENT 7.0 +.TP +.B apply(inp, extra=None) +Apply the filter to input \fIstr\fP or \fIbytes\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIIT\fP) \-\- input string +.IP \(bu 2 +\fBextra\fP (\fIOptional\fP\fI[\fP\fIAny\fP\fI]\fP) \-\- additional options +.UNINDENT +.TP +.B Returns +transformed string; the type can match the input type, +as well as be different \-\- that depends on filter type. +.TP +.B Return type +\fIOT\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.filter.AbstractTracer(*args, **kwargs) +Bases: \fI\%IFilter\fP[\fI\%IT\fP, \fBstr\fP] +.INDENT 7.0 +.UNINDENT +.INDENT 7.0 +.TP +.B apply(inp, extra=None) +Apply the filter to input \fIstr\fP or \fIbytes\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIIT\fP) \-\- input string +.IP \(bu 2 +\fBextra\fP (\fIOptional\fP\fI[\fP\fIAny\fP\fI]\fP) \-\- additional options +.UNINDENT +.TP +.B Returns +transformed string; the type can match the input type, +as well as be different \-\- that depends on filter type. +.TP +.B Return type +\fIOT\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.filter.BytesTracer(*args, **kwargs) +Bases: \fI\%AbstractTracer\fP[\fBbytes\fP] +.sp +str/bytes as byte hex codes, grouped by 4 +.sp +Example output +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C + 0x00 | 35 30 20 35 34 20 35 35 20 C2 B0 43 20 20 33 39 20 2B 30 20 + 0x14 | 20 20 33 39 6D 73 20 31 20 52 55 20 20 E2 88 86 20 35 68 20 + 0x28 | 31 38 6D 20 20 20 EE 8C 8D 20 E2 80 8E 20 2B 32 30 C2 B0 43 + 0x3C | 20 20 54 68 20 30 31 20 4A 75 6E 20 20 31 36 20 32 38 20 20 + 0x50 | E2 96 95 E2 9C 94 E2 96 8F 46 55 4C 4C 20 +.ft P +.fi +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Return type +\fI\%IFilter\fP +.UNINDENT +.INDENT 7.0 +.TP +.B get_max_chars_per_line(inp, addr_shift) +For the details see \fI\%Tracers math\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIbytes\fP) \-\- +.IP \(bu 2 +\fBaddr_shift\fP (\fIint\fP) \-\- +.UNINDENT +.TP +.B Return type +int +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B apply(inp, extra=None) +Apply the filter to input \fIstr\fP or \fIbytes\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIIT\fP) \-\- input string +.IP \(bu 2 +\fBextra\fP (\fIOptional\fP\fI[\fP\fIAny\fP\fI]\fP) \-\- additional options +.UNINDENT +.TP +.B Returns +transformed string; the type can match the input type, +as well as be different \-\- that depends on filter type. +.TP +.B Return type +\fIOT\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.filter.AbstractStringTracer(*args, **kwargs) +Bases: \fI\%AbstractTracer\fP[\fBstr\fP] +.INDENT 7.0 +.UNINDENT +.INDENT 7.0 +.TP +.B apply(inp, extra=None) +Apply the filter to input \fIstr\fP or \fIbytes\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIIT\fP) \-\- input string +.IP \(bu 2 +\fBextra\fP (\fIOptional\fP\fI[\fP\fIAny\fP\fI]\fP) \-\- additional options +.UNINDENT +.TP +.B Returns +transformed string; the type can match the input type, +as well as be different \-\- that depends on filter type. +.TP +.B Return type +\fIOT\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.filter.StringTracer(*args, **kwargs) +Bases: \fI\%AbstractStringTracer\fP +.sp +str as byte hex codes (UTF\-8), grouped by characters +.sp +Example output +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C + 0 | 35 30 20 35 34 20 35 35 20 c2b0 43 20 |50␣54␣55␣°C␣ + 12 | 20 33 39 20 2b 30 20 20 20 33 39 6d |␣39␣+0␣␣␣39m + 24 | 73 20 31 20 52 55 20 20 e28886 20 35 68 |s␣1␣RU␣␣∆␣5h + 36 | 20 31 38 6d 20 20 20 ee8c8d 20 e2808e 20 2b |␣18m␣␣␣␣‎␣+ + 48 | 32 30 c2b0 43 20 20 54 68 20 30 31 20 |20°C␣␣Th␣01␣ + 60 | 4a 75 6e 20 20 31 36 20 32 38 20 20 |Jun␣␣16␣28␣␣ + 72 | e29695 e29c94 e2968f 46 55 4c 4c 20 |▕✔▏FULL␣ +.ft P +.fi +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Return type +\fI\%IFilter\fP +.UNINDENT +.INDENT 7.0 +.TP +.B get_max_chars_per_line(inp, addr_shift) +For the details see \fI\%Tracers math\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIstr\fP) \-\- +.IP \(bu 2 +\fBaddr_shift\fP (\fIint\fP) \-\- +.UNINDENT +.TP +.B Return type +int +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B apply(inp, extra=None) +Apply the filter to input \fIstr\fP or \fIbytes\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIIT\fP) \-\- input string +.IP \(bu 2 +\fBextra\fP (\fIOptional\fP\fI[\fP\fIAny\fP\fI]\fP) \-\- additional options +.UNINDENT +.TP +.B Returns +transformed string; the type can match the input type, +as well as be different \-\- that depends on filter type. +.TP +.B Return type +\fIOT\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.filter.StringUcpTracer(*args, **kwargs) +Bases: \fI\%AbstractStringTracer\fP +.sp +str as Unicode codepoints +.sp +Example output +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C + 0 |U+ 20 34 36 20 34 36 20 34 36 20 B0 43 20 20 33 39 20 2B |␣46␣46␣46␣°C␣␣39␣+ + 18 |U+ 30 20 20 20 35 20 6D 73 20 31 20 52 55 20 20 2206 20 37 |0␣␣␣5␣ms␣1␣RU␣␣∆␣7 + 36 |U+ 68 20 32 33 6D 20 20 20 FA93 200E 20 2B 31 33 B0 43 20 20 |h␣23m␣␣␣望‎␣+13°C␣␣ + 54 |U+ 46 72 20 30 32 20 4A 75 6E 20 20 30 32 3A 34 38 20 20 |Fr␣02␣Jun␣␣02:48␣␣ + 72 |U+ 2595 2714 258F 46 55 4C 4C 20 |▕✔▏FULL␣ +.ft P +.fi +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Return type +\fI\%IFilter\fP +.UNINDENT +.INDENT 7.0 +.TP +.B get_max_chars_per_line(inp, addr_shift) +For the details see \fI\%Tracers math\fP\&. +.INDENT 7.0 +.TP +.B Parameters +\fBinp\fP \-\- +.TP +.B Return type +int +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B apply(inp, extra=None) +Apply the filter to input \fIstr\fP or \fIbytes\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIIT\fP) \-\- input string +.IP \(bu 2 +\fBextra\fP (\fIOptional\fP\fI[\fP\fIAny\fP\fI]\fP) \-\- additional options +.UNINDENT +.TP +.B Returns +transformed string; the type can match the input type, +as well as be different \-\- that depends on filter type. +.TP +.B Return type +\fIOT\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.filter.TracerExtra(label: \(aqstr\(aq = \(aq\(aq, addr_shift: \(aqint\(aq = 0, hash: \(aqbool\(aq = False) +.INDENT 7.0 +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.filter.dump(data, tracer_cls=None, extra=None, force_width=None) +\&. +.INDENT 7.0 +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.filter.get_max_ucs_chars_cp_length(string) +\&. +.INDENT 7.0 +.TP +.B Return type +int +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.filter.get_max_utf8_bytes_char_length(string) +cc +.INDENT 7.0 +.TP +.B Return type +int +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.filter.ljust_sgr(string, width, fillchar=\(aq \(aq) +SGR\-formatting\-aware implementation of \fBstr.ljust\fP\&. +.sp +Return a left\-justified string of length \fBwidth\fP\&. Padding is done +using the specified fill character (default is a space). +.INDENT 7.0 +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.filter.center_sgr(string, width, fillchar=\(aq \(aq) +SGR\-formatting\-aware implementation of \fBstr.center\fP\&. +.sp +Return a centered string of length \fBwidth\fP\&. Padding is done using the +specified fill character (default is a space). +.INDENT 7.0 +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.filter.rjust_sgr(string, width, fillchar=\(aq \(aq) +SGR\-formatting\-aware implementation of \fBstr.rjust\fP\&. +.sp +Return a right\-justified string of length \fBwidth\fP\&. Padding is done +using the specified fill character (default is a space). +.INDENT 7.0 +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.filter.apply_filters(inp, *args) +Method for applying dynamic filter list to a target string/bytes. +.sp +Example (will replace all \fBESC\fP control characters to \fBE\fP and +thus make SGR params visible): +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +>>> from pytermor import SeqIndex +>>> test_str = f\(aq{SeqIndex.RED}test{SeqIndex.COLOR_OFF}\(aq +>>> apply_filters(test_str, SgrStringReplacer(\(aqE\e2\e3\e4\(aq)) +\(aqE[31mtestE[39m\(aq + +>>> apply_filters(\(aqtest\(aq, OmniSanitizer) +\(aq.[31mtest.[39m\(aq +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +Note that type of \fBinp\fP argument must be same as filter parameterized +input type (\fI\%IT\fP), i.e. \fI\%StringReplacer\fP is \fBIFilter[str, str]\fP type, +so you can apply it only to \fIstr\fP\-type inputs. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBinp\fP (\fIIT\fP) \-\- String/bytes to filter. +.IP \(bu 2 +\fBargs\fP (\fIUnion\fP\fI[\fP\fI\%IFilter\fP\fI, \fP\fIType\fP\fI[\fP\fI\%IFilter\fP\fI]\fP\fI]\fP) \-\- Instance(s) implementing \fI\%IFilter\fP or their type(s). +.UNINDENT +.TP +.B Return type +\fIOT\fP +.UNINDENT +.UNINDENT +.SS pytermor.numfmt +.sp +utilnum +.sp +Module Attributes +.TS +center; +|l|l|. +_ +T{ +\fI\%PREFIXES_SI_DEC\fP +T} T{ +Prefix preset used by \fI\%format_si()\fP and \fI\%format_bytes_human()\fP\&. +T} +_ +.TE +.sp +Functions +.TS +center; +|l|l|. +_ +T{ +\fI\%format_auto_float\fP(val, req_len[, allow_exp_form]) +T} T{ +Dynamically adjust decimal digit amount and format to fill up the output string with as many significant digits as possible, and keep the output length strictly equal to \fBreq_len\fP at the same time. +T} +_ +T{ +\fI\%format_bytes_human\fP(val[, auto_color]) +T} T{ +Invoke special case of fixed\-length SI formatter optimized for processing byte\-based values. +T} +_ +T{ +\fI\%format_si\fP(val[, unit, auto_color]) +T} T{ +Invoke fixed\-length decimal SI formatter; format \fBvalue\fP as a unitless value with SI\-prefixes; a unit can be provided as an argument of \fI\%format()\fP method. +T} +_ +T{ +\fI\%format_si_binary\fP(val[, unit, auto_color]) +T} T{ +Invoke fixed\-length binary SI formatter which formats \fBvalue\fP as binary size (\(dqKiB\(dq, \(dqMiB\(dq) with base 1024. +T} +_ +T{ +\fI\%format_thousand_sep\fP(val[, separator]) +T} T{ +Returns input \fBval\fP with integer part split into groups of three digits, joined then with \fBseparator\fP string. +T} +_ +T{ +\fI\%format_time\fP(val_sec[, auto_color]) +T} T{ +Invoke dynamic\-length general\-purpose time formatter, which supports a wide range of output units, including seconds, minutes, hours, days, weeks, months, years, milliseconds, microseconds, nanoseconds etc. +T} +_ +T{ +\fI\%format_time_delta\fP(val_sec[, max_len, auto_color]) +T} T{ +Format time interval using the most suitable format with one or two time units, depending on \fBmax_len\fP argument. +T} +_ +T{ +\fI\%format_time_delta_longest\fP(val_sec[, auto_color]) +T} T{ +Wrapper around \fI\%format_time_delta()\fP with pre\-set longest formatter. +T} +_ +T{ +\fI\%format_time_delta_shortest\fP(val_sec[, auto_color]) +T} T{ +Wrapper around \fI\%format_time_delta()\fP with pre\-set shortest formatter. +T} +_ +T{ +\fI\%format_time_ms\fP(value_ms[, auto_color]) +T} T{ +Invoke a variation of \fBformatter_time\fP specifically configured to format small time intervals. +T} +_ +T{ +\fI\%format_time_ns\fP(value_ns[, auto_color]) +T} T{ +Wrapper for \fI\%format_time_ms()\fP expecting input value as nanoseconds. +T} +_ +T{ +\fI\%highlight\fP(string) +T} T{ +T} +_ +.TE +.sp +Classes +.TS +center; +|l|l|. +_ +T{ +\fI\%BaseUnit\fP(oom[, unit, prefix, _integer]) +T} T{ +T} +_ +T{ +\fI\%DualBaseUnit\fP(name[, in_next, ...]) +T} T{ +TU +T} +_ +T{ +\fI\%DualFormatter\fP([fallback, units, auto_color, ...]) +T} T{ +Formatter designed for time intervals. +T} +_ +T{ +\fI\%DualFormatterRegistry\fP() +T} T{ +Simple DualFormatter registry for storing formatters and selecting the suitable one by max output length. +T} +_ +T{ +\fI\%DynamicFormatter\fP([fallback, units, ...]) +T} T{ +A simplified version of static formatter for cases, when length of the result string doesn\(aqt matter too much (e.g., for log output), and you don\(aqt have intention to customize the output (too much). +T} +_ +T{ +\fI\%Highlighter\fP([dim_units]) +T} T{ +S +T} +_ +T{ +\fBNumFormatter\fP(auto_color, highlighter) +T} T{ +T} +_ +T{ +\fI\%StaticFormatter\fP([fallback, max_value_len, ...]) +T} T{ +Format \fBvalue\fP using settings passed to constructor. +T} +_ +T{ +\fBSupportsFallback\fP() +T} T{ +T} +_ +.TE +.INDENT 0.0 +.TP +.B pytermor.numfmt.PREFIXES_SI_DEC = [\(aqq\(aq, \(aqr\(aq, \(aqy\(aq, \(aqz\(aq, \(aqa\(aq, \(aqf\(aq, \(aqp\(aq, \(aqn\(aq, \(aqµ\(aq, \(aqm\(aq, None, \(aqk\(aq, \(aqM\(aq, \(aqG\(aq, \(aqT\(aq, \(aqP\(aq, \(aqE\(aq, \(aqZ\(aq, \(aqY\(aq, \(aqR\(aq, \(aqQ\(aq] +Prefix preset used by \fI\%format_si()\fP and \fI\%format_bytes_human()\fP\&. Covers values +from 10^{\-30} to 10^{32}\&. Note lower\-cased \(aqk\(aq prefix. +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.numfmt.Highlighter(dim_units=True) +S +.INDENT 7.0 +.UNINDENT +.INDENT 7.0 +.TP +.B colorize(string) +parse and highlight +.INDENT 7.0 +.TP +.B Parameters +\fBstring\fP (\fIstr\fP) \-\- +.TP +.B Returns + +.TP +.B Return type +\fI\%Text\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B apply(intp, frac, sep, pfx, unit) +highlight already parsed +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBintp\fP (\fIstr\fP) \-\- +.IP \(bu 2 +\fBfrac\fP (\fIstr\fP) \-\- +.IP \(bu 2 +\fBsep\fP (\fIstr\fP) \-\- +.IP \(bu 2 +\fBpfx\fP (\fIstr\fP) \-\- +.IP \(bu 2 +\fBunit\fP (\fIstr\fP) \-\- +.UNINDENT +.TP +.B Returns + +.TP +.B Return type +\fIList\fP[\fI\%Fragment\fP] +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.numfmt.StaticFormatter(fallback=None, *, max_value_len=None, auto_color=None, allow_negative=None, allow_fractional=None, discrete_input=None, unit=None, unit_separator=None, mcoef=None, pad=None, legacy_rounding=None, prefixes=None, prefix_refpoint_shift=None, value_mapping=None, highlighter=None) +Bases: \fBNumFormatter\fP +.sp +Format \fBvalue\fP using settings passed to constructor. The purpose of this class +is to fit into specified string length as much significant digits as it\(aqs +theoretically possible by using multipliers and unit prefixes. Designed +for metric systems with bases 1000 or 1024. +.sp +The key property of this formatter is maximum length \-\- the output will not +excess specified amount of characters no matter what (that\(aqs what is \(dqstatic\(dq for). +.sp +You can create your own formatters if you need fine tuning of the +output and customization. If that\(aqs not the case, there are facade +methods \fI\%format_si()\fP, \fI\%format_si_binary()\fP and \fI\%format_bytes_human()\fP, +which will invoke predefined formatters and doesn\(aqt require setting up. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBfallback\fP (\fI\%StaticFormatter\fP) \-\- For any (constructing) instance attribute without a value (=\fINone\fP): +look up for this attribute in \fBfallback\fP instance, and if the value is +specified, take it and save as yours own; if the attribute is undefined in +\fBfallback\fP as well, use the default class value for this attribute instead. +.IP \(bu 2 +\fBmax_value_len\fP (\fIint\fP) \-\- +.sp +[default: 4] Target string length. Must be at least \fB3\fP, because it\(aqs a +minimum requirement for formatting values from 0 to 999. +Next number to 999 is 1000, which will be formatted as \(dq1k\(dq. +.sp +Setting \fBallow_negative\fP to \fITrue\fP increases lower bound to \fB4\fP because +the values now can be less than 0, and minus sign also occupies one char in +the output. +.sp +Setting \fBmcoef\fP to anything other than 1000.0 also increases the minimum +by 1, to \fB5\fP\&. The reason is that non\-decimal coefficients like 1024 require +additional char to render as switching to the next prefix happens later: +\(dq999 b\(dq, \(dq1000 b\(dq, \(dq1001 b\(dq, ...\(dq1023 b\(dq, \(dq1 Kb\(dq. + +.IP \(bu 2 +\fBauto_color\fP (\fIbool\fP) \-\- [default: \fIFalse\fP] Enable automatic colorizing of the result. Color depends +on order of magnitude of the value, and always the same, e.g.: blue color for +numbers in [1000; 10^6) and [10^{\-3}; 1) ranges (prefixes +nearest to 1, kilo\- and milli\-); cyan for values in [10^6; 10^9) and +[10^{\-6}; 10^{\-3}) ranges (next ones, mega\-/micro\-), etc. The values +from [1; 999] are colored in neutral gray. See \fI\%Highlighter\fP\&. +.IP \(bu 2 +\fBallow_negative\fP (\fIbool\fP) \-\- [default: \fITrue\fP] Allow negative numbers handling, or (if set to \fIFalse\fP) +ignore the sign and round all of them to 0.0. This option effectively +increases lower limit of \fBmax_value_len\fP by 1 (when enabled). +.IP \(bu 2 +\fBallow_fractional\fP (\fIbool\fP) \-\- [default: \fITrue\fP] Allows the usage of fractional values in the output. If +set to \fIFalse\fP, the results will be rounded. Does not affect lower +limit of \fBmax_value_len\fP\&. +.IP \(bu 2 +\fBdiscrete_input\fP (\fIbool\fP) \-\- [default: \fIFalse\fP] If set to \fITrue\fP, truncate the fractional part off the +input and do not use floating\-point format for \fIbase output\fP, i.e., without +prefix and multiplying coefficient. Useful when the values are originally +discrete (e.g., bytes). Note that the same effect could be achieved by +setting \fBallow_fractional\fP to \fIFalse\fP, except that it will influence +prefixed output as well (\(dq1.08 kB\(dq \-> \(dq1kB\(dq). +.IP \(bu 2 +\fBunit\fP (\fIstr\fP) \-\- [default: empty \fIstr\fP] Unit to apply prefix to (e.g., \(dqm\(dq, \(aqB\(dq). +Can be empty. +.IP \(bu 2 +\fBunit_separator\fP (\fIstr\fP) \-\- [default: a space] String to place in between the value and the +(prefixed) unit. Can be empty. +.IP \(bu 2 +\fBmcoef\fP (\fIfloat\fP) \-\- +.sp +[default: 1000.0] Multiplying coefficient applied to the value: +.sp +.ce +V_{out} = V_{in} * b^{(\-m/3)}, +.ce 0 +.sp +where: V_{in} is an input value, V_{out} is a numeric part +of the output, b is \fBmcoef\fP (base), and m is the order of +magnitude corresponding to a selected unit prefix. For example, in case +of default (decimal) formatter and input value equal to 17345989 the selected +prefix will be \(dqM\(dq with the order of magnitude = 6: +.sp +.ce +V_{out} = 17345989*1000^{(\-6/3)} = 17345989*10^{\-6} = 17.346 . +.ce 0 + +.IP \(bu 2 +\fBpad\fP (\fIbool\fP\fI|\fP\fI\%Align\fP) \-\- [default: \fIFalse\fP] @TODO +.IP \(bu 2 +\fBlegacy_rounding\fP (\fIbool\fP) \-\- [default: \fIFalse\fP] @TODO +.IP \(bu 2 +\fBprefixes\fP (\fIlist\fP\fI[\fP\fIstr\fP\fI|\fP\fINone\fP\fI]\fP) \-\- +.sp +[default: \fI\%PREFIXES_SI_DEC\fP] Prefix list from min power to max. +Reference point (with zero\-power multiplier, or 1.0) is determined by +searching for \fINone\fP in the list provided, therefore it\(aqs a requirement +for the argument to have at least one \fINone\fP value. Prefix list for a +formatter without fractional values support could look like this: +.INDENT 2.0 +.INDENT 3.5 +.sp +.nf +.ft C +[None, \(dqk\(dq, \(dqM\(dq, \(dqG\(dq, \(dqT\(dq] +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +Prefix step is fixed to log_{10} 1000 = 3, as specified for +metric prefixes. + +.IP \(bu 2 +\fBprefix_refpoint_shift\fP (\fIint\fP) \-\- [default: 0] Should be set to a non\-zero number if input represents +already prefixed value; e.g. to correctly format a variable, +which stores the frequency in MHz, set prefix shift to 2; +the formatter then will render 2333 as \(dq2.33 GHz\(dq instead of +incorrect \(dq2.33 kHz\(dq. +.IP \(bu 2 +\fBvalue_mapping\fP (\fIt.Dict\fP\fI[\fP\fIfloat\fP\fI, \fP\fIRT\fP\fI] \fP\fI| \fP\fIt.Callable\fP\fI[\fP\fI[\fP\fIfloat\fP\fI]\fP\fI, \fP\fIRT\fP\fI]\fP) \-\- @TODO +.IP \(bu 2 +\fBhighlighter\fP (\fIt.Type\fP\fI[\fP\fI\%Highlighter\fP\fI] \fP\fI| \fP\fI\%Highlighter\fP) \-\- +.sp +\&... + +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B get_max_len(unit=None) +.INDENT 7.0 +.TP +.B Parameters +\fBunit\fP (\fIOptional\fP\fI[\fP\fIstr\fP\fI]\fP) \-\- Unit override. Set to \fINone\fP to use formatter default. +.TP +.B Returns +Maximum length of the result. Note that constructor argument +is \fBmax_value_len\fP, which is a different parameter. +.TP +.B Return type +int +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B format(val, unit=None, auto_color=None) +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBval\fP (\fIfloat\fP) \-\- Input value. +.IP \(bu 2 +\fBunit\fP (\fIOptional\fP\fI[\fP\fIstr\fP\fI]\fP) \-\- Unit override. Set to \fINone\fP to use formatter default. +.IP \(bu 2 +\fBauto_color\fP (\fIOptional\fP\fI[\fP\fIbool\fP\fI]\fP) \-\- Color mode, \fIbool\fP to enable/disable auto\-colorizing, +\fINone\fP to use formatter default value. +.UNINDENT +.TP +.B Returns +Formatted value, \fIText\fP if colorizing is on, \fIstr\fP otherwise. +.TP +.B Return type +\fIRT\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.numfmt.DynamicFormatter(fallback=None, units=None, *, auto_color=None, allow_fractional=None, unit_separator=None, oom_shift=None, highlighter=None) +Bases: \fBNumFormatter\fP +.sp +A simplified version of static formatter for cases, when length of the result +string doesn\(aqt matter too much (e.g., for log output), and you don\(aqt have +intention to customize the output (too much). +.sp +\fBNOTE:\fP +.INDENT 7.0 +.INDENT 3.5 +Mp mp not note +.UNINDENT +.UNINDENT +.INDENT 7.0 +.UNINDENT +.INDENT 7.0 +.TP +.B format(val, auto_color=False, oom_shift=None) +,,, +:param val: +:param oom_shift: +:param auto_color: +:return: +.INDENT 7.0 +.TP +.B Return type +\fIRT\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.numfmt.BaseUnit(oom: \(aqfloat\(aq, unit: \(aqstr\(aq = \(aq\(aq, prefix: \(aqstr\(aq = \(aq\(aq, _integer: \(aqbool\(aq = None) +.INDENT 7.0 +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.numfmt.DualFormatter(fallback=None, units=None, *, auto_color=None, allow_negative=None, allow_fractional=None, unit_separator=None, pad=None, plural_suffix=None, overflow_msg=None, highlighter=None) +Bases: \fBNumFormatter\fP +.sp +Formatter designed for time intervals. Key feature of this formatter is +ability to combine two units and display them simultaneously, +e.g. return \(dq3h 48min\(dq instead of \(dq228 mins\(dq or \(dq3 hours\(dq, etc. +.sp +It is possible to create custom formatters if fine tuning of the output and +customization is necessary; otherwise use a facade method \fI\%format_time_delta()\fP, +which selects appropriate formatter by specified max length from a preset list. +.sp +Example output: +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +\(dq10 secs\(dq, \(dq5 mins\(dq, \(dq4h 15min\(dq, \(dq5d 22h\(dq +.ft P +.fi +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBfallback\fP (\fI\%DualFormatter\fP) \-\- +.IP \(bu 2 +\fBunits\fP (\fIt.List\fP\fI[\fP\fI\%DualBaseUnit\fP\fI]\fP) \-\- +.IP \(bu 2 +\fBauto_color\fP (\fIbool\fP) \-\- If \fITrue\fP, the result will be colorized depending on unit type. +.IP \(bu 2 +\fBallow_negative\fP (\fIbool\fP) \-\- +.IP \(bu 2 +\fBallow_fractional\fP (\fIbool\fP) \-\- +.IP \(bu 2 +\fBunit_separator\fP (\fIstr\fP) \-\- +.IP \(bu 2 +\fBpad\fP (\fIbool\fP\fI | \fP\fI\%Align\fP) \-\- Set to \fITrue\fP to pad the value with spaces on the left side +and ensure it\(aqs length is equal to \fI\%max_len\fP, or to \fIFalse\fP +to allow shorter result strings. +.IP \(bu 2 +\fBplural_suffix\fP (\fIstr\fP) \-\- +.IP \(bu 2 +\fBoverflow_msg\fP (\fIstr\fP) \-\- +.IP \(bu 2 +\fBhighlighter\fP (\fIt.Type\fP\fI[\fP\fI\%Highlighter\fP\fI]\fP) \-\- +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property max_len: int +This property cannot be set manually, it is +computed on initialization automatically. +.INDENT 7.0 +.TP +.B Returns +Maximum possible output string length. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B format(val_sec, auto_color=None) +Pretty\-print difference between two moments in time. If input +value is too big for the current formatter to handle, return \(dqOVERFLOW\(dq +string (or a part of it, depending on \fBmax_len\fP). +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBval_sec\fP (\fIfloat\fP) \-\- Input value in seconds. +.IP \(bu 2 +\fBauto_color\fP (\fIOptional\fP\fI[\fP\fIbool\fP\fI]\fP) \-\- Color mode, \fIbool\fP to enable/disable colorizing, +\fINone\fP to use formatter default value. +.UNINDENT +.TP +.B Returns +Formatted time delta, \fIText\fP if colorizing is on, \fIstr\fP otherwise. +.TP +.B Return type +\fIRT\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B format_base(val_sec, auto_color=None) +Pretty\-print difference between two moments in time. If input +value is too big for the current formatter to handle, return \fINone\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBval_sec\fP (\fIfloat\fP) \-\- Input value in seconds. +.IP \(bu 2 +\fBauto_color\fP (\fIOptional\fP\fI[\fP\fIbool\fP\fI]\fP) \-\- Color mode, \fIbool\fP to enable/disable colorizing, +\fINone\fP to use formatter default value. +.UNINDENT +.TP +.B Returns +Formatted value as \fIText\fP if colorizing is on; as \fIstr\fP +otherwise. Returns \fINone\fP on overflow. +.TP +.B Return type +\fIOptional\fP[\fIRT\fP] +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.numfmt.DualBaseUnit(name, in_next=None, overflow_after=None, custom_short=None, collapsible_after=None) +TU +.sp +\fBIMPORTANT:\fP +.INDENT 7.0 +.INDENT 3.5 +\fBin_next\fP and \fBoverflow_after\fP are mutually exclusive, and either of +them is required. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBname\fP (\fIstr\fP) \-\- A unit name to display. +.IP \(bu 2 +\fBin_next\fP (\fIint\fP) \-\- +.sp +The base \-\- how many current units the next (single) unit contains, +e.g., for an hour in context of days: +.INDENT 2.0 +.INDENT 3.5 +.sp +.nf +.ft C +CustomBaseUnit(\(dqhour\(dq, 24) +.ft P +.fi +.UNINDENT +.UNINDENT + +.IP \(bu 2 +\fBoverflow_after\fP (\fIint\fP) \-\- Value upper limit. +.IP \(bu 2 +\fBcustom_short\fP (\fIstr\fP) \-\- Use specified short form instead of first letter +of \fBname\fP when operating in double\-value mode. +.IP \(bu 2 +\fBcollapsible_after\fP (\fIint\fP) \-\- Min threshold for double output to become a regular one. +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.numfmt.DualFormatterRegistry +Simple DualFormatter registry for storing formatters and selecting +the suitable one by max output length. +.INDENT 7.0 +.TP +.B register(*formatters) +\&... +.INDENT 7.0 +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B find_matching(max_len) +\&... +.INDENT 7.0 +.TP +.B Return type +\fI\%pytermor.numfmt.DualFormatter\fP | None +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B get_by_max_len(max_len) +\&... +.INDENT 7.0 +.TP +.B Return type +\fI\%pytermor.numfmt.DualFormatter\fP | None +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B get_shortest() +\&... +.INDENT 7.0 +.TP +.B Return type +\fI\%pytermor.numfmt.DualFormatter\fP | None +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B get_longest() +\&... +.INDENT 7.0 +.TP +.B Return type +\fI\%pytermor.numfmt.DualFormatter\fP | None +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.numfmt.format_thousand_sep(val, separator=\(aq \(aq) +Returns input \fBval\fP with integer part split into groups of three digits, +joined then with \fBseparator\fP string. +.sp +.nf +.ft C +>>> format_thousand_sep(260341) +\(aq260 341\(aq +>>> format_thousand_sep(\-9123123123.55, \(aq,\(aq) +\(aq\-9,123,123,123.55\(aq +.ft P +.fi +.INDENT 7.0 +.TP +.B Max output len +(L + max(0, floor(M/3))), +.sp +where \fIL\fP is \fBval\fP length, and \fIM\fP is +order of magnitude of \fBval\fP +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBval\fP (\fIint\fP\fI | \fP\fIfloat\fP) \-\- value to format +.IP \(bu 2 +\fBseparator\fP (\fIstr\fP) \-\- character(s) to use as thousand separators +.UNINDENT +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.numfmt.format_auto_float(val, req_len, allow_exp_form=True) +Dynamically adjust decimal digit amount and format to fill up the output string +with as many significant digits as possible, and keep the output length strictly +equal to \fBreq_len\fP at the same time. +.sp +For values impossible to fit into a string of required length and when rounding +doesn\(aqt help (e.g. 12 500 000 and 5 chars) algorithm switches to scientific notation, +and the result looks like \(aq1.2e7\(aq. If this feature is explicitly disabled +with \fBallow_exp_form\fP = \fIFalse\fP, then: +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.IP 1. 3 +if absolute value is less than 1, zeros will be returned (\(aq0.0000\(aq); +.IP 2. 3 +if value is a big number (like 10^9), \fBValueError\fP will be +raised instead. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +.nf +.ft C +>>> format_auto_float(0.012345678, 5) +\(aq0.012\(aq +>>> format_auto_float(0.123456789, 5) +\(aq0.123\(aq +>>> format_auto_float(1.234567891, 5) +\(aq1.235\(aq +>>> format_auto_float(12.34567891, 5) +\(aq12.35\(aq +>>> format_auto_float(123.4567891, 5) +\(aq123.5\(aq +>>> format_auto_float(1234.567891, 5) +\(aq 1235\(aq +>>> format_auto_float(12345.67891, 5) +\(aq12346\(aq +.ft P +.fi +.INDENT 7.0 +.TP +.B Max output len +\fIadjustable\fP +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBval\fP (\fIfloat\fP) \-\- Value to format. +.IP \(bu 2 +\fBreq_len\fP (\fIint\fP) \-\- Required output string length. +.IP \(bu 2 +\fBallow_exp_form\fP (\fIbool\fP) \-\- Allow scientific notation usage when that\(aqs the only way +of fitting the value into a string of required length. +.UNINDENT +.TP +.B Raises +\fBValueError\fP \-\- When value is too long and \fBallow_exp_form\fP is \fIFalse\fP\&. +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.numfmt.format_si(val, unit=None, auto_color=None) +Invoke fixed\-length decimal SI formatter; format \fBvalue\fP as a unitless value with +SI\-prefixes; a unit can be provided as an argument of \fI\%format()\fP method. +Suitable for formatting any SI unit with values from 10^{\-30} to +10^{32}\&. +.sp +Total maximum length is \fBmax_value_len + 2\fP, which is \fB6\fP +by default (4 from value + 1 from separator and + 1 from prefix). +If the unit is defined and is a non\-empty string, the maximum output +length increases by length of that unit. +.sp +Extending the formatter +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +my_formatter = StaticFormatter(formatter_si) +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +.nf +.ft C +>>> format_si(1010, \(aqm²\(aq) +\(aq1.01 km²\(aq +>>> format_si(0.223, \(aqg\(aq) +\(aq223 mg\(aq +>>> format_si(1213531546, \(aqW\(aq) # great scott +\(aq1.21 GW\(aq +>>> format_si(1.22e28, \(aqeV\(aq) # the Planck energy +\(aq12.2 ReV\(aq +.ft P +.fi +.INDENT 7.0 +.TP +.B Max output len +6 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBval\fP (\fIfloat\fP) \-\- Input value (unitless). +.IP \(bu 2 +\fBunit\fP (\fIOptional\fP\fI[\fP\fIstr\fP\fI]\fP) \-\- A unit override [default unit is an empty string]. +.IP \(bu 2 +\fBauto_color\fP (\fIOptional\fP\fI[\fP\fIbool\fP\fI]\fP) \-\- Color mode override, \fIbool\fP to enable/disable colorizing +depending on unit type, \fINone\fP to use formatters\(aq setting +value [\fIFalse\fP by default]. +.UNINDENT +.TP +.B Returns +Formatted value, \fIText\fP if colorizing is on, \fIstr\fP otherwise. +.TP +.B Return type +\fIRT\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.numfmt.format_si_binary(val, unit=None, auto_color=False) +Invoke fixed\-length binary SI formatter which formats \fBvalue\fP as binary +size (\(dqKiB\(dq, \(dqMiB\(dq) with base 1024. Unit can be customized. Covers values +from 0 to 10^{32}\&. +.sp +While being similar to \fBformatter_si\fP, this formatter +differs in one aspect. Given a variable with default value = 995, +formatting it results in \(dq995 B\(dq. After increasing it +by 20 it equals to 1015, which is still not enough to become +a kilobyte \-\- so returned value will be \(dq1015 B\(dq. Only after one +more increase (at 1024 and more) the value will morph into \(dq1.00 KiB\(dq +form. +.sp +That\(aqs why the initial \fBmax_value_len\fP should be at least 5 \-\- because it +is a minimum requirement for formatting values from 1023 to \-1023. However, +The negative values for this formatter are disabled by default and rendered +as 0, which decreases the \fBmax_value_len\fP minimum value back to 4. +.sp +Total maximum length of the result is \fBmax_value_len + 4\fP = \fB8\fP +(base + 1 from separator + 1 from unit + 2 from prefix, assuming all of +them have default values defined in \fBformatter_si_binary\fP). +.sp +Extending the formatter +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +my_formatter = StaticFormatter(formatter_si_binary) +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +.nf +.ft C +>>> format_si_binary(1010) # 1010 b < 1 kb +\(aq1010 B\(aq +>>> format_si_binary(1080) +\(aq1.05 KiB\(aq +>>> format_si_binary(45200) +\(aq44.1 KiB\(aq +>>> format_si_binary(1.258 * pow(10, 6), \(aqb\(aq) +\(aq1.20 Mib\(aq +.ft P +.fi +.INDENT 7.0 +.TP +.B Max output len +8 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBval\fP (\fIfloat\fP) \-\- Input value in bytes. +.IP \(bu 2 +\fBunit\fP (\fIOptional\fP\fI[\fP\fIstr\fP\fI]\fP) \-\- A unit override [default unit is \(dqB\(dq]. +.IP \(bu 2 +\fBauto_color\fP (\fIbool\fP) \-\- Color mode override, \fIbool\fP to enable/disable colorizing +depending on unit type, \fINone\fP to use formatters\(aq setting +value [\fIFalse\fP by default]. +.UNINDENT +.TP +.B Returns +Formatted value, \fIText\fP if colorizing is on, \fIstr\fP otherwise. +.TP +.B Return type +\fIRT\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.numfmt.format_bytes_human(val, auto_color=False) +Invoke special case of fixed\-length SI formatter optimized for processing +byte\-based values. Inspired by default stats formatting used in +\fI\%htop\fP\&. Comprises traits of both preset SI formatters, +the key ones being: +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.IP \(bu 2 +expecting integer inputs; +.IP \(bu 2 +prohibiting negative inputs; +.IP \(bu 2 +operating in decimal mode with the base of 1000 (not 1024); +.IP \(bu 2 +the absence of units and value\-unit separators in the output, while +prefixes are still present; +.IP \(bu 2 +(if colors allowed) utilizing \fI\%Highlighter\fP with a bit customized setup, +as detailed below. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +Total maximum length is \fBmax_value_len + 1\fP, which is \fB5\fP +by default (4 from value + 1 from prefix). +.INDENT 7.0 +.INDENT 3.5 +.IP "Highlighting options" +.sp +Default highlighter for this formatter does not render units (as well as +prefixes) dimmed. The main reason for that is the absence of actual unit in +the output of this formatter, while prefixes are still there; this allows +to format the fractional output this way: [1].57[k], where brackets [] +indicate brighter colors. +.sp +This format is acceptable because only essential info gets highlighted; however, +in case of other formatters with actual units in the output this approach leads +to complex and mixed\-up formatting; furthermore, it doesn\(aqt matter if the +highlighting affects the prefix part only or both prefix and unit parts \-\- in +either case it\(aqs just too much formatting on a unit of surface: +[1].53 [Ki]B (looks patchworky). +.UNINDENT +.UNINDENT +.SS Default formatters comparison +.TS +center; +|l|l|l|l|. +_ +T{ +Value +T} T{ +\fBSI(unit=\(aqB\(aq)\fP +T} T{ +\fBSI_BINARY\fP +T} T{ +\fBBYTES_HUMAN\fP +T} +_ +T{ +1568 +T} T{ +\(aq1.57 kB\(aq +T} T{ +\(aq1.53 KiB\(aq +T} T{ +\(aq1.57k\(aq +T} +_ +T{ +218371331 +T} T{ +\(aq218 MB\(aq +T} T{ +\(aq208 MiB\(aq +T} T{ +\(aq218M\(aq +T} +_ +T{ +0.25 +T} T{ +\(aq250 mB\(aq [1] +T} T{ +\(aq0 B\(aq +T} T{ +\(aq0\(aq +T} +_ +T{ +\-1218371331232 +T} T{ +\(aq\-1.2 TB\(aq +T} T{ +\(aq0 B\(aq +T} T{ +\(aq0\(aq +T} +_ +.TE +.IP [1] 5 +250 millibytes is not something you would see every day +.sp +Extending the formatter +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +my_formatter = StaticFormatter(formatter_bytes_human, unit_separator=\(dq \(dq) +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +.nf +.ft C +>>> format_bytes_human(990) +\(aq990\(aq +>>> format_bytes_human(1010) +\(aq1.01k\(aq +>>> format_bytes_human(45200) +\(aq45.2k\(aq +>>> format_bytes_human(1.258 * pow(10, 6)) +\(aq1.26M\(aq +.ft P +.fi +.INDENT 7.0 +.TP +.B Max output len +5 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBval\fP (\fIint\fP) \-\- Input value in bytes. +.IP \(bu 2 +\fBauto_color\fP (\fIbool\fP) \-\- Color mode override, \fIbool\fP to enable/disable colorizing +depending on unit type, \fINone\fP to use formatters\(aq setting +value [\fIFalse\fP by default]. +.UNINDENT +.TP +.B Returns +Formatted value, \fIText\fP if colorizing is on, \fIstr\fP otherwise. +.TP +.B Return type +\fIRT\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.numfmt.format_time(val_sec, auto_color=None) +Invoke dynamic\-length general\-purpose time formatter, which supports a +wide range of output units, including seconds, minutes, hours, days, weeks, +months, years, milliseconds, microseconds, nanoseconds etc. +.sp +Extending the formatter +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +my_formatter = DynamicFormatter(formatter_time, unit_separator=\(dq \(dq) +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +.nf +.ft C +>>> format_time(12) +\(aq12.0 s\(aq +>>> format_time(65536) +\(aq18 h\(aq +>>> format_time(0.00324) +\(aq3.2 ms\(aq +.ft P +.fi +.INDENT 7.0 +.TP +.B Max output len +\fIvarying\fP +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBval_sec\fP (\fIfloat\fP) \-\- Input value in seconds. +.IP \(bu 2 +\fBauto_color\fP (\fIOptional\fP\fI[\fP\fIbool\fP\fI]\fP) \-\- Color mode override, \fIbool\fP to enable/disable colorizing +depending on unit type, \fINone\fP to use formatters\(aq setting +value [\fIFalse\fP by default]. +.UNINDENT +.TP +.B Return type +\fIRT\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.numfmt.format_time_ms(value_ms, auto_color=None) +Invoke a variation of \fBformatter_time\fP specifically configured to +format small time intervals. +.sp +Extending the formatter +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +my_formatter = DynamicFormatter(formatter_time_ms, unit_separator=\(dq \(dq) +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +.nf +.ft C +>>> format_time_ms(1) +\(aq1ms\(aq +>>> format_time_ms(344) +\(aq344ms\(aq +>>> format_time_ms(0.967) +\(aq967µs\(aq +.ft P +.fi +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBvalue_ms\fP (\fIfloat\fP) \-\- Input value in milliseconds. +.IP \(bu 2 +\fBauto_color\fP (\fIOptional\fP\fI[\fP\fIbool\fP\fI]\fP) \-\- Color mode override, \fIbool\fP to enable/disable colorizing +depending on unit type, \fINone\fP to use formatters\(aq setting +value [\fIFalse\fP by default]. +.UNINDENT +.TP +.B Returns + +.TP +.B Return type +\fIRT\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.numfmt.format_time_ns(value_ns, auto_color=None) +Wrapper for \fI\%format_time_ms()\fP expecting input value as nanoseconds. +.sp +.nf +.ft C +>>> format_time_ns(1003000) +\(aq1ms\(aq +>>> format_time_ns(3232332224) +\(aq3s\(aq +>>> format_time_ns(9932248284343.32) +\(aq2h\(aq +.ft P +.fi +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBvalue_ns\fP (\fIfloat\fP) \-\- Input value in nanoseconds. +.IP \(bu 2 +\fBauto_color\fP (\fIOptional\fP\fI[\fP\fIbool\fP\fI]\fP) \-\- Color mode override, \fIbool\fP to enable/disable colorizing +depending on unit type, \fINone\fP to use formatters\(aq setting +value [\fIFalse\fP by default]. +.UNINDENT +.TP +.B Returns + +.TP +.B Return type +\fIRT\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.numfmt.format_time_delta(val_sec, max_len=None, auto_color=None) +Format time interval using the most suitable format with one or +two time units, depending on \fBmax_len\fP argument. Key feature +of this formatter is an ability to combine two units and display +them simultaneously, e.g. return \(dq3h 48min\(dq instead of \(dq228 mins\(dq +or \(dq3 hours\(dq, and on top of that \-\- fixed\-length output. +.sp +There are predefined formatters with output lengths of \fB3, 4, 5, +6\fP and \fB10\fP characters. Therefore, you can pass in any value +from 3 inclusive and it\(aqs guarenteed that result\(aqs length +will be less or equal to required length. If \fI\%max_len\fP is +omitted, longest registred formatter will be used. +.sp +\fBNOTE:\fP +.INDENT 7.0 +.INDENT 3.5 +Negative values are supported by formatters 5 and 10 only. +.UNINDENT +.UNINDENT +.sp +.nf +.ft C +>>> format_time_delta(10, 3) +\(aq10s\(aq +>>> format_time_delta(10, 6) +\(aq10.0s\(aq +>>> format_time_delta(15350, 4) +\(aq4 h\(aq +>>> format_time_delta(15350) +\(aq4h 15min\(aq +.ft P +.fi +.INDENT 7.0 +.TP +.B Max output len +3, 4, 5, 6, 10 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBval_sec\fP (\fIfloat\fP) \-\- Input value in seconds. +.IP \(bu 2 +\fBmax_len\fP (\fIOptional\fP\fI[\fP\fIint\fP\fI]\fP) \-\- Maximum output string length (total). +.IP \(bu 2 +\fBauto_color\fP (\fIOptional\fP\fI[\fP\fIbool\fP\fI]\fP) \-\- Color mode override, \fIbool\fP to enable/disable colorizing +depending on unit type, \fINone\fP to use formatters\(aq setting +value [\fIFalse\fP by default]. +.UNINDENT +.TP +.B Return type +\fIRT\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.numfmt.format_time_delta_shortest(val_sec, auto_color=None) +Wrapper around \fI\%format_time_delta()\fP with pre\-set shortest formatter. +.INDENT 7.0 +.TP +.B Max output len +3 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBval_sec\fP (\fIfloat\fP) \-\- Input value in seconds. +.IP \(bu 2 +\fBauto_color\fP (\fIOptional\fP\fI[\fP\fIbool\fP\fI]\fP) \-\- Color mode override, \fIbool\fP to enable/disable colorizing +depending on unit type, \fINone\fP to use formatters\(aq setting +value [\fIFalse\fP by default]. +.UNINDENT +.TP +.B Return type +\fIRT\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.numfmt.format_time_delta_longest(val_sec, auto_color=None) +Wrapper around \fI\%format_time_delta()\fP with pre\-set longest formatter. +.INDENT 7.0 +.TP +.B Max output len +10 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBval_sec\fP (\fIfloat\fP) \-\- Input value in seconds. +.IP \(bu 2 +\fBauto_color\fP (\fIOptional\fP\fI[\fP\fIbool\fP\fI]\fP) \-\- Color mode override, \fIbool\fP to enable/disable colorizing +depending on unit type, \fINone\fP to use formatters\(aq setting +value [\fIFalse\fP by default]. +.UNINDENT +.TP +.B Return type +\fIRT\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.numfmt.highlight(string) +.INDENT 7.0 +.INDENT 3.5 +.SS Todo +.sp +@TODO +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Max output len +\fIsame as input\fP +.TP +.B Parameters +\fBstring\fP (\fIstr\fP) \-\- input text +.TP +.B Return type +\fIRT\fP +.UNINDENT +.UNINDENT +.SS pytermor.renderer +.sp +Renderers transform \fI\%Style\fP instances into lower\-level abstractions like +\fI\%SGR sequences\fP, tmux\-compatible directives, HTML markup etc., +depending on renderer type. Default global renderer type is \fI\%SgrRenderer\fP\&. +.sp +Functions +.TS +center; +|l|l|. +_ +T{ +\fI\%force_ansi_rendering\fP() +T} T{ +Shortcut for forcing all control sequences to be present in the output of a global renderer. +T} +_ +T{ +\fI\%force_no_ansi_rendering\fP() +T} T{ +Shortcut for disabling all output formatting of a global renderer. +T} +_ +.TE +.sp +Classes +.TS +center; +|l|l|. +_ +T{ +\fI\%HtmlRenderer\fP() +T} T{ +Translate \fI\%Styles\fP attributes into a rudimentary HTML markup. +T} +_ +T{ +\fI\%IRenderer\fP(*[, allow_cache, allow_format]) +T} T{ +Renderer interface. +T} +_ +T{ +\fI\%NoOpRenderer\fP() +T} T{ +Special renderer type that does nothing with the input string and just returns it as is (i.e. +T} +_ +T{ +\fI\%OutputMode\fP(value) +T} T{ +Determines what types of SGR sequences are allowed to use in the output. +T} +_ +T{ +\fI\%RendererManager\fP() +T} T{ +Class for global rendering mode setup. +T} +_ +T{ +\fI\%SgrDebugger\fP([output_mode]) +T} T{ +Subclass of regular \fI\%SgrRenderer\fP with two differences \-\- instead of rendering the proper ANSI escape sequences it renders them with \fBESC\fP character replaced by \(dqǝ\(dq, and encloses the whole sequence into \(aq()\(aq for visual separation. +T} +_ +T{ +\fI\%SgrRenderer\fP([output_mode, io]) +T} T{ +Default renderer invoked by \fI\%Text.render()\fP\&. +T} +_ +T{ +\fI\%TmuxRenderer\fP() +T} T{ +Translates \fI\%Styles\fP attributes into \fI\%tmux\-compatible\fP markup. +T} +_ +.TE +.INDENT 0.0 +.TP +.B class pytermor.renderer.RendererManager +Class for global rendering mode setup. For the details and recommendations +see \fI\%Renderer setup\fP\&. +.INDENT 7.0 +.TP +.B classmethod set_default(renderer=None) +Select a global renderer. See also: \fI\%Default renderers priority\fP\&. +.INDENT 7.0 +.TP +.B Parameters +\fBrenderer\fP (\fIOptional\fP\fI[\fP\fIUnion\fP\fI[\fP\fI\%IRenderer\fP\fI, \fP\fIType\fP\fI[\fP\fI\%IRenderer\fP\fI]\fP\fI]\fP\fI]\fP) \-\- +.sp +Default renderer to use globally. Calling this method without arguments +will result in library default renderer \fI\%SgrRenderer\fP being set as default. +.sp +All the methods with the \fBrenderer\fP argument (e.g., \fI\%text.render()\fP) +will use the global default one if said argument is omitted or set to \fINone\fP\&. +.sp +You can specify either the renderer class, in which case manager will +instantiate it with the default parameters, or provide already instantiated +and set up renderer, which will be registered as global. + +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B classmethod get_default() +Get global renderer instance (\fI\%SgrRenderer\fP, or the one provided earlier with +\fI\%set_default()\fP). +.INDENT 7.0 +.TP +.B Return type +\fI\%IRenderer\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.renderer.IRenderer(*, allow_cache=None, allow_format=None) +Renderer interface. +.INDENT 7.0 +.UNINDENT +.INDENT 7.0 +.TP +.B property is_caching_allowed: bool +.INDENT 7.0 +.TP +.B Returns +\fITrue\fP if caching of renderer\(aqs results makes any sense and \fIFalse\fP +otherwise. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property is_format_allowed: bool +.INDENT 7.0 +.TP +.B Returns +\fITrue\fP if renderer is set up to produce formatted output and will do +it on invocation, and \fIFalse\fP otherwise. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B abstract render(string, fmt=None) +Apply colors and attributes described in \fBfmt\fP argument to +\fBstring\fP and return the result. Output format depends on renderer\(aqs +class, which defines the implementation. +.sp +\fBIMPORTANT:\fP +.INDENT 7.0 +.INDENT 3.5 +Renderer\(aqs method \fI\%IRenderer.render()\fP can work only with primitive \fIstr\fP +instances. \fI\%IRenderable\fP instances like \fI\%Fragment\fP or \fI\%Text\fP should be +rendered using module\-level function \fI\%render()\fP or their own instance +method \fI\%IRenderable.render()\fP\&. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBstring\fP (\fIstr\fP) \-\- String to format. +.IP \(bu 2 +\fBfmt\fP (\fIOptional\fP\fI[\fP\fIFT\fP\fI]\fP) \-\- Style or color to apply. If \fBfmt\fP is a \fBIColor\fP instance, +it is assumed to be a foreground color. See \fI\%FT\fP\&. +.UNINDENT +.TP +.B Returns +String with formatting applied, or without it, depending on +renderer settings. +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B clone(*args, **kwargs) +Make a copy of the renderer with the same setup. +.INDENT 7.0 +.TP +.B Return type +\fI_T\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.renderer.OutputMode(value) +Bases: \fI\%ExtendedEnum\fP +.sp +Determines what types of SGR sequences are allowed to use in the output. +.INDENT 7.0 +.TP +.B NO_ANSI = \(aqno_ansi\(aq +The renderer discards all color and format information completely. +.UNINDENT +.INDENT 7.0 +.TP +.B XTERM_16 = \(aqxterm_16\(aq +16\-colors mode. Enforces the renderer to approximate all color types +to \fI\%Color16\fP and render them as basic mode selection SGR sequences +(\fBESC [31m\fP, \fBESC [42m\fP etc). See \fBColor.approximate()\fP for approximation +algorithm details. +.UNINDENT +.INDENT 7.0 +.TP +.B XTERM_256 = \(aqxterm_256\(aq +256\-colors mode. Allows the renderer to use either \fI\%Color16\fP or \fI\%Color256\fP +(but RGB will be approximated to 256\-color pallette). +.UNINDENT +.INDENT 7.0 +.TP +.B TRUE_COLOR = \(aqtrue_color\(aq +RGB color mode. Does not apply restrictions to color rendering. +.UNINDENT +.INDENT 7.0 +.TP +.B AUTO = \(aqauto\(aq +Lets the renderer select the most suitable mode by itself. See +\fI\%Output mode auto\-selection\fP for the details. +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.renderer.SgrRenderer(output_mode=OutputMode.AUTO, io=<_io.TextIOWrapper name=\(aq\(aq mode=\(aqw\(aq encoding=\(aqutf\-8\(aq>) +Bases: \fI\%IRenderer\fP +.sp +Default renderer invoked by \fI\%Text.render()\fP\&. Transforms \fI\%Color\fP instances +defined in \fBfmt\fP into ANSI control sequence bytes and merges them with +input string. Type of resulting \fI\%SequenceSGR\fP depends on type of \fI\%Color\fP +instances in \fBfmt\fP argument and current output mode of the renderer. +.INDENT 7.0 +.IP 1. 3 +\fI\%ColorRGB\fP can be rendered as True Color sequence, 256\-color sequence +or 16\-color sequence depending on specified \fI\%OutputMode\fP and +\fI\%Config.prefer_rgb\fP\&. +.IP 2. 3 +\fI\%Color256\fP can be rendered as 256\-color sequence or 16\-color +sequence. +.IP 3. 3 +\fI\%Color16\fP will be rendered as 16\-color sequence. +.IP 4. 3 +Nothing of the above will happen and all formatting will be discarded +completely if output device is not a terminal emulator or if the developer +explicitly set up the renderer to do so (\fI\%OutputMode.NO_ANSI\fP). +.UNINDENT +.sp +Renderer approximates RGB colors to closest \fBindexed\fP colors if terminal doesn\(aqt +support RGB output. In case terminal doesn\(aqt support even 256 colors, it +falls back to 16\-color palette and picks closest samples again the same way. +See \fI\%OutputMode\fP documentation for exact mappings. +.sp +.nf +.ft C +>>> SgrRenderer(OutputMode.XTERM_256).render(\(aqtext\(aq, Styles.WARNING_LABEL) +\(aqtext\(aq +>>> SgrRenderer(OutputMode.NO_ANSI).render(\(aqtext\(aq, Styles.WARNING_LABEL) +\(aqtext\(aq +.ft P +.fi +.sp +Detailed \fI\%OutputMode.AUTO\fP algorithm is described in \fI\%Output mode auto\-selection\fP\&. +.INDENT 7.0 +.TP +.B Cache allowed +\fITrue\fP +.TP +.B Format allowed +\fIFalse\fP if \fBoutput_mode\fP is \fI\%OutputMode.NO_ANSI\fP, +\fITrue\fP otherwise. +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBoutput_mode\fP (\fIstr\fP\fI | \fP\fI\%OutputMode\fP) \-\- can be set up explicitly, or kept at the default value +\fI\%OutputMode.AUTO\fP; in the latter case the renderer will +select the appropriate mode by itself (see \fI\%Output mode auto\-selection\fP). +.IP \(bu 2 +\fBio\fP (\fIt.IO\fP) \-\- specified in order to check if output device is a tty +or not and can be omitted when output mode is set up +explicitly. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B render(string, fmt=None) +Apply colors and attributes described in \fBfmt\fP argument to +\fBstring\fP and return the result. Output format depends on renderer\(aqs +class, which defines the implementation. +.sp +\fBIMPORTANT:\fP +.INDENT 7.0 +.INDENT 3.5 +Renderer\(aqs method \fI\%IRenderer.render()\fP can work only with primitive \fIstr\fP +instances. \fI\%IRenderable\fP instances like \fI\%Fragment\fP or \fI\%Text\fP should be +rendered using module\-level function \fI\%render()\fP or their own instance +method \fI\%IRenderable.render()\fP\&. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBstring\fP (\fIstr\fP) \-\- String to format. +.IP \(bu 2 +\fBfmt\fP (\fIOptional\fP\fI[\fP\fIFT\fP\fI]\fP) \-\- Style or color to apply. If \fBfmt\fP is a \fBIColor\fP instance, +it is assumed to be a foreground color. See \fI\%FT\fP\&. +.UNINDENT +.TP +.B Returns +String with formatting applied, or without it, depending on +renderer settings. +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B clone() +Make a copy of the renderer with the same setup. +.INDENT 7.0 +.TP +.B Return type +\fI\%SgrRenderer\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property is_caching_allowed: bool +.INDENT 7.0 +.TP +.B Returns +\fITrue\fP if caching of renderer\(aqs results makes any sense and \fIFalse\fP +otherwise. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property is_format_allowed: bool +.INDENT 7.0 +.TP +.B Returns +\fITrue\fP if renderer is set up to produce formatted output and will do +it on invocation, and \fIFalse\fP otherwise. +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.renderer.TmuxRenderer +Bases: \fI\%IRenderer\fP +.sp +Translates \fI\%Styles\fP attributes into +\fI\%tmux\-compatible\fP +markup. [1] +.sp +.nf +.ft C +>>> TmuxRenderer().render(\(aqtext\(aq, Style(fg=\(aqblue\(aq, bold=True)) +\(aq#[fg=blue bold]text#[fg=default nobold]\(aq +.ft P +.fi +.INDENT 7.0 +.TP +.B Cache allowed +\fITrue\fP +.TP +.B Format allowed +\fITrue\fP, because tmux markup can be used without regard +to the type of output device and its capabilities \-\- all the +dirty work will be done by the multiplexer himself. +.UNINDENT +.IP [1] 5 +\fI\%tmux\fP is a commonly used terminal +multiplexer. +.INDENT 7.0 +.TP +.B render(string, fmt=None) +Apply colors and attributes described in \fBfmt\fP argument to +\fBstring\fP and return the result. Output format depends on renderer\(aqs +class, which defines the implementation. +.sp +\fBIMPORTANT:\fP +.INDENT 7.0 +.INDENT 3.5 +Renderer\(aqs method \fI\%IRenderer.render()\fP can work only with primitive \fIstr\fP +instances. \fI\%IRenderable\fP instances like \fI\%Fragment\fP or \fI\%Text\fP should be +rendered using module\-level function \fI\%render()\fP or their own instance +method \fI\%IRenderable.render()\fP\&. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBstring\fP (\fIstr\fP) \-\- String to format. +.IP \(bu 2 +\fBfmt\fP (\fIOptional\fP\fI[\fP\fIFT\fP\fI]\fP) \-\- Style or color to apply. If \fBfmt\fP is a \fBIColor\fP instance, +it is assumed to be a foreground color. See \fI\%FT\fP\&. +.UNINDENT +.TP +.B Returns +String with formatting applied, or without it, depending on +renderer settings. +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B clone(*args, **kwargs) +Make a copy of the renderer with the same setup. +.INDENT 7.0 +.TP +.B Return type +\fI_T\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property is_caching_allowed: bool +.INDENT 7.0 +.TP +.B Returns +\fITrue\fP if caching of renderer\(aqs results makes any sense and \fIFalse\fP +otherwise. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property is_format_allowed: bool +.INDENT 7.0 +.TP +.B Returns +\fITrue\fP if renderer is set up to produce formatted output and will do +it on invocation, and \fIFalse\fP otherwise. +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.renderer.NoOpRenderer +Bases: \fI\%IRenderer\fP +.sp +Special renderer type that does nothing with the input string and just +returns it as is (i.e. raw text without any \fI\%Styles\fP applied. +Often used as a default argument value (along with similar \(dqNoOps\(dq like +\fI\%NOOP_STYLE\fP, \fBNOOP_COLOR\fP etc.) +.sp +.nf +.ft C +>>> NoOpRenderer().render(\(aqtext\(aq, Style(fg=\(aqgreen\(aq, bold=True)) +\(aqtext\(aq +.ft P +.fi +.INDENT 7.0 +.TP +.B Cache allowed +\fIFalse\fP +.TP +.B Format allowed +\fIFalse\fP, nothing to apply → nothing to allow. +.UNINDENT +.INDENT 7.0 +.TP +.B render(string, fmt=None) +Return the \fBstring\fP argument untouched, don\(aqt mind the \fBfmt\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBstring\fP (\fIstr\fP) \-\- String to format ignore. +.IP \(bu 2 +\fBfmt\fP (\fIOptional\fP\fI[\fP\fIFT\fP\fI]\fP) \-\- Style or color to appl discard. +.UNINDENT +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B clone(*args, **kwargs) +Make a copy of the renderer with the same setup. +.INDENT 7.0 +.TP +.B Return type +\fI_T\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property is_caching_allowed: bool +.INDENT 7.0 +.TP +.B Returns +\fITrue\fP if caching of renderer\(aqs results makes any sense and \fIFalse\fP +otherwise. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property is_format_allowed: bool +.INDENT 7.0 +.TP +.B Returns +\fITrue\fP if renderer is set up to produce formatted output and will do +it on invocation, and \fIFalse\fP otherwise. +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.renderer.HtmlRenderer +Bases: \fI\%IRenderer\fP +.sp +Translate \fI\%Styles\fP attributes into a rudimentary HTML markup. +All the formatting is inlined into \fBstyle\fP attribute of the \fB\fP +elements. Can be optimized by extracting the common styles as CSS classes +and referencing them by DOM elements instead. +.sp +.nf +.ft C +>>> HtmlRenderer().render(\(aqtext\(aq, Style(fg=\(aqred\(aq, bold=True)) +\(aqtext\(aq +.ft P +.fi +.INDENT 7.0 +.TP +.B Cache allowed +\fITrue\fP +.TP +.B Format allowed +\fITrue\fP, because the capabilities of the terminal have +nothing to do with HTML markup meant for web\-browsers. +.UNINDENT +.INDENT 7.0 +.TP +.B render(string, fmt=None) +Apply colors and attributes described in \fBfmt\fP argument to +\fBstring\fP and return the result. Output format depends on renderer\(aqs +class, which defines the implementation. +.sp +\fBIMPORTANT:\fP +.INDENT 7.0 +.INDENT 3.5 +Renderer\(aqs method \fI\%IRenderer.render()\fP can work only with primitive \fIstr\fP +instances. \fI\%IRenderable\fP instances like \fI\%Fragment\fP or \fI\%Text\fP should be +rendered using module\-level function \fI\%render()\fP or their own instance +method \fI\%IRenderable.render()\fP\&. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBstring\fP (\fIstr\fP) \-\- String to format. +.IP \(bu 2 +\fBfmt\fP (\fIOptional\fP\fI[\fP\fIFT\fP\fI]\fP) \-\- Style or color to apply. If \fBfmt\fP is a \fBIColor\fP instance, +it is assumed to be a foreground color. See \fI\%FT\fP\&. +.UNINDENT +.TP +.B Returns +String with formatting applied, or without it, depending on +renderer settings. +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B clone(*args, **kwargs) +Make a copy of the renderer with the same setup. +.INDENT 7.0 +.TP +.B Return type +\fI_T\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property is_caching_allowed: bool +.INDENT 7.0 +.TP +.B Returns +\fITrue\fP if caching of renderer\(aqs results makes any sense and \fIFalse\fP +otherwise. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property is_format_allowed: bool +.INDENT 7.0 +.TP +.B Returns +\fITrue\fP if renderer is set up to produce formatted output and will do +it on invocation, and \fIFalse\fP otherwise. +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.renderer.SgrDebugger(output_mode=OutputMode.AUTO) +Bases: \fI\%SgrRenderer\fP +.sp +Subclass of regular \fI\%SgrRenderer\fP with two differences \-\- instead of rendering the +proper ANSI escape sequences it renders them with \fBESC\fP character replaced by \(dqǝ\(dq, +and encloses the whole sequence into \(aq()\(aq for visual separation. +.sp +Can be used for debugging of assembled sequences, because such a transformation +reliably converts a control sequence into a harmless piece of bytes completely +ignored by the terminals. +.sp +.nf +.ft C +>>> SgrDebugger(OutputMode.XTERM_16).render(\(aqtext\(aq, Style(fg=\(aqred\(aq, bold=True)) +\(aq(ǝ[1;31m)text(ǝ[22;39m)\(aq +.ft P +.fi +.INDENT 7.0 +.TP +.B Cache allowed +\fITrue\fP +.TP +.B Format allowed +adjustable +.UNINDENT +.INDENT 7.0 +.TP +.B property is_format_allowed: bool +.INDENT 7.0 +.TP +.B Returns +\fITrue\fP if renderer is set up to produce formatted output and will do +it on invocation, and \fIFalse\fP otherwise. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B render(string, fmt=None) +Apply colors and attributes described in \fBfmt\fP argument to +\fBstring\fP and return the result. Output format depends on renderer\(aqs +class, which defines the implementation. +.sp +\fBIMPORTANT:\fP +.INDENT 7.0 +.INDENT 3.5 +Renderer\(aqs method \fI\%IRenderer.render()\fP can work only with primitive \fIstr\fP +instances. \fI\%IRenderable\fP instances like \fI\%Fragment\fP or \fI\%Text\fP should be +rendered using module\-level function \fI\%render()\fP or their own instance +method \fI\%IRenderable.render()\fP\&. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBstring\fP (\fIstr\fP) \-\- String to format. +.IP \(bu 2 +\fBfmt\fP (\fIOptional\fP\fI[\fP\fIFT\fP\fI]\fP) \-\- Style or color to apply. If \fBfmt\fP is a \fBIColor\fP instance, +it is assumed to be a foreground color. See \fI\%FT\fP\&. +.UNINDENT +.TP +.B Returns +String with formatting applied, or without it, depending on +renderer settings. +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B clone() +Make a copy of the renderer with the same setup. +.INDENT 7.0 +.TP +.B Return type +\fI\%SgrDebugger\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property is_caching_allowed: bool +.INDENT 7.0 +.TP +.B Returns +\fITrue\fP if caching of renderer\(aqs results makes any sense and \fIFalse\fP +otherwise. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B set_format_always() +Force all control sequences to be present in the output. +.UNINDENT +.INDENT 7.0 +.TP +.B set_format_auto() +Reset the force formatting flag and let the renderer decide by itself +(see \fI\%SgrRenderer\fP docs for the details). +.UNINDENT +.INDENT 7.0 +.TP +.B set_format_never() +Force disabling of all output formatting. +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.renderer.force_ansi_rendering() +Shortcut for forcing all control sequences to be present in the +output of a global renderer. +.sp +Note that it applies only to the renderer that is set up as default at +the moment of calling this method, i.e., all previously created instances, +as well as the ones that will be created afterwards, are unaffected. +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.renderer.force_no_ansi_rendering() +Shortcut for disabling all output formatting of a global renderer. +.UNINDENT +.SS pytermor.style +.sp +Reusable data classes that control the appearance of the output \-\- colors +(text/background/underline) and attributes (\fIbold\fP, \fIunderlined\fP, \fIitalic\fP, etc.). +Instances can inherit attributes from each other, which allows to avoid meaningless +definition repetitions; multiple inheritance is also supported. +.sp +Module Attributes +.TS +center; +|l|l|. +_ +T{ +\fI\%NOOP_STYLE\fP +T} T{ +Special style passing the text through without any modifications. +T} +_ +.TE +.sp +Functions +.TS +center; +|l|l|. +_ +T{ +\fBis_ft\fP(arg) +T} T{ +T} +_ +T{ +\fI\%make_style\fP([fmt]) +T} T{ +General \fI\%Style\fP constructor. +T} +_ +T{ +\fI\%merge_styles\fP([origin, fallbacks, overwrites]) +T} T{ +Bulk style merging method. +T} +_ +.TE +.sp +Classes +.TS +center; +|l|l|. +_ +T{ +\fI\%FrozenStyle\fP(*args, **kwargs) +T} T{ +T} +_ +T{ +\fI\%MergeMode\fP(value) +T} T{ +An enumeration. +T} +_ +T{ +\fI\%Style\fP([fallback, fg, bg, frozen, bold, dim, ...]) +T} T{ +Create new text render descriptior. +T} +_ +T{ +\fI\%Styles\fP() +T} T{ +Some ready\-to\-use styles which also can be used as examples. +T} +_ +.TE +.INDENT 0.0 +.TP +.B class pytermor.style.MergeMode(value) +Bases: \fBstr\fP, \fBEnum\fP +.sp +An enumeration. +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.style.Style(fallback=None, fg=None, bg=None, frozen=False, *, bold=None, dim=None, italic=None, underlined=None, overlined=None, crosslined=None, double_underlined=None, curly_underlined=None, underline_color=None, inversed=None, blink=None, framed=None, class_name=None) +Create new text render descriptior. +.sp +Both \fBfg\fP and \fBbg\fP can be specified as existing \fBColor\fP instance as well +as plain \fIstr\fP or \fIint\fP (for the details see \fI\%resolve_color()\fP). +.sp +.nf +.ft C +>>> Style(fg=\(aqgreen\(aq, bold=True) + +>>> Style(bg=0x0000ff) + +>>> Style(fg=\(aqDeepSkyBlue1\(aq, bg=\(aqgray3\(aq) + +.ft P +.fi +.sp +Attribute merging from \fBfallback\fP works this way: +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.IP \(bu 2 +If constructor argument is \fInot\fP empty (\fITrue\fP, \fIFalse\fP, \fBColor\fP +etc.), keep it as attribute value. +.IP \(bu 2 +If constructor argument is empty (\fINone\fP, \fBNOOP_COLOR\fP), take the +value from \fBfallback\fP\(aqs corresponding attribute. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +See \fI\%merge_fallback()\fP and \fI\%merge_overwrite()\fP methods and take the +differences into account. The method used in the constructor is the first one. +.sp +\fBIMPORTANT:\fP +.INDENT 7.0 +.INDENT 3.5 +Both empty (i.e., \fINone\fP) attributes of type \fBColor\fP after initialization +will be replaced with special constant \fBNOOP_COLOR\fP, which behaves like +there was no color defined, and at the same time makes it safer to work +with nullable color\-type variables. Merge methods are aware of this and +trear \fBNOOP_COLOR\fP as \fINone\fP\&. +.UNINDENT +.UNINDENT +.sp +\fBIMPORTANT:\fP +.INDENT 7.0 +.INDENT 3.5 +\fINone\fP and \fBNOOP_COLOR\fP are always treated as placeholders for fallback +values, i.e., they can\(aqt be used as \fIresetters\fP \-\- that\(aqs what \fBDEFAULT_COLOR\fP +is for. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBfallback\fP (\fI\%Style\fP) \-\- Copy empty attributes from speicifed fallback style. +See \fI\%merge_fallback()\fP\&. +.IP \(bu 2 +\fBfg\fP (\fICXT\fP) \-\- Foreground (=text) color. +.IP \(bu 2 +\fBbg\fP (\fICXT\fP) \-\- Background color. +.IP \(bu 2 +\fBfrozen\fP (\fIbool\fP) \-\- Set to \fITrue\fP to make an immutable instance. +.IP \(bu 2 +\fBbold\fP (\fIbool\fP) \-\- Bold or increased intensity. +.IP \(bu 2 +\fBdim\fP (\fIbool\fP) \-\- Faint, decreased intensity. +.IP \(bu 2 +\fBitalic\fP (\fIbool\fP) \-\- Italic. +.IP \(bu 2 +\fBunderlined\fP (\fIbool\fP) \-\- Underline. +.IP \(bu 2 +\fBoverlined\fP (\fIbool\fP) \-\- Overline. +.IP \(bu 2 +\fBcrosslined\fP (\fIbool\fP) \-\- Strikethrough. +.IP \(bu 2 +\fBdouble_underlined\fP (\fIbool\fP) \-\- Double underline. +.IP \(bu 2 +\fBcurly_underlined\fP (\fIbool\fP) \-\- Curly underline. +.IP \(bu 2 +\fBunderline_color\fP (\fICXT\fP) \-\- Underline color, if applicable. +.IP \(bu 2 +\fBinversed\fP (\fIbool\fP) \-\- Swap foreground and background colors. +.IP \(bu 2 +\fBblink\fP (\fIbool\fP) \-\- Blinking effect. +.IP \(bu 2 +\fBframed\fP (\fIbool\fP) \-\- Enclosed in a rectangle border. +.IP \(bu 2 +\fBclass_name\fP (\fIstr\fP) \-\- Custom class name for the element. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property fg: \fI\%RenderColor\fP +Foreground (i.e., text) color. Can be set as \fI\%CDT\fP or \fBColor\fP, +stored always as \fBColor\fP\&. +.UNINDENT +.INDENT 7.0 +.TP +.B property bg: \fI\%RenderColor\fP +Background color. Can be set as \fI\%CDT\fP or \fBColor\fP, stored always +as \fBColor\fP\&. +.UNINDENT +.INDENT 7.0 +.TP +.B property underline_color: \fI\%RenderColor\fP +Underline color. Can be set as \fI\%CDT\fP or \fBColor\fP, stored always +as \fBColor\fP\&. +.UNINDENT +.INDENT 7.0 +.TP +.B bold: bool +Bold or increased intensity (depending on terminal settings). +.UNINDENT +.INDENT 7.0 +.TP +.B dim: bool +Faint, decreased intensity. +.INDENT 7.0 +.INDENT 3.5 +.IP "Terminal\-based rendering" +.sp +Terminals apply this effect to foreground (=text) color, but when +it\(aqs used together with \fI\%inversed\fP, they usually make the background +darker instead. +.sp +Also note that usually it affects indexed colors only and has no effect +on RGB\-based ones (True Color mode). +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B italic: bool +Italic (some terminals may display it as inversed instead). +.UNINDENT +.INDENT 7.0 +.TP +.B underlined: bool +Underline. +.UNINDENT +.INDENT 7.0 +.TP +.B overlined: bool +Overline. +.UNINDENT +.INDENT 7.0 +.TP +.B crosslined: bool +Strikethrough. +.UNINDENT +.INDENT 7.0 +.TP +.B double_underlined: bool +Double underline. +.UNINDENT +.INDENT 7.0 +.TP +.B curly_underlined: bool +Curly underline. +.UNINDENT +.INDENT 7.0 +.TP +.B inversed: bool +Swap foreground and background colors. When inversed effect is active, +changing the background color will actually change the text color, and +vice versa. +.UNINDENT +.INDENT 7.0 +.TP +.B blink: bool +Blinking effect. Supported by a limited set of \fI\%renderers\fP\&. +.UNINDENT +.INDENT 7.0 +.TP +.B framed: bool +Add a rectangular border around the text; the border color is equal to +the text color. Supported by a limited set of \fI\%renderers\fP and +(even more) limited amount of terminal emulators. +.UNINDENT +.INDENT 7.0 +.TP +.B class_name: str +Arbitary string used by some \fI\%renderers\fP, e.g. by \(ga +\fBHtmlRenderer\(ga\fP, which will include the value of this property to an output +element class list. This property is not inheritable. +.UNINDENT +.INDENT 7.0 +.TP +.B clone(frozen=False) +Make a copy of the instance. Note that a copy is mutable by default +even if an original was frozen. +.INDENT 7.0 +.TP +.B Parameters +\fBfrozen\fP \-\- Set to \fITrue\fP to make an immutable instance. +.TP +.B Return type +\fI\%Style\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B autopick_fg() +Pick \fBfg_color\fP depending on \fBbg_color\fP\&. Set \fBfg_color\fP to +either 3% gray (almost black) if background is bright, or to 80% gray +(bright gray) if it is dark. If background is None, do nothing. +.INDENT 7.0 +.INDENT 3.5 +.SS Todo +.sp +check if there is a better algorithm, +because current thinks text on #000080 should be black +.UNINDENT +.UNINDENT +.sp +Modifies the instance in\-place and returns it as well (for chained calls). +.INDENT 7.0 +.TP +.B Return type +\fI\%Style\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B flip() +Swap foreground color and background color. Modifies the instance in\-place +and returns it as well (for chained calls). +.INDENT 7.0 +.TP +.B Return type +\fI\%Style\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B merge(mode, other) +Method that allows specifying merging mode as an argument. Initially +designed for template substitutions done by \fBTemplateEngine\fP\&. Invokes +either of these (depending on \fBmode\fP value): +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.IP \(bu 2 +\fI\%merge_fallback()\fP +.IP \(bu 2 +\fI\%merge_overwrite()\fP +.IP \(bu 2 +\fI\%merge_replace()\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBmode\fP (\fI\%MergeMode\fP) \-\- Merge mode to use. +.IP \(bu 2 +\fBother\fP (\fI\%Style\fP) \-\- Style to merge the attributes with. +.UNINDENT +.TP +.B Return type +\fI\%Style\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B merge_fallback(fallback) +Merge current style with specified \fBfallback\fP \fI\%style\fP, following +the rules: +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.IP 1. 3 +\fBself\fP attribute value is in priority, i.e. when both \fBself\fP and +\fBfallback\fP attributes are defined, keep \fBself\fP value. +.IP 2. 3 +If \fBself\fP attribute is \fINone\fP, take the value from \fBfallback\fP\(aqs +corresponding attribute, and vice versa. +.IP 3. 3 +If both attribute values are \fINone\fP, keep the \fINone\fP\&. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +All attributes corresponding to constructor arguments except \fBfallback\fP +are subject to merging. \fBNOOP_COLOR\fP is treated like \fINone\fP (default for \fI\%fg\fP +and \fI\%bg\fP). +.sp +Modifies the instance in\-place and returns it as well (for chained calls). +.sp +Merging different values in fallback mode +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C + FALLBACK BASE(SELF) RESULT + +\-\-\-\-\-\-\-+ +\-\-\-\-\-\-+ +\-\-\-\-\-\-+ +ATTR\-1 | False \-\-Ø | True ===>| True | BASE val is in priority +ATTR\-2 | True \-\-\-\-\-| None |\-\->| True | no BASE val, taking FALLBACK val +ATTR\-3 | None | | True ===>| True | BASE val is in priority +ATTR\-4 | None | | None | | None | no vals, keeping unset + +\-\-\-\-\-\-\-+ +\-\-\-\-\-\-+ +\-\-\-\-\-\-+ +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +\fBSEE ALSO:\fP +.INDENT 7.0 +.INDENT 3.5 +\fI\%merge_styles\fP for the examples. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +\fBfallback\fP (\fI\%Style\fP) \-\- Style to merge the attributes with. +.TP +.B Return type +\fI\%Style\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B merge_overwrite(overwrite) +Merge current style with specified \fBoverwrite\fP \fI\%style\fP, following +the rules: +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.IP 1. 3 +\fBoverwrite\fP attribute value is in priority, i.e. when both \fBself\fP +and \fBoverwrite\fP attributes are defined, replace \fBself\fP value with +\fBoverwrite\fP one (in contrast to \fI\%merge_fallback()\fP, which works the +opposite way). +.IP 2. 3 +If \fBself\fP attribute is \fINone\fP, take the value from \fBoverwrite\fP\(aqs +corresponding attribute, and vice versa. +.IP 3. 3 +If both attribute values are \fINone\fP, keep the \fINone\fP\&. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +All attributes corresponding to constructor arguments except \fBfallback\fP +are subject to merging. \fBNOOP_COLOR\fP is treated like \fINone\fP (default for \fI\%fg\fP +and \fI\%bg\fP). +.sp +Modifies the instance in\-place and returns it as well (for chained calls). +.sp +Merging different values in overwrite mode +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C + BASE(SELF) OVERWRITE RESULT + +\-\-\-\-\-\-+ +\-\-\-\-\-\-\-+ +\-\-\-\-\-\-\-+ +ATTR\-1 | True ==Ø | False \-\-\->| False | OVERWRITE val is in priority +ATTR\-2 | None | | True \-\-\-\->| True | OVERWRITE val is in priority +ATTR\-3 | True ====| None |==>| True | no OVERWRITE val, keeping BASE val +ATTR\-4 | None | | None | | None | no vals, keeping unset + +\-\-\-\-\-\-+ +\-\-\-\-\-\-\-+ +\-\-\-\-\-\-\-+ +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +\fBSEE ALSO:\fP +.INDENT 7.0 +.INDENT 3.5 +\fI\%merge_styles\fP for the examples. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +\fBoverwrite\fP (\fI\%Style\fP) \-\- Style to merge the attributes with. +.TP +.B Return type +\fI\%Style\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B merge_replace(replacement) +Not an actual \(dqmerge\(dq: discard all the attributes of the current +instance and replace them with the values from \fBreplacement\fP\&. Generally +speaking, it makes sense only in \fBTemplateEngine\fP context, as style +management using the template tags is quite limited, while there are +far more elegant ways to do the same from the regular python code. +.sp +Modifies the instance in\-place and returns it as well (for chained calls). +.sp +Merging different values in replace mode +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C + BASE(SELF) REPLACE RESULT + +\-\-\-\-\-\-+ +\-\-\-\-\-\-\-+ +\-\-\-\-\-\-\-+ +ATTR\-1 | False =Ø | True \-\-\->| True | REPLACE val is in priority +ATTR\-2 | True ==Ø | False \-\->| False | REPLACE val is in priority +ATTR\-3 | None | | False \-\->| False | REPLACE val is in priority +ATTR\-4 | True ==Ø | None \-\-\->| None | ... even when it is unset + +\-\-\-\-\-\-+ +\-\-\-\-\-\-\-+ +\-\-\-\-\-\-\-+ +.ft P +.fi +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +\fBreplacement\fP (\fI\%Style\fP) \-\- Style to merge the attributes with. +.TP +.B Return type +\fI\%Style\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.style.FrozenStyle(*args, **kwargs) +Bases: \fI\%Style\fP +.INDENT 7.0 +.TP +.B autopick_fg() +Pick \fBfg_color\fP depending on \fBbg_color\fP\&. Set \fBfg_color\fP to +either 3% gray (almost black) if background is bright, or to 80% gray +(bright gray) if it is dark. If background is None, do nothing. +.INDENT 7.0 +.INDENT 3.5 +.SS Todo +.sp +check if there is a better algorithm, +because current thinks text on #000080 should be black +.UNINDENT +.UNINDENT +.sp +Modifies the instance in\-place and returns it as well (for chained calls). +.INDENT 7.0 +.TP +.B Return type +\fI\%Style\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property bg: \fI\%RenderColor\fP +Background color. Can be set as \fI\%CDT\fP or \fBColor\fP, stored always +as \fBColor\fP\&. +.UNINDENT +.INDENT 7.0 +.TP +.B clone(frozen=False) +Make a copy of the instance. Note that a copy is mutable by default +even if an original was frozen. +.INDENT 7.0 +.TP +.B Parameters +\fBfrozen\fP \-\- Set to \fITrue\fP to make an immutable instance. +.TP +.B Return type +\fI\%Style\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property fg: \fI\%RenderColor\fP +Foreground (i.e., text) color. Can be set as \fI\%CDT\fP or \fBColor\fP, +stored always as \fBColor\fP\&. +.UNINDENT +.INDENT 7.0 +.TP +.B flip() +Swap foreground color and background color. Modifies the instance in\-place +and returns it as well (for chained calls). +.INDENT 7.0 +.TP +.B Return type +\fI\%Style\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B merge(mode, other) +Method that allows specifying merging mode as an argument. Initially +designed for template substitutions done by \fBTemplateEngine\fP\&. Invokes +either of these (depending on \fBmode\fP value): +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.IP \(bu 2 +\fI\%merge_fallback()\fP +.IP \(bu 2 +\fI\%merge_overwrite()\fP +.IP \(bu 2 +\fI\%merge_replace()\fP +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBmode\fP (\fI\%MergeMode\fP) \-\- Merge mode to use. +.IP \(bu 2 +\fBother\fP (\fI\%Style\fP) \-\- Style to merge the attributes with. +.UNINDENT +.TP +.B Return type +\fI\%Style\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B merge_fallback(fallback) +Merge current style with specified \fBfallback\fP \fI\%style\fP, following +the rules: +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.IP 1. 3 +\fBself\fP attribute value is in priority, i.e. when both \fBself\fP and +\fBfallback\fP attributes are defined, keep \fBself\fP value. +.IP 2. 3 +If \fBself\fP attribute is \fINone\fP, take the value from \fBfallback\fP\(aqs +corresponding attribute, and vice versa. +.IP 3. 3 +If both attribute values are \fINone\fP, keep the \fINone\fP\&. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +All attributes corresponding to constructor arguments except \fBfallback\fP +are subject to merging. \fBNOOP_COLOR\fP is treated like \fINone\fP (default for \fI\%fg\fP +and \fI\%bg\fP). +.sp +Modifies the instance in\-place and returns it as well (for chained calls). +.sp +Merging different values in fallback mode +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C + FALLBACK BASE(SELF) RESULT + +\-\-\-\-\-\-\-+ +\-\-\-\-\-\-+ +\-\-\-\-\-\-+ +ATTR\-1 | False \-\-Ø | True ===>| True | BASE val is in priority +ATTR\-2 | True \-\-\-\-\-| None |\-\->| True | no BASE val, taking FALLBACK val +ATTR\-3 | None | | True ===>| True | BASE val is in priority +ATTR\-4 | None | | None | | None | no vals, keeping unset + +\-\-\-\-\-\-\-+ +\-\-\-\-\-\-+ +\-\-\-\-\-\-+ +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +\fBSEE ALSO:\fP +.INDENT 7.0 +.INDENT 3.5 +\fI\%merge_styles\fP for the examples. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +\fBfallback\fP (\fI\%Style\fP) \-\- Style to merge the attributes with. +.TP +.B Return type +\fI\%Style\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B merge_overwrite(overwrite) +Merge current style with specified \fBoverwrite\fP \fI\%style\fP, following +the rules: +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.IP 1. 3 +\fBoverwrite\fP attribute value is in priority, i.e. when both \fBself\fP +and \fBoverwrite\fP attributes are defined, replace \fBself\fP value with +\fBoverwrite\fP one (in contrast to \fI\%merge_fallback()\fP, which works the +opposite way). +.IP 2. 3 +If \fBself\fP attribute is \fINone\fP, take the value from \fBoverwrite\fP\(aqs +corresponding attribute, and vice versa. +.IP 3. 3 +If both attribute values are \fINone\fP, keep the \fINone\fP\&. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +All attributes corresponding to constructor arguments except \fBfallback\fP +are subject to merging. \fBNOOP_COLOR\fP is treated like \fINone\fP (default for \fI\%fg\fP +and \fI\%bg\fP). +.sp +Modifies the instance in\-place and returns it as well (for chained calls). +.sp +Merging different values in overwrite mode +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C + BASE(SELF) OVERWRITE RESULT + +\-\-\-\-\-\-+ +\-\-\-\-\-\-\-+ +\-\-\-\-\-\-\-+ +ATTR\-1 | True ==Ø | False \-\-\->| False | OVERWRITE val is in priority +ATTR\-2 | None | | True \-\-\-\->| True | OVERWRITE val is in priority +ATTR\-3 | True ====| None |==>| True | no OVERWRITE val, keeping BASE val +ATTR\-4 | None | | None | | None | no vals, keeping unset + +\-\-\-\-\-\-+ +\-\-\-\-\-\-\-+ +\-\-\-\-\-\-\-+ +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +\fBSEE ALSO:\fP +.INDENT 7.0 +.INDENT 3.5 +\fI\%merge_styles\fP for the examples. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +\fBoverwrite\fP (\fI\%Style\fP) \-\- Style to merge the attributes with. +.TP +.B Return type +\fI\%Style\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B merge_replace(replacement) +Not an actual \(dqmerge\(dq: discard all the attributes of the current +instance and replace them with the values from \fBreplacement\fP\&. Generally +speaking, it makes sense only in \fBTemplateEngine\fP context, as style +management using the template tags is quite limited, while there are +far more elegant ways to do the same from the regular python code. +.sp +Modifies the instance in\-place and returns it as well (for chained calls). +.sp +Merging different values in replace mode +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C + BASE(SELF) REPLACE RESULT + +\-\-\-\-\-\-+ +\-\-\-\-\-\-\-+ +\-\-\-\-\-\-\-+ +ATTR\-1 | False =Ø | True \-\-\->| True | REPLACE val is in priority +ATTR\-2 | True ==Ø | False \-\->| False | REPLACE val is in priority +ATTR\-3 | None | | False \-\->| False | REPLACE val is in priority +ATTR\-4 | True ==Ø | None \-\-\->| None | ... even when it is unset + +\-\-\-\-\-\-+ +\-\-\-\-\-\-\-+ +\-\-\-\-\-\-\-+ +.ft P +.fi +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +\fBreplacement\fP (\fI\%Style\fP) \-\- Style to merge the attributes with. +.TP +.B Return type +\fI\%Style\fP +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property underline_color: \fI\%RenderColor\fP +Underline color. Can be set as \fI\%CDT\fP or \fBColor\fP, stored always +as \fBColor\fP\&. +.UNINDENT +.INDENT 7.0 +.TP +.B bold: bool +Bold or increased intensity (depending on terminal settings). +.UNINDENT +.INDENT 7.0 +.TP +.B dim: bool +Faint, decreased intensity. +.INDENT 7.0 +.INDENT 3.5 +.IP "Terminal\-based rendering" +.sp +Terminals apply this effect to foreground (=text) color, but when +it\(aqs used together with \fI\%inversed\fP, they usually make the background +darker instead. +.sp +Also note that usually it affects indexed colors only and has no effect +on RGB\-based ones (True Color mode). +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B italic: bool +Italic (some terminals may display it as inversed instead). +.UNINDENT +.INDENT 7.0 +.TP +.B underlined: bool +Underline. +.UNINDENT +.INDENT 7.0 +.TP +.B overlined: bool +Overline. +.UNINDENT +.INDENT 7.0 +.TP +.B crosslined: bool +Strikethrough. +.UNINDENT +.INDENT 7.0 +.TP +.B double_underlined: bool +Double underline. +.UNINDENT +.INDENT 7.0 +.TP +.B curly_underlined: bool +Curly underline. +.UNINDENT +.INDENT 7.0 +.TP +.B inversed: bool +Swap foreground and background colors. When inversed effect is active, +changing the background color will actually change the text color, and +vice versa. +.UNINDENT +.INDENT 7.0 +.TP +.B blink: bool +Blinking effect. Supported by a limited set of \fI\%renderers\fP\&. +.UNINDENT +.INDENT 7.0 +.TP +.B framed: bool +Add a rectangular border around the text; the border color is equal to +the text color. Supported by a limited set of \fI\%renderers\fP and +(even more) limited amount of terminal emulators. +.UNINDENT +.INDENT 7.0 +.TP +.B class_name: str +Arbitary string used by some \fI\%renderers\fP, e.g. by \(ga +\fBHtmlRenderer\(ga\fP, which will include the value of this property to an output +element class list. This property is not inheritable. +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.style.NOOP_STYLE = <*_NoOpStyle[]> +Special style passing the text through without any modifications. +.sp +\fBIMPORTANT:\fP +.INDENT 7.0 +.INDENT 3.5 +Casting to \fIbool\fP results in \fBFalse\fP for all \fBNOOP\fP instances in the +library (\fI\%NOOP_SEQ\fP, \fBNOOP_COLOR\fP and \fI\%NOOP_STYLE\fP). This is intended. +.UNINDENT +.UNINDENT +.sp +This class is immutable, i.e. \fI\%LogicError\fP will be raised upon an attempt to +modify any of its attributes, which could potentially lead to schrödinbugs: +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +st1.merge_fallback(Style(bold=True), [Style(italic=False)]) +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +If \fBst1\fP is a regular style instance, it\(aqs safe to call self\-modifying methods, +but if it happens to be a \fI\%NOOP_STYLE\fP, the statement could have been alter the +internal state of the style, which is referenced all over the library, which could +lead to the changes appearing in an unexpected places. +.sp +To be safe from this outcome one could merge styles via frontend method \fI\%merge_styles\fP, +which always makes a copy of \fBorigin\fP argument and thus cannot lead to such results. +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.style.Styles +Some ready\-to\-use styles which also can be used as examples. All instances +are immutable. +.INDENT 7.0 +.TP +.B WARNING = <*Style[yellow]> +.UNINDENT +.INDENT 7.0 +.TP +.B WARNING_LABEL = <*Style[yellow +BOLD]> +.UNINDENT +.INDENT 7.0 +.TP +.B WARNING_ACCENT = <*Style[hi\-yellow]> +.UNINDENT +.INDENT 7.0 +.TP +.B ERROR = <*Style[red]> +.UNINDENT +.INDENT 7.0 +.TP +.B ERROR_LABEL = <*Style[red +BOLD]> +.UNINDENT +.INDENT 7.0 +.TP +.B ERROR_ACCENT = <*Style[hi\-red]> +.UNINDENT +.INDENT 7.0 +.TP +.B CRITICAL = <*Style[hi\-white|x160]> +.UNINDENT +.INDENT 7.0 +.TP +.B CRITICAL_LABEL = <*Style[hi\-white|x160 +BOLD]> +.UNINDENT +.INDENT 7.0 +.TP +.B CRITICAL_ACCENT = <*Style[hi\-white|x160 +BLIN +BOLD]> +.UNINDENT +.INDENT 7.0 +.TP +.B INCONSISTENCY = <*Style[hi\-yellow|x160]> +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.style.make_style(fmt=None) +General \fI\%Style\fP constructor. Accepts a variety of argument types: +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.IP \(bu 2 +.INDENT 2.0 +.TP +.B \fI\%CDT\fP (\fIstr\fP or \fIint\fP) +This argument type implies the creation of basic \fI\%Style\fP +with the only attribute set being \fI\%fg\fP (i.e., text color). For the +details on color resolving see \fI\%resolve_color()\fP\&. +.UNINDENT +.IP \(bu 2 +.INDENT 2.0 +.TP +.B \fI\%Style\fP +Existing style instance. Return it as is. +.UNINDENT +.IP \(bu 2 +.INDENT 2.0 +.TP +.B \fINone\fP +Return \fI\%NOOP_STYLE\fP\&. +.UNINDENT +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +\fBfmt\fP (\fIFT\fP) \-\- See \fI\%FT\fP\&. +.TP +.B Return type +\fI\%Style\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.style.merge_styles(origin=<*_NoOpStyle[]>, *, fallbacks=(), overwrites=()) +Bulk style merging method. First merge \fBfallbacks\fP \fBstyles\fP with the +\fBorigin\fP in the same order they are iterated, using \fI\%merge_fallback()\fP algorithm; +then do the same for \fBoverwrites\fP styles, but using \fI\%merge_overwrite()\fP merge +method. +.sp +\fBIMPORTANT:\fP +.INDENT 7.0 +.INDENT 3.5 +The original \fBorigin\fP is left untouched, as all the operations are performed on +its clone. To make things clearer the name of the argument differs from the ones +that are modified in\-place (\fBbase\fP and \fBorigin\fP). +.UNINDENT +.UNINDENT +.sp +Dual mode merge diagram +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C + +\-\-\-\-\-+ +\-\-\-\-\-+ + >\-\-\-\->\-\-\-\->\-\-\-\-\->\-\-\-\->\-\-\-\-\-\-\-> >\-\-\-\-\-\-\-(B)\-update\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-> | + | | | | | | | | R | + | | | | | | B >=>Ø [0]>\-[1]>\-[2]> .. \-[n]> | E | +[0]>\-[1]>\-[2]>\- .. >\-[n]>\->Ø | A >=>Ø | | | | | S | + | | >\- .. \-\-\-\-\-\-\->Ø | S >=>Ø >\-\-\-(D)\-update\-\-\-\-\->\-\-\-> U | + | >\-\-\-\-\- .. \-\-\-\-\-\-\->Ø | E | (C) drop | L | + >\-\-\-\-\-\-\-\-\-\- .. \-\-\-\-\-\-\->Ø | |=================(E)=keep========> T | + (A) | | | | + FALLBACKS drop +\-\-\-\-\-+ OVERWRITES +\-\-\-\-\-+ +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +The key actions are marked with (\fBA\fP) to (\fBE\fP) letters. In reality the algorithm +works in slightly different order, but the exact scheme would be less illustrative. +.INDENT 7.0 +.TP +.B (A),(B) +Iterate \fBfallback\fP styles one by one; discard all the attributes of a +current \fBfallback\fP style, that are already set in \fBorigin\fP style +(i.e., that are not \fINones\fP). Update all \fBorigin\fP style empty attributes +with corresponding \fBfallback\fP values, if they exist and are not empty. +Repeat these steps for the next \fBfallback\fP in the list, until the list +is empty. +.sp +Fallback merge algorithm example №1 +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +>>> origin = Style(fg=\(aqred\(aq) +\&... +>>> fallbacks = [Style(fg=\(aqblue\(aq), Style(bold=True), Style(bold=False)] +\&... +>>> merge_styles(origin, fallbacks=fallbacks) + +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +In the example above: +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.IP \(bu 2 +the first fallback will be ignored, as \fI\%fg\fP is already set; +.IP \(bu 2 +the second fallback will be applied (\fBorigin\fP style will now have \fI\%bold\fP +set to \fITrue\fP; +.IP \(bu 2 +which will make the handler ignore third fallback completely; if third +fallback was encountered earlier than the 2nd one, \fBorigin\fP \fI\%bold\fP attribute +would have been set to \fIFalse\fP, but alas. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +\fBNOTE:\fP +.INDENT 7.0 +.INDENT 3.5 +Fallbacks allow to build complex style conditions, e.g. take a look into +\fI\%Highlighter.colorize()\fP method: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +int_st = merge_styles(st, fallbacks=[Style(bold=True)]) +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +Instead of using \fBStyle(st, bold=True)\fP the merging algorithm is invoked. +This changes the logic of \(dqbold\(dq attribute application \-\- if there is a +necessity to explicitly forbid bold text at origin/parent level, one could write: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +STYLE_NUL = Style(STYLE_DEFAULT, cv.GRAY, bold=False) +STYLE_PRC = Style(STYLE_DEFAULT, cv.MAGENTA) +STYLE_KIL = Style(STYLE_DEFAULT, cv.BLUE) +\&... +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +As you can see, resulting \fBint_st\fP will be bold for all styles other +than \fBSTYLE_NUL\fP\&. +.sp +Fallback merge algorithm example №2 +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +>>> merge_styles(Style(fg=cv.BLUE), fallbacks=[Style(bold=True)]) + +>>> merge_styles(Style(fg=cv.GRAY, bold=False), fallbacks=[Style(bold=True)]) + +.ft P +.fi +.UNINDENT +.UNINDENT +.UNINDENT +.UNINDENT +.TP +.B (C),(D),(E) +Iterate \fBoverwrite\fP styles one by one; discard all the attributes of a \fBorigin\fP +style that have a non\-empty counterpart in \fBoverwrite\fP style, and put +corresponding \fBoverwrite\fP attribute values instead of them. Keep \fBorigin\fP +attribute values that have no counterpart in current \fBoverwrite\fP style (i.e., +if attribute value is \fINone\fP). Then pick next \fBoverwrite\fP style from the input +list and repeat all these steps. +.sp +Overwrite merge algorithm example +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +>>> origin = Style(fg=\(aqred\(aq) +\&... +>>> overwrites = [Style(fg=\(aqblue\(aq), Style(bold=True), Style(bold=False)] +\&... +>>> merge_styles(origin, overwrites=overwrites) + +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +In the example above all the \fBoverwrites\fP will be applied in order they were +put into \fIlist\fP, and the result attribute values are equal to the last +encountered non\-empty values in \fBoverwrites\fP list. +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBorigin\fP (\fI\%Style\fP) \-\- Initial style, or the source of attributes. +.IP \(bu 2 +\fBfallbacks\fP (\fIIterable\fP\fI[\fP\fI\%Style\fP\fI]\fP) \-\- List of styles to be used as a backup attribute storage, or. +in other words, to be \(dqmerged up\(dq with the origin; affects the unset +attributes of the current style and replaces these values with its +own. Uses \fI\%merge_fallback()\fP merging strategy. +.IP \(bu 2 +\fBoverwrites\fP (\fIIterable\fP\fI[\fP\fI\%Style\fP\fI]\fP) \-\- List of styles to be used as attribute storage force override +regardless of actual \fBorigin\fP attribute valuse (so called +\(dqmerging down\(dq with the origin). +.UNINDENT +.TP +.B Returns +Clone of \fBorigin\fP style with all specified styles merged into. +.TP +.B Return type +\fI\%Style\fP +.UNINDENT +.UNINDENT +.SS pytermor.template +.sp +Functions +.TS +center; +|l|l|. +_ +T{ +\fBrender\fP(tpl, renderer) +T} T{ +T} +_ +T{ +\fBsubstitute\fP(tpl) +T} T{ +T} +_ +.TE +.sp +Classes +.TS +center; +|l|l|. +_ +T{ +\fBTemplateEngine\fP([custom_styles, global_style]) +T} T{ +T} +_ +.TE +.SS pytermor.term +.sp +A +.sp +Module Attributes +.TS +center; +|l|l|. +_ +T{ +\fI\%RCP_REGEX\fP +T} T{ +Regular expression for RCP sequence parsing. +T} +_ +.TE +.sp +Functions +.TS +center; +|l|l|. +_ +T{ +\fI\%compose_clear_line_fill_bg\fP(basis[, line, column]) +T} T{ +.INDENT 0.0 +.TP +.B param basis +.UNINDENT +T} +_ +T{ +\fI\%compose_hyperlink\fP(url[, label]) +T} T{ +Syntax: \fB(OSC 8 ; ;) (url) (ST) (label) (OSC 8 ; ;) (ST)\fP, where \fI\%OSC\fP is \fBESC ]\fP\&. +T} +_ +T{ +\fI\%confirm\fP([attempts, default, keymap, prompt, ...]) +T} T{ +Ensure the next action is manually confirmed by user. +T} +_ +T{ +\fI\%decompose_report_cursor_position\fP(string) +T} T{ +Parse RCP sequence that usually comes from a terminal as a response to \fI\%QCP\fP sequence and contains a cursor\(aqs current line and column. +T} +_ +T{ +\fI\%get_char_width\fP(char, block) +T} T{ +General\-purpose method for getting width of a character in terminal columns. +T} +_ +T{ +\fI\%get_preferable_wrap_width\fP([force_width]) +T} T{ +Return preferable terminal width for comfort reading of wrapped text (max=120). +T} +_ +T{ +\fI\%get_terminal_width\fP([fallback, pad]) +T} T{ +Return current terminal width with an optional \(dqsafety buffer\(dq, which ensures that no unwanted line wrapping will happen. +T} +_ +T{ +\fI\%guess_char_width\fP(c) +T} T{ +Determine how many columns are needed to display a character in a terminal. +T} +_ +T{ +\fI\%make_clear_display\fP() +T} T{ +Create ED sequence that clears an entire screen. +T} +_ +T{ +\fI\%make_clear_display_after_cursor\fP() +T} T{ +Create ED sequence that clears a part of the screen from cursor to the end of the screen. +T} +_ +T{ +\fI\%make_clear_display_before_cursor\fP() +T} T{ +Create ED sequence that clears a part of the screen from cursor to the beginning of the screen. +T} +_ +T{ +\fI\%make_clear_history\fP() +T} T{ +Create ED sequence that clears history, i.e., invisible lines on the top that can be scrolled back down. +T} +_ +T{ +\fI\%make_clear_line\fP() +T} T{ +Create EL sequence that clears an entire line at the cursor position. +T} +_ +T{ +\fI\%make_clear_line_after_cursor\fP() +T} T{ +Create EL sequence that clears a part of the line from cursor to the end of the same line. +T} +_ +T{ +\fI\%make_clear_line_before_cursor\fP() +T} T{ +Create EL sequence that clears a part of the line from cursor to the beginning of the same line. +T} +_ +T{ +\fI\%make_color_256\fP(code[, target]) +T} T{ +Wrapper for creation of \fI\%SequenceSGR\fP that sets foreground (or background) to one of 256\-color palette value.: +T} +_ +T{ +\fI\%make_color_rgb\fP(r, g, b[, target]) +T} T{ +Wrapper for creation of \fI\%SequenceSGR\fP operating in True Color mode (16M). Valid values for \fBr\fP, \fBg\fP and \fBb\fP are in range of [0; 255]. This range linearly translates into [0x00; 0xFF] for each channel. The result value is composed as \(dq#RRGGBB\(dq. For example, a sequence with color of #ff3300 can be created with::. +T} +_ +T{ +\fI\%make_disable_alt_screen_buffer\fP() +T} T{ +C +T} +_ +T{ +\fI\%make_enable_alt_screen_buffer\fP() +T} T{ +C +T} +_ +T{ +\fI\%make_erase_in_display\fP([mode]) +T} T{ +Create ED sequence that clears a part of the screen or the entire screen. +T} +_ +T{ +\fI\%make_erase_in_line\fP([mode]) +T} T{ +Create EL sequence that clears a part of the line or the entire line at the cursor position. +T} +_ +T{ +\fI\%make_hide_cursor\fP() +T} T{ +C +T} +_ +T{ +\fI\%make_hyperlink\fP() +T} T{ +Create a hyperlink in the text \fI(supported by limited amount of terminals)\fP\&. +T} +_ +T{ +\fI\%make_move_cursor_down\fP([lines]) +T} T{ +Create CUD sequence that moves the cursor down by specified amount of \fBlines\fP\&. +T} +_ +T{ +\fI\%make_move_cursor_down_to_start\fP([lines]) +T} T{ +Create CNL sequence that moves the cursor to the beginning of the line and down by specified amount of \fBlines\fP\&. +T} +_ +T{ +\fI\%make_move_cursor_left\fP([columns]) +T} T{ +Create CUB sequence that moves the cursor left by specified amount of \fBcolumns\fP\&. +T} +_ +T{ +\fI\%make_move_cursor_right\fP([columns]) +T} T{ +Create CUF sequence that moves the cursor right by specified amount of \fBcolumns\fP\&. +T} +_ +T{ +\fI\%make_move_cursor_up\fP([lines]) +T} T{ +Create CUU sequence that moves the cursor up by specified amount of \fBlines\fP\&. +T} +_ +T{ +\fI\%make_move_cursor_up_to_start\fP([lines]) +T} T{ +Create CPL sequence that moves the cursor to the beginning of the line and up by specified amount of \fBlines\fP\&. +T} +_ +T{ +\fI\%make_query_cursor_position\fP() +T} T{ +Create QCP sequence that requests an output device to respond with a structure containing current cursor coordinates (\fBRCP\fP). +T} +_ +T{ +\fI\%make_reset_cursor\fP() +T} T{ +Create CUP sequence without params, which moves the cursor to top left corner of the screen. +T} +_ +T{ +\fI\%make_restore_cursor_position\fP() +T} T{ +.INDENT 0.0 +.TP +.B example +\fBESC 8\fP +.UNINDENT +T} +_ +T{ +\fI\%make_restore_screen\fP() +T} T{ +C +T} +_ +T{ +\fI\%make_save_cursor_position\fP() +T} T{ +.INDENT 0.0 +.TP +.B example +\fBESC 7\fP +.UNINDENT +T} +_ +T{ +\fI\%make_save_screen\fP() +T} T{ +C +T} +_ +T{ +\fI\%make_set_cursor\fP([line, column]) +T} T{ +Create CUP sequence that moves the cursor to specified amount \fBline\fP and \fBcolumn\fP\&. +T} +_ +T{ +\fI\%make_set_cursor_column\fP([column]) +T} T{ +Create CHA sequence that sets cursor horizontal position to \fBcolumn\fP\&. +T} +_ +T{ +\fI\%make_set_cursor_line\fP([line]) +T} T{ +Create VPA sequence that sets cursor vertical position to \fBline\fP\&. +T} +_ +T{ +\fI\%make_show_cursor\fP() +T} T{ +C +T} +_ +T{ +\fI\%measure_char_width\fP(char[, clear_after]) +T} T{ +Low\-level function that returns the exact character width in terminal columns. +T} +_ +T{ +\fI\%wait_key\fP([block]) +T} T{ +Wait for a key press on the console and return it. +T} +_ +.TE +.INDENT 0.0 +.TP +.B pytermor.term.RCP_REGEX +Regular expression for RCP sequence parsing. +See \fI\%decompose_report_cursor_position()\fP\&. +.INDENT 7.0 +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_color_256(code, target=ColorTarget.FG) +Wrapper for creation of \fI\%SequenceSGR\fP that sets foreground +(or background) to one of 256\-color palette value.: +.sp +.nf +.ft C +>>> make_color_256(141) + +.ft P +.fi +.sp +\fBSEE ALSO:\fP +.INDENT 7.0 +.INDENT 3.5 +\fI\%Color256\fP class. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBcode\fP (\fIint\fP) \-\- Index of the color in the palette, 0 \-\- 255. +.IP \(bu 2 +\fBtarget\fP (\fI\%ColorTarget\fP) \-\- +.UNINDENT +.TP +.B Example +\fBESC [38;5;141m\fP +.TP +.B Return type +\fI\%SequenceSGR\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_color_rgb(r, g, b, target=ColorTarget.FG) +Wrapper for creation of \fI\%SequenceSGR\fP operating in True Color mode (16M). +Valid values for \fBr\fP, \fBg\fP and \fBb\fP are in range of [0; 255]. This range +linearly translates into [0x00; 0xFF] for each channel. The result +value is composed as \(dq#RRGGBB\(dq. For example, a sequence with color of +#ff3300 can be created with: +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +>>> make_color_rgb(255, 51, 0) + +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +\fBSEE ALSO:\fP +.INDENT 7.0 +.INDENT 3.5 +\fI\%ColorRGB\fP class. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBr\fP (\fIint\fP) \-\- Red channel value, 0 \-\- 255. +.IP \(bu 2 +\fBg\fP (\fIint\fP) \-\- Blue channel value, 0 \-\- 255. +.IP \(bu 2 +\fBb\fP (\fIint\fP) \-\- Green channel value, 0 \-\- 255. +.IP \(bu 2 +\fBtarget\fP (\fI\%ColorTarget\fP) \-\- +.UNINDENT +.TP +.B Example +\fBESC [38;2;255;51;0m\fP +.TP +.B Return type +\fI\%SequenceSGR\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_reset_cursor() +Create CUP sequence without params, which moves +the cursor to top left corner of the screen. See \fI\%make_set_cursor()\fP\&. +.INDENT 7.0 +.TP +.B Example +\fBESC [H\fP +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_set_cursor(line=1, column=1) +Create CUP sequence that moves the cursor to +specified amount \fBline\fP and \fBcolumn\fP\&. The values are 1\-based, i.e. (1; 1) +is top left corner of the screen. +.sp +\fBNOTE:\fP +.INDENT 7.0 +.INDENT 3.5 +Both sequence params are optional and defaults to 1 if omitted, e.g. +\fBESC [;3H\fP is effectively \fBESC [1;3H\fP, and \fBESC [4H\fP is the +same as \fBESC [4;H\fP or \fBESC [4;1H\fP\&. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Example +\fBESC [9;15H\fP +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_move_cursor_up(lines=1) +Create CUU sequence that moves the cursor up by +specified amount of \fBlines\fP\&. If the cursor is already at the top of the +screen, this has no effect. +.INDENT 7.0 +.TP +.B Example +\fBESC [2A\fP +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_move_cursor_down(lines=1) +Create CUD sequence that moves the cursor down by +specified amount of \fBlines\fP\&. If the cursor is already at the bottom of the +screen, this has no effect. +.INDENT 7.0 +.TP +.B Example +\fBESC [3B\fP +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_move_cursor_left(columns=1) +Create CUB sequence that moves the cursor left by +specified amount of \fBcolumns\fP\&. If the cursor is already at the left edge of +the screen, this has no effect. +.INDENT 7.0 +.TP +.B Example +\fBESC [4D\fP +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_move_cursor_right(columns=1) +Create CUF sequence that moves the cursor right by +specified amount of \fBcolumns\fP\&. If the cursor is already at the right edge +of the screen, this has no effect. +.INDENT 7.0 +.TP +.B Example +\fBESC [5C\fP +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_move_cursor_up_to_start(lines=1) +Create CPL sequence that moves the cursor +to the beginning of the line and up by specified amount of \fBlines\fP\&. +.INDENT 7.0 +.TP +.B Example +\fBESC [2F\fP +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_move_cursor_down_to_start(lines=1) +Create CNL sequence that moves the cursor +to the beginning of the line and down by specified amount of \fBlines\fP\&. +.INDENT 7.0 +.TP +.B Example +\fBESC [3E\fP +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_set_cursor_line(line=1) +Create VPA sequence that sets +cursor vertical position to \fBline\fP\&. +.INDENT 7.0 +.TP +.B Example +\fBESC [9d\fP +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_set_cursor_column(column=1) +Create CHA sequence that sets +cursor horizontal position to \fBcolumn\fP\&. +.INDENT 7.0 +.TP +.B Parameters +\fBcolumn\fP (\fIint\fP) \-\- New cursor horizontal position. +.TP +.B Example +\fBESC [15G\fP +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_query_cursor_position() +Create QCP sequence that requests an output +device to respond with a structure containing current cursor coordinates +(\fBRCP\fP). +.sp +\fBWARNING:\fP +.INDENT 7.0 +.INDENT 3.5 +Sending this sequence to the terminal may \fBblock\fP infinitely. Consider +using a thread or set a timeout for the main thread using a signal. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Example +\fBESC [6n\fP +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_erase_in_display(mode=0) +Create ED sequence that clears a part of the screen +or the entire screen. Cursor position does not change. +.INDENT 7.0 +.TP +.B Parameters +\fBmode\fP (\fIint\fP) \-\- +.sp +Sequence operating mode. +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.IP \(bu 2 +If set to 0, clear from cursor to the end of the screen. +.IP \(bu 2 +If set to 1, clear from cursor to the beginning of the screen. +.IP \(bu 2 +If set to 2, clear the entire screen. +.IP \(bu 2 +If set to 3, clear terminal history (xterm only). +.UNINDENT +.UNINDENT +.UNINDENT + +.TP +.B Example +\fBESC [0J\fP +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_clear_display_after_cursor() +Create ED sequence that clears a part of the screen +from cursor to the end of the screen. Cursor position does not change. +.INDENT 7.0 +.TP +.B Example +\fBESC [0J\fP +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_clear_display_before_cursor() +Create ED sequence that clears a part of the screen +from cursor to the beginning of the screen. Cursor position does not change. +.INDENT 7.0 +.TP +.B Example +\fBESC [1J\fP +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_clear_display() +Create ED sequence that clears an entire screen. +Cursor position does not change. +.INDENT 7.0 +.TP +.B Example +\fBESC [2J\fP +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_clear_history() +Create ED sequence that clears history, i.e., +invisible lines on the top that can be scrolled back down. Cursor position +does not change. This is a xterm extension. +.INDENT 7.0 +.TP +.B Example +\fBESC [3J\fP +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_erase_in_line(mode=0) +Create EL sequence that clears a part of the line +or the entire line at the cursor position. Cursor position does not change. +.INDENT 7.0 +.TP +.B Parameters +\fBmode\fP (\fIint\fP) \-\- +.sp +Sequence operating mode. +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.IP \(bu 2 +If set to 0, clear from cursor to the end of the line. +.IP \(bu 2 +If set to 1, clear from cursor to the beginning of the line. +.IP \(bu 2 +If set to 2, clear the entire line. +.UNINDENT +.UNINDENT +.UNINDENT + +.TP +.B Example +\fBESC [0K\fP +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_clear_line_after_cursor() +Create EL sequence that clears a part of the line +from cursor to the end of the same line. Cursor position does not change. +.INDENT 7.0 +.TP +.B Example +\fBESC [0K\fP +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_clear_line_before_cursor() +Create EL sequence that clears a part of the line +from cursor to the beginning of the same line. Cursor position does not +change. +.INDENT 7.0 +.TP +.B Example +\fBESC [1K\fP +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_clear_line() +Create EL sequence that clears an entire line +at the cursor position. Cursor position does not change. +.INDENT 7.0 +.TP +.B Example +\fBESC [2K\fP +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_show_cursor() +C +.INDENT 7.0 +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_hide_cursor() +C +.INDENT 7.0 +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_save_screen() +C +.INDENT 7.0 +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_restore_screen() +C +.INDENT 7.0 +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_enable_alt_screen_buffer() +C +.INDENT 7.0 +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_disable_alt_screen_buffer() +C +.INDENT 7.0 +.TP +.B Return type +\fI\%SequenceCSI\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_hyperlink() +Create a hyperlink in the text \fI(supported by limited amount of terminals)\fP\&. +Note that a complete set of commands to define a hyperlink consists of 4 +oh them (two \fI\%OSC\-8\fP and two \fI\%ST\fP). +.sp +\fBSEE ALSO:\fP +.INDENT 7.0 +.INDENT 3.5 +compose_hyperlink()\(ga. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Return type +\fI\%SequenceOSC\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_save_cursor_position() +.INDENT 7.0 +.TP +.B Example +\fBESC 7\fP +.TP +.B Return type +\fI\%SequenceFp\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.make_restore_cursor_position() +.INDENT 7.0 +.TP +.B Example +\fBESC 8\fP +.TP +.B Return type +\fI\%SequenceFp\fP +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.compose_clear_line_fill_bg(basis, line=None, column=None) +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBbasis\fP (\fI\%SequenceSGR\fP) \-\- +.IP \(bu 2 +\fBline\fP (\fIOptional\fP\fI[\fP\fIint\fP\fI]\fP) \-\- +.IP \(bu 2 +\fBcolumn\fP (\fIOptional\fP\fI[\fP\fIint\fP\fI]\fP) \-\- +.UNINDENT +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.compose_hyperlink(url, label=None) +Syntax: \fB(OSC 8 ; ;) (url) (ST) (label) (OSC 8 ; ;) (ST)\fP, where +\fI\%OSC\fP is \fBESC ]\fP\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBurl\fP (\fIstr\fP) \-\- +.IP \(bu 2 +\fBlabel\fP (\fIOptional\fP\fI[\fP\fIstr\fP\fI]\fP) \-\- +.UNINDENT +.TP +.B Example +\fBESC ]8;;http://localhost ESC \eText ESC ]8;; ESC \e\fP +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.decompose_report_cursor_position(string) +Parse RCP sequence that usually comes from +a terminal as a response to \fI\%QCP\fP sequence and +contains a cursor\(aqs current line and column. +.INDENT 7.0 +.INDENT 3.5 +.SS Todo +.sp +make a separate Seq class for this? +.UNINDENT +.UNINDENT +.sp +.nf +.ft C +>>> decompose_report_cursor_position(\(aq\(aq) +(9, 15) +.ft P +.fi +.INDENT 7.0 +.TP +.B Parameters +\fBstring\fP (\fIstr\fP) \-\- Terminal response with a sequence. +.TP +.B Returns +Current line and column if the expected sequence exists +in \fBstring\fP, \fINone\fP otherwise. +.TP +.B Return type +\fIOptional\fP[\fITuple\fP[int, int]] +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.get_terminal_width(fallback=80, pad=2) +Return current terminal width with an optional \(dqsafety buffer\(dq, which +ensures that no unwanted line wrapping will happen. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBfallback\fP (\fIint\fP) \-\- Default value when shutil is unavailable and environment +variable COLUMNS is unset. +.IP \(bu 2 +\fBpad\fP (\fIint\fP) \-\- Additional safety space to prevent unwanted line wrapping. +.UNINDENT +.TP +.B Return type +int +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.get_preferable_wrap_width(force_width=None) +Return preferable terminal width for comfort reading of wrapped text (max=120). +.INDENT 7.0 +.TP +.B Parameters +\fBforce_width\fP (\fIOptional\fP\fI[\fP\fIint\fP\fI]\fP) \-\- Ignore current terminal width and use this value as a result. +.TP +.B Return type +int +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.wait_key(block=True) +Wait for a key press on the console and return it. +.INDENT 7.0 +.TP +.B Parameters +\fBblock\fP (\fIbool\fP) \-\- Determines setup of O_NONBLOCK flag. +.TP +.B Return type +\fIOptional\fP[AnyStr] +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.confirm(attempts=1, default=False, keymap=None, prompt=None, quiet=False, required=False) +Ensure the next action is manually confirmed by user. Print the terminal +prompt with \fBprompt\fP text and wait for a keypress. Return \fITrue\fP +if user pressed \fBY\fP and \fIFalse\fP in all the other cases (by default). +.sp +Valid keys are \fBY\fP and \fBN\fP (case insensitive), while all the other keys +and combinations are considered invalid, and will trigger the return of the +\fBdefault\fP value, which is \fIFalse\fP if not set otherwise. In other words, +by default the user is expected to press either \fBY\fP or \fBN\fP, and if +that\(aqs not the case, the confirmation request will be automatically failed. +.sp +\fBCtrl+C\fP instantly aborts the confirmation process regardless of attempts +count and raises \fI\%UserAbort\fP\&. +.sp +Example keymap (default one): +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +keymap = {\(dqy\(dq: True, \(dqn\(dq: False} +.ft P +.fi +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBattempts\fP (\fIint\fP) \-\- Set how many times the user is allowed to perform the +input before auto\-cancellation (or auto\-confirmation) will +occur. 1 means there will be only one attempt, the first one. +When set to \-1, allows to repeat the input infinitely. +.IP \(bu 2 +\fBdefault\fP (\fIbool\fP) \-\- Default value that will be returned when user presses invalid +key (e.g. \fBBackspace\fP, \fBCtrl+Q\fP etc.) and his +\fBattempts\fP counter decreases to 0. Setting this to \fITrue\fP +effectively means that the user\(aqs only way to deny the request +is to press \fBN\fP or \fBCtrl+C\fP, while all the other +keys are treated as \fBY\fP\&. +.IP \(bu 2 +\fBkeymap\fP (\fIOptional\fP\fI[\fP\fIMapping\fP\fI[\fP\fIstr\fP\fI, \fP\fIbool\fP\fI]\fP\fI]\fP) \-\- Key to result mapping. +.IP \(bu 2 +\fBprompt\fP (\fIOptional\fP\fI[\fP\fIstr\fP\fI]\fP) \-\- String to display before each input attempt. Default is: +\fB\(dqPress Y to continue, N to cancel, Ctrl+C to abort: \(dq\fP +.IP \(bu 2 +\fBquiet\fP (\fIbool\fP) \-\- If set to \fITrue\fP, suppress all messages to stdout and work +silently. +.IP \(bu 2 +\fBrequired\fP (\fIbool\fP) \-\- If set to \fITrue\fP, raise \fI\%UserCancel\fP or \fI\%UserAbort\fP when +user rejects to confirm current action. If set to \fIFalse\fP, +do not raise any exceptions, just return \fIFalse\fP\&. +.UNINDENT +.TP +.B Raises +.INDENT 7.0 +.IP \(bu 2 +\fI\%UserAbort\fP \-\- On corresponding event, if \fBrequired\fP is \fITrue\fP\&. +.IP \(bu 2 +\fI\%UserCancel\fP \-\- On corresponding event, if \fBrequired\fP is \fITrue\fP\&. +.UNINDENT +.TP +.B Returns +\fITrue\fP if there was a confirmation by user\(aqs input or +automatically, \fIFalse\fP otherwise. +.TP +.B Return type +bool +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.get_char_width(char, block) +General\-purpose method for getting width of a character in terminal columns. +.sp +Uses \fI\%guess_char_width()\fP method based on \fBunicodedata\fP package, +or/and QCP\-RCP ANSI control sequence communication protocol. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBchar\fP (\fIstr\fP) \-\- Input char. +.IP \(bu 2 +\fBblock\fP (\fIbool\fP) \-\- Set to \fITrue\fP if you prefer slow, but 100% accurate +\fI\%measuring\fP (which \fBblocks\fP and +requires an output tty), or \fIFalse\fP for a device\-independent, +deterministic and non\-blocking \fI\%guessing\fP, +which works most of the time, although there could be rare +cases when it is not precise enough. +.UNINDENT +.TP +.B Return type +int +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.measure_char_width(char, clear_after=True) +Low\-level function that returns the exact character width in terminal columns. +.sp +The main idea is to reset a cursor position to 1st column, print the required +character and \fI\%QCP\fP control sequence; after that +wait for the response and \fBparse\fP it. +Normally it contains the cursor coordinates, which can tell the exact width of a +character in question. +.sp +After reading the response clear it from the screen and reset the cursor to +column 1 again. +.sp +\fBIMPORTANT:\fP +.INDENT 7.0 +.INDENT 3.5 +The \fBstdout\fP must be a tty. If it is not, consider using +\fI\%guess_char_width()\fP instead, or \fBIOError\fP will be raised. +.UNINDENT +.UNINDENT +.sp +\fBWARNING:\fP +.INDENT 7.0 +.INDENT 3.5 +Invoking this method produces a bit of garbage in the output stream, +which looks like this: \fB⠁\fP\&. By default, it is hidden using +screen line clearing (see \fBclear_after\fP). +.UNINDENT +.UNINDENT +.sp +\fBWARNING:\fP +.INDENT 7.0 +.INDENT 3.5 +Invoking this method may \fBblock\fP infinitely. Consider using a thread +or set a timeout for the main thread using a signal if that is unwanted. +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBchar\fP (\fIstr\fP) \-\- Input char. +.IP \(bu 2 +\fBclear_after\fP (\fIbool\fP) \-\- Send \fI\%EL\fP control sequence after the +terminal response to hide excessive utility information from +the output if set to \fITrue\fP, or leave it be otherwise. +.UNINDENT +.TP +.B Raises +\fBIOError\fP \-\- If \fBstdout\fP is not a terminal emulator. +.TP +.B Return type +int +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.term.guess_char_width(c) +Determine how many columns are needed to display a character in a terminal. +.sp +Returns \-1 if the character is not printable. +Returns 0, 1 or 2 for other characters. +.sp +Utilizes \fBunicodedata\fP table. A terminal emulator is unnecessary. +.INDENT 7.0 +.TP +.B Parameters +\fBc\fP (\fIstr\fP) \-\- +.TP +.B Return type +int +.UNINDENT +.UNINDENT +.SS pytermor.text +.sp +\(dqFront\-end\(dq module of the library. Contains \fIrenderables\fP \-\- classes supporting +high\-level operations such as nesting\-aware style application, concatenating and +cropping of styled strings before the rendering, text alignment and wrapping, etc. +Also provides rendering entrypoints \fI\%render()\fP and \fI\%echo()\fP\&. +.sp +Functions +.TS +center; +|l|l|. +_ +T{ +\fI\%apply_style_selective\fP(regex, string[, st]) +T} T{ +Main purpose: application of under(over|cross)lined styles to strings containing more than one word. +T} +_ +T{ +\fI\%apply_style_words_selective\fP(string, st) +T} T{ +\&. +T} +_ +T{ +\fI\%distribute_padded\fP() +T} T{ +.INDENT 0.0 +.TP +.B param max_len +.UNINDENT +T} +_ +T{ +\fI\%echo\fP([string, fmt, renderer, nl, file, ...]) +T} T{ +\&. +T} +_ +T{ +\fI\%echoi\fP([string, fmt, renderer, file, flush]) +T} T{ +echo inline +T} +_ +T{ +\fBis_rt\fP(arg) +T} T{ +T} +_ +T{ +\fI\%render\fP([string, fmt, renderer]) +T} T{ +\&. +T} +_ +T{ +\fI\%wrap_sgr\fP(rendered, width[, indent_first, ...]) +T} T{ +A workaround to make standard library \fBtextwrap.wrap()\fP more friendly to an SGR\-formatted strings. +T} +_ +.TE +.sp +Classes +.TS +center; +|l|l|. +_ +T{ +\fI\%Composite\fP(*parts) +T} T{ +Simple class\-container supporting concatenation of any \fI\%IRenderable\fP instances with each other without extra logic on top of it. +T} +_ +T{ +\fI\%Fragment\fP([string, fmt, close_this, close_prev]) +T} T{ + +T} +_ +T{ +\fI\%FrozenText\fP(*fargs[, width, align, fill, ...]) +T} T{ +Multi\-fragment text with style nesting support. +T} +_ +T{ +\fI\%IRenderable\fP() +T} T{ +I +T} +_ +T{ +\fI\%SimpleTable\fP(*rows[, width, sep, border_st]) +T} T{ +Table class with dynamic (not bound to each other) rows. +T} +_ +T{ +\fI\%Text\fP(*fargs[, width, align, fill, overflow, ...]) +T} T{ +T} +_ +.TE +.INDENT 0.0 +.TP +.B class pytermor.text.IRenderable +Bases: \fBSized\fP, \fBABC\fP +.sp +I +.INDENT 7.0 +.TP +.B abstract as_fragments() +a\-s +.INDENT 7.0 +.TP +.B Return type +\fIList\fP[\fI\%Fragment\fP] +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B abstract raw() +pass +.INDENT 7.0 +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B abstract render(renderer=None) +pass +.INDENT 7.0 +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B abstract set_width(width) +raise NotImplementedError +.INDENT 7.0 +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B abstract property has_width: bool +return self._width is not None +.UNINDENT +.INDENT 7.0 +.TP +.B abstract property allows_width_setup: bool +return False +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.text.Fragment(string=\(aq\(aq, fmt=None, *, close_this=True, close_prev=False) +Bases: \fI\%IRenderable\fP +.sp + +.sp +Can be formatted with f\-strings. The text \fB:s\fP mode is required. +Supported features: +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.IP \(bu 2 +width [of the result]; +.IP \(bu 2 +max length [of the content]; +.IP \(bu 2 +alignment; +.IP \(bu 2 +filling. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +.nf +.ft C +>>> f\(dq{Fragment(\(aq1234567890\(aq):*^8.4s}\(dq +\(aq**1234**\(aq +.ft P +.fi +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBstring\fP (\fIstr\fP) \-\- +.IP \(bu 2 +\fBfmt\fP (\fIFT\fP) \-\- +.IP \(bu 2 +\fBclose_this\fP (\fIbool\fP) \-\- +.IP \(bu 2 +\fBclose_prev\fP (\fIbool\fP) \-\- +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B as_fragments() +a\-s +.INDENT 7.0 +.TP +.B Return type +\fIList\fP[\fI\%Fragment\fP] +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B raw() +pass +.INDENT 7.0 +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property has_width: bool +return self._width is not None +.UNINDENT +.INDENT 7.0 +.TP +.B property allows_width_setup: bool +return False +.UNINDENT +.INDENT 7.0 +.TP +.B render(renderer=None) +pass +.INDENT 7.0 +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B set_width(width) +raise NotImplementedError +.INDENT 7.0 +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.text.FrozenText(*fargs, width=None, align=None, fill=\(aq \(aq, overflow=\(aq\(aq, pad=0, pad_styled=True) +Bases: \fI\%IRenderable\fP +.sp +Multi\-fragment text with style nesting support. +.INDENT 7.0 +.TP +.B Parameters +\fBalign\fP (\fIstr\fP\fI | \fP\fI\%Align\fP) \-\- default is left +.UNINDENT +.INDENT 7.0 +.TP +.B as_fragments() +a\-s +.INDENT 7.0 +.TP +.B Return type +\fIList\fP[\fI\%Fragment\fP] +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B raw() +pass +.INDENT 7.0 +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B render(renderer=None) +Core rendering method +.INDENT 7.0 +.TP +.B Parameters +\fBrenderer\fP \-\- +.TP +.B Returns + +.TP +.B Return type + +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property allows_width_setup: bool +return False +.UNINDENT +.INDENT 7.0 +.TP +.B property has_width: bool +return self._width is not None +.UNINDENT +.INDENT 7.0 +.TP +.B set_width(width) +raise NotImplementedError +.INDENT 7.0 +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.text.Text(*fargs, width=None, align=None, fill=\(aq \(aq, overflow=\(aq\(aq, pad=0, pad_styled=True) +Bases: \fI\%FrozenText\fP +.INDENT 7.0 +.UNINDENT +.INDENT 7.0 +.TP +.B set_width(width) +raise NotImplementedError +.INDENT 7.0 +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property allows_width_setup: bool +return False +.UNINDENT +.INDENT 7.0 +.TP +.B as_fragments() +a\-s +.INDENT 7.0 +.TP +.B Return type +\fIList\fP[\fI\%Fragment\fP] +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property has_width: bool +return self._width is not None +.UNINDENT +.INDENT 7.0 +.TP +.B raw() +pass +.INDENT 7.0 +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B render(renderer=None) +Core rendering method +.INDENT 7.0 +.TP +.B Parameters +\fBrenderer\fP \-\- +.TP +.B Returns + +.TP +.B Return type + +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.text.Composite(*parts) +Bases: \fI\%IRenderable\fP +.sp +Simple class\-container supporting concatenation of +any \fI\%IRenderable\fP instances with each other without +extra logic on top of it. Renders parts joined by an +empty string. +.INDENT 7.0 +.TP +.B Parameters +\fBparts\fP (\fIRT\fP) \-\- text parts in any format implementing +\fI\%IRenderable\fP interface. +.UNINDENT +.INDENT 7.0 +.TP +.B as_fragments() +a\-s +.INDENT 7.0 +.TP +.B Return type +\fIList\fP[\fI\%Fragment\fP] +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B raw() +pass +.INDENT 7.0 +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B render(renderer=None) +pass +.INDENT 7.0 +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B set_width(width) +raise NotImplementedError +.INDENT 7.0 +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property has_width: bool +return self._width is not None +.UNINDENT +.INDENT 7.0 +.TP +.B property allows_width_setup: bool +return False +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B class pytermor.text.SimpleTable(*rows, width=None, sep=\(aq \(aq, border_st=<*_NoOpStyle[]>) +Bases: \fI\%IRenderable\fP +.sp +Table class with dynamic (not bound to each other) rows. By defualt expands to +the maximum width (terminal size). +.sp +Allows 0 or 1 dynamic\-width cell in each row, while all the others should be +static, i.e., be instances of \fI\%FrozenText\fP\&. +.sp +.nf +.ft C +>>> echo( +\&... SimpleTable( +\&... [ +\&... Text(\(dq1\(dq, width=1), +\&... Text(\(dqword\(dq, width=6, align=\(aqcenter\(aq), +\&... Text(\(dqsmol string\(dq), +\&... ], +\&... [ +\&... Text(\(dq2\(dq, width=1), +\&... Text(\(dqpadded word\(dq, width=6, align=\(aqcenter\(aq, pad=2), +\&... Text(\(dqbiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiig string\(dq), +\&... ], +\&... width=30, +\&... sep=\(dq|\(dq +\&... ), file=sys.stdout) +|1| word |smol string | +|2| padd |biiiiiiiiiiiiiiiiii| +.ft P +.fi +.sp +Create +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBrows\fP (\fIt.Iterable\fP\fI[\fP\fIRT\fP\fI]\fP) \-\- +.IP \(bu 2 +\fBwidth\fP (\fIint\fP) \-\- Table width, in characters. When omitted, equals to terminal size +if applicable, and to fallback value (80) otherwise. +.IP \(bu 2 +\fBsep\fP (\fIstr\fP) \-\- +.IP \(bu 2 +\fBborder_st\fP (\fI\%Style\fP) \-\- +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B as_fragments() +a\-s +.INDENT 7.0 +.TP +.B Return type +\fIList\fP[\fI\%Fragment\fP] +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B raw() +pass +.INDENT 7.0 +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B property allows_width_setup: bool +return False +.UNINDENT +.INDENT 7.0 +.TP +.B property has_width: bool +return self._width is not None +.UNINDENT +.INDENT 7.0 +.TP +.B render(renderer=None) +pass +.INDENT 7.0 +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B set_width(width) +raise NotImplementedError +.INDENT 7.0 +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.text.render(string=\(aq\(aq, fmt=<*_NoOpStyle[]>, renderer=None) +\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBstring\fP (\fIUnion\fP\fI[\fP\fIRT\fP\fI, \fP\fIIterable\fP\fI[\fP\fIRT\fP\fI]\fP\fI]\fP) \-\- 2 +.IP \(bu 2 +\fBfmt\fP (\fIFT\fP) \-\- 2 +.IP \(bu 2 +\fBrenderer\fP (\fIOptional\fP\fI[\fP\fIUnion\fP\fI[\fP\fI\%IRenderer\fP\fI, \fP\fIType\fP\fI[\fP\fI\%IRenderer\fP\fI]\fP\fI]\fP\fI]\fP) \-\- 2 +.UNINDENT +.TP +.B Returns + +.TP +.B Return type +\fIUnion\fP[str, \fIList\fP[str]] +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.text.echo(string=\(aq\(aq, fmt=<*_NoOpStyle[]>, renderer=None, *, nl=True, file=<_io.TextIOWrapper name=\(aq\(aq mode=\(aqw\(aq encoding=\(aqutf\-8\(aq>, flush=True, wrap=False, indent_first=0, indent_subseq=0) +\&. +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBstring\fP (\fIUnion\fP\fI[\fP\fIRT\fP\fI, \fP\fIIterable\fP\fI[\fP\fIRT\fP\fI]\fP\fI]\fP) \-\- +.IP \(bu 2 +\fBfmt\fP (\fIFT\fP) \-\- +.IP \(bu 2 +\fBrenderer\fP (\fIOptional\fP\fI[\fP\fI\%IRenderer\fP\fI]\fP) \-\- +.IP \(bu 2 +\fBnl\fP (\fIbool\fP) \-\- +.IP \(bu 2 +\fBfile\fP (\fIIO\fP) \-\- +.IP \(bu 2 +\fBflush\fP (\fIbool\fP) \-\- +.IP \(bu 2 +\fBwrap\fP (\fIbool\fP\fI | \fP\fIint\fP) \-\- +.IP \(bu 2 +\fBindent_first\fP (\fIint\fP) \-\- +.IP \(bu 2 +\fBindent_subseq\fP (\fIint\fP) \-\- +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.text.echoi(string=\(aq\(aq, fmt=<*_NoOpStyle[]>, renderer=None, *, file=<_io.TextIOWrapper name=\(aq\(aq mode=\(aqw\(aq encoding=\(aqutf\-8\(aq>, flush=True) +echo inline +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBstring\fP (\fIUnion\fP\fI[\fP\fIRT\fP\fI, \fP\fIIterable\fP\fI[\fP\fIRT\fP\fI]\fP\fI]\fP) \-\- +.IP \(bu 2 +\fBfmt\fP (\fIFT\fP) \-\- +.IP \(bu 2 +\fBrenderer\fP (\fIOptional\fP\fI[\fP\fI\%IRenderer\fP\fI]\fP) \-\- +.IP \(bu 2 +\fBfile\fP (\fIIO\fP) \-\- +.IP \(bu 2 +\fBflush\fP (\fIbool\fP) \-\- +.UNINDENT +.TP +.B Returns + +.TP +.B Return type +None +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.text.distribute_padded(max_len: int, *values: str, pad_left: int = 0, pad_right: int = 0) -> str +.TP +.B pytermor.text.distribute_padded(max_len: int, *values: RT, pad_left: int = 0, pad_right: int = 0) -> \fI\%Text\fP +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBmax_len\fP \-\- +.IP \(bu 2 +\fBvalues\fP \-\- +.IP \(bu 2 +\fBpad_left\fP \-\- +.IP \(bu 2 +\fBpad_right\fP \-\- +.UNINDENT +.TP +.B Returns + +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.text.wrap_sgr(rendered, width, indent_first=0, indent_subseq=0) +A workaround to make standard library \fBtextwrap.wrap()\fP more friendly +to an SGR\-formatted strings. +.sp +The main idea is +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBrendered\fP (\fIstr\fP\fI | \fP\fIlist\fP\fI[\fP\fIstr\fP\fI]\fP) \-\- +.IP \(bu 2 +\fBwidth\fP (\fIint\fP) \-\- +.IP \(bu 2 +\fBindent_first\fP (\fIint\fP) \-\- +.IP \(bu 2 +\fBindent_subseq\fP (\fIint\fP) \-\- +.UNINDENT +.TP +.B Return type +str +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.text.apply_style_words_selective(string, st) +\&... +.INDENT 7.0 +.TP +.B Return type +\fISequence\fP[\fI\%Fragment\fP] +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B pytermor.text.apply_style_selective(regex, string, st=<*_NoOpStyle[]>) +Main purpose: application of under(over|cross)lined styles to strings +containing more than one word. Although the method can be used with any style and +splitting rule provided. The result is a sequence of \fI\%Fragments\fP +with styling applied only to specified parts of the original string. +.sp +Regex should consist of two groups, first for parts to apply style to, second +for parts to return without any style (see \fI\%NOOP_STYLE\fP). This regex is +used internally for python\(aqs \fBre.findall()\fP method. +.sp +The example below demonstrates how to color all the capital letters in the string +in red color: +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +>>> render([ +\&... *apply_style_selective( +\&... re.compile(R\(aq([A\-Z]+)([^A\-Z]+|$)\(aq), +\&... \(dqA few CAPITALs\(dq, +\&... Style(fg=\(aqred\(aq), +\&... ) +\&... ], renderer=SgrRenderer(OutputMode.XTERM_16)) +[\(aqA\(aq, \(aq few \(aq, \(aqCAPITAL\(aq, \(aqs\(aq] +.ft P +.fi +A few CAPITALs +.UNINDENT +.UNINDENT +.INDENT 7.0 +.TP +.B Parameters +.INDENT 7.0 +.IP \(bu 2 +\fBregex\fP (\fIPattern\fP) \-\- +.IP \(bu 2 +\fBstring\fP (\fIstr\fP) \-\- +.IP \(bu 2 +\fBst\fP (\fI\%Style\fP) \-\- +.UNINDENT +.TP +.B Return type +\fISequence\fP[\fI\%Fragment\fP] +.UNINDENT +.UNINDENT +.SH APPENDIX +.SS Tracers math +.sp +The library provides a few implementations of \fI\%AbstractTracer\fP, each of them +having an algorithm that determines the maximum amount of data per line +depending on current output device (terminal) width. Some of these algorithms +are non\-linear and for the clarity listed below. +.SS BytesTracer +.sp +Display \fIstr\fP/\fIbytes\fP as byte hex codes, grouped by 4. +.sp +Example output +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C + 0x00 | 35 30 20 35 34 20 35 35 20 C2 B0 43 20 20 33 39 20 2B 30 20 + 0x14 | 20 20 33 39 6D 73 20 31 20 52 55 20 20 E2 88 86 20 35 68 20 + 0x28 | 31 38 6D 20 20 20 EE 8C 8D 20 E2 80 8E 20 2B 32 30 C2 B0 43 + 0x3C | 20 20 54 68 20 30 31 20 4A 75 6E 20 20 31 36 20 32 38 20 20 + 0x50 | E2 96 95 E2 9C 94 E2 96 8F 46 55 4C 4C 20 +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +The amount of characters that will fit into one line (with taking into account +all the formatting and the fact that chars are displayed in groups of 4) +depends on terminal width and on max address value (the latter determines the +size of the leftmost field \-\- current line address). Let\(aqs express output line +length L_O in a general way \-\- through C_L (characters per line) and +L_{adr} (length of maximum address value for given input): +.sp +.ce +L_O& = L_{spc} + L_{sep} + L_{adr} + L_{hex}, \e\e\e\e\e +L_{adr}& = 2 + 2 \ecdot ceil(\efrac{L_{Ihex}}{2}), \eqquad\eqquad (1) \e\e\e\e\e +L_{hex}& = 3C_L + floor(\efrac{C_L}{4}), + + +.ce 0 +.sp +where: +.INDENT 0.0 +.INDENT 3.5 +.INDENT 0.0 +.IP \(bu 2 +L_{spc} = 3 is static whitespace total length, +.IP \(bu 2 +L_{sep} = 1 is separator (\fB\(dq|\(dq\fP) length, +.IP \(bu 2 +L_{Ihex} = len(L_I) is \fIlength\fP of (hexadecimal) \fIlength\fP of input. +Here is an example, consider input data I 10 bytes long: +.INDENT 2.0 +.INDENT 3.5 +.sp +.ce +L_I& = len(I) = 10_{10} = A_{16}, \e\e\e\e\e +L_{Ihex}& = len(L_I) = len(A_{16}) = 1, \e\e\e\e\e + L_{adr}& = 2 + 2 \ecdot ceil(\efrac{1}{2}) = 4, + + +.ce 0 +.UNINDENT +.UNINDENT +.sp +which corresponds to address formatted as 0x0A\&. One more example \-\- +input data 1000 bytes long: +.INDENT 2.0 +.INDENT 3.5 +.sp +.ce +L_I& = len(I) = 1000_{10} = 3E8_{16}, \e\e\e\e\e +L_{Ihex}& = len(L_I) = len(3E8_{16}) = 3 , \e\e\e\e\e + L_{adr}& = 2 + 2 \ecdot ceil(\efrac{3}{2}) = 6 , + + +.ce 0 +.UNINDENT +.UNINDENT +.sp +which matches the length of an actual address 0x03E8). Note that the +expression 2 \ecdot ceil(\efrac{L_{Ihex}}{2}) is used for rounding L_{adr} up +to next even integer to avoid printing the addresses in 0x301 form, +and displaying them more or less aligned instead. The first constant item +2 in (1) represents 0x prefix. +.IP \(bu 2 +L_{hex} represents amount of chars required to display C_L hexadecimal bytes. +First item 3C_L is trivial and corresponds to every byte\(aqs hexadecimal value +plus a space after (giving us 2+1=3, e.g. \fB\(dq34 \(dq\fP), while the second one +represents one extra space character per each 4\-byte group. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +Let\(aqs introduce L_T as current terminal width, then \eboxed{L_O \eleqslant L_T}, which +leads to the following inequation: +.sp +.ce +L_{spc} + L_{sep} + L_{adr} + L_{hex} \eleqslant L_T . + + +.ce 0 +.sp +Substitute the variables: +.sp +.ce +3 + 1 + 2 + 2 \ecdot ceil(\efrac{L_{Ihex}}{2}) + 3C_L + floor(\efrac{C_L}{4}) \eleqslant L_T . + + +.ce 0 +.sp +Suppose we limit C_L values to the integer factor of 4, then: +.sp +.ce +3C_L + floor(\efrac{C_L}{4}) = 3.25C_L \eqquad \eforall C_L \ein [4, 8, 12..) , \eqquad (2) + + +.ce 0 +.sp +which gives us: +.sp +.ce +6 + 2 \ecdot ceil(\efrac{L_{Ihex}}{2}) + 3.25C_L \eleqslant L_T &, \e\e\e\e\e +3.25C_L \eleqslant L_T \- 2 \ecdot ceil(\efrac{L_{Ihex}}{2}) \- 6 &, \e\e\e\e\e +13C_L \eleqslant 4L_T \- 8 \ecdot ceil(\efrac{L_{Ihex}}{2}) \- 24 &. + + +.ce 0 +.sp +Therefore: +.sp +.ce +C_{Lmax} = floor(\efrac{4L_T \- 4 \ecdot ceil(\efrac{L_{Ihex}}{2}) \- 24}{13}) . + + +.ce 0 +.sp +Last step would be to round the result (down) to the nearest integer +factor of 4 as we have agreed earlier in (2)\&. +.SS StringTracer +.sp +Display \fIstr\fP as byte hex codes (UTF\-8), grouped by characters. +.sp +Example output +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C + 0 | 35 30 20 35 34 20 35 35 20 c2b0 43 20 |50␣54␣55␣°C␣ + 12 | 20 33 39 20 2b 30 20 20 20 33 39 6d |␣39␣+0␣␣␣39m + 24 | 73 20 31 20 52 55 20 20 e28886 20 35 68 |s␣1␣RU␣␣∆␣5h + 36 | 20 31 38 6d 20 20 20 ee8c8d 20 e2808e 20 2b |␣18m␣␣␣␣‎␣+ + 48 | 32 30 c2b0 43 20 20 54 68 20 30 31 20 |20°C␣␣Th␣01␣ + 60 | 4a 75 6e 20 20 31 36 20 32 38 20 20 |Jun␣␣16␣28␣␣ + 72 | e29695 e29c94 e2968f 46 55 4c 4c 20 |▕✔▏FULL␣ +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +Calculations for this class are different, although the base +formula for output line length L_O is the same: +.sp +.ce +L_O& = L_{spc} + L_{sep} + L_{adr} + L_{hex}, \e\e\e\e\e +L_{adr}& = len(L_I), \e\e\e\e\e +L_{hex}& = (2C_{Umax} + 1) \ecdot C_L + + +.ce 0 +.sp +where: +.INDENT 0.0 +.INDENT 3.5 +.INDENT 0.0 +.IP \(bu 2 +L_{spc} = 3 is static whitespace total length, +.IP \(bu 2 +L_{sep} = 2 is separators \fB\(dq|\(dq\fP total length, +.IP \(bu 2 +L_{adr} is length of maximum address value and is equal to \fIlength\fP +of \fIlength\fP of input data without any transformations (because the +output is decimal, in contrast with \fBBytesTracer\fP), +.IP \(bu 2 +L_{hex} is hex representation length (2 chars multiplied to +C_{Umax} plus 1 for space separator per each character), +.IP \(bu 2 +C_{Umax} is maximum UTF\-8 bytes amount for a single codepoint +encountered in the input (for example, C_{Umax} equals to 1 for +input string consisting of ASCII\-7 characters only, like \fB\(dqABCDE\(dq\fP, +2 for \fB\(dqэйцукен\(dq\fP, 3 for \fB\(dq硸馆邚\(dq\fP and 4 for \fB\(dq􏿿\(dq\fP, +which is U+10FFFF), +.IP \(bu 2 +L_{chr} = C_L is char representation length (equals to C_L), and +.IP \(bu 2 +C_L is chars per line setting. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +Then the condition of fitting the data to a terminal can be written as: +.sp +.ce +L_{spc} + L_{sep} + L_{adr} + L_{hex} + L_{chr} \eleqslant L_T , + + +.ce 0 +.sp +where L_T is current terminal width. Next: +.sp +.ce +3 + 2 + L_{adr} + (2C_{Umax}+1) \ecdot C_L + C_L ,& \eleqslant L_T \e\e\e\e\e + L_{adr} + 5 + (2C_{Umax}+2) \ecdot C_L ,& \eleqslant L_T + + +.ce 0 +.sp +Express C_L through L_T, L_{adr} and C_{Umax}: +.sp +.ce +(2C_{Umax}+2) \ecdot C_L \eleqslant L_T \- L_{adr} \- 5 , + + +.ce 0 +.sp +Therefore maximum chars per line equals to: +.sp +.ce +C_{Lmax} = floor(\efrac{L_T \- L_{adr} \- 5}{2C_{Umax}+2}). + + +.ce 0 +.sp +Example +.sp +Consider terminal width is 80, input data is 64 characters long +and consists of U+10FFFF codepoints only (C_{Umax}=4). Then: +.INDENT 0.0 +.INDENT 3.5 +.sp +.ce +L_{adr} &= len(L_I) = len(64) = 2, \e\e\e +C_{Lmax} &= floor(\efrac{78 \- 2 \- 5}{8+2}), \e\e\e + &= floor(7.1) = 7. + + +.ce 0 +.UNINDENT +.UNINDENT +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +Max width value used in calculations is slightly smaller than real one, +that\(aqs why output lines are 78 characters long (instead of 80) \-\- +there is a 2\-char reserve to ensure that the output will fit to the +terminal window regardless of terminal emulator type and implementation. +.UNINDENT +.UNINDENT +.sp +The calculations always consider the maximum possible length of input +data chars, and even if it will consist of the highest order codepoints +only, it will be perfectly fine. +.sp +Example output of highest order codepoints +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C + 0 | f4808080 f4808080 f4808080 f4808080 f4808080 f4808080 f4808080 |􀀀􀀀􀀀􀀀􀀀􀀀􀀀 + 7 | f4808080 f4808080 f4808080 f4808080 f4808080 f4808080 f4808080 |􀀀􀀀􀀀􀀀􀀀􀀀􀀀 + 14 | ... +.ft P +.fi +.UNINDENT +.UNINDENT +.SS StringUcpTracer +.sp +Display \fIstr\fP as Unicode codepoints. +.sp +Example output +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C + 0 |U+ 20 34 36 20 34 36 20 34 36 20 B0 43 20 20 33 39 20 2B |␣46␣46␣46␣°C␣␣39␣+ + 18 |U+ 30 20 20 20 35 20 6D 73 20 31 20 52 55 20 20 2206 20 37 |0␣␣␣5␣ms␣1␣RU␣␣∆␣7 + 36 |U+ 68 20 32 33 6D 20 20 20 FA93 200E 20 2B 31 33 B0 43 20 20 |h␣23m␣␣␣望‎␣+13°C␣␣ + 54 |U+ 46 72 20 30 32 20 4A 75 6E 20 20 30 32 3A 34 38 20 20 |Fr␣02␣Jun␣␣02:48␣␣ + 72 |U+ 2595 2714 258F 46 55 4C 4C 20 |▕✔▏FULL␣ +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +Calculations for \fI\%StringUcpTracer\fP are almost the same as for \fI\%StringTracer\fP, +expect that sum of static parts of L_O equals to 7 instead +of 5 (because of \(dqU+\(dq prefix being displayed). +.sp +The second difference is using C_{UCmax} instead of +C_{Umax}; the former variable is the amount of \(dqn\(dq in +U+nnnn identifier of the character, while the latter is amount of +bytes required to encode the character in UTF\-8. Final formula is: +.sp +.ce +C_{Lmax} = floor(\efrac{L_T \- L_{adr} \- 7}{C_{UCmax}+2}). + + +.ce 0 +.SH CONFIGURATION +.sp +The library initializes it\(aqs own config class just after being imported +(\fBinit_config()\fP). There are two ways to customize the setup: +.INDENT 0.0 +.INDENT 3.5 +.INDENT 0.0 +.IP 1. 3 +create new \fI\%Config\fP instance from scratch and activate with +\fBreplace_config()\fP; +.IP 2. 3 +or preliminarily set the corresponding environment variables to intended +values, and the default config instance will catch them up on initialization. +Environment variable names are rendered in the documentation like this: +PYTERMOR_VARIABLE_NAME\&. +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.INDENT 3.5 +.SH TODO +.sp +check up sphinx\(aqs directive \(dqenvvar\(dq and same text role (or whats its name...) +.UNINDENT +.UNINDENT +.SS Variables +.INDENT 0.0 +.TP +.B Config.renderer_class +Explicitly set default renderer class (e.g. \fBTmuxRenderer\fP). Default renderer +class is used for rendering if there is no explicitly specified one. +Corresponding environment variable is PYTERMOR_RENDERER_CLASS\&. +See also: \fI\%Default renderers priority\fP\&. +.UNINDENT +.INDENT 0.0 +.TP +.B Config.force_output_mode +is a standard for in\-band signaling to control cursor location, color, +font styling, and other options on video text terminals and terminal +emulators. Certain sequences of bytes, most starting with an ASCII escape +character and a bracket character, are embedded into text. The terminal +interprets these sequences as commands, rather than text to display +verbatim. Corresponding environment variable is +PYTERMOR_FORCE_OUTPUT_MODE\&. +.UNINDENT +.INDENT 0.0 +.TP +.B Config.default_output_mode +is a standard for in\-band signaling to control cursor location, color, +font styling, and other options on video text terminals and terminal +emulators. Certain sequences of bytes, most starting with an ASCII escape +character and a bracket character, are embedded into text. The terminal +interprets these sequences as commands, rather than text to display +verbatim. Corresponding environment variable is +PYTERMOR_DEFAULT_OUTPUT_MODE\&. +.UNINDENT +.INDENT 0.0 +.TP +.B Config.prefer_rgb +is a standard for in\-band signaling to control cursor location, color, +font styling, and other options on video text terminals and terminal +emulators. Certain sequences of bytes, most starting with an ASCII escape +character and a bracket character, are embedded into text. The terminal +interprets these sequences as commands, rather than text to display +verbatim. Corresponding environment variable is PYTERMOR_PREFER_RGB\&. +.UNINDENT +.INDENT 0.0 +.TP +.B Config.trace_renders +is a standard for in\-band signaling to control cursor location, color, +font styling, and other options on video text terminals and terminal +emulators. Certain sequences of bytes, most starting with an ASCII escape +character and a bracket character, are embedded into text. The terminal +interprets these sequences as commands, rather than text to display +verbatim. yare\-yare\-daze Corresponding environment variable is +PYTERMOR_TRACE_RENDERS\&. +.UNINDENT +.SH CHANGELOG +.SS Releases +.sp +This project uses Semantic Versioning \-\- \fI\%https://semver.org\fP \fI(starting from v2.0)\fP +.SS pending +.INDENT 0.0 +.IP \(bu 2 +\&... +.IP \(bu 2 + changelog update +.IP \(bu 2 +[FIX] noop color .id read +.IP \(bu 2 +[FIX] legacy virtual SequenceSGR descendants +.IP \(bu 2 +[NEW] \fI\%DynamicColor\fP +.IP \(bu 2 +[REFACTOR] split color hierarchy into \fI\%ResolvableColor\fP, \fI\%RenderColor\fP and \fBRealColor\fP +.IP \(bu 2 +[FIX] restricted \fI\%DynamicColor\fP to \fI\%RenderColor\fP functionally +.IP \(bu 2 +[REFACTOR] \fI\%DynamicColor\fP deferred mechanism +.IP \(bu 2 +[FIX] missing imports +.IP \(bu 2 +[DOCS] update +.IP \(bu 2 + +.nf +| +.fi +U|pdate README.md +.IP "System Message: WARNING/2 (docs/_include/CHANGES.rst:, line 16)" +Inline substitution_reference start\-string without end\-string. +.IP \(bu 2 + +.nf +| +.fi +U|pdate README.md +.IP "System Message: WARNING/2 (docs/_include/CHANGES.rst:, line 17)" +Inline substitution_reference start\-string without end\-string. +.IP \(bu 2 +[NEW] deferred \fI\%cval\fP instantiating +.IP \(bu 2 +[DOCS] colored LaTeX output +.IP \(bu 2 +[DOCS] examples +.IP \(bu 2 +[DOCS] features WIP +.IP \(bu 2 +[DOCS] index rewrite +.IP \(bu 2 +[REFACTOR] latex configuration files +.IP \(bu 2 +[DOCS] bgcolor latex custom class +.IP \(bu 2 +[FIX] color16_equiv approximation issue +.IP \(bu 2 +[REFACTOR] made \fI\%Color256\fP non\-deferred +.IP \(bu 2 +[DOCS] tracers math +.IP \(bu 2 +[REMOVE] \fBlog\fP module +.IP \(bu 2 +[FIX] conflict color tokens are allowed as long as original names differ +.IP \(bu 2 +[FIX] \fI\%Color16\fP, \fI\%Color256\fP, \fI\%ColorRGB\fP hash computation +.UNINDENT +.SS 2.99\-dev +.sp +Aug 23 +.INDENT 0.0 +.IP \(bu 2 +[CI/CD] artifact uploading +.IP \(bu 2 +[DOCS] \fBRenderers\fP and \fBANSI sequences review\fP pages +.IP \(bu 2 +[DOCS] library structure diagram optimized for dark mode +.IP \(bu 2 +[FIX] logging +.IP \(bu 2 +[FIX] \fI\%format_auto_float\fP edge case +.IP \(bu 2 +[FIX] \fI\%DualFormatter\fP tuning +.IP \(bu 2 +[FIX] imports +.IP \(bu 2 +[FIX] \fI\%template\fP splitter mode +.IP \(bu 2 +[FIX] \fI\%compose_clear_line_fill_bg\fP now correctlyl handle requests to fill line from the middle +.IP \(bu 2 +[FIX] \fI\%SequenceNf\fP assembling +.IP \(bu 2 + docker image based on python 3.10 <\- 3.8 +.IP \(bu 2 + test dependencies +.IP \(bu 2 + missing imports +.IP \(bu 2 +[NEW] \fI\%common\fP helpers: \fI\%only\fP, \fI\%but\fP, \fI\%ours\fP, \fI\%others\fP, \fBisiterable\fP, \fI\%flatten\fP, \fI\%char_range\fP +.IP \(bu 2 +[NEW] auto\-normalization of RGB values +.IP \(bu 2 +[NEW] substitute, is_rt, cut, fit +.IP \(bu 2 +[NEW] AbstractNamedGroupsRefilter, AbstractRegexValRefilter, AbstractStringTracer, AbstractTracer, IRefilter, OmniPadder +.IP \(bu 2 +[NEW] highlighter._multiapply +.IP \(bu 2 +[NEW] \fI\%Text\fP constructor fragment in args autodetect +.IP \(bu 2 +[NEW] TestSgrVisualizer +.IP \(bu 2 +[NEW] automated customizing of library structure diagram generation +.IP \(bu 2 +[NEW] added tuple support into fargs\-parsing +.IP \(bu 2 +[NEW] http colors +.IP \(bu 2 +[NEW] \fI\%template\fP option STYLE_WORDS_SELECTIVE_COMMA +.IP \(bu 2 +[NEW] +16 named colors +.IP \(bu 2 +[NEW] +1 more named color +.IP \(bu 2 +[NEW] addr_offset param for \fBTracers\fP +.IP \(bu 2 +[NEW] \fI\%fit\fP support for \fBfillchar\fP customizing +.IP \(bu 2 +[NEW] \fBTracers\fP handling empty input +.IP \(bu 2 +[NEW] +1 named color +.IP \(bu 2 +[NEW] \fBTempateEngine\fP \fBglobal_style\fP argument \fBTempalteEngine.render()\fP method +.IP \(bu 2 +[NEW] color difference formula updated to CIE76 ΔE* +.IP \(bu 2 +[NEW] \fBxkcd\fP named colors +.IP \(bu 2 +[NEW] fargs now support arbitrary order of arguments independent of their types +.IP \(bu 2 +[REFACTOR] transferred \fBmake_*\fP methods from \fI\%ansi\fP to \fI\%term\fP\&. and \fBparser\fP to \fI\%ansi\fP +.IP \(bu 2 +[REFACTOR] moved \fBtrace()\fP from \fI\%filter\fP to \fBlog\fP +.IP \(bu 2 +[REFACTOR] render tracing log level +.IP \(bu 2 +[REFACTOR] simplified \fI\%ArgTypeError\fP +.IP \(bu 2 +[REFACTOR] optimized imports +.IP \(bu 2 +[REFACTOR] \fBTemplateEngine\fP +.IP \(bu 2 +[REFACTOR] \fBmeasure\fP \fI\%fit\fP +.IP \(bu 2 +[REFACTOR] merged \fBconv\fP and \fI\%color\fP modules into sole \fI\%color\fP, also merged two class hierarchies into one +.IP \(bu 2 +[REFACTOR] color transformation methods +.IP \(bu 2 +[REMOVE] \fBAbstractRegexValRefilter\fP, \fBStringAligner\fP +.IP \(bu 2 +[REMOVE] \fBTemplateRenderer\fP +.IP \(bu 2 +[TESTS] \fI\%common\fP module +.IP \(bu 2 +[TESTS] covered \fI\%filter\fP module +.IP \(bu 2 +[TESTS] +.IP \(bu 2 +[TESTS] \fI\%template\fP +.IP \(bu 2 +[TESTS] 99% coverage +.IP \(bu 2 +[TESTS] 100% coverage +.IP \(bu 2 +[TESTS] fix params +.IP \(bu 2 +[TESTS] 100% coverage again +.UNINDENT +.SS v2.75\-dev +.sp +Jun 23 +.INDENT 0.0 +.IP \(bu 2 +[DOCS] fixed pydoc escaped spaces to stop python\(aqs warnings whining that breaks the CI +.IP \(bu 2 +[FIX] \fI\%ESCAPE_SEQ_REGEX\fP +.IP \(bu 2 +[FIX] \fBESC_SEQ_REGEX\fP +.IP \(bu 2 +[FIX] \fI\%filter.AbstractTracer\fP faulty offset rendering +.IP \(bu 2 +[FIX] \fBflake8\fP +.IP \(bu 2 +[FIX] \fBmake_clear_display_and_history()\fP \-> \fI\%make_clear_history()\fP +.IP \(bu 2 +[FIX] \fI\%numfmt\fP exports +.IP \(bu 2 +[FIX] \fBpydeps\fP invocation +.IP \(bu 2 +[FIX] \fI\%template\fP options parsing issue +.IP \(bu 2 + add \fB__updated__\fP field to init file +.IP \(bu 2 + add \fBupdated\fP field in _version.py +.IP \(bu 2 + CI coverage now running on python 3.10 (was 3.8) +.IP \(bu 2 + cleanup +.IP \(bu 2 + disabled verbose mode on CI +.IP \(bu 2 + pdf documentation +.IP \(bu 2 + replaced GITHUB_TOKEN secret to COVERALLS_REPO_TOKEN +.IP \(bu 2 + upload to coveralls debug mode !@#$ +.IP \(bu 2 +[NEW] \fI\%IRenderable.raw()\fP method +.IP \(bu 2 +[NEW] \fBText.split_by_spaces()\fP, \fI\%Composite\fP +.IP \(bu 2 +[NEW] \(dqfrozen\(dq \fI\%Style\fP attribute +.IP \(bu 2 +[NEW] \(aqskylight\-blue\(aq named color +.IP \(bu 2 +[NEW] +3 base sequence classes, +26 preset sequences +.IP \(bu 2 +[NEW] \fB__str__\fP methods override for named tuples \fI\%RGB\fP, \fI\%HSV\fP +.IP \(bu 2 +[NEW] \fI\%contains_sgr\fP method +.IP \(bu 2 +[NEW] \fI\%cval\fP atlassian colors +.IP \(bu 2 +[NEW] \fBparser\fP module +.IP \(bu 2 +[NEW] \fI\%force_ansi_rendering\fP, \fI\%force_no_ansi_rendering\fP +.IP \(bu 2 +[NEW] \fI\%LAB\fP, \fI\%XYZ\fP named tuples + conversions +.IP \(bu 2 +[NEW] \fI\%StringReplacerChain\fP filter +.IP \(bu 2 +[NEW] \fI\%Style\fP, \fI\%SgrRenderer\fP and \fI\%TmuxRenderer\fP support of all the above +.IP \(bu 2 +[NEW] \fBTemplateEngine\fP comment support +.IP \(bu 2 +[NEW] \fBTracers\fP auto\-width mode +.IP \(bu 2 +[NEW] \fButilmisc\fP color transform methods overloaded +.IP \(bu 2 +[NEW] add \fI\%ColorTarget\fP enum as there are three extended color modes instead of two +.IP \(bu 2 +[NEW] add \fBSubtypedParam\fP support that allows specifying SGRs with subparams like \(aqESC[4:3m\(aq +.IP \(bu 2 +[NEW] implement missing 1st\-level sequence classes +.IP \(bu 2 +[NEW] IntCodes: \fBFRAMED\fP (+\(ga\(ga_OFF\(ga\(ga), \fBUNDERLINE_COLOR_EXTENDED\fP (+\(ga\(ga_OFF\(ga\(ga) +.IP \(bu 2 +[NEW] math rendering as png +.IP \(bu 2 +[NEW] SeqIndex: \fBCURLY_UNDERLINED\fP, \fBFRAMED\fP, \fBFRAMED_OFF\fP +.IP \(bu 2 +[REFACTOR] split \fBcommons\fP into \fBlog\fP and \fBexcepiton\fP modules +.IP \(bu 2 +[REFACTOR] \fBTemplateEngine\fP +.IP \(bu 2 +[REFACTOR] color resolver +.IP \(bu 2 +[REFACTOR] made \fBmeasure\fP and \fBtrace\fP private +.IP \(bu 2 +[REFACTOR] sequence internal composition +.IP \(bu 2 +[REFACTOR] split \fBPYTERMOR_OUTPUT_MODE\fP env var into \fBPYTERMOR_FORCE_OUTPUT_MODE\fP and \fBPYTERMOR_AUTO_OUTPUT_MODE\fP +.IP \(bu 2 +[REWORK] \fButil*\fP \-> \fI\%numfmt\fP, \fI\%filter\fP, \fBconv\fP +.IP \(bu 2 +[REWORK] doc pages tree +.IP \(bu 2 +[TESTS] 83% coverage +.IP \(bu 2 +[TESTS] \fI\%Style\fP/\fBIColor\fP reprs +.IP \(bu 2 +[TESTS] coverage 87% +.IP \(bu 2 +[TESTS] moar +.IP \(bu 2 +[UPDATE] Update coverage.yml +.UNINDENT +.SS v2.48\-dev +.sp +Apr 23 +.INDENT 0.0 +.IP \(bu 2 +[DOCS] small fixes +.IP \(bu 2 +[DOCS] updated changelog +.IP \(bu 2 +[FIX] \fI\%measure_char_width\fP and \fI\%get_char_width\fP internal logic +.IP \(bu 2 +[FIX] pipelines +.IP \(bu 2 +[FIX] \fI\%AbstractTracer\fP failure on empty input +.IP \(bu 2 +[FIX] \fI\%StaticFormatter\fP padding +.IP \(bu 2 +[FIX] bug in \fI\%SimpleTable\fP renderer when row is wider than a terminal +.IP \(bu 2 +[FIX] debug logging +.IP \(bu 2 + coverage git ignore +.IP \(bu 2 + \fBcli\-docker\fP make command +.IP \(bu 2 + \fBDockerfile\fP for repeatable builds +.IP \(bu 2 + \fBhatch\fP as build backend +.IP \(bu 2 + copyrights update +.IP \(bu 2 + host system/docker interchangable building automations +.IP \(bu 2 +[NEW] \fI\%format_time\fP, \fI\%format_time_ms\fP, \fI\%format_time_ns\fP +.IP \(bu 2 +[NEW] \fBHightlighter\fP from static methods to real class +.IP \(bu 2 +[NEW] \fBlab_to_rgb()\fP +.IP \(bu 2 +[NEW] numeric formatters fallback mechanics +.IP \(bu 2 +[REFACTOR] \fBTDF_REGISTRY\fP \-> \fBdual_registry\- \(ga\(gaFORMATTER_\(ga\fP constants from top\-level imports +.IP \(bu 2 +[REFACTOR] \fButilnum._TDF_REGISTRY\fP \-> \fBTDF_REGISTRY\fP +.IP \(bu 2 +[REFACTOR] edited highlighter styles +.IP \(bu 2 +[REFACTOR] naming: +.INDENT 2.0 +.IP \(bu 2 +\fBCustomBaseUnit\fP \-> \fI\%DualBaseUnit\fP +.IP \(bu 2 +\fBDynamicBaseFormatter\fP \-> \fI\%DynamicFormatter\fP +.IP \(bu 2 +\fBStaticBaseFormatter\fP \-> \fI\%StaticFormatter\fP +.UNINDENT +.IP \(bu 2 +[TESTS] numeric formatters colorizing +.IP \(bu 2 +[UPDATE] README +.IP \(bu 2 +[UPDATE] license is now Lesser GPL v3 +.UNINDENT +.SS v2.40\-dev +.sp +Feb 23 +.INDENT 0.0 +.IP \(bu 2 +[DOCS] \fBchangelog\fP update +.IP \(bu 2 +[DOCS] \fButilnum\fP module +.IP \(bu 2 +[DOCS] rethinking of references style +.IP \(bu 2 +[FIX] \fI\%parse\fP method of TemplateEngine +.IP \(bu 2 +[FIX] \fI\%Highlighter\fP +.IP \(bu 2 +[FIX] critical \fI\%Styles\fP color +.IP \(bu 2 + 2023 copytight update +.IP \(bu 2 +[NEW] \fBcoveralls.io\fP integration +.IP \(bu 2 +[NEW] \fI\%echoi\fP, \fI\%flatten\fP, \fI\%flatten1\fP methods; \fI\%SimpleTable\fP class +.IP \(bu 2 +[NEW] \fI\%StringLinearizer\fP, \fI\%WhitespaceRemover\fP +.IP \(bu 2 +[NEW] \fI\%text\fP Fragments validation +.IP \(bu 2 +[NEW] \fI\%Configuration\fP class +.IP \(bu 2 +[NEW] \fBhex\fP rst text role +.IP \(bu 2 +[NEW] \fButilnum.format_bytes_human()\fP +.IP \(bu 2 +[NEW] add \fBes7s C45/Kalm\fP to rgb colors list +.IP \(bu 2 +[NEW] methods \fBpercentile\fP and \fBmedian\fP ; \fBrender_benchmark\fP example +.IP \(bu 2 +[REFACTOR] \fI\%IRenderable\fP rewrite +.IP \(bu 2 +[REFACTOR] \fI\%distribute_padded\fP overloads +.IP \(bu 2 +[REFACTOR] attempt to break cyclic dependency of \fButil.*\fP modules +.IP \(bu 2 +[REFACTOR] moved color transformations and type vars from \fB_commons\fP +.IP \(bu 2 +[TESTS] additional coverage for \fButilnum\fP +.UNINDENT +.SS v2.32\-dev +.sp +Jan 23 +.INDENT 0.0 +.IP \(bu 2 +[DOCS] \fButilnum\fP update +.IP \(bu 2 +[DOCS] docstrings, typing +.IP \(bu 2 +[DOCS] \fButilnum\fP module +.IP \(bu 2 +[FIX] \fBformat_prefixed\fP and \fI\%format_auto_float\fP inaccuracies +.IP \(bu 2 +[FIX] \fBText.prepend\fP typing +.IP \(bu 2 +[FIX] \fI\%TmuxRenderer\fP RGB output +.IP \(bu 2 +[NEW] \fI\%Color256\fP aliases \(dqcolorNN\(dq +.IP \(bu 2 +[NEW] \fI\%Highlighter\fP from \fBes7s\fP, colorizing options of \fButilnum\fP helpers +.IP \(bu 2 +[NEW] \fI\%IRenderable\fP result caching +.IP \(bu 2 +[NEW] \fI\%pad\fP, \fI\%padv\fP helpers +.IP \(bu 2 +[NEW] \fBprefix_refpoint_shift\fP argument of PrefixedUnitFormatter +.IP \(bu 2 +[NEW] \fBPrefixedUnitFormatter\fP inheritance +.IP \(bu 2 +[NEW] \fBString\fP and \fBFixedString\fP base renderables +.IP \(bu 2 +[NEW] \fI\%style.merge_styles()\fP +.IP \(bu 2 +[NEW] \fBRenderable\fP __eq__ methods +.IP \(bu 2 +[NEW] \fBStyledString\fP +.IP \(bu 2 +[NEW] \fButilmisc\fP get_char_width(), guess_char_width(), measure_char_width() +.IP \(bu 2 +[NEW] style merging strategies: \fI\%merge_fallback()\fP, \fI\%merge_overwrite\fP +.IP \(bu 2 +[NEW] subsecond delta support for \fBTimeDeltaFormatter\fP +.IP \(bu 2 +[TESTS] \fButilnum\fP update +.IP \(bu 2 +[TESTS] integrated in\-code doctests into pytest +.UNINDENT +.SS v2.23\-dev +.INDENT 0.0 +.IP \(bu 2 +[FIX] \fBOmniHexPrinter\fP missed out newlines +.IP \(bu 2 +[NEW] \fI\%dump\fP printer caching +.IP \(bu 2 +[NEW] \fBPrinters\fP and \fBMappers\fP +.IP \(bu 2 +[NEW] \fI\%SgrRenderer\fP now supports non\-default IO stream specifying +.IP \(bu 2 +[NEW] \fButilstr.StringHexPrinter\fP and \fButilstr.StringUcpPrinter\fP +.IP \(bu 2 +[NEW] add missing \fBhsv_to_rgb\fP function +.IP \(bu 2 +[NEW] extracted \fI\%resolve\fP, \fI\%approximate\fP, \fI\%find_closest\fP from \fI\%Color\fP class to module level, as well as color transform functions +.IP \(bu 2 +[NEW] split \fI\%Text\fP to \fI\%Text\fP and \fI\%FrozenText\fP +.UNINDENT +.SS v2.18\-dev +.INDENT 0.0 +.IP \(bu 2 +[FIX] Disabled automatic rendering of \fI\%echo()\fP and \fI\%render()\fP\&. +.IP \(bu 2 +[NEW] \fI\%ArgCountError\fP migrated from \fBes7s/core\fP\&. +.IP \(bu 2 +[NEW] \fBblack\fP code style. +.IP \(bu 2 +[NEW] \fI\%cval\fP autobuild. +.IP \(bu 2 +[NEW] Add \fBOmniHexPrinter\fP and \fI\%chunk()\fP helper. +.IP \(bu 2 +[NEW] Typehinting. +.UNINDENT +.SS v2.14\-dev +.sp +Dec 22 +.INDENT 0.0 +.IP \(bu 2 +[DOCS] Docs design fixes. +.IP \(bu 2 +[NEW] \fI\%confirm()\fP helper command. +.IP \(bu 2 +[NEW] \fBEscapeSequenceStringReplacer\fP filter. +.IP \(bu 2 +[NEW] \fBexamples/terminal_benchmark\fP script. +.IP \(bu 2 +[NEW] \fBStringFilter\fP and \fBOmniFilter\fP classes. +.IP \(bu 2 +[NEW] Minor core improvements. +.IP \(bu 2 +[NEW] RGB and variations full support. +.IP \(bu 2 +[TESTS] Tests for \fI\%color\fP module. +.UNINDENT +.SS v2.6\-dev +.sp +Nov 22 +.INDENT 0.0 +.IP \(bu 2 +[NEW] \fBTemplateEngine\fP implementation. +.IP \(bu 2 +[NEW] \fI\%Text\fP nesting. +.IP \(bu 2 +[REFACTOR] Changes in \fBConfigurableRenderer.force_styles\fP logic. +.IP \(bu 2 +[REFACTOR] Got rid of \fBSpan\fP class. +.IP \(bu 2 +[REFACTOR] Package reorganizing. +.IP \(bu 2 +[REFACTOR] Rewrite of \fI\%color\fP module. +.UNINDENT +.SS v2.2\-dev +.sp +Oct 22 +.INDENT 0.0 +.IP \(bu 2 +[NEW] \fI\%TmuxRenderer\fP +.IP \(bu 2 +[NEW] \fI\%wait_key()\fP input helper. +.IP \(bu 2 +[NEW] Color config. +.IP \(bu 2 +[NEW] IRenderable\(ga interface. +.IP \(bu 2 +[NEW] Named colors list. +.UNINDENT +.SS v2.1\-dev +.sp +Aug 22 +.INDENT 0.0 +.IP \(bu 2 +[NEW] Color presets. +.IP \(bu 2 +[TESTS] More unit tests for formatters. +.UNINDENT +.SS v2.0\-dev +.sp +Jul 22 +.INDENT 0.0 +.IP \(bu 2 +[REWORK] Complete library rewrite. +.IP \(bu 2 +[DOCS] \fBsphinx\fP and \fBreadthedocs\fP integraton. +.IP \(bu 2 +[NEW] High\-level abstractions \fI\%Color\fP, \fI\%Renderer\fP and \fI\%Style\fP\&. +.IP \(bu 2 +[TESTS] \fBpytest\fP and \fBcoverage\fP integration. +.IP \(bu 2 +[TESTS] Unit tests for formatters and new modules. +.UNINDENT +.SS v1.8 +.sp +Jun 22 +.INDENT 0.0 +.IP \(bu 2 +[NEW] \fBformat_prefixed_unit\fP extended for working with decimal and binary metric prefixes. +.IP \(bu 2 +[NEW] \fBsequence.NOOP\fP SGR sequence and \fBspan.NOOP\fP format. +.IP \(bu 2 +[NEW] \fI\%format_time_delta\fP extended with new settings. +.IP \(bu 2 +[NEW] Added 3 formatters: \fBformat_prefixed_unit\fP, \fI\%format_time_delta\fP, \fI\%format_auto_float\fP\&. +.IP \(bu 2 +[NEW] Max decimal points for \fBauto_float\fP extended from (2) to (max\-2). +.IP \(bu 2 +[REFACTOR] Utility classes reorganization. +.IP \(bu 2 +[REFACTOR] Value rounding transferred from \fI\%format_auto_float\fP to \fBformat_prefixed_unit\fP\&. +.IP \(bu 2 +[TESTS] Unit tests output formatting. +.UNINDENT +.SS v1.7 +.sp +May 22 +.INDENT 0.0 +.IP \(bu 2 +[FIX] Print reset sequence as \fB\ee[m\fP instead of \fB\ee[0m\fP\&. +.IP \(bu 2 +[NEW] \fBSpan\fP constructor can be called without arguments. +.IP \(bu 2 +[NEW] Added \fBspan.BG_BLACK\fP format. +.IP \(bu 2 +[NEW] Added \fI\%ljust_sgr\fP, \fI\%rjust_sgr\fP, \fI\%center_sgr\fP util functions to align strings with SGRs correctly. +.IP \(bu 2 +[NEW] Added SGR code lists. +.UNINDENT +.SS v1.6 +.INDENT 0.0 +.IP \(bu 2 +[REFACTOR] Renamed \fBcode\fP module to \fBsgr\fP because of conflicts in PyCharm debugger (\fBpydevd_console_integration.py\fP). +.IP \(bu 2 +[REFACTOR] Ridded of \fBEmptyFormat\fP and \fBAbstractFormat\fP classes. +.IP \(bu 2 +[TESTS] Excluded \fBtests\fP dir from distribution package. +.UNINDENT +.SS v1.5 +.INDENT 0.0 +.IP \(bu 2 +[REFACTOR] Removed excessive \fBEmptySequenceSGR\fP \-\- default \fBSGR\fP class was specifically implemented to print out as empty string instead of \fB\ee[m\fP if constructed without params. +.UNINDENT +.SS v1.4 +.INDENT 0.0 +.IP \(bu 2 +[NEW] \fBSpan.wrap()\fP now accepts any type of argument, not only \fIstr\fP\&. +.IP \(bu 2 +[NEW] Added equality methods for \fI\%SequenceSGR\fP and \fBSpan\fP classes/subclasses. +.IP \(bu 2 +[REFACTOR] Rebuilt \fBSequence\fP inheritance tree. +.IP \(bu 2 +[TESTS] Added some tests for \fBfmt.*\fP and \fBseq.*\fP classes. +.UNINDENT +.SS v1.3 +.INDENT 0.0 +.IP \(bu 2 +[NEW] Added \fBspan.GRAY\fP and \fBspan.BG_GRAY\fP format presets. +.IP \(bu 2 +[REFACTOR] Interface revisioning. +.UNINDENT +.SS v1.2 +.INDENT 0.0 +.IP \(bu 2 +[NEW] \fBEmptySequenceSGR\fP and \fBEmptyFormat\fP classes. +.IP \(bu 2 +[NEW] \fBopening_seq\fP and \fBclosing_seq\fP properties for \fBSpan\fP class. +.UNINDENT +.SS v1.1 +.sp +Apr 22 +.INDENT 0.0 +.IP \(bu 2 +[NEW] Autoformat feature. +.UNINDENT +.SS v1.0 +.INDENT 0.0 +.IP \(bu 2 + First public version. +.UNINDENT +.SS v0.90 +.sp +Mar 22 +.INDENT 0.0 +.IP \(bu 2 + First commit. +.UNINDENT +.SH LICENSE +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + +.ft P +.fi +.UNINDENT +.UNINDENT +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, \(dqthis License\(dq refers to version 3 of the GNU Lesser +General Public License, and the \(dqGNU GPL\(dq refers to version 3 of the GNU +General Public License. + + \(dqThe Library\(dq refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An \(dqApplication\(dq is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A \(dqCombined Work\(dq is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the \(dqLinked +Version\(dq. + + The \(dqMinimal Corresponding Source\(dq for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The \(dqCorresponding Application Code\(dq for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user\(aqs computer + system, and (b) will operate properly with a modified version + of the Library that is interface\-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License \(dqor any later version\(dq +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy\(aqs public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. + +.ft P +.fi +.UNINDENT +.UNINDENT +.SS Disclaimer of Warranty +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER +PARTIES PROVIDE THE PROGRAM \(dqAS IS\(dq WITHOUT WARRANTY OF ANY KIND, EITHER +EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE +QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE +DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +.ft P +.fi +.UNINDENT +.UNINDENT +.SS Limitation of Liability +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS +PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, +INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE +THE PROGRAM, INCLUDING BUT NOT LIMITED TO LOSSES OF DATA, FAILURES OF THE +PROGRAM TO OPERATE WITH OTHER PROGRAMS, OTHER LOSSES AS WELL AS ACQUISITIONS, +BREAKDOWNS, REPAIRS, UNSCREWINGS, BLACKOUTS, FAINTINGS, INJURIES, BURNS, SNOW +AVALANCHES, EARTHQUAKES, VOLCANIC, GEYSER AND LIMNIC ERUPTIONS, TYPHOONS, +METEORITE AND SATELLITE FALLS AND OTHER NATURAL DISASTERS, AS WELL AS +BEHAVIORAL DEVIATIONS OF PEOPLE, SHARKS, SNAKES AND OTHER ANIMALS, ROBBERIES, +ASSAULTS, RAPES, THEFTS AND BURGLARIES, DRUNKEN BRAWLS AND RIOTS, INCESTS, +ABORTIONS, SHOULDER DISLOCATIONS, MILITARY CONSCRIPTIONS, DISFELLOWSHIPPINGS, +CONFINEMENTS AND EXTRADITIONS, DIVORCEMENTS, DEMOTIONS AND PROMOTIONS, EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +.ft P +.fi +.UNINDENT +.UNINDENT +.SH DOCS GUIDELINES +.sp +(mostly as a reminder for myself) +.SS General +.INDENT 0.0 +.IP \(bu 2 +Basic types and built\-in values should be surrounded with asterisks: +.INDENT 2.0 +.INDENT 3.5 +\fB*True*\fP → \fITrue\fP +.sp +\fB*None*\fP → \fINone\fP +.sp +\fB*int*\fP → \fIint\fP +.UNINDENT +.UNINDENT +.IP \(bu 2 +Library classes, methods, etc. should be enclosed in single backticks in order to become a hyperlinks: +.INDENT 2.0 +.INDENT 3.5 +\fB\(gaSgrRenderer.render()\(ga\fP → \fI\%SgrRenderer.render()\fP +.UNINDENT +.UNINDENT +.sp +If class name is ambiguous (e.g., there is a glossary term with the same name), the solution is to specify the type explicitly: +.INDENT 2.0 +.INDENT 3.5 +\fB:class:\(ga.Style\(ga\fP → \fI\%Style\fP +.UNINDENT +.UNINDENT +.IP \(bu 2 +Argument names and string literals that include escape sequences or their fragments should be wrapped in double backticks: +.INDENT 2.0 +.INDENT 3.5 +\fB\(ga\(gaarg1\(ga\(ga\fP → \fBarg1\fP +.sp +\fB\(ga\(gaESC\ [31m\ ESC\ [m\(ga\(ga\fP → \fBESC [31m ESC [m\fP +.UNINDENT +.UNINDENT +.sp +On the top of that, ESC control char should be padded with spaces for better readability. This also triggers automatic application of custom style for even more visual difference. +.IP \(bu 2 +Any formula should be formatted using LaTeX syntax (\fB:math:\fP role or +\fB\&.. math::\fP directive): +.INDENT 2.0 +.INDENT 3.5 +.sp +.ce +d_{min} = 350*10^{\-3} + + +.ce 0 +.UNINDENT +.UNINDENT +.UNINDENT +.SS Hexadecimals +.sp +Hexadecimal numbers should be displayed using \fB:hex:\fP role (applies to all +examples below except the last one). In general, when the characters are +supposed to be typed manually, or when the result length is 6+ chars, it\(aqs +better to use lower case; when the numbers are distinct or \(dqU+\(dq notation is +used, the upper case is acceptable: +.INDENT 0.0 +.TP +.B separate bytes +0x1B 0x23 0x88 +.TP +.B Unicode codepoints +U+21BC ; U+F0909 +.TP +.B hex dump +\(dq0x 00 AF 00 BB 11 BD AA B5\(dq +.TP +.B UTF\-8 +e0a489 efbfbe efbfaf f0af8cb3 +.TP +.B RGB colors (\fIint\fP/\fIstr\fP forms) +0xeb0c0c ; #ff00ff +.UNINDENT +.sp +escaped strings +.INDENT 0.0 +.INDENT 3.5 +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +\(dq\eu21bc\(dq, \(dq\eU000f0909\(dq, re.compile(R\(dq\ex1b\e[[0\-9;]*m\(dq) +.ft P +.fi +.UNINDENT +.UNINDENT +.UNINDENT +.UNINDENT +.SS References +.TS +center; +|l|l|l|. +_ +T{ +External +pages +T} T{ +\fI\%github\fP and +\fI\%gitlab\fP +T} T{ +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +\(gagithub\(ga_ and +\(gagitlab \(ga_ + +\&.. _github: //github.com +.ft P +.fi +.UNINDENT +.UNINDENT +T} +_ +T{ +External pydoc +T} T{ +\fBre.Match\fP +T} T{ +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +:class:\(gare.Match\(ga +.ft P +.fi +.UNINDENT +.UNINDENT +T} +_ +T{ +Internal page +T} T{ +\fI\%Guide · Low\-level\fP or +\fI\%high\-level\fP +T} T{ +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +\(gaguide\-lo\(ga or +\(gahigh\-level \(ga +.ft P +.fi +.UNINDENT +.UNINDENT +T} +_ +T{ +Internal page +setup +T} T{ +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +\&.. _guide.core\-api\-1: +.ft P +.fi +.UNINDENT +.UNINDENT +T} +_ +T{ +Internal pydoc +T} T{ +\fI\%wait_key()\fP, +\fI\%Style\fP +T} T{ +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +\(gawait_key()\(ga, +:class:\(ga.Style\(ga +.ft P +.fi +.UNINDENT +.UNINDENT +T} +_ +T{ +Internal anchor +T} T{ +\fI\%References\fP +T} T{ +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +\(gaReferences\(ga_ +.ft P +.fi +.UNINDENT +.UNINDENT +T} +_ +T{ +Term in glossary +T} T{ +\fI\%rendering\fP +T} T{ +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +:term:\(garendering\(ga +.ft P +.fi +.UNINDENT +.UNINDENT +T} +_ +T{ +Inlined +definition +T} T{ +.nf +classifier for 1st time ... +.in +2 +\&... or \fIclassifier\fP later +.in -2 +.fi +T} T{ +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +:def:\(gaclassifier\(ga for 1st time ... + ... or *classifier* later +.ft P +.fi +.UNINDENT +.UNINDENT +T} +_ +T{ +Abbreviation +T} T{ +EL +T} T{ +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +:abbr:\(gaEL (Erase in Line)\(ga +.ft P +.fi +.UNINDENT +.UNINDENT +T} +_ +.TE +.SS Headers +.SS Section header +.SS Subsection header +.SS Paragraph header +.sp +Rubric +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +########################## +Docs guidelines +########################## +\&.. part header + +================= +Headers +================= +\&.. chapter header + +\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- +Section header +\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- + +Subsection header +\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- + +Paragraph header +\(dq\(dq\(dq\(dq\(dq\(dq\(dq\(dq\(dq\(dq\(dq\(dq\(dq\(dq\(dq\(dq\(dq\(dq + +\&.. rubric:: Rubric + +\&.. code\-block:: rst + + ... +.ft P +.fi +.UNINDENT +.UNINDENT +.SH AUTHOR +Alexandr Shavykin +.SH COPYRIGHT +2022-2023, A. Shavykin +.\" Generated by docutils manpage writer. +. diff --git a/docs-build/2.106.4.pdf b/docs-build/2.106.4.pdf new file mode 100644 index 00000000..da02c7c6 Binary files /dev/null and b/docs-build/2.106.4.pdf differ diff --git a/docs/_generated/features/formatter-si.png b/docs/_generated/features/formatter-si.png new file mode 100644 index 00000000..cab4729b Binary files /dev/null and b/docs/_generated/features/formatter-si.png differ diff --git a/docs/_generated/features/formatter-time-delta.png b/docs/_generated/features/formatter-time-delta.png new file mode 100644 index 00000000..177f0cd2 Binary files /dev/null and b/docs/_generated/features/formatter-time-delta.png differ diff --git a/docs/_generated/features/formatter-time-ns.png b/docs/_generated/features/formatter-time-ns.png new file mode 100644 index 00000000..8567cd0c Binary files /dev/null and b/docs/_generated/features/formatter-time-ns.png differ diff --git a/docs/_generated/features/named-colors.png b/docs/_generated/features/named-colors.png new file mode 100644 index 00000000..eafdaac2 Binary files /dev/null and b/docs/_generated/features/named-colors.png differ diff --git a/docs/_generated/features/xterm-truecolor.png b/docs/_generated/features/xterm-truecolor.png new file mode 100644 index 00000000..f49925af Binary files /dev/null and b/docs/_generated/features/xterm-truecolor.png differ diff --git a/docs/_static/color.css b/docs/_static/color.css index 7f3f9e86..9327d753 100644 --- a/docs/_static/color.css +++ b/docs/_static/color.css @@ -89,9 +89,37 @@ color: purple; } +.xdaracu { + color: #DA9AC4; +} +.redonblue { + color: red; + background: blue; +} +.yellowonredline { + color: yellow; + background: red; + font-weight: bold; +} +.blackonyellow { + color: black; + background: yellow; +} +.blackonblue { + color: black; + background: blue; +} -.bgteal { +.bgteal, +.bgtealline { background-color: teal; +} +.bgteal { + color: teal; + margin: 0.25em; +} +.yellowonredline, +.bgtealline { display: block; } diff --git a/docs/_static/custom-furo.css b/docs/_static/custom-furo.css index abdcfb5e..6bdc3a04 100644 --- a/docs/_static/custom-furo.css +++ b/docs/_static/custom-furo.css @@ -196,9 +196,15 @@ div.graphviz { background: var(--color-pt-doctest-background); border: 1px solid var(--color-pt-doctest-border) } -.highlight-output > .highlight, -body[data-theme="dark"] .highlight-output > .highlight { - background: var(--color-pt-output-background); +.output { + border: 1px inset var(--color-pt-doctest-border); + border-radius: 0; + box-sizing: border-box; +} +.output p, +.output div { + background: #000 !important; + color: #fff !important; } .highlight-adjacent:not(:last-of-type) { margin-bottom: 0 !important; @@ -227,6 +233,10 @@ button.copybtn { background: var(--color-pt-doctest-background); } +body:not([data-theme="light"]) .highlight .hll { + background-color: #1c4161; +} + /** Hyperlinks **/ a, @@ -281,6 +291,9 @@ a.image-reference img { .bottom-of-page .icons { gap: 0.75rem; } +.fullwidthimage img { + margin: 0; +} body .graphviz-default, body[data-theme="dark"] .graphviz-dark { @@ -512,6 +525,10 @@ dl[class].field-list em { /** XTerm palette **/ +.bgteal { + border: 1px solid var(--color-foreground-border); +} + table.xterm-palette td { font-family: ASM, monospace; text-align: center; diff --git a/docs/_static/custom.js b/docs/_static/custom.js index 58bc0850..28ae334c 100644 --- a/docs/_static/custom.js +++ b/docs/_static/custom.js @@ -49,12 +49,24 @@ function formatEnvLists() { } function squashNeighbourCodeSetions() { - // find "highlight-adjacent"s _preceeded_ by a "highlight-default"s - // and add adjacent classes to the latter. as of 2023 ":has" selector - // is not guaranteed to work in ALL browsers, but to hell with that - $("div.highlight-default:has(+ div.highlight-adjacent)").each( + // find "highlight-adjacent"'s _preceeded_ by a div with a "highlight" + // div inside and add adjacent classes to that parent div: + // + //
+ // ...
+ // + //
...
+ // + // $("div:has(div.highlight):has(+ div.highlight-adjacent)").each( + // (idx, el) => el.classList.add("highlight-adjacent") + // ); + + // actually found a bit better way; this will match all languages, + // including .highlight-python and .highlight-console: + $("div[class|=highlight]:has(+ div.highlight-adjacent)").each( (idx, el) => el.classList.add("highlight-adjacent") ); + // as of 2023 ":has" selector is not guaranteed to work in ALL browsers, but to hell with that } function formatEscCharLabels() { diff --git a/docs/conf_extras/_prolog.rsti b/docs/conf_extras/_prolog.rsti index 612f2f7c..c16c79cc 100644 --- a/docs/conf_extras/_prolog.rsti +++ b/docs/conf_extras/_prolog.rsti @@ -32,15 +32,44 @@ .. include:: .. include:: +.. role:: xdaracu + :class: xdaracu + +.. role:: redonblue + :class: redonblue + +.. role:: yellowonredline + :class: yellowonredline + +.. role:: blackonyellow + :class: blackonyellow + +.. role:: blackonblue + :class: blackonblue + .. role:: bgteal :class: bgteal +.. role:: bgtealline + :class: bgtealline + .. |nbspt| unicode:: 0xA0 :trim: -.. |nbspt5| replace:: |nbspt| |nbspt| |nbspt| |nbspt| |nbspt| - -.. |nbspt10| replace:: |nbspt5| |nbspt5| +.. |nbspt2| replace:: |nbspt|\ |nbspt| +.. |nbspt3| replace:: |nbspt2|\ |nbspt| +.. |nbspt4| replace:: |nbspt3|\ |nbspt| +.. |nbspt5| replace:: |nbspt4|\ |nbspt| +.. |nbspt6| replace:: |nbspt5|\ |nbspt| +.. |nbspt7| replace:: |nbspt6|\ |nbspt| +.. |nbspt8| replace:: |nbspt7|\ |nbspt| +.. |nbspt9| replace:: |nbspt8|\ |nbspt| +.. |nbspt10| replace:: |nbspt9|\ |nbspt| +.. |nbspt11| replace:: |nbspt10|\ |nbspt| +.. |nbspt12| replace:: |nbspt11|\ |nbspt| +.. |nbspt13| replace:: |nbspt12|\ |nbspt| +.. |nbspt14| replace:: |nbspt13|\ |nbspt| +.. |nbspt15| replace:: |nbspt14|\ |nbspt| .. role:: badge :class: badge diff --git a/docs/conf_extras/latex_elements.py b/docs/conf_extras/latex_elements.py index e26ed7c7..2672b887 100644 --- a/docs/conf_extras/latex_elements.py +++ b/docs/conf_extras/latex_elements.py @@ -10,13 +10,15 @@ def get() -> dict: # 'passoptionstopackages': r'\PassOptionsToPackage{svgnames}{xcolor}', # "papersize" : "a4paper", # letter,a4paper "pointsize" : "10pt", # 10,11,12 - "inputenc" : "", # -+ - "utf8extra" : "", # -+- both necessary for unicode in pdf + "inputenc" : "\\usepackage[utf8]", # ⎫ + "utf8extra" : "", # ⎭ both necessary for unicode in pdf "classoptions" : ",openany,oneside", # remove blank pages "babel" : "\\usepackage[english]{babel}", # quote symbols and more - "pxunit" : "0.5bp", # (dpi = 72*bp) doesnt work btw + "pxunit" : "0.5bp", # (dpi = 72*bp) doesnt work btw "figure_align" : "H", # text wrapping - "fncychap" : read_x('latex_fncychap.sty'), # chapter start pages + "fncychap" : read_x('latex_fncychap.sty'), # chapter start pages + #'fontpkg' : '\\usepackage{amsmath,amsfonts,amssymb,amsthm}', + # 'fontpkg' : '\\usepackage[defaultsans]{lato}', "printindex" : r"\footnotesize\raggedright\printindex", # decrease font for index } diff --git a/docs/conf_extras/latex_preamble.sty b/docs/conf_extras/latex_preamble.sty index 0cd9a8d8..49619ab5 100644 --- a/docs/conf_extras/latex_preamble.sty +++ b/docs/conf_extras/latex_preamble.sty @@ -1,5 +1,6 @@ -\usepackage{tcolorbox} +\RequirePackage{xcolor}\usepackage{tcolorbox} \usepackage{pgffor} +\usepackage{charter} % main font \newcommand{\DUroleblack}[1]{{\color[HTML]{000000} #1}} \newcommand{\DUrolegray}[1]{{\color[HTML]{808080} #1}} @@ -22,12 +23,58 @@ \newcommand{\DUrolenavy}[1]{{\color[HTML]{000080} #1}} \newcommand{\DUrolepurple}[1]{{\color[HTML]{800080} #1}} +\newtcbox{fgbgbox}[1][]{notitle,on line,size=fbox,left=0pt,right=0pt,boxrule=0px,arc=0pt,outer arc=0pt,#1} + +\definecolor{xdaracu}{HTML}{DA9AC4} + +\newcommand{\DUrolexdaracu}[1]{{\begin{fgbgbox}[colupper=xdaracu,colback=black]{#1}\end{fgbgbox}}} +\newcommand{\DUroleredonblue}[1]{{\begin{fgbgbox}[colupper=red,colback=blue]{#1}\end{fgbgbox}}} +\newcommand{\DUroleblackonyellow}[1]{{\begin{fgbgbox}[colupper=black,colback=yellow]{#1}\end{fgbgbox}}} +\newcommand{\DUroleblackonblue}[1]{{\begin{fgbgbox}[colupper=black,colback=blue]{#1}\end{fgbgbox}}} + \newcommand{\DUrolebgteal}[1] +{{ + \begin{tcbox}[ + notitle,on line,size=small, + boxrule=1px,arc=0pt,outer arc=0pt, + colback=teal,colupper=teal,colframe=black, + ]{ #1 } + \end{tcbox} +}} + +\newcommand{\DUrolebgtealline}[1] {{ \begin{tcolorbox}[ - on line,arc=0pt,outer arc=0pt, - top=0pt,left=0pt,right=0pt,bottom=0pt, - colback=teal,width=\linewidth + width=\linewidth,notitle,size=small, + boxrule=0pt,arc=0pt,outer arc=0pt, + colback=teal,colupper=white, ]{ #1 } \end{tcolorbox} }} + +\newcommand{\DUroleyellowonredline}[1] +{{ + \begin{tcolorbox}[ + width=\linewidth,notitle,size=small, + boxrule=0pt,arc=0pt,outer arc=0pt, + colback=red,colupper=yellow,fontupper=\bfseries, + ]{ #1 } + \end{tcolorbox} +}} + + +\newenvironment{sphinxclassoutputcaption} +{\begin{centering}} +{\end{centering}} + +\newtcolorbox{sphinxclassoutput}{ + width=\linewidth,notitle,size=title, + before skip=0pt,after skip=.5cm,center,add to width=7pt, + boxrule=1px,arc=0pt,outer arc=0pt, + colback=black,colupper=white,fontupper=\ttfamily, +} + +\newtcolorbox{sphinxclassoutputstandalone}{ + size=minimal,before skip=.5cm, + boxrule=0px,arc=0pt,outer arc=0pt, +} diff --git a/docs/demo/examples.auto-wrap.html b/docs/demo/examples.auto-wrap.html deleted file mode 100644 index 529653d2..00000000 --- a/docs/demo/examples.auto-wrap.html +++ /dev/null @@ -1,5 +0,0 @@ -
-
-imported rich.inspect
-
-
diff --git a/docs/demo/examples.auto-wrap.py b/docs/demo/examples.auto-wrap.py deleted file mode 100644 index 2537b341..00000000 --- a/docs/demo/examples.auto-wrap.py +++ /dev/null @@ -1,3 +0,0 @@ -import pytermor as pt - -pt.echo(pt.enclose(pt.SeqIndex.CYAN, "imported") + " rich.inspect") diff --git a/docs/demo/examples.fragments-fstrings.html b/docs/demo/examples.fragments-fstrings.html deleted file mode 100644 index ec0398e3..00000000 --- a/docs/demo/examples.fragments-fstrings.html +++ /dev/null @@ -1,7 +0,0 @@ -
-
-  bisect              Use binary search to find the commit that introduced a bug
-  diff                Show changes between commits, commit and working tree, etc
-  grep                Print lines matching a pattern
-
-
diff --git a/docs/demo/examples.fragments-fstrings.py b/docs/demo/examples.fragments-fstrings.py deleted file mode 100644 index 4661d278..00000000 --- a/docs/demo/examples.fragments-fstrings.py +++ /dev/null @@ -1,12 +0,0 @@ -import pytermor as pt - -data = [ - ("bisect", "Use binary search to find the commit that introduced a bug"), - ("diff", "Show changes between commits, commit and working tree, etc"), - ("grep", "Print lines matching a pattern"), -] - -st = pt.Style(fg=pt.cv.GREEN) -for name, desc in data: - frag = pt.Fragment(name, st) - pt.echo(f" {frag:<16s} {desc}") diff --git a/docs/demo/examples.frozentexts.html b/docs/demo/examples.frozentexts.html deleted file mode 100644 index 9a47ae31..00000000 --- a/docs/demo/examples.frozentexts.html +++ /dev/null @@ -1,7 +0,0 @@ -
-
-  add               Add file contents to the index
-  mv                Move or rename a file, a directory, or a symlink
-  restore           Restore working tree files
-
-
diff --git a/docs/demo/examples.frozentexts.py b/docs/demo/examples.frozentexts.py deleted file mode 100644 index 550caa53..00000000 --- a/docs/demo/examples.frozentexts.py +++ /dev/null @@ -1,11 +0,0 @@ -import pytermor as pt - -data = [ - ("add", "Add file contents to the index"), - ("mv", "Move or rename a file, a directory, or a symlink"), - ("restore", "Restore working tree files"), -] -st = pt.Style(fg=pt.cv.GREEN) - -for name, desc in data: - pt.echo([pt.FrozenText(" ", name, st, width=18, pad=4), desc]) diff --git a/docs/demo/examples.manual-wrap.html b/docs/demo/examples.manual-wrap.html deleted file mode 100644 index 529653d2..00000000 --- a/docs/demo/examples.manual-wrap.html +++ /dev/null @@ -1,5 +0,0 @@ -
-
-imported rich.inspect
-
-
diff --git a/docs/demo/examples.manual-wrap.py b/docs/demo/examples.manual-wrap.py deleted file mode 100644 index c8d3293c..00000000 --- a/docs/demo/examples.manual-wrap.py +++ /dev/null @@ -1,3 +0,0 @@ -import pytermor as pt - -print(f"{pt.SeqIndex.CYAN}imported{pt.SeqIndex.RESET} rich.inspect", end="") diff --git a/docs/demo/examples.refilters.html b/docs/demo/examples.refilters.html deleted file mode 100644 index ebf00bca..00000000 --- a/docs/demo/examples.refilters.html +++ /dev/null @@ -1,7 +0,0 @@ -
-
-   reset             Reset current HEAD to the specified state
-   switch            Switch branches
-   tag               Create, list, delete or verify a tag object signed with GPG
-
-
diff --git a/docs/demo/examples.refilters.py b/docs/demo/examples.refilters.py deleted file mode 100644 index 91d0f20b..00000000 --- a/docs/demo/examples.refilters.py +++ /dev/null @@ -1,19 +0,0 @@ -import re -import pytermor as pt - -s = """ - reset Reset current HEAD to the specified state - switch Switch branches - tag Create, list, delete or verify a tag object signed with GPG -""" - -class SgrNamedGroupsRefilter(pt.AbstractNamedGroupsRefilter): - def _render(self, v: pt.IT, st: pt.FT) -> str: - return pt.render(v, st, pt.SgrRenderer) - -f = SgrNamedGroupsRefilter( - re.compile(r"(\s+)(?P\S+)(.+)"), - {"cmd": pt.cv.GREEN}, -) - -pt.echo(pt.apply_filters(s, f)) diff --git a/docs/demo/examples.regexp-group-rendering.html b/docs/demo/examples.regexp-group-rendering.html deleted file mode 100644 index 789ac99b..00000000 --- a/docs/demo/examples.regexp-group-rendering.html +++ /dev/null @@ -1,7 +0,0 @@ -
-
-   fetch             Download objects and refs from another repository
-   pull              Fetch from and integrate with another repository or a local branch
-   push              Update remote refs along with associated objects
-
-
diff --git a/docs/demo/examples.regexp-group-rendering.py b/docs/demo/examples.regexp-group-rendering.py deleted file mode 100644 index ac3fe996..00000000 --- a/docs/demo/examples.regexp-group-rendering.py +++ /dev/null @@ -1,30 +0,0 @@ -import re -import pytermor as pt - -s = """ - fetch Download objects and refs from another repository - pull Fetch from and integrate with another repository or a local branch - push Update remote refs along with associated objects -""" - -regex = re.compile(r"^(\s+)(\S+)(.+)$") -for line in s.splitlines(): - pt.echo( - regex.sub( - pt.render(r"\1" + pt.Fragment(r"\2", pt.cv.GREEN) + r"\3"), - line, - ) - ) - -# [extra-1-start] -def replace_expand(m: re.Match) -> str: - tpl = pt.render(r"\1" + pt.Fragment(r"\2", pt.cv.GREEN) + r"\3") - return m.expand(tpl) -regex.sub(replace_expand, "...") -# [extra-1-end] - -# [extra-2-start] -def replace_manual(m: re.Match) -> str: - return pt.render(m.group(1) + pt.Fragment(m.group(2), pt.cv.GREEN) + m.group(3)) -regex.sub(replace_manual, "...") -# [extra-2-end] diff --git a/docs/demo/examples.templates.html b/docs/demo/examples.templates.html deleted file mode 100644 index 3ab2c69b..00000000 --- a/docs/demo/examples.templates.html +++ /dev/null @@ -1,7 +0,0 @@ -
-
grow, mark and tweak your common history
-   branch            List, create, or delete branches
-   commit            Record changes to the repository
-   merge             Join two or more development histories together
-
-
diff --git a/docs/demo/examples.templates.py b/docs/demo/examples.templates.py deleted file mode 100644 index 6a4d6bf0..00000000 --- a/docs/demo/examples.templates.py +++ /dev/null @@ -1,9 +0,0 @@ -import pytermor as pt - -s = """@st:[fg=yellow bold] @cmd:[fg=green] -:[st]grow, mark and tweak your common history:[-] - :[cmd]branch:[-] List, create, or delete branches - :[cmd]commit:[-] Record changes to the repository - :[cmd]merge:[-] Join two or more development histories together -""" -pt.echo(pt.TemplateEngine().substitute(s)) diff --git a/docs/demo/examples.texts.html b/docs/demo/examples.texts.html deleted file mode 100644 index b8651226..00000000 --- a/docs/demo/examples.texts.html +++ /dev/null @@ -1,5 +0,0 @@ -
-
-work on the current change (see also: git help everyday)
-
-
diff --git a/docs/demo/examples.texts.py b/docs/demo/examples.texts.py deleted file mode 100644 index 384aefba..00000000 --- a/docs/demo/examples.texts.py +++ /dev/null @@ -1,11 +0,0 @@ -import pytermor as pt - -subtitle_st = pt.Style(fg=pt.cv.YELLOW, bold=True) -command_st = pt.Style(fg=pt.cv.GREEN) -text = pt.FrozenText( - ("work on the current change ", subtitle_st), - "(see also: ", - "git help everyday", command_st, - ")" -) -pt.echo(text) diff --git a/docs/demo/examples/fragments.py b/docs/demo/examples/fragments.py deleted file mode 100644 index fafbbe7f..00000000 --- a/docs/demo/examples/fragments.py +++ /dev/null @@ -1,12 +0,0 @@ -from collections.abc import Iterable -import pytermor as pt - -data = [ - ("clone", "Clone a repository into a new directory"), - ("init", "Create an empty Git repository or reinitialize an existing one"), -] - -st = pt.Style(fg=pt.cv.GREEN) -for name, desc in data: - frag = pt.Fragment(name.ljust(16), st) - pt.echo(' ' + frag + desc) diff --git a/docs/demo/examples/fragments.rst b/docs/demo/examples/fragments.rst deleted file mode 100644 index 52749acc..00000000 --- a/docs/demo/examples/fragments.rst +++ /dev/null @@ -1,4 +0,0 @@ -.. container:: highlight highlight-manual highlight-adjacent - - | |nbspt| |nbspt| |nbspt| :green:`clone` |nbspt10| |nbspt| Clone a repository into a new directory - | |nbspt| |nbspt| |nbspt| :green:`init` |nbspt10| |nbspt| |nbspt| Create an empty Git repository or reinitialize an existing one diff --git a/docs/demo/examples/input.txt b/docs/demo/examples/input.txt deleted file mode 100644 index fd9a6450..00000000 --- a/docs/demo/examples/input.txt +++ /dev/null @@ -1,6 +0,0 @@ -These are common Git commands used in various situations: - -start a working area (see also: git help tutorial) - clone Clone a repository into a new directory - init Create an empty Git repository or reinitialize an existing one - [..] diff --git a/docs/demo/examples/output.rst b/docs/demo/examples/output.rst deleted file mode 100644 index d7f71749..00000000 --- a/docs/demo/examples/output.rst +++ /dev/null @@ -1,12 +0,0 @@ -.. container:: code-block-caption - - Part of the output - -.. container:: highlight highlight-manual highlight-adjacent - - | These are common Git commands used in various situations: - | - | :olive:`start a working area` (see also: :green:`git help tutorial`) - | |nbspt| |nbspt| |nbspt| :green:`clone` |nbspt10| |nbspt| Clone a repository into a new directory - | |nbspt| |nbspt| |nbspt| :green:`init` |nbspt10| |nbspt| |nbspt| Create an empty Git repository or reinitialize an existing one - | |nbspt| |nbspt| |nbspt| [..] diff --git a/docs/demo/examples/prerender.py b/docs/demo/examples/prerender.py deleted file mode 100644 index ff228987..00000000 --- a/docs/demo/examples/prerender.py +++ /dev/null @@ -1,8 +0,0 @@ -import pytermor as pt - -subtitle = pt.render("start a working area", pt.Style(fg=pt.cv.YELLOW, bold=True)) -subtitle += " (see also: " -subtitle += pt.render("git help tutorial", pt.cv.GREEN) -subtitle += ")" - -pt.echo(subtitle) diff --git a/docs/demo/examples/prerender.rst b/docs/demo/examples/prerender.rst deleted file mode 100644 index 0fb10f88..00000000 --- a/docs/demo/examples/prerender.rst +++ /dev/null @@ -1,3 +0,0 @@ -.. container:: highlight highlight-manual highlight-adjacent - - :olive:`start a working area` (see also: :green:`git help tutorial`) diff --git a/docs/demo/examples/preset-compositons.py b/docs/demo/examples/preset-compositons.py deleted file mode 100644 index 94cb44a1..00000000 --- a/docs/demo/examples/preset-compositons.py +++ /dev/null @@ -1,5 +0,0 @@ -import pytermor as pt - -col_sgr = pt.make_color_256(30, pt.ColorTarget.BG) + pt.ansi.SeqIndex.BLACK -seq = pt.compose_clear_line_fill_bg(col_sgr) -pt.echo(seq + 'AAAA BBBB') diff --git a/docs/demo/examples/preset-compositons.rst b/docs/demo/examples/preset-compositons.rst deleted file mode 100644 index 30883f2d..00000000 --- a/docs/demo/examples/preset-compositons.rst +++ /dev/null @@ -1,3 +0,0 @@ -.. container:: highlight highlight-manual highlight-adjacent - - :bgteal:`AAA BBBB` diff --git a/docs/demo/features.color-modes.html b/docs/demo/features.color-modes.html deleted file mode 100644 index c704d86a..00000000 --- a/docs/demo/features.color-modes.html +++ /dev/null @@ -1,9 +0,0 @@ -
-
- xterm_16     · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · 
-
- xterm_256    · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · 
-
- true_color   · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · 
-
-
diff --git a/docs/demo/features.color-modes.py b/docs/demo/features.color-modes.py deleted file mode 100644 index f36f0d5d..00000000 --- a/docs/demo/features.color-modes.py +++ /dev/null @@ -1,8 +0,0 @@ -import pytermor as pt - -for outm in ['xterm_16', 'xterm_256', 'true_color']: - print(' '+outm.ljust(12), end="") - for c in range((W := 80) + 1): - b = pt.RGB.from_ratios(1 - (p := c / W), 2 * min(p, 1 - p), p).int - f = pt.Fragment(" ·"[c & 1], pt.Style(fg=(1 << 24) - b, bg=b, bold=True)) - print(f.render(pt.SgrRenderer(outm)), end=["", 2*"\n"][c >= W], flush=True) diff --git a/docs/demo/features.color-spaces.html b/docs/demo/features.color-spaces.html deleted file mode 100644 index 6bd5459e..00000000 --- a/docs/demo/features.color-spaces.html +++ /dev/null @@ -1,8 +0,0 @@ -
-
-RGB[#DA9AC4][R=218 G=154 B=196]
-HSV[H=321° S=29% V=85%]
-XYZ[X=50.43 Y=42.00% Z=57.66]
-LAB[L=70.872% a=30.339 b=-12.031]
-
-
diff --git a/docs/demo/features.color-spaces.py b/docs/demo/features.color-spaces.py deleted file mode 100644 index dc2dac48..00000000 --- a/docs/demo/features.color-spaces.py +++ /dev/null @@ -1,5 +0,0 @@ -import pytermor as pt - -col = pt.RGB(0xDA9AC4) -for v in [col.rgb, col.hsv, col.xyz, col.lab]: - print(repr(v)) diff --git a/docs/demo/features.fargs.html b/docs/demo/features.fargs.html deleted file mode 100644 index b21be221..00000000 --- a/docs/demo/features.fargs.html +++ /dev/null @@ -1,5 +0,0 @@ -
-
-This is red This is white This is black on yellow
-
-
diff --git a/docs/demo/features.fargs.py b/docs/demo/features.fargs.py deleted file mode 100644 index be014c1c..00000000 --- a/docs/demo/features.fargs.py +++ /dev/null @@ -1,9 +0,0 @@ -import pytermor as pt - -ex_st = pt.Style(bg='#ffff00', fg='black') -text = pt.FrozenText( - 'This is red ', pt.cv.RED, - "This is white ", - "This is black on yellow", ex_st, -) -pt.echo(text) diff --git a/docs/demo/features.formatters.py b/docs/demo/features.formatters.py index 84add262..3d7d6969 100644 --- a/docs/demo/features.formatters.py +++ b/docs/demo/features.formatters.py @@ -1,13 +1,28 @@ import io import math +import re import typing as t import pytermor as pt +from pytermor import IRenderer, FT, make_style, Color16 n = lambda j: math.pi**j r = range # DRAFT +class RudimentaryLatexRenderer(IRenderer): + def render(self, string: str, fmt: FT = None) -> str: + if not string: + return "" + style = make_style(fmt) + if not style.fg: + return string + if isinstance(style.fg, Color16): + return f':{style.fg.name}:`{string}`' + print(style) + raise NotImplementedError + + def p(fn: t.Callable, rmin=5, rmax=21, color=True): buf = io.StringIO() print(["+-", ""][color] + "-" * 35 + ["--", "-+"][color], file=buf) @@ -20,7 +35,7 @@ def p(fn: t.Callable, rmin=5, rmax=21, color=True): print(sep, end="|", file=buf) [ pt.echo( - pt.rjust_sgr(pt.render(fn(n(i), auto_color=color), renderer=pt.HtmlRenderer), 10) + pt.rjust_sgr(pt.render(fn(n(i), auto_color=color), renderer=pt.SgrRenderer).replace('`:', '`\ :'), 10) + " " + ["", "|\n|", ""][i % 3], nl=False, @@ -49,4 +64,4 @@ def p(fn: t.Callable, rmin=5, rmax=21, color=True): continue prevt = t if len(t) > 3 or len(t) == 0: - print(t) + print(re.sub(r'[+|-]', ' ', t)) diff --git a/docs/demo/features.formatters.si.html b/docs/demo/features.formatters.si.html deleted file mode 100644 index 6f3c71eb..00000000 --- a/docs/demo/features.formatters.si.html +++ /dev/null @@ -1,9 +0,0 @@ -
-
-        306         961      3.02 k          306         961       3.02 k   
-     9.49 k      29.8 k      93.6 k       9.49 k      29.8 k       93.6 k   
-      294 k       924 k      2.90 M        294 k       924 k       2.90 M   
-     9.12 M      28.7 M      90.0 M       9.12 M      28.7 M       90.0 M   
-      283 M       889 M      2.79 G        283 M       889 M       2.79 G   
-
-
diff --git a/docs/demo/features.formatters.time_delta.html b/docs/demo/features.formatters.time_delta.html deleted file mode 100644 index 3e3687ca..00000000 --- a/docs/demo/features.formatters.time_delta.html +++ /dev/null @@ -1,9 +0,0 @@ -
-
-      9.87s       31.0s       1 min         9.87s      31.0s        1 min
-     5 mins     16 mins     50 mins        5 mins    16 mins      50 mins   
-   2h 38min    8h 16min       1d 2h      2h 38min   8h 16min        1d 2h   
-      3d 9h     10 days     1 month         3d 9h    10 days      1 month   
-   3 months   11 months     2 years      3 months  11 months      2 years   
-
-
diff --git a/docs/demo/features.formatters.time_ns.html b/docs/demo/features.formatters.time_ns.html deleted file mode 100644 index ccc98b68..00000000 --- a/docs/demo/features.formatters.time_ns.html +++ /dev/null @@ -1,15 +0,0 @@ -
-
-      306ns       961ns         3µs        306ns       961ns          3µs
-        9µs        29µs        93µs          9µs        29µs         93µs   
-      294µs       924µs         2ms        294µs       924µs          2ms   
-        9ms        28ms        90ms          9ms        28ms         90ms   
-      282ms       888ms          2s        282ms       888ms           2s
-
-         8s         27s          1m           8s         27s           1m   
-         4m         14m         44m           4m         14m          44m   
-         2h          7h         23h           2h          7h          23h   
-         3d          1w          4w           3d          1w           4w   
-        3mo         9mo         2yr          3mo         9mo          2yr   
-
-
diff --git a/docs/demo/features.named-colors.html b/docs/demo/features.named-colors.html deleted file mode 100644 index 0f11ee11..00000000 --- a/docs/demo/features.named-colors.html +++ /dev/null @@ -1,15 +0,0 @@ -
-
-  ....                                       2472    0xe30022  cadmium-red            
-  2462    0x770001  blood                    2473    0xe4000f  nintendo-red           
-  2463    0x8c000f  crimson                  2474    0xe8000d  ku-crimson             
-  2464    0x980002  blood-red                2475    0xf2003c  red  munsell           
-  2465    0x92000a  sangria                  2476    0xe60026  spanish-red            
-  2466    0xaf002a  alabama-crimson          2477    0xfe0002  fire-engine-red        
-  2467    0xbe0032  crimson-glory            2478    0xff000d  bright-red             
-  2468    0xba0001  ue-red                   2479    0xff0038  carmine-red            
-  2469    0xd70040  carmine  m-p             2480    0xff003f  electric-crimson       
-  2470    0xd3003f  utah-crimson             2481    0xff0028  ruddy                  
-  2471    0xcc0033  vivid-crimson            ....
-
-
diff --git a/docs/demo/features.renderers.html b/docs/demo/features.renderers.html deleted file mode 100644 index 9bba77ad..00000000 --- a/docs/demo/features.renderers.html +++ /dev/null @@ -1,20 +0,0 @@ -
-
-This is red This is white This is black on yellow
-
-
-
-
-<span style="color: #800000">This is red </span><span style="">This is white </span><span style="background-color: #ffff00; color: #000000">This is black on yellow</span>
-
-
-
-
-#[fg=red]This is red #[fg=default]This is white #[fg=black bg=#ffff00]This is black on yellow#[fg=default bg=default]
-
-
-
-
-(ǝ[31m)This is red (ǝ[39m)This is white (ǝ[30;48;5;11m)This is black on yellow(ǝ[39;49m)
-
-
diff --git a/docs/demo/features.templates.html b/docs/demo/features.templates.html deleted file mode 100644 index 355c1273..00000000 --- a/docs/demo/features.templates.html +++ /dev/null @@ -1,3 +0,0 @@ -
-
nested formatting and overlaps
-
diff --git a/docs/demo/features.templates.py b/docs/demo/features.templates.py deleted file mode 100644 index 2ccac42b..00000000 --- a/docs/demo/features.templates.py +++ /dev/null @@ -1,4 +0,0 @@ -import pytermor as pt - -s = """:[fg=red]nested for:[bold]mat:[bg=blue]ting a:[fg=yellow]nd :[-]over:[-]laps""" -pt.echo(pt.TemplateEngine().substitute(s)) diff --git a/docs/pages/apidoc/pytermor.common.rst b/docs/pages/apidoc/pytermor.common.rst index d78b76bf..fa0fdb39 100644 --- a/docs/pages/apidoc/pytermor.common.rst +++ b/docs/pages/apidoc/pytermor.common.rst @@ -10,6 +10,7 @@ .. autosummary:: CDT + CXT FT RT filterf diff --git a/docs/pages/cli.rst b/docs/pages/cli.rst deleted file mode 100644 index d23b9bec..00000000 --- a/docs/pages/cli.rst +++ /dev/null @@ -1,49 +0,0 @@ -.. _cli: - -##################### -CLI usage -##################### - -Commands like the ones below can be used for quick experimenting without loading the IDE: - - - One-liner for system-wide installation :comment:`(which is not recommended)`: - - .. code-block:: console - :class: highlight-adjacent - - $ python -c "import pytermor as pt; pt.echo('RED', 'red')" - - .. container:: highlight highlight-manual highlight-adjacent - - :red:`red text` - - - One-liner for virtual environment (`venv`) with `pytermor` pre-installed (see `install`_) - :comment:`(note that the library source code root folder should be used as current working directory)`: - - .. code-block:: console - :class: highlight-adjacent - - $ PYTHONPATH=. venv/bin/python -c "import pytermor as pt; pt.echo('GREEN', 'green')" - - .. container:: highlight highlight-manual highlight-adjacent - - :green:`green text` - - - Interactive mode for virtual environment with `pytermor` pre-installed - :comment:`(again, current working directory should be sources root dir)`: - - .. code-block:: console - :class: highlight-adjacent - - $ PYTHONSTARTUP=.run-startup.py PYTHONPATH=. venv/bin/python -qi - - .. code-block:: python - :class: highlight-adjacent - - python 3.8.10 - pytermor 2.41.1-dev1 - >>> pt.echo("This is warning, be warned", pt.Styles.WARNING) - - .. container:: highlight highlight-manual highlight-adjacent - - :orange:`This is warning, be warned` diff --git a/docs/pages/examples/index.rst b/docs/pages/examples/index.rst index a4f041fa..1904f480 100644 --- a/docs/pages/examples/index.rst +++ b/docs/pages/examples/index.rst @@ -4,6 +4,26 @@ Examples ################### +Most basic example: + +.. code-block:: python + :class: highlight-adjacent + + import pytermor as pt + + pt.force_ansi_rendering() + pt.echo('RED', 'red') + pt.echo('GREEN', pt.cv.GREEN) + pt.echo("This is warning, be warned", pt.Styles.WARNING) + +.. container:: highlight highlight-manual highlight-adjacent output + + | :red:`red text` + | :lime:`green text` + | :orange:`This is warning, be warned` + +For more advanced ones proceed to the next section. + .. toctree:: rendering diff --git a/docs/pages/examples/rendering.rst b/docs/pages/examples/rendering.rst index a3abbf81..2f9a8b36 100644 --- a/docs/pages/examples/rendering.rst +++ b/docs/pages/examples/rendering.rst @@ -12,6 +12,7 @@ definitions, helpers for composing various terminal escape sequences, the escape sequence abstractions themselves, as well as a large set of filters for chain-like application. + .. _rendering-high-level: ----------------------------------- @@ -23,30 +24,61 @@ pipe an output of ``git`` and apply filters to do the job (yet), instead we copy-paste the output to python source code files as string literals and will try to add a formatting using all primary approaches. -.. literalinclude:: /demo/examples/input.txt - :language: plain +.. code-block:: plain :caption: Part of the input -.. include:: /demo/examples/output.rst + These are common Git commands used in various situations: + + start a working area (see also: git help tutorial) + clone Clone a repository into a new directory + init Create an empty Git repository or reinitialize an existing one + [..] + +.. container:: code-block-caption outputcaption + + Part of the output + +.. container:: highlight highlight-manual highlight-adjacent output + + | These are common Git commands used in various situations: + | + | :yellow:`start a working area` (see also: :lime:`git help tutorial`) + | |nbspt3|\ :lime:`clone`\ |nbspt13|\ Clone a repository into a new directory + | |nbspt3|\ :lime:`init`\ |nbspt14|\ Create an empty Git repository or reinitialize an existing one + | |nbspt3|\ [..] + The examples in this part are sorted from simple ones at the beginning to complicated ones at the end. Isolated pre-rendering ================================ + +.. highlight:: python + :linenothreshold: 5 + Use `render()` method to apply a :term:`style` to a string part individually for -each of them. +each of them:: + + import pytermor as pt + + subtitle = pt.render("start a working area", pt.Style(fg=pt.cv.YELLOW, bold=True)) + subtitle += " (see also: " + subtitle += pt.render("git help tutorial", pt.cv.GREEN) + subtitle += ")" -.. literalinclude:: /demo/examples/prerender.py - :linenos: + pt.echo(subtitle) + +.. container:: highlight highlight-manual highlight-adjacent output + + :yellow:`start a working area` (see also: :lime:`git help tutorial`) -.. include:: /demo/examples/prerender.rst `render()` method uses `SgrRenderer` by default, which is set up automatically depending on output device characteristics and environment setup. Note that ``render()`` accepts `FT` as format argument, which can be `Style` or -`Color` or *str* or *int* (there are a few methods to define a color). +`Color` or *str* or *int* (there are a few ways to define a color). Fragments ==================== @@ -54,32 +86,55 @@ Fragments text string along with a `Style` instance and that's it. ``Fragment`` instances can be safely concatenated with a regular *str* (but not -with another `Fragment`) from the left side as well as from the right side (line -#15). If you attempt to add one ``Fragment`` to another ``Fragment``, you'll end +with another `Fragment`) from the left side as well as from the right side +(highlighted line). If you attempt to add one ``Fragment`` to another +``Fragment``, you'll end up with a `Text` instance (see the example after next). -.. literalinclude:: /demo/examples/fragments.py - :linenos: +.. code-block:: + :emphasize-lines: 12 + + from collections.abc import Iterable + import pytermor as pt + + data = [ + ("clone", "Clone a repository into a new directory"), + ("init", "Create an empty Git repository or reinitialize an existing one"), + ] + + st = pt.Style(fg=pt.cv.GREEN) + for name, desc in data: + frag = pt.Fragment(name.ljust(16), st) + pt.echo(' ' + frag + desc) + +.. container:: highlight highlight-manual highlight-adjacent output -.. include:: /demo/examples/fragments.rst + | |nbspt3|\ :lime:`clone`\ |nbspt13|\ Clone a repository into a new directory + | |nbspt3|\ :lime:`init`\ |nbspt14|\ Create an empty Git repository or reinitialize an existing one Fragments in f-strings ====================== Another approach to align a formatted text is to combine Python's *f-strings* -with `Fragment` instances. +with `Fragment` instances:: -.. literalinclude:: /demo/examples.fragments-fstrings.py - :linenos: + import pytermor as pt -.. only:: html + data = [ + ("bisect", "Use binary search to find the commit that introduced a bug"), + ("diff", "Show changes between commits, commit and working tree, etc"), + ("grep", "Print lines matching a pattern"), + ] - .. raw:: html - :file: ../demo/examples.fragments-fstrings.html + st = pt.Style(fg=pt.cv.GREEN) + for name, desc in data: + frag = pt.Fragment(name, st) + pt.echo(f" {frag:<16s} {desc}") -.. only:: latex +.. container:: highlight highlight-manual highlight-adjacent output - .. figure:: /demo/examples.fragments-fstrings.svg - :align: center + | |nbspt3|\ :lime:`bisect`\ |nbspt12|\ Use binary search to find the commit that introduced a bug + | |nbspt3|\ :lime:`diff`\ |nbspt14|\ Show changes between commits, commit and working tree, etc + | |nbspt3|\ :lime:`grep`\ |nbspt14|\ Print lines matching a pattern Texts & FrozenTexts ==================== @@ -91,20 +146,23 @@ but most importantly it supports :def:`fargs` syntax (for the details see `guide which allows to compose formatted text parts much faster and keeps the code compact. Generally speaking, the basic input parameter is either a tuple of string and `Style` or `Color`, which then will be applied to preceeding string, or a standalone string. Usually -explicit definition of a tuple is not neccessary, but there are cases, when it is. +explicit definition of a tuple is not neccessary, but there are cases, when it is:: -.. literalinclude:: /demo/examples.texts.py - :linenos: + import pytermor as pt -.. only:: html + subtitle_st = pt.Style(fg=pt.cv.YELLOW, bold=True) + command_st = pt.Style(fg=pt.cv.GREEN) + text = pt.FrozenText( + ("work on the current change ", subtitle_st), + "(see also: ", + "git help everyday", command_st, + ")" + ) + pt.echo(text) - .. raw:: html - :file: ../demo/examples.texts.html +.. container:: highlight highlight-manual highlight-adjacent output -.. only:: latex - - .. figure:: /demo/examples.texts.svg - :align: center + :yellow:`work on the current change` (see also: :lime:`git help everyday`\ ) `FrozenText` is an immutable version of `Text` (to be precise, its quite the opposite: ``Text`` is a child of ``FrozenText``). @@ -112,19 +170,26 @@ opposite: ``Text`` is a child of ``FrozenText``). We will utilize aligning capabilities of ``FrozenText`` class in a following code fragment: -.. literalinclude:: /demo/examples.frozentexts.py - :linenos: +.. code-block:: :emphasize-lines: 11 -.. only:: html + import pytermor as pt + + data = [ + ("add", "Add file contents to the index"), + ("mv", "Move or rename a file, a directory, or a symlink"), + ("restore", "Restore working tree files"), + ] + st = pt.Style(fg=pt.cv.GREEN) - .. raw:: html - :file: ../demo/examples.frozentexts.html + for name, desc in data: + pt.echo([pt.FrozenText(" ", name, st, width=18, pad=4), desc]) -.. only:: latex +.. container:: highlight highlight-manual highlight-adjacent output - .. figure:: /demo/examples.frozentexts.svg - :align: center + | |nbspt3|\ :lime:`add`\ |nbspt15|\ Add file contents to the index + | |nbspt3|\ :lime:`mv`\ |nbspt15| Move or rename a file, a directory, or a symlink + | |nbspt3|\ :lime:`restore`\ |nbspt11|\ Restore working tree files At highlighted line we compose a `FrozenText` instance with command name and set up desired width (18=16+2 for right margin), and explicitly set up @@ -140,23 +205,26 @@ Template tags ======================== There is a support of library's internal tag format, which allows to inline formatting into the original string, and get the final result by calling just -one method: - -.. literalinclude:: /demo/examples.templates.py - :linenos: +one method:: -.. only:: html + import pytermor as pt - .. raw:: html - :file: ../demo/examples.templates.html + s = """@st:[fg=yellow bold] @cmd:[fg=green] + :[st]grow, mark and tweak your common history:[-] + :[cmd]branch:[-] List, create, or delete branches + :[cmd]commit:[-] Record changes to the repository + :[cmd]merge:[-] Join two or more development histories together + """ + pt.echo(pt.TemplateEngine().substitute(s)) -.. only:: latex +.. container:: highlight highlight-manual highlight-adjacent output - .. figure:: /demo/examples.templates.svg - :align: center + | |nbspt3|\ :lime:`branch`\ |nbspt12|\ List, create, or delete branches + | |nbspt3|\ :lime:`commit`\ |nbspt12|\ Record changes to the repository + | |nbspt3|\ :lime:`merge`\ |nbspt13|\ Join two or more development histories together -Here ``@st:[fg=yellow bold]`` is a definition of a custom user style named ``st``, -``:[st]`` is a opening tag for that style, and ``:[-]`` is a closing tag matching +Here ``"@st:[fg=yellow bold]"`` is a definition of a custom user style named *"st"*, +``":[st]"`` is a opening tag for that style, and ``":[-]"`` is a closing tag matching the most recently opened one. See `guide.templates` for the details. .. Template postprocessing @@ -170,38 +238,47 @@ A little bit artificial example, but this method can be applied to solve real tasks nevertheless. The trick is to apply the desired style to a string containing special characters like ``r"\1"``, which will represent regexp group 1 after passing it into ``re.sub()``. The actual -string being passed as 2nd argument will be ``ESC [ 32m \1 ESC [ m``. Regexp -substitution function will replace all ``\1`` with a matching group in every +string being passed as 2nd argument will be ``" ESC [ 32m \1 ESC [ m"``. Regexp +substitution function will replace all ``"\1"`` with a matching group in every line of the input, therefore the match will end up being surrounded with -(already rendered) SGRs responsible for green text color, ???, PROFIT: +(already rendered) SGRs responsible for green text color, ???, PROFIT:: -.. literalinclude:: /demo/examples.regexp-group-rendering.py - :linenos: - :end-before: [extra-1-start] + import re + import pytermor as pt -.. only:: html + s = """ + fetch Download objects and refs from another repository + pull Fetch from and integrate with another repository or a local branch + push Update remote refs along with associated objects + """ - .. raw:: html - :file: ../demo/examples.regexp-group-rendering.html + regex = re.compile(r"^(\s+)(\S+)(.+)$") + for line in s.splitlines(): + pt.echo( + regex.sub( + pt.render(r"\1" + pt.Fragment(r"\2", pt.cv.GREEN) + r"\3"), + line, + ) + ) -.. only:: latex +.. container:: highlight highlight-manual highlight-adjacent output - .. figure:: /demo/examples.regexp-group-rendering.svg - :align: center + | |nbspt3|\ :lime:`fetch`\ |nbspt13|\ Download objects and refs from another repository + | |nbspt3|\ :lime:`pull`\ |nbspt14|\ Fetch from and integrate with another repository or a local branch + | |nbspt3|\ :lime:`push`\ |nbspt14|\ Update remote refs along with associated objects -For more complex logic it's usually better to extract it into separate function: +For more complex logic it's usually better to extract it into separate function:: -.. literalinclude:: /demo/examples.regexp-group-rendering.py - :linenos: - :start-after: [extra-1-start] - :end-before: [extra-1-end] + def replace_expand(m: re.Match) -> str: + tpl = pt.render(r"\1" + pt.Fragment(r"\2", pt.cv.GREEN) + r"\3") + return m.expand(tpl) + regex.sub(replace_expand, "...") -Another approach: +Another approach:: -.. literalinclude:: /demo/examples.regexp-group-rendering.py - :linenos: - :start-after: [extra-2-start] - :end-before: [extra-2-end] + def replace_manual(m: re.Match) -> str: + return pt.render(m.group(1) + pt.Fragment(m.group(2), pt.cv.GREEN) + m.group(3)) + regex.sub(replace_manual, "...") Refilters ======================== @@ -220,18 +297,34 @@ value is a `FT`), then (#19) the refilter is applied and result is printed. is placed into **high**\ -level group, because no manipulation at byte level or at color channel level is performed. -.. literalinclude:: /demo/examples.refilters.py - :linenos: +:: + + import re + import pytermor as pt + + s = """ + reset Reset current HEAD to the specified state + switch Switch branches + tag Create, list, delete or verify a tag object signed with GPG + """ -.. only:: html + class SgrNamedGroupsRefilter(pt.AbstractNamedGroupsRefilter): + def _render(self, v: pt.IT, st: pt.FT) -> str: + return pt.render(v, st, pt.SgrRenderer) - .. raw:: html - :file: ../demo/examples.refilters.html + f = SgrNamedGroupsRefilter( + re.compile(r"(\s+)(?P\S+)(.+)"), + {"cmd": pt.cv.GREEN}, + ) -.. only:: latex + pt.echo(pt.apply_filters(s, f)) + +.. container:: highlight highlight-manual highlight-adjacent output + + | |nbspt3|\ :lime:`reset`\ |nbspt13|\ Reset current HEAD to the specified state + | |nbspt3|\ :lime:`switch`\ |nbspt12|\ Switch branches + | |nbspt3|\ :lime:`tag`\ |nbspt15|\ Create, list, delete or verify a tag object signed with GPG - .. figure:: /demo/examples.refilters.svg - :align: center .. _rendering-low-level: @@ -248,28 +341,37 @@ individual basis. Preset compositions ==================================== -Preset composition methods produce sequence instances or already rendered -sequence bytes as if they were rendered by `SgrRenderer`. Methods with -names starting with ``make_`` return seq. instances, and methods named -``compose_*`` return *str*, which means that more than one sequence were -involved. +Preset composition methods produce sequence instances or ready-to-print +strings as if they were rendered by `SgrRenderer`. Methods with +names starting with ``make_`` return single sequence instance each, while +methods named ``compose_*`` return *str*\ ings which are several sequences +rendered and concatenated. -In the next example we create an SGR which colors text to black, and bg to -:hex:`0xffaf00` (line #3), then compose a sequence chain which includes: +In the next example we create an SGR which sets background color to +:bgteal:`@`\ :hex:`#008787` (highlighted line) by specifying :term:`xterm-256` +code 30 (see `guide.xterm-256-palette`), then compose a string which includes: - :abbr:`CUP (Cursor Position)` instruction: ``ESC [1;1H``; - - SGR instruction with our prev. defined colors: ``ESC [30;48;5;214m``; + - SGR instruction with our color: ``ESC [48;5;30m``; - :abbr:`EL (Erase in Line)` instruction: ``ESC [0K``. -Effectively this results in a whole terminal line colored with colors specified, +Effectively this results in a whole terminal line colored with a specified color, and note that we did not fill the line with spaces or something like that -- this method is (in theory) faster, because the tty needs to process only ~10-20 characters of input instead of 120+ (average terminal width). -.. literalinclude:: /demo/examples/preset-compositons.py - :linenos: +.. code-block:: + :emphasize-lines: 3 + + import pytermor as pt -.. include:: /demo/examples/preset-compositons.rst + col_sgr = pt.make_color_256(30, pt.ColorTarget.BG) + seq = pt.compose_clear_line_fill_bg(col_sgr) + pt.echo(seq + 'AAAA BBBB') + +.. container:: highlight highlight-manual highlight-adjacent output + + :bgtealline:`AAA BBBB` .. note :: @@ -298,20 +400,15 @@ Assisted wrapping ==================================== Similar to the next one, but here we call helper method `ansi.enclose()`, which automatically builds the closing sequence complement to specified opening one, -while there we pick and insert a closing sequence manually. - -.. literalinclude:: /demo/examples.auto-wrap.py - :linenos: +while there we pick and insert a closing sequence manually:: -.. only:: html + import pytermor as pt - .. raw:: html - :file: ../demo/examples.auto-wrap.html + pt.echo(pt.enclose(pt.SeqIndex.CYAN, "imported") + " rich.inspect") -.. only:: latex +.. container:: highlight highlight-manual highlight-adjacent output - .. figure:: /demo/examples.auto-wrap.svg - :align: center + :cyan:`imported` rich.inspect Manual wrapping ==================================== @@ -327,39 +424,34 @@ be "hard-reset" sequence, which resets the terminal format stack completely (``E ones. `SeqIndex` class contains prepared sequences which can be inserted into f-string -directly without any modifications. +directly without any modifications:: -.. literalinclude:: /demo/examples.manual-wrap.py - :linenos: + import pytermor as pt -.. only:: html + print(f"{pt.SeqIndex.CYAN}imported{pt.SeqIndex.RESET} rich.inspect", end="") - .. raw:: html - :file: ../demo/examples.manual-wrap.html +.. container:: highlight highlight-manual highlight-adjacent output -.. only:: latex - - .. figure:: /demo/examples.manual-wrap.svg - :align: center + :cyan:`imported` rich.inspect Manual instantiating ==================================== In case of necessity of some non-standard sequence types or "illegal" parameter values there is also a possibility to build the sequence from the scratch, instantiating one of the base sequence classes and providing required parameters -values. +values:: + + import pytermor as pt + + print(pt.SequenceCSI("J", 2).assemble(), end="") + # which is equivalent to: + print(pt.make_erase_in_display(2).assemble(), end="") If your case is covered with an existing helper method in `term` package, use it instead of making new instance directly. This approach will make it easier to maintain the code, if something in internal logic of sequence base classes changes in the future. -.. code:: python - - print(pt.SequenceCSI("J", 2).assemble(), end="") - # equivalent to - print(pt.make_erase_in_display(2).assemble(), end="") - Manual assembling :sup:`(don't do this)` ======================================== The last resort method which works in 100% is to assemble the sequence char by char @@ -381,38 +473,42 @@ In short: - they are hard to maintain, - they are hard to debug. -Even if it seems OK for a while: - -.. code-block:: python +Even if it seems OK for a while:: print('\x1b[41m', end="(;¬_¬)") - print('\x1b[41m\x1b[2J\x1b[1;1H', end="(O∆O)") - -...things get worse pretty fast: - -.. code-block:: python - :emphasize-lines: 1 - - print('\x1b[38;2;232;232;22m\x1b[1;41m\x1b[2J\x1b[1;1H', end="(╯°□°)╯") + print('\x1b[1;1H\x1b[41m\x1b[0K', end="(O∆O)") -Compare with the next fragment, which does literally the same as the *highlighted line* -from the example above, but is much easier to read thanks to low-level abstractions: +...things get worse pretty fast:: -.. code-block:: python + print('\x1b[1;1H\x1b[38;2;232;232;22m\x1b[1;41m\x1b[0K', end="(╯°□°)╯") - print(pt.make_color_rgb(232, 232, 22), end="") - print(pt.ansi.SeqIndex.BOLD + pt.ansi.SeqIndex.BG_RED, end="") - print(pt.make_erase_in_display(2).assemble(), end="") - print(pt.make_reset_cursor().assemble(), end="(°~°)") +Compare with the next fragment, which does literally the same as the line +from the example above, but is much easier to read thanks to low-level abstractions:: -Or after adding some high-level abstractions as well: + import pytermor as pt + print( + pt.make_reset_cursor(), + pt.make_color_rgb(232, 232, 22), + pt.ansi.SeqIndex.BOLD, + pt.ansi.SeqIndex.BG_RED, + pt.make_erase_in_line(), + sep="", end="(°~°)", + ) -.. code-block:: python +Or doing the same with high-level abstractions instead:: + import pytermor as pt st = pt.Style(fg=0xe8e816, bg='red', bold=True) fill = pt.compose_clear_line_fill_bg(st.fg.to_sgr()) pt.echo(fill + "(°v°♡)", st) -.. an empty comment that prevents pycharm from eating up - two consecutive newlines at the end, which are required - when the article ends with a code block +.. container:: highlight highlight-manual highlight-adjacent output + + :yellowonredline:`(°v°♡)` + +.. note :: + + The last example also automatically resets the terminal back to normal + state, so that the text that is printed afterwards doesn't have any formatting, + in contrast with other examples requiring to assemble and print `SeqIndex.COLOR_OFF` + and `SeqIndex.BG_COLOR_OFF` (or just `SeqIndex.RESET`) at the end (which is omitted). diff --git a/docs/pages/features.rst b/docs/pages/features.rst index 36e65860..f9269cb7 100644 --- a/docs/pages/features.rst +++ b/docs/pages/features.rst @@ -4,44 +4,43 @@ Features ################# +.. highlight:: python + ================================== Flexible input formats ================================== `guide.fargs` allows to compose formatted text parts much faster and keeps the code -compact: - -.. literalinclude:: /demo/features.fargs.py - :linenos: +compact:: -.. only:: html + import pytermor as pt - .. raw:: html - :file: ../demo/features.fargs.html + ex_st = pt.Style(bg='#ffff00', fg='black') + text = pt.FrozenText( + 'This is red ', pt.cv.RED, + "This is white ", + "This is black on yellow", ex_st, + ) + pt.echo(text) -.. only:: latex +.. container:: highlight highlight-manual highlight-adjacent output - .. figure:: /demo/features.fargs.svg - :align: center + :red:`This is red`\ |nbsp| This is white\ |nbsp| :blackonyellow:`This is black on yellow` ================================== Content-aware format nesting ================================== -r -Template tags and non-closing `Fragments ` allow to build complex formats. -.. literalinclude:: /demo/features.templates.py - :linenos: +Template tags and non-closing `Fragments ` allow to build complex formats:: -.. only:: html + import pytermor as pt - .. raw:: html - :file: ../demo/features.templates.html + s = ":[fg=red]fg :[bg=blue]and bg :[fg=black]formatting with:[-] overlap:[-] support" + pt.echo(pt.TemplateEngine().substitute(s)) -.. only:: latex +.. container:: highlight highlight-manual highlight-adjacent output - .. figure:: /demo/features.templates.svg - :align: center + :red:`fg` :redonblue:`and bg\ \ `\ :blackonblue:`formatting with\ \ `\ :redonblue:`overlap` :red:`support` ================================== @@ -53,40 +52,45 @@ The library supports extended color modes: - XTerm 256 colors indexed mode - True Color RGB mode (16M colors) +:: -.. literalinclude:: /demo/features.color-modes.py - :linenos: + import pytermor as pt -.. only:: html + for outm in ['xterm_16', 'xterm_256', 'true_color']: + print(' '+outm.ljust(12), end="") + for c in range((W := 80) + 1): + b = pt.RGB.from_ratios(1 - (p := c / W), 2 * min(p, 1 - p), p).int + f = pt.Fragment(" ·"[c & 1], pt.Style(fg=(1 << 24) - b, bg=b, bold=True)) + print(f.render(pt.SgrRenderer(outm)), end=["", 2*"\n"][c >= W], flush=True) - .. raw:: html - :file: ../demo/features.color-modes.html +.. container:: highlight highlight-manual highlight-adjacent output fullwidthimage -.. only:: latex - - .. figure:: /demo/features.color-modes.svg + .. image:: /_generated/features/xterm-truecolor.png + :width: 100% :align: center + :class: no-scaled-link ================================== Different color spaces ================================== -Currently supported spaces: `RGB`, `HSV`, `XYZ`, `LAB`. Any of these -can be transparently translated to any other. - -.. literalinclude:: /demo/features.color-spaces.py - :linenos: +Currently supported spaces: `RGB`, `HSV`, `XYZ`, `LAB`. A color defined +in any of these can be transparently translated into any other:: -.. only:: html + import pytermor as pt - .. raw:: html - :file: ../demo/features.color-spaces.html + col = pt.RGB(0xDA9AC4) + st = pt.Style(fg=col) + for v in [col.rgb, col.hsv, col.xyz, col.lab]: + pt.echo(repr(v), st) -.. only:: latex - .. figure:: /demo/features.color-spaces.svg - :align: center +.. container:: highlight highlight-manual highlight-adjacent output + | :xdaracu:`RGB[#DA9AC4][R=218 G=154 B=196]` + | :xdaracu:`HSV[H=321° S=29% V=85%]` + | :xdaracu:`XYZ[X=50.43 Y=42.00% Z=57.66]` + | :xdaracu:`LAB[L=70.872% a=30.339 b=-12.031]` ================================== Named colors collection @@ -95,15 +99,16 @@ Named colors collection Registry containing more than 2400 named colors, in addition to default 256 from ``xterm`` palette. -.. only:: html +.. code-block:: console - .. raw:: html - :file: ../demo/features.named-colors.html + $ /run-cli examples/list_named_rgb.py -.. only:: latex +.. container:: highlight highlight-manual highlight-adjacent output fullwidthimage - .. figure:: /demo/features.named-colors.svg - :align: center + .. image:: /_generated/features/named-colors.png + :width: 100% + :align: center + :class: no-scaled-link ================================== @@ -115,19 +120,18 @@ formatted strings from `IRenderable` instances, which, in general, consist of a text piece and a :term:`Style` -- a set of formatting rules. Concrete implementation of the renderer determines the target format and/or platform. - This is how `SgrRenderer`, `HtmlRenderer`, `TmuxRenderer`, `SgrDebugger` (from top to bottom) output can be seen in a terminal emulator: -.. only:: html +.. container:: highlight highlight-manual outputstandalone output - .. raw:: html - :file: ../demo/features.renderers.html - -.. only:: latex - - .. figure:: /demo/features.renderers.svg - :align: center + | :red:`This is red`\ |nbsp| This is white\ |nbsp| :blackonyellow:`This is black on yellow` + | + | This is red This is white This is black on yellow + | + | #[fg=red]This is red #[fg=default]This is white #[fg=black bg=#ffff00]This is black on yellow#[fg=default bg=default] + | + | (·[31m)This is red (·[39m)This is white (·[30;48;5;11m)This is black on yellow(·[39;49m) ================================== @@ -136,41 +140,41 @@ Number formatters Set of highly customizable helpers, see `numfmt`. -`format_si()` output sample: - -.. only:: html +.. container:: code-block-caption outputcaption - .. raw:: html - :file: ../demo/features.formatters.si.html + `format_si()` output sample -.. only:: latex +.. container:: highlight highlight-manual highlight-adjacent output fullwidthimage - .. figure:: /demo/features.formatters.si.svg + .. image:: /_generated/features/formatter-si.png + :width: 100% :align: center + :class: no-scaled-link -`format_time_ns()` output samples: -.. only:: html +.. container:: code-block-caption outputcaption - .. raw:: html - :file: ../demo/features.formatters.time_ns.html + `format_time_ns()` output samples -.. only:: latex +.. container:: highlight highlight-manual highlight-adjacent output fullwidthimage - .. figure:: /demo/features.formatters.time_ns.svg + .. image:: /_generated/features/formatter-time-ns.png + :width: 100% :align: center + :class: no-scaled-link -`format_time_delta()` output sample: -.. only:: html +.. container:: code-block-caption outputcaption - .. raw:: html - :file: ../demo/features.formatters.time_delta.html + `format_time_delta()` output sample -.. only:: latex +.. container:: highlight highlight-manual highlight-adjacent output fullwidthimage - .. figure:: /demo/features.formatters.time_delta.svg + .. image:: /_generated/features/formatter-time-delta.png + :width: 100% :align: center + :class: no-scaled-link + ================================== Data dumps diff --git a/docs/pages/guide-hi/core-api-1.rst b/docs/pages/guide-hi/core-api-1.rst index e277b3db..dc783ff8 100644 --- a/docs/pages/guide-hi/core-api-1.rst +++ b/docs/pages/guide-hi/core-api-1.rst @@ -1,7 +1,7 @@ .. _guide.core-api-1: ########################## -Core API +Core API I ########################## ================ diff --git a/docs/pages/index.rst b/docs/pages/index.rst index d9ad78b0..d476fdc5 100644 --- a/docs/pages/index.rst +++ b/docs/pages/index.rst @@ -20,21 +20,22 @@ escape sequence parser and provides support for several color spaces, which is also used for fluent color approximation if terminal capabilities do not allow to work in True Color mode. See `features` page for the details. +No dependencies required, only Python Standard Library :comment:`(although there +are some for testing and docs building).` + The library is extendable and supports a variety of formatters (called `renderers`), which determine the output syntax: -- `SgrRenderer`, global default; formats the text with ANSI escape sequences for ttys; +- `SgrRenderer`, global default; formats the text with ANSI escape sequences for + terminal emulators; - `TmuxRenderer`, suitable for integration with tmux (terminal multiplexer); -- `HtmlRenderer`, which makes a HTML page with all the formatting composed by CSS styles; -- `SgrDebugger`, same as ``SgrRenderer``, but ESC (:hex:`0x1B`) bytes are replaced with a regular - letter, therefore all the sequences are no longer sequences and can be seen as a text, for SGR - debugging; +- `HtmlRenderer`, which makes a HTML page with all the formatting composed by + CSS styles; +- `SgrDebugger`, same as ``SgrRenderer``, but control bytes are replaced with a + regular letter, therefore all the sequences are no longer sequences and can be + seen as a text, for SGR debugging; - etc. -No dependencies required, only Python Standard Library :comment:`(although there -are some for testing and docs building).` - - .. only:: html .. grid:: 3 @@ -45,31 +46,26 @@ are some for testing and docs building).` :ref:`install` - *installation, in-depth review* - .. grid-item-card:: :ref:`features` - *summary* - .. grid-item-card:: - :ref:`structure` + :ref:`examples` - *module dependency graph* .. grid-item-card:: :ref:`guide.core-api-1` - *main classes/functions (high-level)* + *high abstraction level* .. grid-item-card:: :ref:`guide.core-api-2` - *main classes/functions (low-level)* + *low abstraction level* .. grid-item-card:: @@ -79,7 +75,9 @@ are some for testing and docs building).` .. grid-item-card:: - :ref:`config` + :ref:`structure` + + *module dependency graph* .. grid-item-card:: @@ -101,19 +99,18 @@ are some for testing and docs building).` install features - structure examples/index .. toctree:: :caption: Documentation :maxdepth: 2 + structure guide-hi/index guide-lo/index apidoc appendix/index config - cli .. toctree:: :caption: Development diff --git a/docs/pages/structure.rst b/docs/pages/structure.rst index 215f6473..87e09ee8 100644 --- a/docs/pages/structure.rst +++ b/docs/pages/structure.rst @@ -19,7 +19,7 @@ Library structure :class: graphviz-default :caption: Module dependency graph [#]_ - .. [#] Overly common modules (``exception``, ``log``, ``config`` and ``common`` itself) are not shown, as they turn the graph into a mess. Same applies to internal modules which name starts with ``_``. + .. [#] Overly common modules (``exception``, ``config`` and ``common`` itself) are not shown, as they turn the graph into a mess. Same applies to internal modules which name starts with ``_``. .. autosummary:: diff --git a/examples/list_named_rgb.py b/examples/list_named_rgb.py index eef6f763..a0f65ca4 100755 --- a/examples/list_named_rgb.py +++ b/examples/list_named_rgb.py @@ -113,8 +113,8 @@ def load(self): class _OriginLoader(ILoader): def load(self) -> t.Iterable[_IColorRGB]: - for k, v in pt.ColorRGB._registry._map.items(): - yield _ColorRGBOriginAdapter(v, k) + for v in pt.ColorRGB._registry._set: + yield _ColorRGBOriginAdapter(v, [v.name]) class _ConfigLoader(ILoader): @@ -268,8 +268,8 @@ class Main(): def __init__(self): pt.force_ansi_rendering() #pt.RendererManager.set_default(pt.HtmlRenderer) - - config_list = [*_ConfigLoader().load()] + pt.cvr.load() + # config_list = [*_ConfigLoader().load()] origin_list = [*_OriginLoader().load()] self.run(origin_list) diff --git a/pytermor/__init__.py b/pytermor/__init__.py index 7355b063..2032bdd1 100644 --- a/pytermor/__init__.py +++ b/pytermor/__init__.py @@ -66,6 +66,7 @@ from .color import resolve_color as resolve_color from .common import Align as Align from .common import CDT as CDT +from .common import CXT as CXT from .common import ExtendedEnum as ExtendedEnum from .common import FT as FT from .common import OVERFLOW_CHAR as OVERFLOW_CHAR diff --git a/pytermor/_version.py b/pytermor/_version.py index 6988f1d0..539c028e 100644 --- a/pytermor/_version.py +++ b/pytermor/_version.py @@ -3,5 +3,5 @@ # (c) 2022-2023. A. Shavykin <0.delameter@gmail.com> # Licensed under GNU Lesser General Public License v3.0 # ----------------------------------------------------------------------------- -__version__ = '2.106.3' -__updated__ = "2023-10-16 00:30:56+03:00" +__version__ = '2.106.4' +__updated__ = "2023-10-17 15:30:12+03:00" diff --git a/pytermor/common.py b/pytermor/common.py index fa31ec34..878ac331 100644 --- a/pytermor/common.py +++ b/pytermor/common.py @@ -33,6 +33,11 @@ - *int* in a [:hex:`0`; :hex:`0xffffff`] range. """ +CXT = t.TypeVar("CXT", int, str, "IColorValue", "RenderColor", None) +""" +:todo:`TODO` +""" + FT = t.TypeVar("FT", int, str, "IColorValue", "Style", None) """ :abbr:`FT (Format type)` is a style descriptor. Used as a shortcut precursor for actual diff --git a/pytermor/style.py b/pytermor/style.py index e33fae08..5bbe5fc0 100644 --- a/pytermor/style.py +++ b/pytermor/style.py @@ -17,7 +17,7 @@ from typing import Any from .color import Color, NOOP_COLOR, resolve_color, IColorValue, ColorRGB, RenderColor, RealColor -from .common import CDT, FT +from .common import CDT, CXT, FT from .cval import cv from .exception import ArgTypeError, LogicError @@ -118,15 +118,15 @@ def underline_color(self) -> RenderColor: return self._underline_color @fg.setter - def fg(self, val: CDT | RenderColor | None): + def fg(self, val: CXT): self._fg: RenderColor = self._resolve_color(val) @bg.setter - def bg(self, val: CDT | RenderColor | None): + def bg(self, val: CXT): self._bg: RenderColor = self._resolve_color(val) @underline_color.setter - def underline_color(self, val: CDT | RenderColor | None): + def underline_color(self, val: CXT): self._underline_color: RenderColor = self._resolve_color(val) bold: bool @@ -207,8 +207,8 @@ def _attributes(self) -> t.FrozenSet: def __init__( self, fallback: Style = None, - fg: CDT | RenderColor = None, - bg: CDT | RenderColor = None, + fg: CXT = None, + bg: CXT = None, frozen: bool = False, *, bold: bool = None, @@ -219,7 +219,7 @@ def __init__( crosslined: bool = None, double_underlined: bool = None, curly_underlined: bool = None, - underline_color: CDT | RenderColor = None, + underline_color: CXT = None, inversed: bool = None, blink: bool = None, framed: bool = None, @@ -447,7 +447,7 @@ def _ensure_not_frozen(self) -> None: if hasattr(self, "_frozen") and self._frozen: raise LogicError(f"{self.__class__.__qualname__} is immutable") - def _resolve_color(self, arg: CDT | IColorValue | RenderColor | None) -> RenderColor | None: + def _resolve_color(self, arg: CXT) -> RenderColor | None: if arg is None: return NOOP_COLOR if isinstance(arg, RenderColor): @@ -457,7 +457,7 @@ def _resolve_color(self, arg: CDT | IColorValue | RenderColor | None) -> RenderC if isinstance(arg, (str, int)) and not isinstance(arg, bool): # undesirable isinstance(True, int) --> #000001 return resolve_color(arg) - raise ArgTypeError(arg, "arg", CDT, IColorValue, None) + raise ArgTypeError(arg, "arg", CXT, IColorValue, None) def __setattr__(self, name: str, value: Any) -> None: self._ensure_not_frozen() diff --git a/pytermor/text.py b/pytermor/text.py index 161ac17d..dd32a942 100644 --- a/pytermor/text.py +++ b/pytermor/text.py @@ -917,7 +917,7 @@ def apply_style_selective( ... ], renderer=SgrRenderer(OutputMode.XTERM_16)) ['\x1b[31mA\x1b[39m', ' few ', '\x1b[31mCAPITAL\x1b[39m', 's'] - .. container:: highlight highlight-manual highlight-adjacent highlight-output + .. container:: highlight highlight-manual highlight-adjacent highlight-output output :red:`A` few :red:`CAPITAL`\ s diff --git a/tests/test_exception.py b/tests/test_exception.py index ec5342b3..2be3e182 100644 --- a/tests/test_exception.py +++ b/tests/test_exception.py @@ -11,7 +11,7 @@ import pytest import pytermor as pt -from pytermor import ArgTypeError, Color, CDT, FT, IT, Style, Color256 +from pytermor import ArgTypeError, Color, CXT, FT, IT, Style, Color256 from pytermor.exception import ArgCountError from tests import format_test_params @@ -39,7 +39,7 @@ class TestArgTypeError: lambda: pt.make_style(pt.Style), ), ( - ["Argument", "arg", CDT, Color, "list"], + ["Argument", "arg", CXT, Color, "list"], lambda: setattr(pt.Style(), "fg", [None]), ), (