Skip to content

xnano.region

xnano.region

xnano.region

A rectangle of cells: standalone, or a live view of a canvas or a placement.

Classes:

  • Region –

    A rectangle of cells that you can read and write, one cell or dot at a time.

Functions:

  • write –

    Build a standalone region from text (does not draw).

  • box –

    Build an empty standalone rectangle of cells with a border (does not draw).

Region

Region(buffer: Buffer, *, owner: Canvas[object, object] | Placement[object, object] | None = None, inset: tuple[int, int, int, int] = (0, 0, 0, 0), resolution: Resolution = 'cells', is_standalone: bool = False, look: Appearance | None = None, is_text: bool = False)

Bases: _Looked

A rectangle of cells that you can read and write, one cell or dot at a time.

A region is either standalone, made by write or box, which owns its cells and can be written into a canvas, or a live view of the cells of a canvas or a placement, from canvas.region and placement.region. Coordinates are region coordinates, (0, 0) being the top-left cell. (x, y) in region and region.local(point) use screen cells, the frame of context.mouse.position.

The default resolution is one cell. region.half_blocks addresses two pixels per cell (one above the other) and region.braille eight dots per cell (two by four, one color for the whole cell). Reading gives a Pixel; assigning accepts a pixel, a color (the background of a cell, the color of a pixel or dot), a str (text) or, over a slice, anything write accepts.

A standalone region owns color, border, padding and margin and draws them in its own cells, so its coordinates include them: (0, 0) of a bordered region is the corner of the border. On a live view they belong to the canvas or the placement, and the coordinates address the area inside them. A region written into a canvas is a snapshot: changing the region afterwards changes nothing on the canvas. A region made by write draws its text again whenever its look changes, so cells you edited are replaced; edit the cells of a box instead.

Attributes:

Examples:

import xnano

card = xnano.write('hello', border='rounded')
assert card.render().splitlines()[0] == '╭─────╮'

with xnano.new(width=8, height=2) as canvas:
    region = canvas.region
    region[0:4, 0:1] = 'abcd'
    region[5, 0] = xnano.Pixel('diamond', foreground='red')
    region[0, 1] = (0, 0, 255)
    assert region[5, 0].character == '◆'
    assert region[1, 0].character == 'b'
    assert (1, 1) in region
    dots = region.braille
    assert (dots.width, dots.height) == (16, 8)

Wrap a buffer. Get a region from write, box or canvas.region instead.

Parameters:

  • buffer (Buffer) –

    The core buffer whose cells the region addresses.

  • owner (Canvas[object, object] | Placement[object, object] | None, default: None ) –

    The canvas or placement a live view belongs to.

  • inset (tuple[int, int, int, int], default: (0, 0, 0, 0) ) –

    Cells left out on the left, top, right and bottom of the buffer.

  • resolution (Resolution, default: 'cells' ) –

    'cells', 'half_blocks' or 'braille'.

  • is_standalone (bool, default: False ) –

    Whether the region owns its buffer and its look.

  • look (Appearance | None, default: None ) –

    The look of a standalone region.

  • is_text (bool, default: False ) –

    Whether a standalone region shows the text of its look.

Methods:

  • __contains__ –

    Whether a screen cell is inside the region.

  • local –

    Convert a screen cell into a cell of this region.

  • resize –

    Change the size of the region, in cells.

  • __getitem__ –

    Read a cell (a Pixel) or take a part of the region.

  • __setitem__ –

    Write a pixel, a color, text or content into a cell or a part of the region.

  • shade –

    Color every cell, pixel or dot from a function of its position, in one write.

  • draw_color_bytes –

    Draw a row-major RGBA image with its top-left pixel at (x, y).

  • draw_image –

    Draw an image with its top-left pixel at (x, y).

  • cell_for_pixel –

    Return the cell that holds a pixel or dot.

  • pixel_for_cell –

    Return the pixel or dot at an anchor of a cell.

  • copy –

    Return a standalone region with a copy of these cells and, for one, its look.

  • render –

    Draw the region to a string.

  • __str__ –

    Return the characters of the region, so print(region) shows it.

  • __xnano_render__ –

    Return the buffer that shows the region: its own, or a copy for a view.

  • __setattr__ –

    Set an attribute, or raise AttributeError for an unknown public name.

