Metadata-Version: 2.4
Name: cs-ascii_art
Version: 20260403
Summary: Utilities to assist with ASCII art such as railroad diagrams; since these use Unicode box drawing characters and are better for diagrams such as railroad diagrams, this is neither ASCII nor art.
Keywords: python3
Author-email: Cameron Simpson <cs@cskk.id.au>
Description-Content-Type: text/markdown
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
Requires-Dist: cs.context>=20250528
Requires-Dist: cs.deco>=20251230
Project-URL: MonoRepo Commits, https://bitbucket.org/cameron_simpson/css/commits/branch/main
Project-URL: Monorepo Git Mirror, https://github.com/cameron-simpson/css
Project-URL: Monorepo Hg/Mercurial Mirror, https://hg.sr.ht/~cameron-simpson/css
Project-URL: Source, https://github.com/cameron-simpson/css/blob/main/lib/python/cs/ascii_art.py

Utilities to assist with ASCII art such as railroad diagrams;
since these use Unicode box drawing characters and are better
for diagrams such as railroad diagrams, this is neither ASCII
nor art.

*Latest release 20260403*:
Add LARGE_CIRCLE.

This is still pretty alpha.

The current demo mode runs:

    rrprint(
        RR_START,
        RRRepeat("repeat me"),
        "2 lines\naaaa",
        (
            "one",
            "two",
            "three",
            "one\n"
            "two\n"
            "three\n"
            "four\n"
            "five",
            ["a", "sequence"],
        ),
        RR_END,
    )

which prints:

                                  ╭|one|──────────╮
                                  ├|two|──────────┤
                                  ├|three|────────┤
                       ╭───────╮  │╭─────╮        │
                       │2 lines│  ││one  │        │
    ├┼──┬|repeat me|┬──┤aaaa   ├──┤│two  │        ├──┼┤
        ╰─────←─────╯  ╰───────╯  ├┤three├────────┤
                                  ││four │        │
                                  ││five │        │
                                  │╰─────╯        │
                                  ╰|a|──|sequence|╯

Short summary:
* `box_char`: Return the Unicode entity for a box drawing glyph with the specified line weight and lines.
* `box_char_name`: Compute the Unicode entity name for a box drawing glyph with the specified line weight and lines.
* `Cell`: A representation of a character cell for a hypothetical future "drawing on a canvas" mode.
* `render`: A decorator to wrap rendering methods with the prevailing render context, as updated by any keyword arguments supplied to the method.
* `render_mode`: A context manager to temporarily apply `render_kw` to the rendering mode context `ctx` (default from `RRBase.render_context`). Yields the render context.
* `RR_END`: A bare text based symbol like `RR_START` or `RR_END`.
* `RR_START`: A bare text based symbol like `RR_START` or `RR_END`.
* `RRBase`: The abstract base class for various boxes.
* `RRChoice`: RRChoice(content: list[cs.ascii_art.RRBase] = <factory>).
* `RRMerge`: RRMerge multiple inputs into a single output.
* `RROptional`: RROptional(content: cs.ascii_art.RRBase, above: bool = False, middle: str = '→').
* `rrprint`: Promote the arguments to `RRBase` instances, make into an `RRSequence` and print it.
* `RRRepeat`: RRRepeat(content: cs.ascii_art.RRBase, above: bool = False, middle: str = '←').
* `RRSequence`: A railroad sequence.
* `RRSplit`: RRSplit a single input into multiple outputs.
* `RRStack`: An unadorned vertical stack of the content.
* `RRTextBox`: A text box with borders.
* `Symbol`: A bare text based symbol like `RR_START` or `RR_END`.
* `Terminal`: Like a symbol, but with a marker either side.
* `test_railroad`: Exercise various boxes.

Module contents:
- <a name="box_char_name"></a>`box_char_name(heavy=False, arc=False, up=False, down=False, left=False, right=False)`: Compute the Unicode entity name for a box drawing glyph with
  the specified line weight and lines.

  See: https://www.unicode.org/charts/nameslist/n_2500.html

  Parameters:
  * `arc`: return an arc character instead of a rectangluar box corner
  * `heavy`: the line wieght: `HEAVY` for `True`, `LIGHT` for `False`
  * `up`: with a line upward from the centre
  * `down`: with a line downward from the centre
  * `left`: with a line leftward from the centre
  * `right`: with a line rightward from the centre
- <a name="Cell"></a>`class Cell`: A representation of a character cell for a hypothetical future
  "drawing on a canvas" mode.
- <a name="render"></a>`render(*da, **dkw)`: A decorator to wrap rendering methods with the prevailing
  render context, as updated by any keyword arguments supplied
  to the method.

  The decorator may be suplied with its own defaults; these
  will be applied to the render context first, then whatever
  render keyword arguments as supplied to the method.

  The decorated method accepts an optional `ctx` parameter
  to use as the render context; the default comes from
  `self.render_context` which is normally an attribute of
  `self.__class__`.

  The wrapped method is called with a keyword argument for every
  attribute of the updated render context.
  The render context is returned to its previous state on return
  from the method.

  This means that the render methods have an unusual signature,
  for example:

      @render(heavy=True)
      def renderlines(self, *, heavy, attach_w, attach_e, **_):

  This:
  - enumerates only the keyword parameters of interest to the method
  - "default" values should not be supplied as `None` in the
    method definition
  - has a `_` to collect any uninteresting render parameters

  The interesting parameters should arrive prefilled and also
  do not need to be passed into interior calls to render methods
  because the render context has these values. Only values
  different from the render context need provision.