Source code in xnano/region.py
def __init__(
    self,
    buffer: _core.Buffer,
    *,
    owner: Canvas[object, object] | Placement[object, object] | None = None,
    inset: tuple[int, int, int, int] = (0, 0, 0, 0),
    resolution: Resolution = 'cells',
    is_standalone: bool = False,
    look: Appearance | None = None,
    is_text: bool = False,
) -> None:
    """
    Wrap a buffer. Get a region from ``write``, ``box`` or ``canvas.region`` instead.

    Args:
        buffer: The core buffer whose cells the region addresses.
        owner: The canvas or placement a live view belongs to.
        inset: Cells left out on the left, top, right and bottom of the buffer.
        resolution: ``'cells'``, ``'half_blocks'`` or ``'braille'``.
        is_standalone: Whether the region owns its buffer and its look.
        look: The look of a standalone region.
        is_text: Whether a standalone region shows the text of its look.
    """
    self._buffer = buffer
    self._owner = owner
    self._inset = inset
    self._resolution: Resolution = resolution
    self._is_standalone = is_standalone
    self._is_text = is_text
    self._appearance = look
    self._canvas: Canvas[object, object] | None = None
    self._insets_applied: tuple[int, int, int, int] | None = None
    self._seal()

color property

color: Colors

The colors of a standalone region; see Colors.

border property writable

The border of a standalone region; see BorderAppearance.

padding property writable

The padding of a standalone region; see Edges.

margin property writable

The margin of a standalone region; see Edges.

width property

width: int

The width in cells, or in pixels or dots at the other resolutions.

height property

height: int

The height in cells, or in pixels or dots at the other resolutions.

resolution property

resolution: Resolution

'cells', 'half_blocks' (1 by 2 per cell) or 'braille' (2 by 4).

x property

x: int

The screen column of the region's left edge; 0 for a region that is not on screen.

y property

y: int

The screen row of the region's top edge; 0 for a region that is not on screen.

braille property

braille: Region

The same cells as braille dots: two columns and four rows per cell.

A dot is drawn in the color of its cell, so the eight dots of a cell share one color.

Examples:

import xnano

with xnano.new(width=4, height=2) as canvas:
    dots = canvas.region.braille
    dots[0, 0] = (255, 255, 255)
    assert dots[0, 0].character == '•'
    assert dots[1, 0].character == ' '

half_blocks property

half_blocks: Region

The same cells as pixels, two to a cell: one above the other.

region property

region: Region

The cells of the owner.

__contains__

__contains__(point: object) -> bool

Whether a screen cell is inside the region.

Parameters:

  • point (object) –

    A (x, y) pair or a Point in screen cells, such as context.mouse.position.

Source code in xnano/region.py
def __contains__(self, point: object) -> bool:
    """
    Whether a screen cell is inside the region.

    Args:
        point: A ``(x, y)`` pair or a [`Point`][xnano_core.Point] in screen cells, such
            as ``context.mouse.position``.
    """
    if isinstance(point, _core.Point):
        column, row = point.x, point.y
    elif isinstance(point, tuple) and len(point) == 2:
        column, row = point
    else:
        return False
    width, height = self._cell_size()
    origin_x = self.x
    origin_y = self.y
    return (
        origin_x <= column < origin_x + width and origin_y <= row < origin_y + height
    )

local

local(point: Point) -> Point

Convert a screen cell into a cell of this region.

Parameters:

  • point (Point) –

    A cell in screen coordinates, such as context.mouse.position.

Source code in xnano/region.py
def local(self, point: _core.Point) -> _core.Point:
    """
    Convert a screen cell into a cell of this region.

    Args:
        point: A cell in screen coordinates, such as ``context.mouse.position``.
    """
    point = check_point(point)
    return _core.Point(point.x - self.x, point.y - self.y)

resize

resize(width: int, height: int) -> None

Change the size of the region, in cells.

On a view of a placement this resizes the placement. A standalone region made by box keeps its cells where they fit. A region made by write is sized by its text, border, padding and margin, so it cannot be resized.

Parameters:

  • width (int) –

    The new width in cells.

  • height (int) –

    The new height in cells.

Raises:

  • TerminalError –

    The region is the view of a canvas, whose size follows its screen, a slice of another region, or it was made by write, whose size follows its text.

  • ValueError –

    A size is below 1 or above 65535.

Source code in xnano/region.py
def resize(self, width: int, height: int) -> None:
    """
    Change the size of the region, in cells.

    On a view of a placement this resizes the placement. A standalone region made by
    [`box`][xnano.box] keeps its cells where they fit. A region made by
    [`write`][xnano.write] is sized by its text, border, padding and margin, so it
    cannot be resized.

    Args:
        width: The new width in cells.
        height: The new height in cells.

    Raises:
        TerminalError: The region is the view of a canvas, whose size follows its screen,
            a slice of another region, or it was made by ``write``, whose size follows
            its text.
        ValueError: A size is below 1 or above 65535.
    """
    _check_cell_counts('resize', width, height)
    if width < 1 or height < 1:
        raise ValueError(
            f'A region is at least 1 by 1 cells, but resize got {width} by {height}. '
            f'Pass whole numbers of cells, 1 or more.'
        )
    owner = self._owner
    if self._is_standalone and self._is_text:
        raise TerminalError(
            'A region made by write() is sized by its text, border, padding and margin, '
            'so resize() cannot change it. Make a region of a size you choose with '
            'xnano.box(width, height), or change the text or the padding.'
        )
    if self._is_standalone:
        self._resize_standalone(width, height)
        return
    if owner is None or not hasattr(owner, '_set_axis'):
        if owner is None or any(self._inset):
            raise TerminalError(
                'A slice of a region is a window onto it and cannot be resized. Resize the '
                'region it was taken from with its resize(width, height), or take a new '
                'slice.'
            )
        raise TerminalError(
            'The size of a canvas follows its screen or its width and height; set '
            'those instead of resizing its region.'
        )
    left, top, right, bottom = self._inset
    placement = cast('Placement[object, object]', owner)
    extra_width = left + right
    extra_height = top + bottom
    decorated = getattr(placement, '_decorated', None)
    if decorated is not None:
        extra_width += decorated.insets.horizontal
        extra_height += decorated.insets.vertical
    placement.width = width + extra_width
    placement.height = height + extra_height

__getitem__

__getitem__(key: tuple[int, int]) -> Pixel
__getitem__(key: tuple[int | slice, int | slice]) -> Region
__getitem__(key: tuple[int | slice, int | slice]) -> Pixel | Region

Read a cell (a Pixel) or take a part of the region.

Parameters:

Raises:

  • IndexError –

    A coordinate is outside the region; the message names the valid ranges.

  • TypeError –

    The key is a screen Point or not a pair.

  • ValueError –

    A slice has a step, or a slice is taken from a pixel resolution.