- <a name="render_mode"></a>`render_mode(ctx=None, **render_kw)`: A context manager to temporarily apply `render_kw` to the
  rendering mode context `ctx` (default from `RRBase.render_context`).
  Yields the render context.
- <a name="RR_END"></a>`RR_END = Symbol:'┼┤'`: A bare text based symbol like `RR_START` or `RR_END`.
- <a name="RR_START"></a>`RR_START = Symbol:'├┼'`: A bare text based symbol like `RR_START` or `RR_END`.
- <a name="RRBase"></a>`class RRBase(cs.deco.Promotable)`: The abstract base class for various boxes.

*`RRBase.__str__(self)`*:
Return the default rendering of the text box.

*`RRBase.conn_char(li, lefts: list[int], rights: list[int], arc=True, heavy=False) -> str`*:
Compute the connective `box_char` for a column of connective characters.

*`RRBase.from_str(s: str) -> Union[ForwardRef('Terminal'), ForwardRef('RRTextBox')]`*:
Promote a string to a `Terminal` or `RRTextBox`.
Nonempty strings with no newlines become `Terminal`s,
otherwise a `RRTextBox`.

*`RRBase.horiz(width: int, *, middle='', arc, heavy, ascii=False, left_up=False, left_down=False, right_up=False, right_down=False, **_)`*:
Compute a horizontal line with an optional symbol in the
middle and up or down connections.

*`RRBase.pprint(self, **ppkw)`*:
Call `pprint.pprint` with this railroad node.

*`RRBase.render(self, **render_kw)`*:
Render the text box as a single multiline string.

*`RRBase.render_lines(self, **render_kw)`*:
Render the box as a list of single line strings.
- <a name="RRChoice"></a>`class RRChoice(RRStack)`: RRChoice(content: list[cs.ascii_art.RRBase] = <factory>)
- <a name="RRMerge"></a>`class RRMerge(RRStack)`: RRMerge multiple inputs into a single output.

*`RRMerge.e`*:
The east attachment points of the `RRMerge`, the midpoint of
the interior top and bottom attachment points.

*`RRMerge.es`*:
The east attachment points of the `RRMerge`, the midpoint of
the interior top and bottom attachment points.

*`RRMerge.render_lines(self, *, arc, heavy, attach_e, **_)`*:
Render the `RRMerge` as a list of strings.

*`RRMerge.width`*:
The width of the `RRMerge`, the width of the `RRStack` plus 1
for the right attachments.
- <a name="RROptional"></a>`class RROptional(_RailRoadAround)`: RROptional(content: cs.ascii_art.RRBase, above: bool = False, middle: str = '→')
- <a name="rrprint"></a>`rrprint(*seq, sep='')`: Promote the arguments to `RRBase` instances, make into an
  `RRSequence` and print it.
- <a name="RRRepeat"></a>`class RRRepeat(_RailRoadAround)`: RRRepeat(content: cs.ascii_art.RRBase, above: bool = False, middle: str = '←')
- <a name="RRSequence"></a>`class RRSequence(_RailRoadMulti)`: A railroad sequence.

*`RRSequence.height`*:
The render height ofthe `RRSequence` in lines.

*`RRSequence.render_lines(self, *, sep_len, middle='', **_)`*:
Render the `RRSequence` as a list of one line strings.

*`RRSequence.width`*:
The render width of the `RRSequence` in characters..
- <a name="RRSplit"></a>`class RRSplit(RRStack)`: RRSplit a single input into multiple outputs.

*`RRSplit.render_lines(self, *, arc, heavy, attach_w, **_)`*:
Render the `RRSplit` as a list of strings.

*`RRSplit.w`*:
The west attachment point, the midpoint of the top and
bottom interior west attachment points.

*`RRSplit.width`*:
The width of the `RRSplit` in characters.

*`RRSplit.ws`*:
The west attachment points of the `RRSplit`.
- <a name="RRStack"></a>`class RRStack(_RailRoadMulti)`: An unadorned vertical stack of the content.

*`RRStack.width`*:
The overall width of the content.
- <a name="RRTextBox"></a>`class RRTextBox(RRBase)`: A text box with borders.

*`RRTextBox.e`*:
The vertical offset to the east connection point.

*`RRTextBox.height`*:
The height including the borders

*`RRTextBox.n`*:
The horizontal offset to the north connection point.

*`RRTextBox.render_lines(self, *, heavy, attach_w, attach_e, **_)`*:
Render the text box as a list of single line strings.

*`RRTextBox.s`*:
The horizontal offset to the south connection point.

*`RRTextBox.w`*:
The vertical offset to the west connection point.

*`RRTextBox.width`*:
The width including the borders
- <a name="Symbol"></a>`class Symbol(RRBase)`: A bare text based symbol like `RR_START` or `RR_END`.
- <a name="Terminal"></a>`class Terminal(Symbol)`: Like a symbol, but with a marker either side.
- <a name="test_railroad"></a>`test_railroad()`: Exercise various boxes.

# Release Log



*Release 20260403*:
Add LARGE_CIRCLE.

*Release 20260228*:
Initial release. Basic railroad diagrams and associated utilities.