Source code in xnano/region.py
def __getitem__(self, key: tuple[int | slice, int | slice]) -> Pixel | Region:
    """
    Read a cell (a [`Pixel`][xnano.pixel.Pixel]) or take a part of the region.

    Args:
        key: ``(x, y)`` in region coordinates, or two slices without a step.

    Raises:
        IndexError: A coordinate is outside the region; the message names the valid ranges.
        TypeError: The key is a screen [`Point`][xnano_core.Point] or not a pair.
        ValueError: A slice has a step, or a slice is taken from a pixel resolution.
    """
    if type(key) is tuple and len(key) == 2 and self._resolution == 'cells':
        column, row = key
        if type(column) is int and type(row) is int:
            self._flush_look()
            buffer = self._buffer
            if (
                not any(self._inset)
                and 0 <= column < buffer.width
                and 0 <= row < buffer.height
            ):
                cell = buffer[column, row]
                foreground = cell.foreground
                background = cell.background
                return Pixel._of(
                    cell.symbol,
                    None if foreground is None or foreground.is_reset else foreground,
                    None if background is None or background.is_reset else background,
                )
    self._check_point(key)
    column, row = key
    if isinstance(column, slice) or isinstance(row, slice):
        if self._resolution != 'cells':
            raise ValueError(
                f'A slice of a {self._resolution} region would cut cells in two. '
                f'Take the slice from the cell region (region[0:5, 0:2]) and then '
                f'use .{self._resolution}.'
            )
        width, height = self._cell_size()
        first_x, last_x = self._span(column, width, 'x')
        first_y, last_y = self._span(row, height, 'y')
        left, top, right, bottom = self._inset
        view = Region(
            self._buffer,
            owner=self._owner,
            inset=(
                left + first_x,
                top + first_y,
                right + (width - last_x),
                bottom + (height - last_y),
            ),
        )
        view._canvas = self._canvas
        return view
    column, row = self._check_bounds(column, row)
    surface = self._surface()
    if self._resolution == 'cells':
        cell = surface[column, row]
        return Pixel._of(
            cell.symbol, _plain(cell.foreground), _plain(cell.background)
        )
    if self._resolution == 'half_blocks':
        cell = surface[column, row // 2]
        is_top = row % 2 == 0
        symbol = cell.symbol
        if symbol == '▀':
            color = cell.foreground if is_top else cell.background
        elif symbol == '▄':
            color = cell.background if is_top else cell.foreground
        elif symbol == '█':
            color = cell.foreground
        else:
            color = cell.background
        plain = _plain(color)
        return Pixel._of('█', plain) if plain is not None else Pixel._of(' ')
    cell = surface[column // 2, row // 4]
    code = ord(cell.symbol[0]) - 0x2800 if cell.symbol else -1
    is_set = 0 <= code <= 0xFF and bool(code & _BRAILLE_BITS[row % 4][column % 2])
    return Pixel._of('•', _plain(cell.foreground)) if is_set else Pixel._of(' ')

__setitem__

__setitem__(key: tuple[int | slice, int | slice], value: Pixel | Color | tuple[int, int, int] | str | object) -> None

Write a pixel, a color, text or content into a cell or a part of the region.

  • A Pixel writes its character and colors; over a slice it fills it.
  • A Color or an (red, green, blue) tuple sets the background of a cell (the color of a pixel or dot at the other resolutions). A str is never a color: make one with Color('#336699').
  • A str is text, written from the cell and clipped at the slice.
  • Any other content that write accepts covers a slice.

Parameters:

Raises:

  • IndexError –

    A coordinate is outside the region.

  • TypeError –

    A single cell was given content that needs a slice, a screen Point was used as the key, or text was written at a pixel resolution.

  • ValueError –

    A slice has a step.

Source code in xnano/region.py
def __setitem__(
    self,
    key: tuple[int | slice, int | slice],
    value: Pixel | _core.Color | tuple[int, int, int] | str | object,
) -> None:
    """
    Write a pixel, a color, text or content into a cell or a part of the region.

    * A [`Pixel`][xnano.pixel.Pixel] writes its character and colors; over a slice it fills it.
    * A [`Color`][xnano_core.Color] or an ``(red, green, blue)`` tuple sets the background
      of a cell (the color of a pixel or dot at the other resolutions). A ``str`` is never
      a color: make one with ``Color('#336699')``.
    * A ``str`` is text, written from the cell and clipped at the slice.
    * Any other content that ``write`` accepts covers a slice.

    Args:
        key: ``(x, y)`` in region coordinates, or two slices without a step.
        value: What to write.

    Raises:
        IndexError: A coordinate is outside the region.
        TypeError: A single cell was given content that needs a slice, a screen
            [`Point`][xnano_core.Point] was used as the key, or text was written at a
            pixel resolution.
        ValueError: A slice has a step.
    """
    if type(key) is tuple and len(key) == 2 and self._resolution == 'cells':
        column, row = key
        if type(column) is int and type(row) is int and type(value) is Pixel:
            self._flush_look()
            buffer = self._buffer
            if (
                not any(self._inset)
                and 0 <= column < buffer.width
                and 0 <= row < buffer.height
            ):
                buffer[column, row] = value.cell()
                return
    self._check_point(key)
    column, row = key
    if isinstance(column, int) and isinstance(row, int):
        x, y = self._check_bounds(column, row)
        self._set_cell(x, y, value)
        return
    width, height = self.width, self.height
    first_x, last_x = self._span(column, width, 'x')
    first_y, last_y = self._span(row, height, 'y')
    if last_x <= first_x or last_y <= first_y:
        return
    self._set_block(first_x, last_x, first_y, last_y, value)

shade

shade(function: Callable[[int, int], ColorValue | None]) -> None

Color every cell, pixel or dot from a function of its position, in one write.

At the default resolution the function is called for each cell and the result is the cell's background; region.half_blocks.shade and region.braille.shade call it for each pixel or dot.

Parameters:

  • function (Callable[[int, int], ColorValue | None]) –

    Called with (x, y) in region coordinates; return the color, or None to leave the cell alone.

Examples:

import xnano

with xnano.new(width=4, height=2) as canvas:
    canvas.region.shade(lambda x, y: (x * 60, y * 60, 0) if x < 3 else None)
    assert canvas.region[2, 1].background.to_rgb() == (120, 60, 0)
    canvas.region.half_blocks.shade(lambda x, y: (0, y * 30, 0))
    assert canvas.region.half_blocks[0, 3].foreground is not None
Source code in xnano/region.py
def shade(self, function: Callable[[int, int], ColorValue | None]) -> None:
    """
    Color every cell, pixel or dot from a function of its position, in one write.

    At the default resolution the function is called for each cell and the result is
    the cell's background; ``region.half_blocks.shade`` and ``region.braille.shade`` call
    it for each pixel or dot.

    Args:
        function: Called with ``(x, y)`` in region coordinates; return the color, or
            ``None`` to leave the cell alone.

    Examples:
        ```python
        import xnano

        with xnano.new(width=4, height=2) as canvas:
            canvas.region.shade(lambda x, y: (x * 60, y * 60, 0) if x < 3 else None)
            assert canvas.region[2, 1].background.to_rgb() == (120, 60, 0)
            canvas.region.half_blocks.shade(lambda x, y: (0, y * 30, 0))
            assert canvas.region.half_blocks[0, 3].foreground is not None
        ```
    """
    _check_shade_function(function)
    if self._resolution == 'cells':
        width, height = self._cell_size()
        if width == 0 or height == 0:
            return
        colors = [
            function(column, row) for row in range(height) for column in range(width)
        ]
        self._surface().set_background_colors(colors, width=width)
        return
    view = self._pixel_view()
    colored: list[tuple[int, int, RGB]] = []
    for row in range(view.height):
        for column in range(view.width):
            color = function(column, row)
            if color is not None:
                colored.append((column, row, to_rgb(color)))
    view.write(colored)

draw_color_bytes

draw_color_bytes(data: bytes, *, width: int, height: int, x: int = 0, y: int = 0, mode: RasterMode = 'over') -> None

Draw a row-major RGBA image with its top-left pixel at (x, y).

At the default resolution the image is drawn with half-block pixels.

Parameters:

  • data (bytes) –

    width * height * 4 bytes of red, green, blue and alpha.

  • width (int) –

    The image width in pixels.

  • height (int) –

    The image height in pixels.

  • x (int, default: 0 ) –

    The pixel column of the image's left edge.

  • y (int, default: 0 ) –

    The pixel row of the image's top edge.

  • mode (RasterMode, default: 'over' ) –

    'over' blends by alpha; 'replace' overwrites.

Source code in xnano/region.py
def draw_color_bytes(
    self,
    data: bytes,
    *,
    width: int,
    height: int,
    x: int = 0,
    y: int = 0,
    mode: _core.RasterMode = 'over',
) -> None:
    """
    Draw a row-major RGBA image with its top-left pixel at ``(x, y)``.

    At the default resolution the image is drawn with half-block pixels.

    Args:
        data: ``width * height * 4`` bytes of red, green, blue and alpha.
        width: The image width in pixels.
        height: The image height in pixels.
        x: The pixel column of the image's left edge.
        y: The pixel row of the image's top edge.
        mode: ``'over'`` blends by alpha; ``'replace'`` overwrites.
    """
    self._pixel_view().draw_rgba(
        data, width=width, height=height, x=x, y=y, mode=mode
    )

draw_image

draw_image(image: Image | TerminalImage, *, x: int = 0, y: int = 0, mode: RasterMode = 'over', frame_index: int = 0) -> None

Draw an image with its top-left pixel at (x, y).

Pixels outside the region are skipped, so drawing a large image at a negative x and y scrolls it. At the default resolution the image is drawn with half-block pixels.

Parameters:

  • image (Image | TerminalImage) –

    An Image or a picture from xnano.image. It needs the optional xnano-image package.

  • x (int, default: 0 ) –

    The pixel column of the image's left edge. May be negative.

  • y (int, default: 0 ) –

    The pixel row of the image's top edge. May be negative.

  • mode (RasterMode, default: 'over' ) –

    'over' blends by alpha; 'replace' overwrites.

  • frame_index (int, default: 0 ) –

    Which frame of an animated image to draw.

Source code in xnano/region.py
def draw_image(
    self,
    image: Image | TerminalImage,
    *,
    x: int = 0,
    y: int = 0,
    mode: _core.RasterMode = 'over',
    frame_index: int = 0,
) -> None:
    """
    Draw an image with its top-left pixel at ``(x, y)``.

    Pixels outside the region are skipped, so drawing a large image at a negative ``x``
    and ``y`` scrolls it. At the default resolution the image is drawn with half-block
    pixels.

    Args:
        image: An [`Image`][xnano.Image] or a picture from ``xnano.image``. It needs the
            optional ``xnano-image`` package.
        x: The pixel column of the image's left edge. May be negative.
        y: The pixel row of the image's top edge. May be negative.
        mode: ``'over'`` blends by alpha; ``'replace'`` overwrites.
        frame_index: Which frame of an animated image to draw.
    """
    from xnano._media import Image as MediaImage

    picture = image.image if isinstance(image, MediaImage) else image
    if not hasattr(picture, 'to_rgba'):
        raise TypeError(
            f'draw_image() takes an xnano.Image or a picture from xnano.image, but got '
            f'{image!r}. Load one with xnano.from_image(path) first.'
        )
    self.draw_color_bytes(
        picture.to_rgba(frame_index),
        width=picture.width,
        height=picture.height,
        x=x,
        y=y,
        mode=mode,
    )

cell_for_pixel

cell_for_pixel(x: int, y: int) -> tuple[int, int]

Return the cell that holds a pixel or dot.

Parameters:

  • x (int) –

    The pixel or dot column.

  • y (int) –

    The pixel or dot row.

Source code in xnano/region.py
def cell_for_pixel(self, x: int, y: int) -> tuple[int, int]:
    """
    Return the cell that holds a pixel or dot.

    Args:
        x: The pixel or dot column.
        y: The pixel or dot row.
    """
    if self._resolution == 'cells':
        return (x, y)
    return self._pixel_view().cell_at(x, y)

pixel_for_cell

pixel_for_cell(x: int, y: int, *, anchor: PixelAnchor = 'center') -> tuple[int, int]

Return the pixel or dot at an anchor of a cell.

The mouse reports cells; this picks one pixel of the cell the pointer is over.

Parameters:

  • x (int) –

    The cell column.

  • y (int) –

    The cell row.

  • anchor (PixelAnchor, default: 'center' ) –

    Which pixel of the cell to return.

Source code in xnano/region.py
def pixel_for_cell(
    self, x: int, y: int, *, anchor: PixelAnchor = 'center'
) -> tuple[int, int]:
    """
    Return the pixel or dot at an anchor of a cell.

    The mouse reports cells; this picks one pixel of the cell the pointer is over.

    Args:
        x: The cell column.
        y: The cell row.
        anchor: Which pixel of the cell to return.
    """
    if self._resolution == 'cells':
        return (x, y)
    return self._pixel_view().pixel_at(x, y, anchor=anchor)

copy

copy() -> Region

Return a standalone region with a copy of these cells and, for one, its look.

Source code in xnano/region.py
def copy(self) -> Region:
    """Return a standalone region with a copy of these cells and, for one, its look."""
    copy = Region(_snapshot(self._surface()), is_standalone=True)
    if self._is_standalone and self._appearance is not None:
        import dataclasses

        copy._appearance = dataclasses.replace(
            self._appearance, sides=dict(self._appearance.sides)
        )
        copy._is_text = self._is_text
        copy._insets_applied = self._insets_applied
    return copy

render

render(*, format: Literal['text', 'ansi'] = 'text') -> str

Draw the region to a string.

Parameters:

  • format (Literal['text', 'ansi'], default: 'text' ) –

    'text' for the characters only, 'ansi' with colors and styles.

Examples:

import xnano

assert xnano.write('hi', padding=1).render().splitlines() == ['', ' hi']
Source code in xnano/region.py
def render(self, *, format: Literal['text', 'ansi'] = 'text') -> str:
    """
    Draw the region to a string.

    Args:
        format: ``'text'`` for the characters only, ``'ansi'`` with colors and styles.

    Examples:
        ```python
        import xnano

        assert xnano.write('hi', padding=1).render().splitlines() == ['', ' hi']
        ```
    """
    return _snapshot(self._surface()).render(format=format)

__str__

__str__() -> str

Return the characters of the region, so print(region) shows it.

Source code in xnano/region.py
def __str__(self) -> str:
    """Return the characters of the region, so ``print(region)`` shows it."""
    return self.render()

__xnano_render__

__xnano_render__(context: Context | None = None) -> Buffer

Return the buffer that shows the region: its own, or a copy for a view.

Source code in xnano/region.py
def __xnano_render__(self, context: Context | None = None) -> _core.Buffer:
    """Return the buffer that shows the region: its own, or a copy for a view."""
    if self._is_standalone:
        self._flush_look()
        return self._buffer
    return _snapshot(self._surface())

__setattr__

__setattr__(name: str, value: object) -> None

Set an attribute, or raise AttributeError for an unknown public name.

Source code in xnano/_attributes.py
def __setattr__(self, name: str, value: object) -> None:
    """Set an attribute, or raise ``AttributeError`` for an unknown public name."""
    if (
        name[:1] != '_'
        and self.__dict__.get('_is_sealed')
        and not hasattr(type(self), name)
        and name not in self.__dict__
    ):
        kind = type(self).__name__
        settable = sorted(
            key
            for key in dir(type(self))
            if key[:1] != '_' and _is_settable(type(self), key)
        )
        close = difflib.get_close_matches(name, settable, n=1)
        hint = f' Did you mean {close[0]!r}?' if close else ''
        raise AttributeError(
            f'{kind} has no attribute called {name!r}, so assigning to it would change '
            f'nothing.{hint} The attributes you can assign are: {", ".join(settable)}.'
        )
    object.__setattr__(self, name, value)

write

write(text: str, /, **appearance: Unpack[AppearanceArguments]) -> Region

Build a standalone region from text (does not draw).

The region is sized to the text and is a value that you write into a canvas. It owns its cells. Write it into a canvas with canvas.write(region), print it with render, or change its look afterwards with region.border and its siblings.

Parameters:

  • text (str) –

    The text, line by line.

  • appearance (Unpack[AppearanceArguments], default: {} ) –

    The look of the text: colors, text modifiers, border, title, padding and margin; see AppearanceArguments.

Raises:

Examples:

import xnano

card = xnano.write('hello', border='rounded', padding={'horizontal': 1})
assert card.render().splitlines()[1] == '│ hello │'
card.border = False
assert card.render().strip() == 'hello'
Source code in xnano/region.py
def write(text: str, /, **appearance: Unpack[AppearanceArguments]) -> Region:
    """
    Build a standalone region from text (does not draw).

    The region is sized to the text and is a value that you write into a canvas. It owns its
    cells. Write it into a canvas with ``canvas.write(region)``, print it
    with [`render`][xnano.region.Region.render], or change its look afterwards with
    ``region.border`` and its siblings.

    Args:
        text: The text, line by line.
        appearance: The look of the text: colors, text modifiers, ``border``, ``title``,
            ``padding`` and ``margin``; see [`AppearanceArguments`][xnano.types.AppearanceArguments].

    Raises:
        TypeError: ``text`` is not a string.

    Examples:
        ```python
        import xnano

        card = xnano.write('hello', border='rounded', padding={'horizontal': 1})
        assert card.render().splitlines()[1] == '│ hello │'
        card.border = False
        assert card.render().strip() == 'hello'
        ```
    """
    if not isinstance(text, str):
        raise TypeError(
            f'xnano.write() takes text, but got {text!r}. To show other content, create a '
            f'canvas with xnano.new() and call canvas.write(content).'
        )
    look = _standalone_look('write', text, cast('dict[str, object]', appearance), False)
    region = Region(
        _core.Buffer(width=1, height=1), is_standalone=True, look=look, is_text=True
    )
    region._redraw_look()
    return region

box

box(width: int, height: int, /, **appearance: Unpack[AppearanceArguments]) -> Region

Build an empty standalone rectangle of cells with a border (does not draw).

The region is a value that you write into a canvas.

Parameters:

  • width (int) –

    The width in cells, border included.

  • height (int) –

    The height in cells, border included.

  • appearance (Unpack[AppearanceArguments], default: {} ) –

    The look of the box. border is 'plain' unless you pass another kind or False.

Raises:

  • ValueError –

    A size is below 1 or above 65535.

Examples:

import xnano

frame = xnano.box(5, 3)
assert frame.render().splitlines() == ['┌───┐', '│   │', '└───┘']
Source code in xnano/region.py
def box(width: int, height: int, /, **appearance: Unpack[AppearanceArguments]) -> Region:
    """
    Build an empty standalone rectangle of cells with a border (does not draw).

    The region is a value that you write into a canvas.

    Args:
        width: The width in cells, border included.
        height: The height in cells, border included.
        appearance: The look of the box. ``border`` is ``'plain'`` unless you pass another
            kind or ``False``.

    Raises:
        ValueError: A size is below 1 or above 65535.

    Examples:
        ```python
        import xnano

        frame = xnano.box(5, 3)
        assert frame.render().splitlines() == ['┌───┐', '│   │', '└───┘']
        ```
    """
    _check_cell_counts('xnano.box', width, height)
    if width < 1 or height < 1:
        raise ValueError(
            f'A box is at least 1 by 1 cells, but got {width} by {height}. Pass whole '
            f'numbers of cells, 1 or more.'
        )
    look = _standalone_look('box', '', cast('dict[str, object]', appearance), True)
    region = Region(
        _core.Buffer(width=width, height=height),
        is_standalone=True,
        look=look,
        is_text=False,
    )
    region._redraw_look()
    return region