xnano
xnano
¶
xnano
An extremely nano python terminal experience; built on ratatui.
Modules:
-
appearance–xnano.appearance
-
art–xnano.art
-
audio–xnano.audio
-
buffers–xnano.buffers
-
canvas–xnano.canvas
-
components–xnano.components
-
context–xnano.context
-
cursor–xnano.cursor
-
demo–xnano.demo
-
effects–xnano.effects
-
errors–xnano.errors
-
events–xnano.events
-
expressions–xnano.expressions
-
geometry–xnano.geometry
-
image–xnano.image
-
input–xnano.input
-
music–xnano.music
-
operations–xnano.operations
-
output–xnano.output
-
pixel–xnano.pixel
-
placement–xnano.placement
-
region–xnano.region
-
state–xnano.state
-
styles–xnano.styles
-
symbols–xnano.symbols
-
terminal–xnano.terminal
-
time–xnano.time
-
types–xnano.types
-
widgets–xnano.widgets
Classes:
-
Audio–A sound you can play with
Canvas.playor -
Image–An image and how it is shown: what
Canvas.writetakes -
Canvas–A workspace of text, pixels and sound on a clock, with or without a screen.
-
Context–What a hook is called with.
-
Note–A note, or a chord, to play: a pitch, how long it lasts and how it sounds.
-
Pixel–One cell (or one dot, at half-block and braille resolution) of a region.
-
Terminal–A canvas that draws on your screen and reads your keyboard and mouse.
-
Color–A terminal color: a named palette color, a palette index or a true color.
Functions:
-
from_audio–Load a sound from a WAV file path or from bytes.
-
from_image–Load an image or an animation from a file path or from bytes.
-
draw–Build pixel art from text, a picture, bytes or nothing (does not draw).
-
active–Return the innermost canvas that is running in this thread or task.
-
iter–Iterate over the frames of the active canvas, drawing between them.
-
new–Create a canvas: a virtual terminal with a clock, hooks, sound, a cursor and state.
-
playable–Turn a function into a component that plays itself.
-
renderable–Turn a function into a component that draws itself.
-
note–Make a
Note: a pitch, or several for a chord, with its length and sound. -
play–Play a note, a sound, a symbol name, a melody or a sequence of those.
-
hook–Describe a hook once, to attach to any canvas or placement later.
-
box–Build an empty standalone rectangle of cells with a border (does not draw).
-
write–Build a standalone region from text (does not draw).
-
open–Put a canvas on your screen and return it as a
Terminal.
Audio
dataclass
¶
A sound you can play with Canvas.play or
AudioDevice.play.
Make one from the path of a WAV file, the bytes of one, or a
TerminalSound.
Attributes:
-
sound(TerminalSound) –The rendered sound.
-
symbol(str | None) –The name the sound is registered under in
symbols, orNone.play('kick')plays the sound registered as'kick'.
Examples:
import xnano
from xnano_audio import TerminalSound
audio = xnano.Audio(TerminalSound.from_samples([0.0, 0.5, -0.5, 0.0]))
assert audio.sound.sample_rate == 44100
Load a sound.
Parameters:
-
source(TerminalSound | PathLike[str] | str | bytes) –The path of a WAV file, the bytes of one, or a sound.
-
symbol(str | None, default:None) –A name to register the sound under in
symbols, soplay(name)plays it.
Raises:
-
ImportError–xnano-audiois not installed. Install it withpip install "xnano[audio]". -
TypeError–sourceis not a path, bytes or a sound. -
FileNotFoundError–sourceis a path to a file that does not exist. -
ValueError–The file is not a PCM WAV file that xnano can read, or
symbolcannot be a symbol name, or another kind of value already has it.
Source code in xnano/_media.py
Image
dataclass
¶
Image(source: TerminalImage | PathLike[str] | str | bytes, *, x: Axis | None = None, y: Axis | None = None, width: Axis | None = None, height: Axis | None = None, layer: int = 0, lock: bool = False, fit: ImageFit | None = None, resampling_filter: ResamplingFilter | None = None, background: ColorValue = (0, 0, 0), speed: float = 1.0, symbol: str | None = None)
An image and how it is shown: what Canvas.write takes
to put a picture on the canvas.
Make one from the path of an image file, its bytes, or a
TerminalImage. A file is read once, here, where you can
see it; write never takes a path. The placement values are what write uses when it
is not given its own. An image sized by a percentage (or not sized at all) is converted
again whenever the canvas is resized, so it always fits; give it a number, or
lock=True, and it keeps its size.
Attributes:
-
image(TerminalImage) –The picture.
-
x(Axis | None) –The column of the left edge, or
Nonefor the top-left corner. -
y(Axis | None) –The row of the top edge, or
None. -
width(Axis | None) –The width: cells, a percentage, an expression, or
Nonefor the picture's own. -
height(Axis | None) –The height, in the same forms.
-
layer(int) –Content with a higher layer is drawn over content with a lower one.
-
lock(bool) –Whether the image keeps the size it was shown at when the canvas is resized.
-
fit(ImageFit | None) –How the picture sits in a box of
widthbyheight:'contain'(the default),'cover','stretch','crop'or'smart'. -
resampling_filter(ResamplingFilter | None) –How pixels are blended when it is resized. By default a small picture that is enlarged keeps hard pixel edges (
'nearest') and any other is smoothed ('lanczos3'). -
background(tuple[int, int, int]) –The color behind transparent pixels and padding.
-
symbol(str | None) –The name the image is registered under in
symbols, orNone.
Examples:
import xnano
from xnano.image import TerminalImage
picture = xnano.Image(TerminalImage.from_rgba(2, 2, bytes([255, 0, 0, 255]) * 4), width=8)
with xnano.new(width=20, height=6) as canvas:
canvas.write(picture, x='center')
# xnano.Image('photo.png', width='100%') loads a file, and refits when the window resizes.
Load an image and set how it is shown.
Parameters:
-
source(TerminalImage | PathLike[str] | str | bytes) –The path of an image file (PNG, JPEG, GIF, WebP or XNI), the bytes of one, or an image. An animated file plays on the canvas's clock.
-
x(Axis | None, default:None) –The column of the left edge: cells, a percentage, a word such as
'center', an expression or a range. SeeAxis. -
y(Axis | None, default:None) –The row of the top edge, in the same forms.
-
width(Axis | None, default:None) –The width, in the same forms; the picture's own when
None. -
height(Axis | None, default:None) –The height, in the same forms.
-
layer(int, default:0) –Content with a higher layer is drawn over content with a lower one.
-
lock(bool, default:False) –Keep the size the image has when it is added, whatever the canvas does.
-
fit(ImageFit | None, default:None) –How the picture sits in a box of
widthbyheight. -
resampling_filter(ResamplingFilter | None, default:None) –How pixels are blended when it is resized.
-
background(ColorValue, default:(0, 0, 0)) –The color behind transparent pixels and padding, as a color name, a hex string, an
(r, g, b)tuple or aColor. -
speed(float, default:1.0) –How fast an animated image plays:
2.0is twice as fast. -
symbol(str | None, default:None) –A name to register the image under in
symbols.
Raises:
-
ImportError–xnano-imageis not installed. Install it withpip install "xnano[image]". -
TypeError–sourceis not a path, bytes or an image. -
FileNotFoundError–sourceis a path with no file at it. -
ValueError–symbolcannot be a symbol name, or another kind of value already has it.
Source code in xnano/_media.py
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 | |
Canvas
¶
Canvas(*, width: int | str | None, height: int | str | None, fps: float, bpm: float, is_realtime: bool, deps: object, state: object, title: str | None, gates: Mapping[str, object], appearance: Mapping[str, object], effects: Sequence[RenderableEffectSpecification], enclosing: Canvas[object, object] | None = None, layout: CanvasLayout = 'overlay', edges: EdgeBehavior = 'clip')
Bases: _Hooked[DepsT, StateT], _TextModifiers, Generic[DepsT, StateT]
A workspace of text, pixels and sound on a clock, with or without a screen.
A canvas is a virtual terminal. Create one with new: it has a size, a clock,
hooks, a cursor, sound and state, and no screen, so it draws into memory and its time moves
only when you move it with step or
iter, which makes every run the same. new(realtime=True)
runs it on the wall clock instead, on a thread of its own. open
puts the same object on your screen, where it becomes a Terminal
and its time continues from where it was. It is not the drawing widget
xnano.widgets.Canvas.
How a canvas ends depends on who moves its clock. On a canvas from new(),
quit only ends a running iter(): the canvas stays open
for writing and rendering. On a canvas that runs by itself (realtime=True, or opened
on the screen) its loop ends with quit(), Ctrl-C or a quit key of
run, and that closes the canvas. close
(or leaving the with block) always closes it. The three states are:
| State | Read it from | Meaning |
|---|---|---|
| running | is_running |
open, and its loop has not been asked to end |
| time stopped | time.is_stopped |
frozen by stop(); it still draws and hears input |
| closed | is_closed |
torn down; it cannot draw or listen |
What you put on the canvas is declared on the canvas itself:
write, hook and indexing.
Everything else is grouped by what it is: canvas.time is the
Time, canvas.cursor the one Cursor,
canvas.output the Output of drawn frames and
canvas.audio the AudioDevice.
Any thread may write, remove, draw and play. Hooks run on the canvas's loop, so keep them short.
Attributes:
-
is_closed(bool) –Whether the canvas has been torn down.
-
is_running(bool) –Whether the canvas is open and its loop has not been asked to end.
-
core_buffer(Buffer) –The core buffer everything is added to, as large as the canvas.
-
parent(ParentExpressionScope) –Symbolic expressions for the parent container's
width,heightandsize. -
root(RootExpressionScope) –Symbolic expressions for the root canvas's geometry and clock.
-
size(Size) –The size of the canvas in cells.
-
width(int) –The width of the canvas in cells.
-
height(int) –The height of the canvas in cells.
-
x(int) –The column of the canvas, which is
0for a canvas that is not written into another. -
y(int) –The row of the canvas, which is
0for a canvas that is not written into another. -
title(str | None) –The window title;
Noneclears it. -
fps(float) –The most frames drawn per second.
-
bpm(float) –Beats per minute for beat timers, notes and melodies.
-
deps(DepsT) –The dependencies given to
new(deps=...), which hooks read. -
time(Time) –The
Timeeverything on the canvas runs on. -
cursor(Cursor) –The canvas's one cursor.
-
state–The dataclass given to
new(state=...). -
output(Output) –The
Output: what was drawn, and held-back text. -
audio(AudioDevice) –The
AudioDevice: notes, melodies, sounds and the microphone. -
input(Input) –The keys held down right now, for programs that poll instead of listening.
Examples:
import xnano
with xnano.new(width=12, height=2, fps=10) as canvas:
greeting = canvas.write('hello', x=1, y=1)
for frame in canvas.iter(count=3):
greeting.text = f'frame {frame.index}'
assert canvas.render().splitlines()[1] == ' frame 2'
assert round(canvas.time.elapsed, 3) == 0.3
Create a canvas. Use new instead of calling this.
Parameters:
-
width(int | str | None) –The width in cells or as a percentage of the window, or
Nonefor 80. -
height(int | str | None) –The height in cells or as a percentage of the window, or
Nonefor 24. -
fps(float) –The most frames drawn per second.
-
bpm(float) –Beats per minute.
-
is_realtime(bool) –Whether the canvas runs on the wall clock, on a thread of its own.
-
deps(object) –The dependencies, or the unset marker when none were given.
-
state(object) –A dataclass instance the canvas keeps and validates, or the unset marker.
-
title(str | None) –The window title, or
None. -
gates(Mapping[str, object]) –The input gates that were given, by name.
-
appearance(Mapping[str, object]) –The appearance keywords of the canvas itself, by name.
-
effects(Sequence[RenderableEffectSpecification]) –Effects to apply to the canvas, as dictionaries with a
kindkey. -
enclosing(Canvas[object, object] | None, default:None) –The canvas whose
withblock this one was created in, which its sizes are measured in and which closes it, orNone. -
layout(CanvasLayout, default:'overlay') –How the canvas places what is written on it.
-
edges(EdgeBehavior, default:'clip') –What content written on the canvas does at the edges of its area.
-
API Reference
xnano
-
xnano -
xnano.audio
audioAudioDevice -
xnano.canvas
canvas -
xnano.context
context -
xnano.cursor
cursorCursor -
xnano.input
input -
xnano.operations
operations -
xnano.output
outputOutput -
xnano.placement
placementPlacementwrite -
xnano.region
regionRegion -
xnano.state
stateStateNamespace -
xnano.terminal
terminal -
xnano.time
timeTime -
xnano.types
typesRenderableEffects
-
Methods:
-
__setattr__–Set an attribute, or raise
AttributeErrorfor an unknown public name. -
bold–Make the text bold, or undo it with
False; the same as settingis_bold. -
dim–Dim the text, or undo it with
False; the same as settingis_dim. -
italic–Make the text italic, or undo it with
False; the same as settingis_italic. -
underline–Underline the text, or undo it with
False; the same as settingis_underlined. -
blink–Make the text blink, or undo it with
False; the same as settingis_blinking. -
reverse–Swap the foreground and background, or undo it with
False; the same as settingis_reversed. -
hidden–Hide the text, or undo it with
False; the same as settingis_hidden. -
crossed_out–Strike the text through, or undo it with
False; the same as settingis_crossed_out. -
hook–Call a function when something happens on this canvas or placement.
-
__new__–Refuse a direct call: a canvas is created with
xnano.new. -
open–Put this canvas on your screen, and return it as a
Terminal. -
close–Release everything the canvas holds, and give the screen back if it has one.
-
local–Convert a cell of the screen into a cell of this canvas.
-
move–Move a canvas that is written into another one by a number of cells along each axis.
-
up–Move a written canvas up by
countrows; seemove. -
down–Move a written canvas down by
countrows; seemove. -
left–Move a written canvas left by
countcolumns; seemove. -
right–Move a written canvas right by
countcolumns; seemove. -
new–Create a canvas inside this one and draw it here at once, at the top-left corner.
-
write–Put something on the canvas: text, a widget, a buffer, another canvas or an image.
-
clear–Erase everything written or drawn directly on the canvas's cells.
-
update–Change the canvas's own cells with operations, styles or effects.
-
__or__–Apply an operation, customization or style with
canvas | operation. -
__ior__–Apply an operation, customization or style in place with
canvas |= operation. -
inspect–Evaluate an expression against the canvas and return its value.
-
iter–Iterate over the canvas's frames, drawing between them; pass
count=orseconds=, -
step–Move time by
delta_seconds, one frame by default, and draw exactly one frame. -
deliver_events–Deliver pushed events to their hooks and draw a frame, without moving time.
-
stop–Freeze time: the same as
Time.stop. -
resume–Let time run on from where
stopfroze it. -
quit–Ask the canvas's loop to end.
-
run–Wait until the canvas's loop ends.
-
wait_for_key–Wait until a key is pressed, and return its name.
-
prompt–Prompt for a line of text, and return what was typed.
-
render–Draw the current frame and return it, without a screen.
-
push–Deliver an event to the canvas as if it had been typed, clicked or reported.
-
play–Play a note, a sound, a symbol name, a melody or a sequence of those, and return at once.
-
state_reference–A core reference for one field of the canvas's state.
Source code in xnano/canvas.py
690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 | |
color
property
¶
color: Colors
border
property
writable
¶
border: BorderAppearance
The border: its kind, a setting for each side, its color and its title.
Assign 'plain', 'rounded', 'double' or 'thick' to draw a border
on every side, True for 'plain' and False to remove it. It works on any
content, not only on text.
The border, padding and margin are drawn around the content, so the placement grows by the cells they take. A widget with no size of its own is shrunk to fit its parent, border included.
Examples:
padding
property
writable
¶
padding: PaddingAppearance
The space between the border and the content, edge by edge.
Assign a number of cells, a percentage such as '10%' or a dictionary such as
{'vertical': 1, 'horizontal': 2}, or set one edge with padding.left = 2.
margin
property
writable
¶
margin: MarginAppearance
The transparent space outside the border, edge by edge, set like padding.
output
instance-attribute
¶
The canvas's drawn frames and captured text.
is_closed
property
¶
is_closed: bool
Whether the canvas has been torn down: closed, or its loop has ended.
is_running
property
¶
is_running: bool
Whether the canvas is open and its loop has not been asked to end.
core_buffer
property
¶
core_buffer: Buffer
The core buffer the canvas draws, as large as the canvas.
Everything you write is a child of this buffer, and everything drawn directly on the canvas is stored in it. A canvas with a border, padding or margin draws them around a buffer of its own; this is the buffer inside them.
parent
property
¶
parent: ParentExpressionScope
Symbolic expressions for the parent container's width, height and size.
root
property
¶
root: RootExpressionScope
Symbolic expressions for the root canvas's width, height, size and time.
fps
property
¶
fps: float
The most frames drawn per second, and the rate iter aims for.
bpm
property
writable
¶
bpm: float
Beats per minute: the length of a beat for beat timers, notes and melodies.
It is 120 unless new(bpm=...) said otherwise, and it can change while things
are playing; the change applies from the next beat.
Raises:
-
ValueError–The tempo is not above 0 and at most 600000.
title
property
writable
¶
title: str | None
The window title last set on this canvas.
Assign a single line of printable text to set the title of the window a canvas on the
screen draws in, or None to clear it. A canvas without a screen keeps the value
and shows it when it is opened.
time
property
¶
time: Time
The canvas's Time: how long it has run, stopping, and formulas.
cursor
property
¶
cursor: Cursor
The canvas's Cursor.
A canvas has exactly one cursor. Set its position (a cell, or None to hide
it), shape, is_blinking and is_visible, move it with up, down,
left, right and move, or follow a placement. It can be changed from
any thread, and on the screen the cursor you had before is restored when the canvas
closes.
Examples:
import xnano
with xnano.new(width=10, height=2) as canvas:
canvas.cursor.position = (3, 0)
canvas.cursor.shape = 'bar'
assert canvas.cursor.position.x == 3
region
property
¶
region: Region
The cells of the canvas as a Region: read and write
canvas.region[x, y].
The default resolution is one cell. canvas.region.half_blocks addresses two
pixels per cell and canvas.region.braille eight dots.
Examples:
layout
property
¶
layout: CanvasLayout
How the canvas places what is written on it, chosen when the canvas is created.
'overlay' places every piece on its own over the whole canvas. 'column'
stacks the pieces from top to bottom in the order they are written, and 'row'
from left to right. Each piece then takes a slot: one with a size on the stacking
axis (height in a column, width in a row, in cells or as a percentage) gets
exactly that, and the others share what is left equally. Inside its slot a piece is
positioned as on any canvas, so y='center' and y='50%' are measured in the
slot. Removing a piece gives its slot back. A canvas created inside the with
block of a stacking canvas takes a slot only once it is written.
Examples:
edges
property
writable
¶
edges: EdgeBehavior
What content written on the canvas does at the edges of its area, unless given its own.
'clip' lets it move past the edge, where it is not drawn; 'stop' holds it
inside its area when it moves; 'wrap' continues text on the next rows of its
area. A piece written with edges=... keeps its own; see
Placement.edges.
Raises:
-
ValueError–The value is not
'clip','stop'or'wrap'.
audio
property
¶
audio: AudioDevice
The canvas's AudioDevice: notes, melodies, sounds and the microphone.
It needs the optional xnano-audio package, which is imported the first time this
is read.
Raises:
-
ImportError–xnano-audiois not installed. Install it withpip install "xnano[audio]".
fx
property
¶
The visual effects of the canvas itself, one method for each effect.
canvas.fx.fade_to(background='navy') starts a fade over the whole canvas at once,
and canvas.fx.clear() stops what was started here. A placement has its own
fx, and the sound effects of what the canvas plays are
canvas.audio.fx. See
RenderableEffects.
Examples:
import xnano
with xnano.new('hello', width=8, height=1) as canvas:
canvas.fx.dissolve(duration_milliseconds=300)
assert len(canvas.fx.active) == 1
input
property
¶
input: Input
The keys held down right now, for programs that poll instead of listening.
Read it anywhere, from any thread. A canvas opened with
keyboard='release_events' knows exactly when a key is let go.
state
class-attribute
instance-attribute
¶
The canvas's state: values that hooks and your code share, read and written by path.
canvas.state.get('player.score') reads a value and canvas.state.push('player.score',
3) writes one; see StateNamespace for the path rules. A
canvas created with new(state=Settings()) also gives the fields of the dataclass as
attributes with their declared types, so canvas.state.volume is an int for a field
declared volume: int; a write is checked against the field's type. A type checker
sees get and push only on a canvas without a state dataclass, but both exist on
every canvas.
The state can be used from any thread. A write updates every expression that reads the field and draws a frame.
__setattr__
¶
Set an attribute, or raise AttributeError for an unknown public name.
Source code in xnano/_attributes.py
bold
¶
bold(value: bool = True) -> Self
Make the text bold, or undo it with False; the same as setting is_bold.
Parameters:
-
value(bool, default:True) –Whether the text is bold.
Returns:
-
Self–This canvas or placement, so calls can chain.
Raises:
-
TypeError–valueis notTrueorFalse.
Examples:
import xnano
with xnano.new(width=12, height=1) as canvas:
title = canvas.write('Ready').bold().underline()
assert title.is_bold and title.is_underlined
title.bold(False)
assert not title.is_bold
Source code in xnano/appearance.py
dim
¶
dim(value: bool = True) -> Self
Dim the text, or undo it with False; the same as setting is_dim.
Parameters:
-
value(bool, default:True) –Whether the text is dimmed.
Returns:
-
Self–This canvas or placement, so calls can chain.
Raises:
-
TypeError–valueis notTrueorFalse.
Source code in xnano/appearance.py
italic
¶
italic(value: bool = True) -> Self
Make the text italic, or undo it with False; the same as setting is_italic.
Parameters:
-
value(bool, default:True) –Whether the text is italic.
Returns:
-
Self–This canvas or placement, so calls can chain.
Raises:
-
TypeError–valueis notTrueorFalse.
Source code in xnano/appearance.py
underline
¶
underline(value: bool = True) -> Self
Underline the text, or undo it with False; the same as setting is_underlined.
Parameters:
-
value(bool, default:True) –Whether the text is underlined.
Returns:
-
Self–This canvas or placement, so calls can chain.
Raises:
-
TypeError–valueis notTrueorFalse.
Source code in xnano/appearance.py
blink
¶
blink(value: bool = True) -> Self
Make the text blink, or undo it with False; the same as setting is_blinking.
Parameters:
-
value(bool, default:True) –Whether the text blinks.
Returns:
-
Self–This canvas or placement, so calls can chain.
Raises:
-
TypeError–valueis notTrueorFalse.
Source code in xnano/appearance.py
reverse
¶
reverse(value: bool = True) -> Self
Swap the foreground and background, or undo it with False; the same as setting is_reversed.
Parameters:
-
value(bool, default:True) –Whether foreground and background are swapped.
Returns:
-
Self–This canvas or placement, so calls can chain.
Raises:
-
TypeError–valueis notTrueorFalse.
Source code in xnano/appearance.py
hidden
¶
hidden(value: bool = True) -> Self
Hide the text, or undo it with False; the same as setting is_hidden.
Parameters:
-
value(bool, default:True) –Whether the text is hidden.
Returns:
-
Self–This canvas or placement, so calls can chain.
Raises:
-
TypeError–valueis notTrueorFalse.
Source code in xnano/appearance.py
crossed_out
¶
crossed_out(value: bool = True) -> Self
Strike the text through, or undo it with False; the same as setting is_crossed_out.
Parameters:
-
value(bool, default:True) –Whether the text is struck through.
Returns:
-
Self–This canvas or placement, so calls can chain.
Raises:
-
TypeError–valueis notTrueorFalse.
Source code in xnano/appearance.py
hook
¶
hook(function: Hook[DepsT, StateT] | None = None, /, *, on: HookKind | None = None, when: When[DepsT, StateT] | None = None, every: float | None = None, after: float | None = None, keys: KeyName | Sequence[KeyName] | None = None, requires_deps: bool = False) -> HookHandle[DepsT, StateT] | Callable[[Hook[DepsT, StateT]], HookHandle[DepsT, StateT]]
Call a function when something happens on this canvas or placement.
on says what to listen to. A hook without on hears every input event. A mouse,
scroll or drag hook on a placement hears only the pointer inside the placement, and a
press inside holds the pointer for the hook until the button is released. A pointer hook
that matches an event stops it from reaching the parent; a hook that does not match lets
it through. Keys are not consumed: while nothing has focus, every key hook hears a key.
hook(function, ...) attaches one function, and @target.hook(...) decorates the
function that follows. A hook function may be a generator that receives a new context
at each bare yield: write context = yield. A drag is a loop that runs while
context.mouse.is_down.
every and after are seconds for on='tick' and beats for on='beat':
every=2 means 2 seconds for a tick hook and 2 beats for a beat hook. On a canvas
from new() a hook that is due several times in one step runs once for each
interval, up to 100,000 times in one step; the intervals that remain run in the steps
that follow. The function's return value is ignored, unless it is an operation, a
style or an effect, which is applied to this target.
Parameters:
-
function(Hook[DepsT, StateT] | None, default:None) –The function to call with a
Context, or a function with no parameters, which is called without it. -
on(HookKind | None, default:None) –What to listen to:
'frame','tick','beat','key','mouse','scroll','drag','paste','focus','resize','state'or'custom'. SeeHookKind. -
when(When[DepsT, StateT] | None, default:None) –A condition that must hold: an expression, a function of the context, or a string. See
When. A string tells xnano which input the hook needs, so the mouse, scroll and key-release gates it reads are turned on when the canvas opens. An expression or a function does not, so a condition that readsMouse,Scrollor key releases needs the gate set onnew()oropen()yourself:mouse=True,scroll=Trueorkeyboard='release_events'. A comparison with an input the event does not carry, such askeyboard.keyon a paste, does not hold;!=is one of them, sokeyboard.key != 'q'hears only key events.notandnot innegate the whole comparison, sonot keyboard.key == 'q'andkeyboard.key not in ['q']also hold for events that have no key. -
every(float | None, default:None) –Repeat every this many seconds (
'tick') or beats ('beat'). -
after(float | None, default:None) –Run once after this many seconds (
'tick') or beats ('beat'). -
keys(KeyName | Sequence[KeyName] | None, default:None) –The key or keys an
on='key'hook reacts to, such as'q'or'ctrl+s'. A key hook with keys hears presses and repeats; omit them and testkeyboard.kindto hear releases. -
requires_deps(bool, default:False) –Whether the hook needs the dependencies given to
new(deps=...).
Returns:
-
HookHandle[DepsT, StateT] | Callable[[Hook[DepsT, StateT]], HookHandle[DepsT, StateT]]–The hook, whose
removestops it; or, without a function, the decorator.
Raises:
-
ValueError–The combination of arguments does not make sense, a key name is unknown, or a
whenstring is not a condition. The message says what to write instead. -
TypeError–onis not text,whenis a plainbool, or the function is not callable with a context, or is anasyncfunction. -
TerminalError–requires_depsis true and the canvas was created withoutdeps, or the canvas is on a screen with an input gate this hook needs turned off.
Examples:
import xnano
from xnano_core import Event
with xnano.new(width=8, height=1) as canvas:
heard = []
@canvas.hook(on='key', keys=['q', 'escape'])
def leave(context: xnano.Context) -> None:
heard.append(context.keyboard.key)
@canvas.hook(on='tick', every=0.5)
def blink(context: xnano.Context) -> None:
heard.append('tick')
canvas.push(Event.key_press('q'))
canvas.step(delta_seconds=1.0)
assert heard == ['q', 'tick', 'tick']
Source code in xnano/_hooks.py
872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 | |
__new__
¶
Refuse a direct call: a canvas is created with xnano.new.
Source code in xnano/canvas.py
open
¶
open(*, title: str | None = None, width: int | Percentage | str | None = None, height: int | Percentage | str | None = None, **settings: Unpack[OpenSettings]) -> Terminal[DepsT, StateT]
Put this canvas on your screen, and return it as a Terminal.
The same object is returned: after this, isinstance(canvas, xnano.Terminal) is
true. From then on it runs by itself on a thread of its own and on the wall clock, which
continues from the time the canvas had: elapsed time, the frame count, every and
after timers and a stopped clock carry over, and so do the cursor, the title,
everything written and every hook. Effects that were running start again from their
beginning, and keyboard focus and a captured pointer are released.
width and height are the size of the canvas: the ones given here, else the
ones given to new(), draw in a region of that size below the cursor; a canvas
created without a size, or with '100%' for both, fills the whole window. A
percentage such as '50%' is a share of the window when the canvas is opened. Any other keyword of new() except
realtime may be given and applies before the canvas is shown; a gate given here
wins over the one given to new(). title is the window title.
Parameters:
-
title(str | None, default:None) –The window title;
Nonekeeps the canvas's title. -
width(int | Percentage | str | None, default:None) –The width of the region to draw in: cells, or a percentage of the window.
-
height(int | Percentage | str | None, default:None) –The height of the region to draw in: cells, or a percentage of the window.
-
settings(Unpack[OpenSettings], default:{}) –Gates, appearance keywords,
fps,bpm,effects, anddepsandstatefor a canvas that was created without them; seeOpenSettings.
Returns:
-
Terminal[DepsT, StateT]–This canvas, now attached to the screen.
Raises:
-
TerminalAlreadyOpenError–Another canvas is already on the screen.
-
TerminalError–This canvas is already on the screen, was written into another canvas, has a hook that needs a gate given as
False, or there is no terminal to draw on; the canvas stays as it was. -
TypeError–realtimewas given,depsorstatethat the canvas already has, or an effect that is not a visual effect dictionary. -
ValueError–A
widthwas given without aheight, or a value is out of range.
Examples:
with xnano.new(width=40, height=5) as canvas:
canvas.write('hello', border='rounded')
canvas.step()
canvas.open(mouse=True) # now a xnano.Terminal, 40 by 5 below the prompt
canvas.run(quit_on='q')
Source code in xnano/canvas.py
close
¶
close(*, raise_failure: bool = True) -> None
Release everything the canvas holds, and give the screen back if it has one.
Closing twice is harmless. Leaving a with block closes the canvas, unless it is
part of another canvas or was created inside another canvas's with block: then it
stays usable and closes with that canvas. Closing a canvas closes the canvases created
inside its block that were not written anywhere. Closing a canvas that was written into
another one takes it off and leaves that one running.
Parameters:
-
raise_failure(bool, default:True) –Whether to raise the error a callback raised on the loop, which stopped the canvas. A
withblock passesFalsewhile another error is already propagating.
Raises:
-
TerminalError–A callback raised on the canvas's loop, or the loop would not stop.
Source code in xnano/canvas.py
1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 | |
local
¶
Convert a cell of the screen into a cell of this canvas.
Parameters:
-
point(Point) –A cell in screen coordinates, such as
context.mouse.position.
Examples:
import xnano
from xnano_core import Point
with xnano.new(width=10, height=3) as canvas:
assert canvas.local(Point(4, 1)) == Point(4, 1)
Source code in xnano/canvas.py
move
¶
Move a canvas that is written into another one by a number of cells along each axis.
This moves the placement the canvas is drawn in; see
Placement.move.
Parameters:
-
x(int, default:0) –Columns to move right; a negative number moves left.
-
y(int, default:0) –Rows to move down; a negative number moves up.
Returns:
-
Self–The canvas, so calls can chain.
Raises:
-
TerminalError–The canvas is not written into another canvas, so it sits at the origin and cannot move.
-
TypeError–An amount is not a whole number.
Examples:
import xnano
with xnano.new(width=20, height=3) as outer:
inner = outer.new('box', width=4, height=1)
inner.move(x=2, y=1)
assert (inner.x, inner.y) == (2, 1)
assert outer.render().splitlines()[1] == ' box'
Source code in xnano/canvas.py
up
¶
up(count: int = 1) -> Self
Move a written canvas up by count rows; see move.
Parameters:
-
count(int, default:1) –How many rows to move.
Raises:
-
TerminalError–The canvas is not written into another canvas.
-
TypeError–countis not a whole number. -
ValueError–countis negative.
Source code in xnano/canvas.py
down
¶
down(count: int = 1) -> Self
Move a written canvas down by count rows; see move.
Parameters:
-
count(int, default:1) –How many rows to move.
Raises:
-
TerminalError–The canvas is not written into another canvas.
-
TypeError–countis not a whole number. -
ValueError–countis negative.
Source code in xnano/canvas.py
left
¶
left(count: int = 1) -> Self
Move a written canvas left by count columns; see move.
Parameters:
-
count(int, default:1) –How many columns to move.
Raises:
-
TerminalError–The canvas is not written into another canvas.
-
TypeError–countis not a whole number. -
ValueError–countis negative.
Source code in xnano/canvas.py
right
¶
right(count: int = 1) -> Self
Move a written canvas right by count columns; see move.
Parameters:
-
count(int, default:1) –How many columns to move.
Raises:
-
TerminalError–The canvas is not written into another canvas.
-
TypeError–countis not a whole number. -
ValueError–countis negative.
Source code in xnano/canvas.py
new
¶
new(content: Content | None = None, /, *, width: int | Percentage | str | None = None, height: int | Percentage | str | None = None, effects: Sequence[RenderableEffectSpecification] = (), **settings: Unpack[CanvasSettings]) -> Canvas[DepsT, StateT]
Create a canvas inside this one and draw it here at once, at the top-left corner.
This is new followed by canvas.write(child): the child's size is
measured in this canvas ('50%' is half of it, and no size fills it), it runs on
this canvas's time and hears its input, and it closes with this canvas. Move it with
move and its relatives, or create it with
new and write it with x and y to place it elsewhere.
Parameters:
-
content(Content | None, default:None) –Something to write into the new canvas at once, such as text.
-
width(int | Percentage | str | None, default:None) –The width in cells, or a percentage of this canvas such as
'50%'. -
height(int | Percentage | str | None, default:None) –The height in cells, or a percentage of this canvas.
-
effects(Sequence[RenderableEffectSpecification], default:()) –Effects to apply to the new canvas, as dictionaries with a
kindkey. -
settings(Unpack[CanvasSettings], default:{}) –The input gates and the new canvas's own look; see
CanvasSettings.
Returns:
Raises:
-
TypeError–An appearance keyword was given with content, or a keyword is unknown.
-
ValueError–A size, gate or border kind is out of range.
-
TerminalError–This canvas is closed, or a hook of the new canvas needs a gate this canvas turned off.
Examples:
import xnano
with xnano.new(width=12, height=4) as outer:
panel = outer.new(height='50%', border='plain')
assert (panel.width, panel.height) == (12, 2)
assert outer.render().splitlines()[0] == '┌──────────┐'
Source code in xnano/canvas.py
2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 | |
write
¶
write(content: Content | Canvas[WrittenDepsT, WrittenStateT] | None = None, /, *, x: Axis | None = None, y: Axis | None = None, width: Axis | None = None, height: Axis | None = None, layer: int = 0, lock: bool = False, edges: EdgeBehavior | None = None, effects: Sequence[RenderableEffectSpecification] = (), style: Style | None = None, foreground: ColorValue | None = None, background: ColorValue | None = None, bold: bool = False, dim: bool = False, italic: bool = False, underline: bool = False, blink: bool = False, reverse: bool = False, hidden: bool = False, crossed_out: bool = False, title: str | None = None, border: BorderKind | bool | None = None, border_style: Style | None = None, padding: Spacing | None = None, margin: Spacing | None = None) -> Placement[DepsT, StateT]
Put something on the canvas: text, a widget, a buffer, another canvas or an image.
On a canvas that runs by itself it appears at once: this only declares it, and the
canvas's own loop draws it. Anything you leave out is taken from the content: x
and y default to the top-left corner, and width and height to the size of
the content, so canvas.write('hello') shows five cells of text where it is.
Change the text later by assigning the placement's
text.
Inside the with block of a canvas created in this one's block, what is written here
is placed and clipped within that canvas's area of this one: where it is written, or
the top-left corner while it is not. Positions such as y='center' are measured in
that area, and that canvas's edges applies there.
A canvas from new that is written here becomes part of this one: it
draws inside the placement, its own clock is set aside and it runs on this canvas's
time. It may not have been given state or deps, which belong to the outermost
canvas. Its audio is not carried over: a musical clock it started and a note it was
playing stop, and a formula that reads its audio.beat follows the outer canvas's
musical clock, which starts at the first beat.
An image is added as an Image (never a file path or a bare
TerminalImage; load one with
from_image). With neither width nor height it keeps
its own proportions at its own size, shrunk to fit the canvas. With one of them the
other follows the image's proportions, and with both the image fits inside that box. An
image sized by a percentage, or by the canvas because you gave no size, is converted
again when the canvas is resized, unless it is locked. An animated image plays on the
canvas's clock.
Parameters:
-
content(Content | Canvas[WrittenDepsT, WrittenStateT] | None, default:None) –Text (or a list of lines), a
Bufferor widget, a canvas fromnew(), an image, or anyRenderable;Nonefor an empty placement. -
x(Axis | None, default:None) –The column of the left edge: a number of cells, a percentage string, a word (
'left','center'or'right'), an expression, or a range ((0, 20)) that limits how far it may travel. SeeAxis. -
y(Axis | None, default:None) –The row of the top edge, in the same forms (
'top','center','bottom'). -
width(Axis | None, default:None) –The width, in the same forms; the content's own width when
None. -
height(Axis | None, default:None) –The height, in the same forms; the content's own height when
None. -
layer(int, default:0) –Content with a higher layer is drawn over content with a lower one.
-
lock(bool, default:False) –Keep the position and size the content has now, whatever the canvas's size does afterwards: percentages, words and formulas are read once.
-
edges(EdgeBehavior | None, default:None) –What the content does at the edges of its area:
'clip','stop'or'wrap'; seePlacement.edges. Left out, it follows what it is written on. -
effects(Sequence[RenderableEffectSpecification], default:()) –Effects to start on the placement, as dictionaries with a
kindkey, such as[{'kind': 'effect.fade_to', 'foreground': 'red'}]. -
style(Style | None, default:None) –A ready-made
Stylefor text. The parameters below are applied over it. -
foreground(ColorValue | None, default:None) –The text color.
-
background(ColorValue | None, default:None) –The color behind the text.
-
bold(bool, default:False) –Whether the text is bold.
-
dim(bool, default:False) –Whether the text is dimmed.
-
italic(bool, default:False) –Whether the text is italic.
-
underline(bool, default:False) –Whether the text is underlined.
-
blink(bool, default:False) –Whether the text blinks.
-
reverse(bool, default:False) –Whether foreground and background are swapped.
-
hidden(bool, default:False) –Whether the text is hidden.
-
crossed_out(bool, default:False) –Whether the text is struck through.
-
title(str | None, default:None) –A title on the border of a box around the text.
-
border(BorderKind | bool | None, default:None) –The kind of border for a box around the content, a
BorderKindsuch as'plain','rounded','double'or'thick';Truefor'plain'andFalsefor none. Giving atitlealone draws a plain one. -
border_style(Style | None, default:None) –The style of the box's border.
-
padding(Spacing | None, default:None) –Space between the border and the text: a number of cells, a float or a percentage of the text's size, or a dictionary with
top,right,bottom,left,verticalandhorizontal. Giving it draws the text in a box without a border unlessborderortitleis also given. -
margin(Spacing | None, default:None) –Space outside the box, in the same forms.
Returns:
Raises:
-
TypeError–The content is a file path, raw bytes, or an operation, style or effect (apply those with
canvas.update(...)instead). -
TerminalError–The content is a canvas that cannot be written here.
Examples:
import xnano
with xnano.new(width=20, height=4) as canvas:
box = canvas.write('hello', x='50%', y=1)
assert box.x == 10
assert (box.width, box.height) == (5, 1)
canvas.write(
'Ready',
x='center',
y='bottom',
foreground='green',
bold=True,
border='rounded',
title='Status',
)
Source code in xnano/canvas.py
2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 | |
clear
¶
update
¶
Change the canvas's own cells with operations, styles or effects.
canvas | operation does the same. To put content on the canvas, use
write instead.
Parameters:
-
operations(Operation | Style, default:()) –What to apply, in order: a core operation such as
FillorWrite, a style, or an xnano customization such as an effect.
Returns:
-
Self–The canvas, so calls chain.
Examples:
import xnano
from xnano_core import Fill
with xnano.new(width=4, height=1) as canvas:
canvas.update(Fill('.'))
assert canvas.render() == '....'
canvas | Fill('#')
assert canvas.render() == '####'
Source code in xnano/canvas.py
__or__
¶
Apply an operation, customization or style with canvas | operation.
Source code in xnano/canvas.py
__ior__
¶
Apply an operation, customization or style in place with canvas |= operation.
inspect
¶
inspect(expression: Expression[ValueT]) -> ValueT
Evaluate an expression against the canvas and return its value.
Parameters:
-
expression(Expression[ValueT]) –Any expression, such as
Width,TimeElapsed % 1orcanvas.audio.level.
Examples:
import xnano
from xnano_core import Width
with xnano.new(width=12, height=2) as canvas:
assert canvas.inspect(Width) == 12
Source code in xnano/canvas.py
iter
¶
Iterate over the canvas's frames, drawing between them; pass count= or seconds=,
or break out of the loop.
Each iteration yields a Frame, and whatever you change
before asking for the next one is drawn. On a canvas from new() each iteration
moves the clock by one frame of its fps, so the same loop produces the same
frames every run; without count or seconds it runs as fast as your code. A
canvas that runs by itself draws as you declare, so there this only paces your code
at its fps: if you are slow, frames are skipped rather than queued.
stop freezes the time iter() follows: the
iterations go on drawing and hooks still run, but the clock stands still until
resume. To move a stopped canvas one frame, call
step.
The iteration ends when count frames have been yielded, when the canvas's time has
run for seconds (whichever comes first), when the canvas is asked to
quit or closed, or when you break out of the loop.
Parameters:
-
count(int | None, default:None) –The most frames to yield.
-
seconds(float | None, default:None) –The most seconds of the canvas's time to run for.
Raises:
-
TerminalError–secondswithoutcounton a stopped canvas, which would never reach the end. -
TerminalClosedError–The canvas is closed.
Examples:
import xnano
with xnano.new(width=8, height=1, fps=10) as canvas:
frames = list(canvas.iter(count=3))
assert [frame.elapsed_seconds for frame in frames] == [0.0, 0.1, 0.2]
Source code in xnano/canvas.py
3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 | |
step
¶
Move time by delta_seconds, one frame by default, and draw exactly one frame.
On a canvas from new() this always works, and it moves time even while the
canvas is stopped, which leaves it stopped: it is how a stopped canvas is walked one
frame at a time. A canvas that runs by itself can be stepped only while it is
stopped. One frame is 1 / fps seconds; default steps and the frames of
iter share one count, so sixty of them at fps=60
are exactly one second. A large delta_seconds is one jump: timers that it crossed
all run, and so do fixed-step every hooks, at most 100000 of their steps in one
step; the steps that remain run in the steps that follow.
Parameters:
-
delta_seconds(float | None, default:None) –How far to move, in seconds, above zero; one frame when
None.
Returns:
Raises:
-
ValueError–delta_secondsis not above zero. -
TerminalError–The canvas runs by itself and is not stopped.
-
TerminalClosedError–The canvas was closed.
Examples:
import xnano
with xnano.new(width=8, height=1, fps=10) as canvas:
frame = canvas.step()
assert frame.elapsed_seconds == 0.1
canvas.stop()
canvas.step(delta_seconds=0.5)
assert canvas.time.elapsed == 0.6
assert canvas.time.is_stopped
Source code in xnano/canvas.py
deliver_events
¶
Deliver pushed events to their hooks and draw a frame, without moving time.
Events pushed with push reach their hooks at the
canvas's next step; this is that step on a canvas whose clock you move. A canvas that
runs by itself delivers them on its own.
Examples:
import xnano
from xnano_core import Event
with xnano.new(width=8, height=1) as canvas:
heard = []
canvas.hook(lambda context: heard.append(context.event.kind))
canvas.push(Event.custom('ping'))
canvas.deliver_events()
assert heard == ['custom']
assert canvas.time.elapsed == 0.0
Source code in xnano/canvas.py
stop
¶
Freeze time: the same as Time.stop.
The canvas keeps drawing and hooks still hear input, but animations, effects,
formulas, timers and the beat stand still until resume.
step moves a stopped canvas one frame at a time. To end a
loop, call quit.
Source code in xnano/canvas.py
quit
¶
Ask the canvas's loop to end.
Safe from any thread, including from a hook. A running iter(), run(),
wait_for_key() or prompt() ends. On a canvas from new() the canvas stays
open for writing and rendering; on a canvas that runs by itself (realtime=True, or
on the screen) the loop ends and the canvas closes.
Source code in xnano/canvas.py
run
¶
Wait until the canvas's loop ends.
A canvas that runs by itself draws and listens on its own, so this only keeps your
program alive until a quit key is pressed, or something calls
quit (a hook, another thread). Declare what you want
before calling it.
Parameters:
-
quit_on(KeyName | Sequence[KeyName] | None, default:'ctrl+c') –The key, or keys, that end the loop, such as
'q'or('q', 'escape').'ctrl+c'by default; giveNoneto leave ending to your own code.
Raises:
-
TerminalError–A callback raised on the canvas's loop, or the canvas has a clock that only moves when you move it, so waiting would never end.
Source code in xnano/canvas.py
wait_for_key
¶
Wait until a key is pressed, and return its name.
Your program waits here while the canvas goes on drawing and animating. It reads
like input(): nothing else runs on your thread until the key arrives.
Parameters:
-
keys(KeyName, default:()) –The keys to wait for, such as
'enter'or'q'. Give none to take any key.
Returns:
-
str–The name of the key that was pressed.
Raises:
-
TerminalError–The canvas ended, or has a manual clock, so no key could arrive.
Examples:
In a program: canvas.wait_for_key() after adding "Press any key to start".
Here a timer plays the part of the person pressing the key:
import xnano
from xnano.events import Event
with xnano.new(realtime=True, width=30, height=2) as canvas:
canvas.write('Press enter to start')
@canvas.hook(on='tick', after=0.05)
def press(context: xnano.Context) -> None:
canvas.push(Event.key_press('enter'))
assert canvas.wait_for_key('enter') == 'enter'
Source code in xnano/canvas.py
prompt
¶
Prompt for a line of text, and return what was typed.
The prompt and the answer appear on the canvas while your program waits, like
input(). Enter submits and Backspace deletes.
Parameters:
-
text(str) –What to ask, such as
'Your name: '. -
x(int, default:0) –The column of the prompt.
-
y(int, default:0) –The row of the prompt.
-
default(str, default:'') –Text already in the answer, which the user can edit.
Returns:
-
str–What was typed, without the prompt.
Raises:
-
TerminalError–The canvas ended, or has a manual clock, so no answer could arrive.
Examples:
In a program: name = canvas.prompt('Your name: '). Here a timer plays the part
of the person typing:
import xnano
from xnano.events import Event
with xnano.new(realtime=True, width=30, height=2) as canvas:
@canvas.hook(on='tick', after=0.05)
def type_answer(context: xnano.Context) -> None:
for letter in 'Ada':
canvas.push(Event.key_press(letter))
canvas.push(Event.key_press('enter'))
assert canvas.prompt('Your name: ') == 'Ada'
Source code in xnano/canvas.py
3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 | |
render
¶
Draw the current frame and return it, without a screen.
A canvas that was written into another one returns its own cells alone, at its own size, as they stand in the outer canvas's current frame.
Parameters:
-
format(Literal['text', 'ansi'], default:'text') –'text'for the characters alone,'ansi'for the characters with their colors and styles as escape codes.
Raises:
-
ValueError–formatis neither'text'nor'ansi'.
Examples:
import xnano
with xnano.new(width=6, height=2) as canvas:
canvas.write('hello', y=1)
assert canvas.render().splitlines() == ['', 'hello']
assert 'hello' in canvas.render(format='ansi')
Source code in xnano/canvas.py
push
¶
push(event: Event) -> None
Deliver an event to the canvas as if it had been typed, clicked or reported.
Hooks hear it the same way as input from the keyboard and mouse, at the canvas's
next step, whatever the input gates say. Build events with
Event; Event.custom(name, data=...) makes one of your own.
Parameters:
-
event(Event) –The event to deliver.
Raises:
Examples:
import xnano
from xnano_core import Event
with xnano.new(width=8, height=1) as canvas:
heard = []
canvas.hook(
lambda context: heard.append(context.event.custom_name),
when=lambda context: context.event.kind == 'custom',
)
canvas.push(Event.custom('volume_changed'))
canvas.deliver_events()
assert heard == ['volume_changed']
Source code in xnano/canvas.py
play
¶
play(playable: PlaySource, /, **options: Unpack[PlayOptions]) -> PlayHandle
Play a note, a sound, a symbol name, a melody or a sequence of those, and return at once.
This is audio.play; see it for what playable may
be and for every option. On a canvas from new() the sound is recorded instead of
played; read it with audio.render_sound.
Parameters:
-
playable(PlaySource) –What to play: a note, a sound, a symbol name, melody text such as
'C4 E4 G4:2', a MIDI number, a frequency, or a sequence of those. -
options(Unpack[PlayOptions], default:{}) –The settings of
PlayOptions, such asinstrument,volume,pan,beatsandat_beat.
Returns:
-
PlayHandle–A
PlayHandlethat tells when the sound is over.
Examples:
import xnano
with xnano.new(width=8, height=1, bpm=100) as canvas:
canvas.play('C4 E4 G4:2 rest C5+E5+G5', instrument='bell')
canvas.step(delta_seconds=1.0)
assert canvas.audio.render_sound().duration_milliseconds == 1000.0
Source code in xnano/canvas.py
state_reference
¶
state_reference(reader: Callable[[StateT], ValueT]) -> StateReference[ValueT]
A core reference for one field of the canvas's state.
The reference can be used as an axis, a range bound or a widget parameter.
Parameters:
-
reader(Callable[[StateT], ValueT]) –A function or lambda that reads the field, such as
lambda state: state.volume.
Raises:
-
TypeError–readeris not a function. -
TerminalError–The canvas was created without
state.
Source code in xnano/canvas.py
Context
¶
Context(canvas: Canvas[DepsT_co, StateT_co], owner: Canvas[object, object] | Placement[object, object], hook: HookHandle[object, object], event: Event | TerminalStateChange | Frame | Update | None, core: CoreContext | None, log: ReadLog | None = None)
Bases: Generic[DepsT_co, StateT_co]
What a hook is called with.
The context carries the event and live views of where the hook is attached. Its members are
read when you use them, so a context costs almost nothing to receive. A generator hook
receives a new context each time it resumes, so context.mouse.position is always the
newest event's.
buffer, parent and root are live objects with concrete values:
context.parent.width is an int, and context.buffer has the verbs of a placement
(move, up, down, left and right). On a placement or canvas themselves,
parent and root are formula scopes whose members are expressions, such as
placement.parent.width.
keyboard, mouse, scroll and clipboard are always there; each member is
None (or 0 for the wheel) unless the event the hook is handling is of that kind.
Each has get() and push(value).
Attributes:
-
canvas(Canvas[DepsT_co, StateT_co]) –The root canvas the hook belongs to.
-
event(Event | TerminalStateChange | Frame | Update | None) –The event, a
Frameforhook(on='frame'), anUpdateforhook(on='tick'), aTerminalStateChangeforhook(on='state'), orNonewhen no event caused the call. -
hook(HookHandle[object, object]) –The registration, so the hook can call
hook.remove(). -
keyboard(KeyboardInput) –The key of the event, with
key,kindandmodifiers. -
mouse(MouseInput) –The mouse button or movement of the event, with
position,button,kindandis_down. -
scroll(ScrollInput) –The wheel steps of the event,
xandy. -
clipboard(ClipboardInput) –The pasted text of the event.
-
buffer(Placement[object, object] | Canvas[object, object]) –The placement (or the canvas) the hook is attached to.
-
parent(Placement[object, object] | Canvas[object, object]) –What contains the placement; the canvas itself for a hook on the canvas.
-
root(Canvas[DepsT_co, StateT_co]) –The root canvas.
-
plugin(Plugin) –The attachment of the hook that is running.
-
deps(DepsT_co) –The dependencies given to
new(deps=...). -
fx(EffectController) –Applies effects to the hook's buffer while the hook is active.
-
time(Time) –The canvas's
Time. -
audio(AudioDevice) –The canvas's
AudioDevice. -
cursor(Cursor) –The canvas's cursor.
-
size(Size) –The canvas's size in cells.
-
input(Input) –The keys and mouse buttons held down right now.
Examples:
import xnano
from xnano_core import Event
with xnano.new(width=20, height=3) as canvas:
label = canvas.write('hi', x=2)
heard = []
@label.hook(on='mouse', when="mouse.kind == 'press'")
def pressed(context: xnano.Context) -> None:
heard.append((context.mouse.position.x, context.buffer.x))
canvas.push(Event.mouse_event(column=3, row=0, kind='press', button='left'))
canvas.deliver_events()
assert heard == [(3, 2)]
Create a context. The runtime does this for you; hooks receive one.
Parameters:
-
canvas(Canvas[DepsT_co, StateT_co]) –The root canvas.
-
owner(Canvas[object, object] | Placement[object, object]) –The canvas or placement the hook is attached to.
-
hook(HookHandle[object, object]) –The hook that is called.
-
event(Event | TerminalStateChange | Frame | Update | None) –The event, or
None. -
core(CoreContext | None) –The runtime's context for the event, or
None. -
log(ReadLog | None, default:None) –Where to record what is read, for a component;
Nonefor a hook.
- API Reference xnano
Methods:
-
local–Convert a cell of the screen into a cell of the hook's buffer.
Source code in xnano/context.py
canvas
instance-attribute
¶
canvas: Canvas[DepsT_co, StateT_co] = canvas
The root canvas the hook belongs to.
hook
instance-attribute
¶
hook: HookHandle[object, object] = hook
The registration, so the hook can call hook.remove().
event
property
¶
keyboard
property
¶
keyboard: KeyboardInput
The key of the event; key is None unless the event is a key.
mouse
property
¶
mouse: MouseInput
The mouse button or movement of the event; position is None for any other.
scroll
property
¶
scroll: ScrollInput
The mouse wheel steps of the event; x and y are 0 unless it is a wheel.
clipboard
property
¶
clipboard: ClipboardInput
The pasted text of the event; text is None unless the event is a paste.
buffer
property
¶
The placement the hook is attached to, or the canvas for a hook on the canvas.
parent
property
¶
What contains the hook's placement: another placement, or the canvas.
local
¶
Convert a cell of the screen into a cell of the hook's buffer.
Parameters:
-
point(Point) –A cell in screen coordinates, such as
context.mouse.position.
Examples:
import xnano
from xnano_core import Point
with xnano.new(width=20, height=4) as canvas:
placement = canvas.write('hi', x=10, y=1)
@placement.hook(on='mouse')
def pressed(context: xnano.Context) -> None:
if context.mouse.position is not None:
context.local(context.mouse.position)
assert placement.local(Point(11, 1)) == Point(1, 0)
Source code in xnano/context.py
Note
dataclass
¶
Note(pitch: Pitch | tuple[Pitch, ...], beats: float = 1.0, instrument: InstrumentName = 'piano', velocity: float = 0.8, effects: tuple[PlayableEffectSpecification, ...] = (), symbol: str | None = None)
A note, or a chord, to play: a pitch, how long it lasts and how it sounds.
A note is a plain value. It needs no sound device, no canvas and not even the audio
extra to be created, so a song can be defined at the top of a module and played later
with play or Canvas.play. A sequence of
notes plays one after another. symbol registers the note under a name, so
play('kick') finds it.
Attributes:
-
pitch(Pitch | tuple[Pitch, ...]) –A note name such as
'C#4', a MIDI number from 0 to 127 (60 is middle C), or a tuple of them for a chord. -
beats(float) –How long the note is held, in beats at the canvas's tempo. A beat is half a second at 120 beats per minute.
-
instrument(InstrumentName) –A built-in instrument, from
instrument_names. -
velocity(float) –How hard the note is played, from 0.0 to 1.0.
-
effects(tuple[PlayableEffectSpecification, ...]) –Sound effects as dictionaries with a
kindkey, such as{'kind': 'audio.reverb', 'mix': 0.4}. -
symbol(str | None) –The name the note is registered under in
symbols, orNone.
Raises:
-
TypeError–The pitch is not a note name or a number, or an effect is not a dictionary.
-
ValueError–The pitch is not valid,
beatsis not above 0,velocityis not from 0.0 to 1.0, or the instrument is unknown (checked when theaudioextra is installed, and otherwise when the note is played).
Examples:
import xnano
chord = xnano.Note(('C4', 'E4', 'G4'), beats=2.0, instrument='bell')
assert chord.beats == 2.0
with xnano.new(width=8, height=1) as canvas:
canvas.play([chord, xnano.note('C5')])
canvas.step(delta_seconds=1.0)
assert canvas.audio.render_sound().duration_milliseconds == 1000.0
Methods:
-
__post_init__–Check the values and register the symbol.
-
__xnano_play__–Return this note, so a note is playable like any other component.
pitch
instance-attribute
¶
A note name, a MIDI number, or a tuple of them for a chord.
instrument
class-attribute
instance-attribute
¶
instrument: InstrumentName = 'piano'
The built-in instrument.
velocity
class-attribute
instance-attribute
¶
velocity: float = 0.8
How hard the note is played, from 0.0 to 1.0.
effects
class-attribute
instance-attribute
¶
effects: tuple[PlayableEffectSpecification, ...] = ()
The sound effects, as dictionaries with a kind key.
symbol
class-attribute
instance-attribute
¶
symbol: str | None = None
The registered symbol name, or None.
__post_init__
¶
Check the values and register the symbol.
Source code in xnano/music.py
__xnano_play__
¶
Pixel
dataclass
¶
Pixel(preset_or_character: PixelPreset | str = 'block', *, foreground: ColorValue | None = None, background: ColorValue | None = None, symbol: str | None = None)
One cell (or one dot, at half-block and braille resolution) of a region.
The first argument is a preset name such as 'diamond', the name of a registered
symbol, or a single character that is drawn as it is. A pixel is a value: it compares by
its fields, and region[x, y] returns one and accepts one.
Parameters:
-
preset_or_character(PixelPreset | str, default:'block') –A
PixelPreset, the name of a registered symbol, or one character. -
foreground(ColorValue | None, default:None) –The color of the character.
-
background(ColorValue | None, default:None) –The color behind the character.
-
symbol(str | None, default:None) –A name to register this pixel under, so that
Pixel('wall')finds it later. The name takes two characters or more; seeregister.
Attributes:
-
character(str) –The glyph drawn in the cell or dot.
-
foreground(ColorValue | None) –The color of the glyph, or
Nonefor the cell's own. -
background(ColorValue | None) –The color behind the glyph, or
Nonefor the cell's own. -
symbol(str | None) –The registered symbol name, or
None.
Raises:
-
ValueError–The name is not a preset or a registered symbol (the message lists both and the closest names first), or the character is empty.
Examples:
import xnano
from xnano import Pixel
diamond = Pixel('diamond', foreground='red')
assert diamond.character == '◆'
assert Pixel('x').character == 'x'
with xnano.new(width=4, height=1) as canvas:
canvas.region[1, 0] = diamond
assert canvas.region[1, 0].character == '◆'
Make a pixel from a preset, a symbol name or a character.
Parameters:
-
preset_or_character(PixelPreset | str, default:'block') –A preset name, a registered symbol name or one character.
-
foreground(ColorValue | None, default:None) –The color of the character.
-
background(ColorValue | None, default:None) –The color behind the character.
-
symbol(str | None, default:None) –A name to register this pixel under.
Methods:
-
cell–Return the core cell that draws this pixel.
-
__str__–Return the character of the pixel, so
print(pixel)shows what it draws. -
__xnano_render__–Return a buffer of one cell that shows the pixel.
Source code in xnano/pixel.py
foreground
instance-attribute
¶
foreground: ColorValue | None
The color of the glyph, or None for the cell's own.
background
instance-attribute
¶
background: ColorValue | None
The color behind the glyph, or None for the cell's own.
cell
¶
cell() -> Cell
Return the core cell that draws this pixel.
The cell is built once and kept, so writing the same pixel many times is cheap.
Source code in xnano/pixel.py
__xnano_render__
¶
Return a buffer of one cell that shows the pixel.
Terminal
¶
Terminal(*, width: int | str | None, height: int | str | None, fps: float, bpm: float, is_realtime: bool, deps: object, state: object, title: str | None, gates: Mapping[str, object], appearance: Mapping[str, object], effects: Sequence[RenderableEffectSpecification], enclosing: Canvas[object, object] | None = None, layout: CanvasLayout = 'overlay', edges: EdgeBehavior = 'clip')
Bases: Canvas[DepsT, StateT]
A canvas that draws on your screen and reads your keyboard and mouse.
A canvas becomes a terminal when it is opened, with open or
Canvas.open: it is the same object, and
isinstance(canvas, xnano.Terminal) is how to ask whether a canvas is on the screen.
It has every member of Canvas. It runs by itself: opening it
starts a loop on a thread of its own, and everything you write, remove or draw appears the
moment it is declared, however slowly the rest of your program runs, because declaring
only changes buffers and the loop draws them. A program has one screen, so only one
terminal is open at a time.
Attributes:
-
is_closed(bool) –Whether the terminal has been closed, or its loop has ended.
-
is_running(bool) –Whether the loop is running and has not been asked to end.
Examples:
with xnano.open(width=20, height=2) as terminal:
terminal.write('hello')
assert isinstance(terminal, xnano.Terminal)
terminal.run(quit_on='q')
Create a canvas. Use new instead of calling this.
Parameters:
-
width(int | str | None) –The width in cells or as a percentage of the window, or
Nonefor 80. -
height(int | str | None) –The height in cells or as a percentage of the window, or
Nonefor 24. -
fps(float) –The most frames drawn per second.
-
bpm(float) –Beats per minute.
-
is_realtime(bool) –Whether the canvas runs on the wall clock, on a thread of its own.
-
deps(object) –The dependencies, or the unset marker when none were given.
-
state(object) –A dataclass instance the canvas keeps and validates, or the unset marker.
-
title(str | None) –The window title, or
None. -
gates(Mapping[str, object]) –The input gates that were given, by name.
-
appearance(Mapping[str, object]) –The appearance keywords of the canvas itself, by name.
-
effects(Sequence[RenderableEffectSpecification]) –Effects to apply to the canvas, as dictionaries with a
kindkey. -
enclosing(Canvas[object, object] | None, default:None) –The canvas whose
withblock this one was created in, which its sizes are measured in and which closes it, orNone. -
layout(CanvasLayout, default:'overlay') –How the canvas places what is written on it.
-
edges(EdgeBehavior, default:'clip') –What content written on the canvas does at the edges of its area.
Methods:
-
__setattr__–Set an attribute, or raise
AttributeErrorfor an unknown public name. -
bold–Make the text bold, or undo it with
False; the same as settingis_bold. -
dim–Dim the text, or undo it with
False; the same as settingis_dim. -
italic–Make the text italic, or undo it with
False; the same as settingis_italic. -
underline–Underline the text, or undo it with
False; the same as settingis_underlined. -
blink–Make the text blink, or undo it with
False; the same as settingis_blinking. -
reverse–Swap the foreground and background, or undo it with
False; the same as settingis_reversed. -
hidden–Hide the text, or undo it with
False; the same as settingis_hidden. -
crossed_out–Strike the text through, or undo it with
False; the same as settingis_crossed_out. -
hook–Call a function when something happens on this canvas or placement.
-
__new__–Refuse a direct call: a canvas is created with
xnano.new. -
open–Put this canvas on your screen, and return it as a
Terminal. -
close–Release everything the canvas holds, and give the screen back if it has one.
-
local–Convert a cell of the screen into a cell of this canvas.
-
move–Move a canvas that is written into another one by a number of cells along each axis.
-
up–Move a written canvas up by
countrows; seemove. -
down–Move a written canvas down by
countrows; seemove. -
left–Move a written canvas left by
countcolumns; seemove. -
right–Move a written canvas right by
countcolumns; seemove. -
new–Create a canvas inside this one and draw it here at once, at the top-left corner.
-
write–Put something on the canvas: text, a widget, a buffer, another canvas or an image.
-
clear–Erase everything written or drawn directly on the canvas's cells.
-
update–Change the canvas's own cells with operations, styles or effects.
-
__or__–Apply an operation, customization or style with
canvas | operation. -
__ior__–Apply an operation, customization or style in place with
canvas |= operation. -
inspect–Evaluate an expression against the canvas and return its value.
-
iter–Iterate over the canvas's frames, drawing between them; pass
count=orseconds=, -
step–Move time by
delta_seconds, one frame by default, and draw exactly one frame. -
deliver_events–Deliver pushed events to their hooks and draw a frame, without moving time.
-
stop–Freeze time: the same as
Time.stop. -
resume–Let time run on from where
stopfroze it. -
quit–Ask the canvas's loop to end.
-
run–Wait until the canvas's loop ends.
-
wait_for_key–Wait until a key is pressed, and return its name.
-
prompt–Prompt for a line of text, and return what was typed.
-
render–Draw the current frame and return it, without a screen.
-
push–Deliver an event to the canvas as if it had been typed, clicked or reported.
-
play–Play a note, a sound, a symbol name, a melody or a sequence of those, and return at once.
-
state_reference–A core reference for one field of the canvas's state.
Source code in xnano/canvas.py
690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 | |
region
property
¶
region: Region
The cells of the canvas as a Region: read and write
canvas.region[x, y].
The default resolution is one cell. canvas.region.half_blocks addresses two
pixels per cell and canvas.region.braille eight dots.
Examples:
color
property
¶
color: Colors
border
property
writable
¶
border: BorderAppearance
The border: its kind, a setting for each side, its color and its title.
Assign 'plain', 'rounded', 'double' or 'thick' to draw a border
on every side, True for 'plain' and False to remove it. It works on any
content, not only on text.
The border, padding and margin are drawn around the content, so the placement grows by the cells they take. A widget with no size of its own is shrunk to fit its parent, border included.
Examples:
padding
property
writable
¶
padding: PaddingAppearance
The space between the border and the content, edge by edge.
Assign a number of cells, a percentage such as '10%' or a dictionary such as
{'vertical': 1, 'horizontal': 2}, or set one edge with padding.left = 2.
margin
property
writable
¶
margin: MarginAppearance
The transparent space outside the border, edge by edge, set like padding.
output
instance-attribute
¶
The canvas's drawn frames and captured text.
is_closed
property
¶
is_closed: bool
Whether the canvas has been torn down: closed, or its loop has ended.
is_running
property
¶
is_running: bool
Whether the canvas is open and its loop has not been asked to end.
core_buffer
property
¶
core_buffer: Buffer
The core buffer the canvas draws, as large as the canvas.
Everything you write is a child of this buffer, and everything drawn directly on the canvas is stored in it. A canvas with a border, padding or margin draws them around a buffer of its own; this is the buffer inside them.
parent
property
¶
parent: ParentExpressionScope
Symbolic expressions for the parent container's width, height and size.
root
property
¶
root: RootExpressionScope
Symbolic expressions for the root canvas's width, height, size and time.
fps
property
¶
fps: float
The most frames drawn per second, and the rate iter aims for.
bpm
property
writable
¶
bpm: float
Beats per minute: the length of a beat for beat timers, notes and melodies.
It is 120 unless new(bpm=...) said otherwise, and it can change while things
are playing; the change applies from the next beat.
Raises:
-
ValueError–The tempo is not above 0 and at most 600000.
title
property
writable
¶
title: str | None
The window title last set on this canvas.
Assign a single line of printable text to set the title of the window a canvas on the
screen draws in, or None to clear it. A canvas without a screen keeps the value
and shows it when it is opened.
time
property
¶
time: Time
The canvas's Time: how long it has run, stopping, and formulas.
cursor
property
¶
cursor: Cursor
The canvas's Cursor.
A canvas has exactly one cursor. Set its position (a cell, or None to hide
it), shape, is_blinking and is_visible, move it with up, down,
left, right and move, or follow a placement. It can be changed from
any thread, and on the screen the cursor you had before is restored when the canvas
closes.
Examples:
import xnano
with xnano.new(width=10, height=2) as canvas:
canvas.cursor.position = (3, 0)
canvas.cursor.shape = 'bar'
assert canvas.cursor.position.x == 3
layout
property
¶
layout: CanvasLayout
How the canvas places what is written on it, chosen when the canvas is created.
'overlay' places every piece on its own over the whole canvas. 'column'
stacks the pieces from top to bottom in the order they are written, and 'row'
from left to right. Each piece then takes a slot: one with a size on the stacking
axis (height in a column, width in a row, in cells or as a percentage) gets
exactly that, and the others share what is left equally. Inside its slot a piece is
positioned as on any canvas, so y='center' and y='50%' are measured in the
slot. Removing a piece gives its slot back. A canvas created inside the with
block of a stacking canvas takes a slot only once it is written.
Examples:
edges
property
writable
¶
edges: EdgeBehavior
What content written on the canvas does at the edges of its area, unless given its own.
'clip' lets it move past the edge, where it is not drawn; 'stop' holds it
inside its area when it moves; 'wrap' continues text on the next rows of its
area. A piece written with edges=... keeps its own; see
Placement.edges.
Raises:
-
ValueError–The value is not
'clip','stop'or'wrap'.
audio
property
¶
audio: AudioDevice
The canvas's AudioDevice: notes, melodies, sounds and the microphone.
It needs the optional xnano-audio package, which is imported the first time this
is read.
Raises:
-
ImportError–xnano-audiois not installed. Install it withpip install "xnano[audio]".
fx
property
¶
The visual effects of the canvas itself, one method for each effect.
canvas.fx.fade_to(background='navy') starts a fade over the whole canvas at once,
and canvas.fx.clear() stops what was started here. A placement has its own
fx, and the sound effects of what the canvas plays are
canvas.audio.fx. See
RenderableEffects.
Examples:
import xnano
with xnano.new('hello', width=8, height=1) as canvas:
canvas.fx.dissolve(duration_milliseconds=300)
assert len(canvas.fx.active) == 1
input
property
¶
input: Input
The keys held down right now, for programs that poll instead of listening.
Read it anywhere, from any thread. A canvas opened with
keyboard='release_events' knows exactly when a key is let go.
state
class-attribute
instance-attribute
¶
The canvas's state: values that hooks and your code share, read and written by path.
canvas.state.get('player.score') reads a value and canvas.state.push('player.score',
3) writes one; see StateNamespace for the path rules. A
canvas created with new(state=Settings()) also gives the fields of the dataclass as
attributes with their declared types, so canvas.state.volume is an int for a field
declared volume: int; a write is checked against the field's type. A type checker
sees get and push only on a canvas without a state dataclass, but both exist on
every canvas.
The state can be used from any thread. A write updates every expression that reads the field and draws a frame.
__setattr__
¶
Set an attribute, or raise AttributeError for an unknown public name.
Source code in xnano/_attributes.py
bold
¶
bold(value: bool = True) -> Self
Make the text bold, or undo it with False; the same as setting is_bold.
Parameters:
-
value(bool, default:True) –Whether the text is bold.
Returns:
-
Self–This canvas or placement, so calls can chain.
Raises:
-
TypeError–valueis notTrueorFalse.
Examples:
import xnano
with xnano.new(width=12, height=1) as canvas:
title = canvas.write('Ready').bold().underline()
assert title.is_bold and title.is_underlined
title.bold(False)
assert not title.is_bold
Source code in xnano/appearance.py
dim
¶
dim(value: bool = True) -> Self
Dim the text, or undo it with False; the same as setting is_dim.
Parameters:
-
value(bool, default:True) –Whether the text is dimmed.
Returns:
-
Self–This canvas or placement, so calls can chain.
Raises:
-
TypeError–valueis notTrueorFalse.
Source code in xnano/appearance.py
italic
¶
italic(value: bool = True) -> Self
Make the text italic, or undo it with False; the same as setting is_italic.
Parameters:
-
value(bool, default:True) –Whether the text is italic.
Returns:
-
Self–This canvas or placement, so calls can chain.
Raises:
-
TypeError–valueis notTrueorFalse.
Source code in xnano/appearance.py
underline
¶
underline(value: bool = True) -> Self
Underline the text, or undo it with False; the same as setting is_underlined.
Parameters:
-
value(bool, default:True) –Whether the text is underlined.
Returns:
-
Self–This canvas or placement, so calls can chain.
Raises:
-
TypeError–valueis notTrueorFalse.
Source code in xnano/appearance.py
blink
¶
blink(value: bool = True) -> Self
Make the text blink, or undo it with False; the same as setting is_blinking.
Parameters:
-
value(bool, default:True) –Whether the text blinks.
Returns:
-
Self–This canvas or placement, so calls can chain.
Raises:
-
TypeError–valueis notTrueorFalse.
Source code in xnano/appearance.py
reverse
¶
reverse(value: bool = True) -> Self
Swap the foreground and background, or undo it with False; the same as setting is_reversed.
Parameters:
-
value(bool, default:True) –Whether foreground and background are swapped.
Returns:
-
Self–This canvas or placement, so calls can chain.
Raises:
-
TypeError–valueis notTrueorFalse.
Source code in xnano/appearance.py
hidden
¶
hidden(value: bool = True) -> Self
Hide the text, or undo it with False; the same as setting is_hidden.
Parameters:
-
value(bool, default:True) –Whether the text is hidden.
Returns:
-
Self–This canvas or placement, so calls can chain.
Raises:
-
TypeError–valueis notTrueorFalse.
Source code in xnano/appearance.py
crossed_out
¶
crossed_out(value: bool = True) -> Self
Strike the text through, or undo it with False; the same as setting is_crossed_out.
Parameters:
-
value(bool, default:True) –Whether the text is struck through.
Returns:
-
Self–This canvas or placement, so calls can chain.
Raises:
-
TypeError–valueis notTrueorFalse.
Source code in xnano/appearance.py
hook
¶
hook(function: Hook[DepsT, StateT] | None = None, /, *, on: HookKind | None = None, when: When[DepsT, StateT] | None = None, every: float | None = None, after: float | None = None, keys: KeyName | Sequence[KeyName] | None = None, requires_deps: bool = False) -> HookHandle[DepsT, StateT] | Callable[[Hook[DepsT, StateT]], HookHandle[DepsT, StateT]]
Call a function when something happens on this canvas or placement.
on says what to listen to. A hook without on hears every input event. A mouse,
scroll or drag hook on a placement hears only the pointer inside the placement, and a
press inside holds the pointer for the hook until the button is released. A pointer hook
that matches an event stops it from reaching the parent; a hook that does not match lets
it through. Keys are not consumed: while nothing has focus, every key hook hears a key.
hook(function, ...) attaches one function, and @target.hook(...) decorates the
function that follows. A hook function may be a generator that receives a new context
at each bare yield: write context = yield. A drag is a loop that runs while
context.mouse.is_down.
every and after are seconds for on='tick' and beats for on='beat':
every=2 means 2 seconds for a tick hook and 2 beats for a beat hook. On a canvas
from new() a hook that is due several times in one step runs once for each
interval, up to 100,000 times in one step; the intervals that remain run in the steps
that follow. The function's return value is ignored, unless it is an operation, a
style or an effect, which is applied to this target.
Parameters:
-
function(Hook[DepsT, StateT] | None, default:None) –The function to call with a
Context, or a function with no parameters, which is called without it. -
on(HookKind | None, default:None) –What to listen to:
'frame','tick','beat','key','mouse','scroll','drag','paste','focus','resize','state'or'custom'. SeeHookKind. -
when(When[DepsT, StateT] | None, default:None) –A condition that must hold: an expression, a function of the context, or a string. See
When. A string tells xnano which input the hook needs, so the mouse, scroll and key-release gates it reads are turned on when the canvas opens. An expression or a function does not, so a condition that readsMouse,Scrollor key releases needs the gate set onnew()oropen()yourself:mouse=True,scroll=Trueorkeyboard='release_events'. A comparison with an input the event does not carry, such askeyboard.keyon a paste, does not hold;!=is one of them, sokeyboard.key != 'q'hears only key events.notandnot innegate the whole comparison, sonot keyboard.key == 'q'andkeyboard.key not in ['q']also hold for events that have no key. -
every(float | None, default:None) –Repeat every this many seconds (
'tick') or beats ('beat'). -
after(float | None, default:None) –Run once after this many seconds (
'tick') or beats ('beat'). -
keys(KeyName | Sequence[KeyName] | None, default:None) –The key or keys an
on='key'hook reacts to, such as'q'or'ctrl+s'. A key hook with keys hears presses and repeats; omit them and testkeyboard.kindto hear releases. -
requires_deps(bool, default:False) –Whether the hook needs the dependencies given to
new(deps=...).
Returns:
-
HookHandle[DepsT, StateT] | Callable[[Hook[DepsT, StateT]], HookHandle[DepsT, StateT]]–The hook, whose
removestops it; or, without a function, the decorator.
Raises:
-
ValueError–The combination of arguments does not make sense, a key name is unknown, or a
whenstring is not a condition. The message says what to write instead. -
TypeError–onis not text,whenis a plainbool, or the function is not callable with a context, or is anasyncfunction. -
TerminalError–requires_depsis true and the canvas was created withoutdeps, or the canvas is on a screen with an input gate this hook needs turned off.
Examples:
import xnano
from xnano_core import Event
with xnano.new(width=8, height=1) as canvas:
heard = []
@canvas.hook(on='key', keys=['q', 'escape'])
def leave(context: xnano.Context) -> None:
heard.append(context.keyboard.key)
@canvas.hook(on='tick', every=0.5)
def blink(context: xnano.Context) -> None:
heard.append('tick')
canvas.push(Event.key_press('q'))
canvas.step(delta_seconds=1.0)
assert heard == ['q', 'tick', 'tick']
Source code in xnano/_hooks.py
872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 | |
__new__
¶
Refuse a direct call: a canvas is created with xnano.new.
Source code in xnano/canvas.py
open
¶
open(*, title: str | None = None, width: int | Percentage | str | None = None, height: int | Percentage | str | None = None, **settings: Unpack[OpenSettings]) -> Terminal[DepsT, StateT]
Put this canvas on your screen, and return it as a Terminal.
The same object is returned: after this, isinstance(canvas, xnano.Terminal) is
true. From then on it runs by itself on a thread of its own and on the wall clock, which
continues from the time the canvas had: elapsed time, the frame count, every and
after timers and a stopped clock carry over, and so do the cursor, the title,
everything written and every hook. Effects that were running start again from their
beginning, and keyboard focus and a captured pointer are released.
width and height are the size of the canvas: the ones given here, else the
ones given to new(), draw in a region of that size below the cursor; a canvas
created without a size, or with '100%' for both, fills the whole window. A
percentage such as '50%' is a share of the window when the canvas is opened. Any other keyword of new() except
realtime may be given and applies before the canvas is shown; a gate given here
wins over the one given to new(). title is the window title.
Parameters:
-
title(str | None, default:None) –The window title;
Nonekeeps the canvas's title. -
width(int | Percentage | str | None, default:None) –The width of the region to draw in: cells, or a percentage of the window.
-
height(int | Percentage | str | None, default:None) –The height of the region to draw in: cells, or a percentage of the window.
-
settings(Unpack[OpenSettings], default:{}) –Gates, appearance keywords,
fps,bpm,effects, anddepsandstatefor a canvas that was created without them; seeOpenSettings.
Returns:
-
Terminal[DepsT, StateT]–This canvas, now attached to the screen.
Raises:
-
TerminalAlreadyOpenError–Another canvas is already on the screen.
-
TerminalError–This canvas is already on the screen, was written into another canvas, has a hook that needs a gate given as
False, or there is no terminal to draw on; the canvas stays as it was. -
TypeError–realtimewas given,depsorstatethat the canvas already has, or an effect that is not a visual effect dictionary. -
ValueError–A
widthwas given without aheight, or a value is out of range.
Examples:
with xnano.new(width=40, height=5) as canvas:
canvas.write('hello', border='rounded')
canvas.step()
canvas.open(mouse=True) # now a xnano.Terminal, 40 by 5 below the prompt
canvas.run(quit_on='q')
Source code in xnano/canvas.py
close
¶
close(*, raise_failure: bool = True) -> None
Release everything the canvas holds, and give the screen back if it has one.
Closing twice is harmless. Leaving a with block closes the canvas, unless it is
part of another canvas or was created inside another canvas's with block: then it
stays usable and closes with that canvas. Closing a canvas closes the canvases created
inside its block that were not written anywhere. Closing a canvas that was written into
another one takes it off and leaves that one running.
Parameters:
-
raise_failure(bool, default:True) –Whether to raise the error a callback raised on the loop, which stopped the canvas. A
withblock passesFalsewhile another error is already propagating.
Raises:
-
TerminalError–A callback raised on the canvas's loop, or the loop would not stop.
Source code in xnano/canvas.py
1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 | |
local
¶
Convert a cell of the screen into a cell of this canvas.
Parameters:
-
point(Point) –A cell in screen coordinates, such as
context.mouse.position.
Examples:
import xnano
from xnano_core import Point
with xnano.new(width=10, height=3) as canvas:
assert canvas.local(Point(4, 1)) == Point(4, 1)
Source code in xnano/canvas.py
move
¶
Move a canvas that is written into another one by a number of cells along each axis.
This moves the placement the canvas is drawn in; see
Placement.move.
Parameters:
-
x(int, default:0) –Columns to move right; a negative number moves left.
-
y(int, default:0) –Rows to move down; a negative number moves up.
Returns:
-
Self–The canvas, so calls can chain.
Raises:
-
TerminalError–The canvas is not written into another canvas, so it sits at the origin and cannot move.
-
TypeError–An amount is not a whole number.
Examples:
import xnano
with xnano.new(width=20, height=3) as outer:
inner = outer.new('box', width=4, height=1)
inner.move(x=2, y=1)
assert (inner.x, inner.y) == (2, 1)
assert outer.render().splitlines()[1] == ' box'
Source code in xnano/canvas.py
up
¶
up(count: int = 1) -> Self
Move a written canvas up by count rows; see move.
Parameters:
-
count(int, default:1) –How many rows to move.
Raises:
-
TerminalError–The canvas is not written into another canvas.
-
TypeError–countis not a whole number. -
ValueError–countis negative.
Source code in xnano/canvas.py
down
¶
down(count: int = 1) -> Self
Move a written canvas down by count rows; see move.
Parameters:
-
count(int, default:1) –How many rows to move.
Raises:
-
TerminalError–The canvas is not written into another canvas.
-
TypeError–countis not a whole number. -
ValueError–countis negative.
Source code in xnano/canvas.py
left
¶
left(count: int = 1) -> Self
Move a written canvas left by count columns; see move.
Parameters:
-
count(int, default:1) –How many columns to move.
Raises:
-
TerminalError–The canvas is not written into another canvas.
-
TypeError–countis not a whole number. -
ValueError–countis negative.
Source code in xnano/canvas.py
right
¶
right(count: int = 1) -> Self
Move a written canvas right by count columns; see move.
Parameters:
-
count(int, default:1) –How many columns to move.
Raises:
-
TerminalError–The canvas is not written into another canvas.
-
TypeError–countis not a whole number. -
ValueError–countis negative.
Source code in xnano/canvas.py
new
¶
new(content: Content | None = None, /, *, width: int | Percentage | str | None = None, height: int | Percentage | str | None = None, effects: Sequence[RenderableEffectSpecification] = (), **settings: Unpack[CanvasSettings]) -> Canvas[DepsT, StateT]
Create a canvas inside this one and draw it here at once, at the top-left corner.
This is new followed by canvas.write(child): the child's size is
measured in this canvas ('50%' is half of it, and no size fills it), it runs on
this canvas's time and hears its input, and it closes with this canvas. Move it with
move and its relatives, or create it with
new and write it with x and y to place it elsewhere.
Parameters:
-
content(Content | None, default:None) –Something to write into the new canvas at once, such as text.
-
width(int | Percentage | str | None, default:None) –The width in cells, or a percentage of this canvas such as
'50%'. -
height(int | Percentage | str | None, default:None) –The height in cells, or a percentage of this canvas.
-
effects(Sequence[RenderableEffectSpecification], default:()) –Effects to apply to the new canvas, as dictionaries with a
kindkey. -
settings(Unpack[CanvasSettings], default:{}) –The input gates and the new canvas's own look; see
CanvasSettings.
Returns:
Raises:
-
TypeError–An appearance keyword was given with content, or a keyword is unknown.
-
ValueError–A size, gate or border kind is out of range.
-
TerminalError–This canvas is closed, or a hook of the new canvas needs a gate this canvas turned off.
Examples:
import xnano
with xnano.new(width=12, height=4) as outer:
panel = outer.new(height='50%', border='plain')
assert (panel.width, panel.height) == (12, 2)
assert outer.render().splitlines()[0] == '┌──────────┐'
Source code in xnano/canvas.py
2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 | |
write
¶
write(content: Content | Canvas[WrittenDepsT, WrittenStateT] | None = None, /, *, x: Axis | None = None, y: Axis | None = None, width: Axis | None = None, height: Axis | None = None, layer: int = 0, lock: bool = False, edges: EdgeBehavior | None = None, effects: Sequence[RenderableEffectSpecification] = (), style: Style | None = None, foreground: ColorValue | None = None, background: ColorValue | None = None, bold: bool = False, dim: bool = False, italic: bool = False, underline: bool = False, blink: bool = False, reverse: bool = False, hidden: bool = False, crossed_out: bool = False, title: str | None = None, border: BorderKind | bool | None = None, border_style: Style | None = None, padding: Spacing | None = None, margin: Spacing | None = None) -> Placement[DepsT, StateT]
Put something on the canvas: text, a widget, a buffer, another canvas or an image.
On a canvas that runs by itself it appears at once: this only declares it, and the
canvas's own loop draws it. Anything you leave out is taken from the content: x
and y default to the top-left corner, and width and height to the size of
the content, so canvas.write('hello') shows five cells of text where it is.
Change the text later by assigning the placement's
text.
Inside the with block of a canvas created in this one's block, what is written here
is placed and clipped within that canvas's area of this one: where it is written, or
the top-left corner while it is not. Positions such as y='center' are measured in
that area, and that canvas's edges applies there.
A canvas from new that is written here becomes part of this one: it
draws inside the placement, its own clock is set aside and it runs on this canvas's
time. It may not have been given state or deps, which belong to the outermost
canvas. Its audio is not carried over: a musical clock it started and a note it was
playing stop, and a formula that reads its audio.beat follows the outer canvas's
musical clock, which starts at the first beat.
An image is added as an Image (never a file path or a bare
TerminalImage; load one with
from_image). With neither width nor height it keeps
its own proportions at its own size, shrunk to fit the canvas. With one of them the
other follows the image's proportions, and with both the image fits inside that box. An
image sized by a percentage, or by the canvas because you gave no size, is converted
again when the canvas is resized, unless it is locked. An animated image plays on the
canvas's clock.
Parameters:
-
content(Content | Canvas[WrittenDepsT, WrittenStateT] | None, default:None) –Text (or a list of lines), a
Bufferor widget, a canvas fromnew(), an image, or anyRenderable;Nonefor an empty placement. -
x(Axis | None, default:None) –The column of the left edge: a number of cells, a percentage string, a word (
'left','center'or'right'), an expression, or a range ((0, 20)) that limits how far it may travel. SeeAxis. -
y(Axis | None, default:None) –The row of the top edge, in the same forms (
'top','center','bottom'). -
width(Axis | None, default:None) –The width, in the same forms; the content's own width when
None. -
height(Axis | None, default:None) –The height, in the same forms; the content's own height when
None. -
layer(int, default:0) –Content with a higher layer is drawn over content with a lower one.
-
lock(bool, default:False) –Keep the position and size the content has now, whatever the canvas's size does afterwards: percentages, words and formulas are read once.
-
edges(EdgeBehavior | None, default:None) –What the content does at the edges of its area:
'clip','stop'or'wrap'; seePlacement.edges. Left out, it follows what it is written on. -
effects(Sequence[RenderableEffectSpecification], default:()) –Effects to start on the placement, as dictionaries with a
kindkey, such as[{'kind': 'effect.fade_to', 'foreground': 'red'}]. -
style(Style | None, default:None) –A ready-made
Stylefor text. The parameters below are applied over it. -
foreground(ColorValue | None, default:None) –The text color.
-
background(ColorValue | None, default:None) –The color behind the text.
-
bold(bool, default:False) –Whether the text is bold.
-
dim(bool, default:False) –Whether the text is dimmed.
-
italic(bool, default:False) –Whether the text is italic.
-
underline(bool, default:False) –Whether the text is underlined.
-
blink(bool, default:False) –Whether the text blinks.
-
reverse(bool, default:False) –Whether foreground and background are swapped.
-
hidden(bool, default:False) –Whether the text is hidden.
-
crossed_out(bool, default:False) –Whether the text is struck through.
-
title(str | None, default:None) –A title on the border of a box around the text.
-
border(BorderKind | bool | None, default:None) –The kind of border for a box around the content, a
BorderKindsuch as'plain','rounded','double'or'thick';Truefor'plain'andFalsefor none. Giving atitlealone draws a plain one. -
border_style(Style | None, default:None) –The style of the box's border.
-
padding(Spacing | None, default:None) –Space between the border and the text: a number of cells, a float or a percentage of the text's size, or a dictionary with
top,right,bottom,left,verticalandhorizontal. Giving it draws the text in a box without a border unlessborderortitleis also given. -
margin(Spacing | None, default:None) –Space outside the box, in the same forms.
Returns:
Raises:
-
TypeError–The content is a file path, raw bytes, or an operation, style or effect (apply those with
canvas.update(...)instead). -
TerminalError–The content is a canvas that cannot be written here.
Examples:
import xnano
with xnano.new(width=20, height=4) as canvas:
box = canvas.write('hello', x='50%', y=1)
assert box.x == 10
assert (box.width, box.height) == (5, 1)
canvas.write(
'Ready',
x='center',
y='bottom',
foreground='green',
bold=True,
border='rounded',
title='Status',
)
Source code in xnano/canvas.py
2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 | |
clear
¶
update
¶
Change the canvas's own cells with operations, styles or effects.
canvas | operation does the same. To put content on the canvas, use
write instead.
Parameters:
-
operations(Operation | Style, default:()) –What to apply, in order: a core operation such as
FillorWrite, a style, or an xnano customization such as an effect.
Returns:
-
Self–The canvas, so calls chain.
Examples:
import xnano
from xnano_core import Fill
with xnano.new(width=4, height=1) as canvas:
canvas.update(Fill('.'))
assert canvas.render() == '....'
canvas | Fill('#')
assert canvas.render() == '####'
Source code in xnano/canvas.py
__or__
¶
Apply an operation, customization or style with canvas | operation.
Source code in xnano/canvas.py
__ior__
¶
Apply an operation, customization or style in place with canvas |= operation.
inspect
¶
inspect(expression: Expression[ValueT]) -> ValueT
Evaluate an expression against the canvas and return its value.
Parameters:
-
expression(Expression[ValueT]) –Any expression, such as
Width,TimeElapsed % 1orcanvas.audio.level.
Examples:
import xnano
from xnano_core import Width
with xnano.new(width=12, height=2) as canvas:
assert canvas.inspect(Width) == 12
Source code in xnano/canvas.py
iter
¶
Iterate over the canvas's frames, drawing between them; pass count= or seconds=,
or break out of the loop.
Each iteration yields a Frame, and whatever you change
before asking for the next one is drawn. On a canvas from new() each iteration
moves the clock by one frame of its fps, so the same loop produces the same
frames every run; without count or seconds it runs as fast as your code. A
canvas that runs by itself draws as you declare, so there this only paces your code
at its fps: if you are slow, frames are skipped rather than queued.
stop freezes the time iter() follows: the
iterations go on drawing and hooks still run, but the clock stands still until
resume. To move a stopped canvas one frame, call
step.
The iteration ends when count frames have been yielded, when the canvas's time has
run for seconds (whichever comes first), when the canvas is asked to
quit or closed, or when you break out of the loop.
Parameters:
-
count(int | None, default:None) –The most frames to yield.
-
seconds(float | None, default:None) –The most seconds of the canvas's time to run for.
Raises:
-
TerminalError–secondswithoutcounton a stopped canvas, which would never reach the end. -
TerminalClosedError–The canvas is closed.
Examples:
import xnano
with xnano.new(width=8, height=1, fps=10) as canvas:
frames = list(canvas.iter(count=3))
assert [frame.elapsed_seconds for frame in frames] == [0.0, 0.1, 0.2]
Source code in xnano/canvas.py
3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 | |
step
¶
Move time by delta_seconds, one frame by default, and draw exactly one frame.
On a canvas from new() this always works, and it moves time even while the
canvas is stopped, which leaves it stopped: it is how a stopped canvas is walked one
frame at a time. A canvas that runs by itself can be stepped only while it is
stopped. One frame is 1 / fps seconds; default steps and the frames of
iter share one count, so sixty of them at fps=60
are exactly one second. A large delta_seconds is one jump: timers that it crossed
all run, and so do fixed-step every hooks, at most 100000 of their steps in one
step; the steps that remain run in the steps that follow.
Parameters:
-
delta_seconds(float | None, default:None) –How far to move, in seconds, above zero; one frame when
None.
Returns:
Raises:
-
ValueError–delta_secondsis not above zero. -
TerminalError–The canvas runs by itself and is not stopped.
-
TerminalClosedError–The canvas was closed.
Examples:
import xnano
with xnano.new(width=8, height=1, fps=10) as canvas:
frame = canvas.step()
assert frame.elapsed_seconds == 0.1
canvas.stop()
canvas.step(delta_seconds=0.5)
assert canvas.time.elapsed == 0.6
assert canvas.time.is_stopped
Source code in xnano/canvas.py
deliver_events
¶
Deliver pushed events to their hooks and draw a frame, without moving time.
Events pushed with push reach their hooks at the
canvas's next step; this is that step on a canvas whose clock you move. A canvas that
runs by itself delivers them on its own.
Examples:
import xnano
from xnano_core import Event
with xnano.new(width=8, height=1) as canvas:
heard = []
canvas.hook(lambda context: heard.append(context.event.kind))
canvas.push(Event.custom('ping'))
canvas.deliver_events()
assert heard == ['custom']
assert canvas.time.elapsed == 0.0
Source code in xnano/canvas.py
stop
¶
Freeze time: the same as Time.stop.
The canvas keeps drawing and hooks still hear input, but animations, effects,
formulas, timers and the beat stand still until resume.
step moves a stopped canvas one frame at a time. To end a
loop, call quit.
Source code in xnano/canvas.py
quit
¶
Ask the canvas's loop to end.
Safe from any thread, including from a hook. A running iter(), run(),
wait_for_key() or prompt() ends. On a canvas from new() the canvas stays
open for writing and rendering; on a canvas that runs by itself (realtime=True, or
on the screen) the loop ends and the canvas closes.
Source code in xnano/canvas.py
run
¶
Wait until the canvas's loop ends.
A canvas that runs by itself draws and listens on its own, so this only keeps your
program alive until a quit key is pressed, or something calls
quit (a hook, another thread). Declare what you want
before calling it.
Parameters:
-
quit_on(KeyName | Sequence[KeyName] | None, default:'ctrl+c') –The key, or keys, that end the loop, such as
'q'or('q', 'escape').'ctrl+c'by default; giveNoneto leave ending to your own code.
Raises:
-
TerminalError–A callback raised on the canvas's loop, or the canvas has a clock that only moves when you move it, so waiting would never end.
Source code in xnano/canvas.py
wait_for_key
¶
Wait until a key is pressed, and return its name.
Your program waits here while the canvas goes on drawing and animating. It reads
like input(): nothing else runs on your thread until the key arrives.
Parameters:
-
keys(KeyName, default:()) –The keys to wait for, such as
'enter'or'q'. Give none to take any key.
Returns:
-
str–The name of the key that was pressed.
Raises:
-
TerminalError–The canvas ended, or has a manual clock, so no key could arrive.
Examples:
In a program: canvas.wait_for_key() after adding "Press any key to start".
Here a timer plays the part of the person pressing the key:
import xnano
from xnano.events import Event
with xnano.new(realtime=True, width=30, height=2) as canvas:
canvas.write('Press enter to start')
@canvas.hook(on='tick', after=0.05)
def press(context: xnano.Context) -> None:
canvas.push(Event.key_press('enter'))
assert canvas.wait_for_key('enter') == 'enter'
Source code in xnano/canvas.py
prompt
¶
Prompt for a line of text, and return what was typed.
The prompt and the answer appear on the canvas while your program waits, like
input(). Enter submits and Backspace deletes.
Parameters:
-
text(str) –What to ask, such as
'Your name: '. -
x(int, default:0) –The column of the prompt.
-
y(int, default:0) –The row of the prompt.
-
default(str, default:'') –Text already in the answer, which the user can edit.
Returns:
-
str–What was typed, without the prompt.
Raises:
-
TerminalError–The canvas ended, or has a manual clock, so no answer could arrive.
Examples:
In a program: name = canvas.prompt('Your name: '). Here a timer plays the part
of the person typing:
import xnano
from xnano.events import Event
with xnano.new(realtime=True, width=30, height=2) as canvas:
@canvas.hook(on='tick', after=0.05)
def type_answer(context: xnano.Context) -> None:
for letter in 'Ada':
canvas.push(Event.key_press(letter))
canvas.push(Event.key_press('enter'))
assert canvas.prompt('Your name: ') == 'Ada'
Source code in xnano/canvas.py
3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 | |
render
¶
Draw the current frame and return it, without a screen.
A canvas that was written into another one returns its own cells alone, at its own size, as they stand in the outer canvas's current frame.
Parameters:
-
format(Literal['text', 'ansi'], default:'text') –'text'for the characters alone,'ansi'for the characters with their colors and styles as escape codes.
Raises:
-
ValueError–formatis neither'text'nor'ansi'.
Examples:
import xnano
with xnano.new(width=6, height=2) as canvas:
canvas.write('hello', y=1)
assert canvas.render().splitlines() == ['', 'hello']
assert 'hello' in canvas.render(format='ansi')
Source code in xnano/canvas.py
push
¶
push(event: Event) -> None
Deliver an event to the canvas as if it had been typed, clicked or reported.
Hooks hear it the same way as input from the keyboard and mouse, at the canvas's
next step, whatever the input gates say. Build events with
Event; Event.custom(name, data=...) makes one of your own.
Parameters:
-
event(Event) –The event to deliver.
Raises:
Examples:
import xnano
from xnano_core import Event
with xnano.new(width=8, height=1) as canvas:
heard = []
canvas.hook(
lambda context: heard.append(context.event.custom_name),
when=lambda context: context.event.kind == 'custom',
)
canvas.push(Event.custom('volume_changed'))
canvas.deliver_events()
assert heard == ['volume_changed']
Source code in xnano/canvas.py
play
¶
play(playable: PlaySource, /, **options: Unpack[PlayOptions]) -> PlayHandle
Play a note, a sound, a symbol name, a melody or a sequence of those, and return at once.
This is audio.play; see it for what playable may
be and for every option. On a canvas from new() the sound is recorded instead of
played; read it with audio.render_sound.
Parameters:
-
playable(PlaySource) –What to play: a note, a sound, a symbol name, melody text such as
'C4 E4 G4:2', a MIDI number, a frequency, or a sequence of those. -
options(Unpack[PlayOptions], default:{}) –The settings of
PlayOptions, such asinstrument,volume,pan,beatsandat_beat.
Returns:
-
PlayHandle–A
PlayHandlethat tells when the sound is over.
Examples:
import xnano
with xnano.new(width=8, height=1, bpm=100) as canvas:
canvas.play('C4 E4 G4:2 rest C5+E5+G5', instrument='bell')
canvas.step(delta_seconds=1.0)
assert canvas.audio.render_sound().duration_milliseconds == 1000.0
Source code in xnano/canvas.py
state_reference
¶
state_reference(reader: Callable[[StateT], ValueT]) -> StateReference[ValueT]
A core reference for one field of the canvas's state.
The reference can be used as an axis, a range bound or a widget parameter.
Parameters:
-
reader(Callable[[StateT], ValueT]) –A function or lambda that reads the field, such as
lambda state: state.volume.
Raises:
-
TypeError–readeris not a function. -
TerminalError–The canvas was created without
state.
Source code in xnano/canvas.py
Color
¶
A terminal color: a named palette color, a palette index or a true color.
Maps to ratatui::style::Color.
Parameters:
-
value(ColorName | str | tuple[int, int, int]) –A color name such as
'red'or'light_blue', a hex string such as'#ff8800', a palette index string such as'4', or a(red, green, blue)tuple.
Attributes:
-
black(Color) –The black terminal color.
-
red(Color) –The red terminal color.
-
green(Color) –The green terminal color.
-
yellow(Color) –The yellow terminal color.
-
blue(Color) –The blue terminal color.
-
magenta(Color) –The magenta terminal color.
-
cyan(Color) –The cyan terminal color.
-
gray(Color) –The gray terminal color.
-
dark_gray(Color) –The dark gray terminal color.
-
light_red(Color) –The light red terminal color.
-
light_green(Color) –The light green terminal color.
-
light_yellow(Color) –The light yellow terminal color.
-
light_blue(Color) –The light blue terminal color.
-
light_magenta(Color) –The light magenta terminal color.
-
light_cyan(Color) –The light cyan terminal color.
-
white(Color) –The white terminal color.
-
reset(Color) –The reset terminal color, which follows the terminal theme.
-
is_reset(bool) –Whether this is the
resetcolor.
Raises:
-
ValueError–valueis not a recognized color.
Examples:
assert Color('#ff8800').to_rgb() == (255, 136, 0)
assert Color((1, 2, 3)) == Color.from_rgb(1, 2, 3)
assert Color('red').to_rgb() is None
Create a Color.
Parameters:
-
API Reference
-
xnano
-
xnano -
xnano.appearance
appearance -
xnano.buffers
buffers -
xnano.canvas
canvasCanvascolor -
xnano.operations
operations -
xnano.placement
placementPlacementcolor -
xnano.region
regionRegion__setitem__ -
xnano.styles
stylesColorValue -
xnano.terminal
terminalTerminalcolor -
xnano.types
typesColorValue -
xnano.widgets
widgets
-
-
xnano_core
-
xnano_core -
xnano_core._xnano_core
_xnano_core -
xnano_core._xnano_core._core_types
_core_types
-
-
xnano
-
API Reference
- xnano
-
xnano_core
-
xnano_core -
xnano_core._xnano_core
_xnano_core
-
Methods:
-
parse–Parse a color name, hex string or palette index string.
-
from_tailwind–A true color from a Tailwind palette and shade.
-
indexed–A color from the 256-color palette.
-
from_rgb–A true color from red, green and blue values between 0 and 255.
-
to_rgb–The
(red, green, blue)values of a true color, orNonefor named and indexed colors. -
to_hex–The color as a
'#rrggbb'string. -
from_hsl–A true color from hue, saturation and lightness.
-
from_hsv–A true color from hue, saturation and value.
-
random–A random true color, or a random shade of
base. -
to_hsl–The hue (degrees), saturation and lightness (percentages) of the color.
-
to_hsv–The hue (degrees), saturation and value (percentages) of the color.
-
lerp–The color between this one and
other. -
lighten–A lighter color for a positive
amount, a darker one for a negativeamount. -
darken–A darker color.
-
inverse–The color that has each red, green and blue channel inverted.
-
saturate–The color with its saturation scaled.
Source code in packages/xnano-core/src/xnano_core/_xnano_core/__init__.pyi
is_reset
property
¶
is_reset: bool
Whether this is the reset color, which follows the terminal's theme.
parse
classmethod
¶
Parse a color name, hex string or palette index string.
Examples:
Source code in packages/xnano-core/src/xnano_core/_xnano_core/__init__.pyi
from_tailwind
classmethod
¶
from_tailwind(palette: TailwindColorName, shade: TailwindColorShade) -> Color
A true color from a Tailwind palette and shade.
Color does not read a name such as 'slate-400'. Pass the palette and the
shade here.
Parameters:
-
palette(TailwindColorName) –A palette such as
'slate'or'red'. -
shade(TailwindColorShade) –50,100through900, or950.
Raises:
-
ValueError–paletteis not a palette, orshadeis not a shade.
Examples:
Source code in packages/xnano-core/src/xnano_core/_xnano_core/__init__.pyi
indexed
classmethod
¶
A color from the 256-color palette.
Examples:
from_rgb
classmethod
¶
A true color from red, green and blue values between 0 and 255.
Examples:
Source code in packages/xnano-core/src/xnano_core/_xnano_core/__init__.pyi
to_rgb
¶
The (red, green, blue) values of a true color, or None for named and indexed colors.
Examples:
Source code in packages/xnano-core/src/xnano_core/_xnano_core/__init__.pyi
to_hex
¶
to_hex() -> str
The color as a '#rrggbb' string.
Only a true color has one, as with to_rgb.
Raises:
-
ValueError–The color is named, indexed or
reset, which the terminal's theme chooses.
Examples:
Source code in packages/xnano-core/src/xnano_core/_xnano_core/__init__.pyi
from_hsl
classmethod
¶
A true color from hue, saturation and lightness.
Parameters:
-
hue(float) –Degrees from 0 to 360.
-
saturation(float) –A percentage from 0 to 100.
-
lightness(float) –A percentage from 0 to 100.
Raises:
-
ValueError–A value is out of range.
Examples:
Source code in packages/xnano-core/src/xnano_core/_xnano_core/__init__.pyi
from_hsv
classmethod
¶
A true color from hue, saturation and value.
Parameters:
-
hue(float) –Degrees from 0 to 360.
-
saturation(float) –A percentage from 0 to 100.
-
value(float) –A percentage from 0 to 100.
Raises:
-
ValueError–A value is out of range.
Examples:
Source code in packages/xnano-core/src/xnano_core/_xnano_core/__init__.pyi
random
classmethod
¶
A random true color, or a random shade of base.
Without base every red, green and blue channel is picked at random. With base
the color keeps its hue and saturation and takes a random lightness from 15 to 85
percent, so every color it returns is a lighter or darker shade of base. The
colors come from Python's random
module, so random.seed(...) repeats them.
Parameters:
-
base(Color | ColorName | str | tuple[int, int, int] | None, default:None) –The color to pick shades of, or
Nonefor any color.
Raises:
-
ValueError–baseisColor.reset, or not a color.
Examples:
import random
random.seed(7)
first = Color.random()
random.seed(7)
assert Color.random() == first
hue, saturation, _ = Color.random('#3366cc').to_hsl()
assert round(hue) == 220 and round(saturation) == 60
Source code in packages/xnano-core/src/xnano_core/_xnano_core/__init__.pyi
to_hsl
¶
The hue (degrees), saturation and lightness (percentages) of the color.
Named and indexed colors use their standard values.
Raises:
-
ValueError–The color is
reset.
Examples:
hue, saturation, lightness = Color('#ff0000').to_hsl()
assert round(hue) == 0
assert round(saturation) == 100
assert round(lightness) == 50
Source code in packages/xnano-core/src/xnano_core/_xnano_core/__init__.pyi
to_hsv
¶
The hue (degrees), saturation and value (percentages) of the color.
Named and indexed colors use their standard values.
Raises:
-
ValueError–The color is
reset.
Examples:
hue, saturation, value = Color('#00ff00').to_hsv()
assert round(hue) == 120
assert round(saturation) == 100
assert round(value) == 100
Source code in packages/xnano-core/src/xnano_core/_xnano_core/__init__.pyi
lerp
¶
lerp(other: Color | ColorName | str | tuple[int, int, int], ratio: float, *, color_space: Literal['rgb', 'hsl', 'hsv'] = 'hsl') -> Color
The color between this one and other.
Parameters:
-
other(Color | ColorName | str | tuple[int, int, int]) –The color to blend toward.
-
ratio(float) –0.0is this color and1.0isother. -
color_space(Literal['rgb', 'hsl', 'hsv'], default:'hsl') –The space the blend runs through.
'hsl'and'hsv'keep colors vivid in the middle;'rgb'is the straight average.
Raises:
-
ValueError–A color is
reset, orcolor_spaceis not a color space.
Examples:
middle = Color('#000000').lerp('#ffffff', 0.5, color_space='rgb')
red, green, blue = middle.to_rgb()
assert red == green == blue
assert 126 <= red <= 129
Source code in packages/xnano-core/src/xnano_core/_xnano_core/__init__.pyi
lighten
¶
A lighter color for a positive amount, a darker one for a negative amount.
Parameters:
-
amount(float) –A fraction from -1.0 (black) to 1.0 (white).
-
color_space(Literal['rgb', 'hsl', 'hsv'], default:'hsl') –The space the change runs through.
Raises:
-
ValueError–The color is
reset, orcolor_spaceis not a color space.
Examples:
base = Color('#336699')
assert base.lighten(0.2).to_hsl()[2] > base.to_hsl()[2]
assert base.lighten(-0.2).to_hsl()[2] < base.to_hsl()[2]
Source code in packages/xnano-core/src/xnano_core/_xnano_core/__init__.pyi
darken
¶
A darker color.
Parameters:
-
amount(float) –A fraction from 0.0 (unchanged) to 1.0 (black). Use
lightento make a color lighter. -
color_space(Literal['rgb', 'hsl', 'hsv'], default:'hsl') –The space the change runs through.
Returns:
-
Color–The darkened color; the original is unchanged.
Raises:
-
ValueError–amountis outside 0.0 to 1.0, the color isreset, orcolor_spaceis not a color space.
Examples:
assert Color('#808080').darken(1.0).to_rgb() == (0, 0, 0)
base = Color('#336699')
assert base.darken(0.2).to_hsl()[2] < base.to_hsl()[2]
assert base.darken(0.0) == base
Source code in packages/xnano-core/src/xnano_core/_xnano_core/__init__.pyi
inverse
¶
inverse() -> Color
The color that has each red, green and blue channel inverted.
Named and indexed colors are inverted through their standard values, so the result is always a true color.
Returns:
-
Color–The inverted true color; the original is unchanged.
Raises:
-
ValueError–The color is
reset, which has no fixed value.
Examples:
assert Color('#ff8000').inverse().to_hex() == '#007fff'
assert Color('#ff8000').inverse().inverse() == Color('#ff8000')
Source code in packages/xnano-core/src/xnano_core/_xnano_core/__init__.pyi
saturate
¶
The color with its saturation scaled.
Parameters:
-
factor(float) –0.0removes the saturation,1.0keeps it and more than1.0boosts it. -
color_space(Literal['rgb', 'hsl', 'hsv'], default:'hsl') –The space the change runs through.
Raises:
-
ValueError–The color is
reset, orcolor_spaceis not a color space.
Examples:
Source code in packages/xnano-core/src/xnano_core/_xnano_core/__init__.pyi
from_audio
¶
from_audio(source: TerminalSound | PathLike[str] | str | bytes, /, *, symbol: str | None = None) -> Audio
Load a sound from a WAV file path or from bytes.
This is Audio with the same arguments. Play the result with
canvas.play(sound), or give it a symbol and play it by name.
Parameters:
-
source(TerminalSound | PathLike[str] | str | bytes) –The path of a PCM WAV file, the bytes of one, or a
TerminalSound. -
symbol(str | None, default:None) –A name to register the sound under in
symbols, soplay(name)plays it.
Returns:
Raises:
-
ImportError–xnano-audiois not installed. Install it withpip install "xnano[audio]". -
TypeError–sourceis not a path, bytes or a sound. -
ValueError–The file is not a PCM WAV file that xnano can read.
-
FileNotFoundError–The path does not exist.
Examples:
import xnano
from xnano_audio import TerminalSound
beep = xnano.from_audio(TerminalSound.from_samples([0.0, 0.5, -0.5, 0.0]), symbol='beep')
with xnano.new(width=8, height=1) as canvas:
canvas.play('beep')
canvas.step(delta_seconds=0.1)
assert canvas.audio.render_sound().peak > 0.0
Source code in xnano/_media.py
from_image
¶
from_image(source: TerminalImage | PathLike[str] | str | bytes, /, *, x: Axis | None = None, y: Axis | None = None, width: Axis | None = None, height: Axis | None = None, layer: int = 0, lock: bool = False, fit: ImageFit | None = None, resampling_filter: ResamplingFilter | None = None, background: ColorValue = (0, 0, 0), speed: float = 1.0, symbol: str | None = None) -> Image
Load an image or an animation from a file path or from bytes.
This is Image with the same arguments: PNG, JPEG, GIF, WebP and XNI files
are read, and an animated one plays on the canvas's clock. Write the result with
canvas.write(picture).
Parameters:
-
source(TerminalImage | PathLike[str] | str | bytes) –The path of an image file, the bytes of one, or a
TerminalImage. -
x(Axis | None, default:None) –The column of the left edge; see
Image. -
y(Axis | None, default:None) –The row of the top edge.
-
width(Axis | None, default:None) –The width: cells, a percentage, an expression, or
Nonefor the picture's own. -
height(Axis | None, default:None) –The height, in the same forms.
-
layer(int, default:0) –Content with a higher layer is drawn over content with a lower one.
-
lock(bool, default:False) –Keep the size the image has when it is added, whatever the canvas does.
-
fit(ImageFit | None, default:None) –How the picture sits in a box of
widthbyheight. -
resampling_filter(ResamplingFilter | None, default:None) –How pixels are blended when it is resized.
-
background(ColorValue, default:(0, 0, 0)) –The color behind transparent pixels and padding.
-
speed(float, default:1.0) –How fast an animated image plays:
2.0is twice as fast. -
symbol(str | None, default:None) –A name to register the image under in
symbols.
Returns:
Raises:
-
ImportError–xnano-imageis not installed. Install it withpip install "xnano[image]". -
TypeError–sourceis not a path, bytes or an image. -
FileNotFoundError–The path does not exist.
Examples:
import xnano
from xnano.image import TerminalImage
picture = xnano.from_image(
TerminalImage.from_rgba(1, 1, bytes([255, 0, 0, 255])), width=4, symbol='red_dot'
)
assert isinstance(picture, xnano.Image)
assert xnano.symbols.lookup('red_dot') is picture
Source code in xnano/_media.py
draw
¶
draw(source: str | Sequence[str] | Image | TerminalImage | bytes | bytearray | None = None, palette: Mapping[str, ColorValue] | str | None = None, *, width: int | None = None, height: int | None = None, background: ColorValue | None = None, symbol: str | None = None, effects: Sequence[RenderableEffectSpecification] = ()) -> Art
Build pixel art from text, a picture, bytes or nothing (does not draw).
This is how pixel-art sprites are written in code, one character per pixel. Nothing is
drawn: the art is a value that you write into a canvas. Text rows (a multi-line string, which
may be indented, or a list of rows) are painted with a palette that says what each
character means; any character the palette does not name, such as '.', is a
transparent pixel. The palette is a mapping, or one string of character=color pairs.
What source is decides what is made:
- Text with a newline, or a list of rows: pixel art painted with
palette. - Text without a newline: the name of a registered art or image (see
symbols); you get a copy of the art, or the pixels of the image. A one-row picture is a list,draw(['GG'], palette), so that a call never changes meaning because a symbol was registered later. - An
Imageor a picture fromxnano.image: its pixels are copied (the first frame of an animation). bytesof red, green, blue and alpha, withwidthandheight.None: a blank world ofwidthbyheightpixels filled withbackground.
Parameters:
-
source(str | Sequence[str] | Image | TerminalImage | bytes | bytearray | None, default:None) –What to draw.
-
palette(Mapping[str, ColorValue] | str | None, default:None) –The color of each character of text rows, as a mapping to names,
'#rrggbb'strings or(red, green, blue)tuples, or as a string such as'R=#e03040 G=green'. -
width(int | None, default:None) –The width in pixels of
bytesor of a blank world. -
height(int | None, default:None) –The height in pixels.
-
background(ColorValue | None, default:None) –The color behind the art. Transparent pixels show it.
-
symbol(str | None, default:None) –A name to register the art under, so
draw('name')returns a copy of it. -
effects(Sequence[RenderableEffectSpecification], default:()) –Effects to start on the placement when the art is written, as dictionaries with a
kindkey.
Raises:
-
ValueError–The rows are empty or differ in length, the palette or a color in it is not valid, a text without a newline is not a known symbol, or the sizes do not match the bytes.
-
TypeError–sourceis not one of the kinds above.
Examples:
import xnano
heart = xnano.draw(
'''
.RR.RR.
RRRRRRR
.RRRRR.
..RRR..
...R...
''',
'R=#e03040',
)
assert (heart.width, heart.height) == (7, 5)
print(heart.render())
xnano.draw(['G'], {'G': 'green'}, symbol='grass')
assert xnano.draw('grass').width == 1
Source code in xnano/art.py
834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 | |
active
¶
Return the innermost canvas that is running in this thread or task.
A canvas is active from the moment it is created until it ends: the most recently created
one wins, and a canvas that was asked to quit gives way to the
one created before it. A canvas created inside the with block of another one belongs
to that canvas, so the outer canvas stays active. Hooks run on a canvas's loop see that
canvas.
Parameters:
-
is_required(bool, default:True) –Whether to raise when no canvas is running.
Raises:
-
TerminalClosedError–No canvas is running and
is_requiredis true.
Examples:
import xnano
assert xnano.active(is_required=False) is None
with xnano.new(width=4, height=1) as outer:
assert xnano.active() is outer
with xnano.new(width=4, height=1):
assert xnano.active() is outer
assert xnano.active(is_required=False) is None
Source code in xnano/canvas.py
iter
¶
Iterate over the frames of the active canvas, drawing between them.
This is Canvas.iter for the innermost running canvas, so a
loop does not need the canvas in hand.
Parameters:
-
count(int | None, default:None) –The most frames to yield.
-
seconds(float | None, default:None) –The most seconds of the canvas's time to run for.
Raises:
-
TerminalClosedError–No canvas is running.
Examples:
import xnano
with xnano.new(width=8, height=1) as canvas:
ball = canvas.write('o')
for frame in xnano.iter(count=3):
ball.x = frame.index
assert ball.x == 2
Source code in xnano/canvas.py
new
¶
new(content: Content | Canvas[WrittenDepsT, WrittenStateT] | None = None, /, *, width: int | Percentage | str | None = None, height: int | Percentage | str | None = None, fps: float | None = None, bpm: float | None = None, realtime: bool = False, title: str | None = None, effects: Sequence[RenderableEffectSpecification] = (), **settings: Unpack[CanvasSettings]) -> Canvas[None, None]
new(content: Content | Canvas[WrittenDepsT, WrittenStateT] | None = None, /, *, width: int | Percentage | str | None = None, height: int | Percentage | str | None = None, fps: float | None = None, bpm: float | None = None, realtime: bool = False, title: str | None = None, effects: Sequence[RenderableEffectSpecification] = (), state: StateT, **settings: Unpack[CanvasSettings]) -> Canvas[None, StateT]
new(content: Content | Canvas[WrittenDepsT, WrittenStateT] | None = None, /, *, width: int | Percentage | str | None = None, height: int | Percentage | str | None = None, fps: float | None = None, bpm: float | None = None, realtime: bool = False, title: str | None = None, effects: Sequence[RenderableEffectSpecification] = (), deps: DepsT, **settings: Unpack[CanvasSettings]) -> Canvas[DepsT, None]
new(content: Content | Canvas[WrittenDepsT, WrittenStateT] | None = None, /, *, width: int | Percentage | str | None = None, height: int | Percentage | str | None = None, fps: float | None = None, bpm: float | None = None, realtime: bool = False, title: str | None = None, effects: Sequence[RenderableEffectSpecification] = (), deps: DepsT, state: StateT, **settings: Unpack[CanvasSettings]) -> Canvas[DepsT, StateT]
new(content: Content | Canvas[WrittenDepsT, WrittenStateT] | None = None, /, *, width: int | Percentage | str | None = None, height: int | Percentage | str | None = None, fps: float | None = None, bpm: float | None = None, realtime: bool = False, title: str | None = None, effects: Sequence[RenderableEffectSpecification] = (), deps: object = _UNSET, state: object = _UNSET, **settings: object) -> Canvas[DepsT, StateT]
Create a canvas: a virtual terminal with a clock, hooks, sound, a cursor and state.
It has no screen and draws into memory. Its clock moves only when you move it, with
step or iter, so every run is
the same; realtime=True runs it on the wall clock on a thread of its own instead.
Canvas.open (or open) puts it on the screen.
A with block closes it.
A canvas with a manual clock belongs to the thread that created it: use it, and close it,
on that thread, for example with a with block in the worker that made it. A canvas
that several threads use, or that is closed after its thread has ended, is created with
realtime=True.
content, when given, is written at the top-left corner, as canvas.write(content)
would. The appearance keywords (colors, text modifiers, border, border_style)
style the canvas itself, not its content, so they are accepted only without content:
new(border='rounded') borders the canvas, and new().write('hello', border='rounded')
borders the text. A canvas's foreground and background color the cells no content
covers. padding and margin pad and space the canvas itself. title is the
window title.
Created inside the with block of another canvas, the new canvas belongs to that one
from the start but is hidden in it: its size is measured in that canvas ('50%' is
half of it, and no size fills it), it runs on that canvas's time and its hooks hear that
canvas's input. outer.write(canvas, x=..., y=...) shows it, once, where it is
written. Leaving its own with block keeps it; it closes with the canvas it belongs
to. Inside its with block, outer.write(...) places content within the new
canvas's area of outer. It takes that canvas's edges unless given its own.
Canvas.new creates a canvas that is shown at once. A canvas
given state or deps stays on its own, because those belong to the outermost
canvas: it is measured in the canvas around it, takes its fps, bpm and edges
unless given its own, and closes with it.
The input gates (mouse, scroll, keyboard, paste, focus, interrupt,
capture, clear, alternate_screen) are stored and take effect when the canvas
is opened on the screen; see GateSettings.
Parameters:
-
content(Content | Canvas[WrittenDepsT, WrittenStateT] | None, default:None) –Something to write into the canvas at once, such as text or a widget.
-
width(int | Percentage | str | None, default:None) –The width in cells, or a percentage of the window such as
'50%', read when the canvas is created; 80 whenNone. On the screen it is the width of the region the canvas draws in, read again when it is opened. -
height(int | Percentage | str | None, default:None) –The height in cells, or a percentage of the window such as
'50%'; 24 whenNone. On the screen it is the height of the region the canvas draws in, and'100%'for both sizes fills the whole window. -
fps(float | None, default:None) –The most frames drawn per second, and the length of one step of
iter(); the enclosing canvas's, else 60, whenNone. -
bpm(float | None, default:None) –Beats per minute for beat timers, notes and melodies; the enclosing canvas's, else 120, when
None. -
realtime(bool, default:False) –Whether the canvas runs by itself on the wall clock, on a thread of its own.
-
title(str | None, default:None) –The window title, shown when the canvas is on the screen.
-
effects(Sequence[RenderableEffectSpecification], default:()) –Effects to apply to the canvas, as dictionaries with a
kindkey. -
deps(object, default:_UNSET) –Dependencies that hooks read as
context.deps; the canvas never reads them. -
state(object, default:_UNSET) –A dataclass instance the canvas keeps and validates. Hooks read and write it.
-
settings(object, default:{}) –The input gates and the canvas's own look; see
CanvasSettings.
Returns:
-
Canvas[DepsT, StateT]–The
Canvas, which is also the one module-level functions such -
Canvas[DepsT, StateT]–as
activefind.
Raises:
-
TypeError–An appearance keyword was given with content, or a keyword is unknown.
-
ValueError–A size (1 to 65535 cells),
fps,bpm,realtime, gate or border kind is out of range.
Examples:
import xnano
with xnano.new(width=16, height=3) as canvas:
assert (canvas.width, canvas.height) == (16, 3)
assert xnano.active() is canvas
assert not canvas.time.is_realtime
with xnano.new('hello', width=8, height=1) as greeting:
assert greeting.render() == 'hello'
with xnano.new(width=12, height=4) as outer:
with xnano.new(height='50%') as inner:
inner.write('inside')
assert (inner.width, inner.height) == (12, 2)
assert outer.render().strip() == ''
outer.write(inner, y=2)
assert outer.render().splitlines()[2] == 'inside'
assert xnano.active() is outer
Source code in xnano/canvas.py
4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 | |
playable
¶
playable(function: Callable[[], Playable]) -> PlayableFunction[[], None, None]
playable(function: Callable[Concatenate[Context[DepsT, StateT], ParametersT], Playable]) -> PlayableFunction[ParametersT, DepsT, StateT]
playable(function: Callable[Concatenate[Context[DepsT, StateT], ParametersT], Playable] | Callable[[], Playable]) -> PlayableFunction[ParametersT, DepsT, StateT] | PlayableFunction[[], None, None]
Turn a function into a component that plays itself.
The function takes the Context first, then its own parameters,
and returns anything canvas.play accepts; a function with no parameters at all is
called without the context. It is evaluated once when played, and again
on a beat only when it read something that changes (the time or the beat, a state path or
an input), playing the new result each time. canvas.play returns a
PlayHandle whose remove() stops it.
Parameters:
-
function(Callable[Concatenate[Context[DepsT, StateT], ParametersT], Playable] | Callable[[], Playable]) –The function
(context, **own_parameters) -> playable.
Raises:
-
TypeError–The decorated object is a class or is not callable, or the function's first parameter is keyword-only or variadic, so it cannot take the context.
Examples:
import xnano
@xnano.playable
def chord(context: xnano.Context, root: str = 'C4') -> xnano.Note:
return xnano.note(root, beats=0.5)
with xnano.new(width=8, height=1) as canvas:
canvas.play(chord(root='E4'))
canvas.step(delta_seconds=0.5)
assert canvas.audio.render_sound().peak > 0.0
Source code in xnano/components.py
renderable
¶
renderable(function: Callable[[], Renderable]) -> RenderableFunction[[], None, None]
renderable(function: Callable[Concatenate[Context[DepsT, StateT], ParametersT], Renderable]) -> RenderableFunction[ParametersT, DepsT, StateT]
renderable(function: Callable[Concatenate[Context[DepsT, StateT], ParametersT], Renderable] | Callable[[], Renderable]) -> RenderableFunction[ParametersT, DepsT, StateT] | RenderableFunction[[], None, None]
Turn a function into a component that draws itself.
The function takes the Context first, then its own parameters,
and returns anything canvas.write accepts; a function with no parameters at all is
called without the context. The decorated object is the component:
canvas.write(gauge) draws it with its defaults, canvas.write(gauge(ratio=0.7)) gives
it parameters, and gauge.hook(...) adds behavior to its placements.
A component is evaluated once, and again only when it read something that changes: the
time or the event (every frame), the size of its buffer, the parent or the canvas (when
the screen is resized), a state path (when it changes), or an input such as
context.keyboard (when it arrives). What it reads is recorded as it runs. Reads of
context.deps and of mutable fields on self are not tracked: when they change, call
placement.refresh().
Parameters:
-
function(Callable[Concatenate[Context[DepsT, StateT], ParametersT], Renderable] | Callable[[], Renderable]) –The function
(context, **own_parameters) -> content.
Raises:
-
TypeError–The decorated object is a class or is not callable, or the function's first parameter is keyword-only or variadic, so it cannot take the context.
Examples:
import xnano
@xnano.renderable
def gauge(context: xnano.Context, ratio: float = 0.5) -> str:
return '#' * round(ratio * 10)
with xnano.new(width=12, height=1) as canvas:
canvas.write(gauge(ratio=0.3))
assert canvas.render().strip() == '###'
Source code in xnano/components.py
note
¶
note(pitch: Pitch | Sequence[Pitch], *, beats: float = 1.0, instrument: InstrumentName = 'piano', velocity: float = 0.8, effects: Sequence[PlayableEffectSpecification] = (), symbol: str | None = None) -> Note
Make a Note: a pitch, or several for a chord, with its length and sound.
Nothing is played and no sound device is needed. Play it with play or
Canvas.play. symbol='kick' registers the note, and then
play('kick') plays it.
Parameters:
-
pitch(Pitch | Sequence[Pitch]) –A note name such as
'C#4', a MIDI number from 0 to 127, or a sequence of them for a chord. -
beats(float, default:1.0) –How long the note is held, in beats.
-
instrument(InstrumentName, default:'piano') –A built-in instrument, from
instrument_names. -
velocity(float, default:0.8) –How hard the note is played, from 0.0 to 1.0.
-
effects(Sequence[PlayableEffectSpecification], default:()) –Sound effects as dictionaries with a
kindkey, such as{'kind': 'audio.reverb'}. -
symbol(str | None, default:None) –
Raises:
-
TypeError–The pitch is not a note name or a number.
-
ValueError–A value is out of range or the instrument is unknown.
Examples:
import xnano
kick = xnano.note('C2', instrument='kick', symbol='kick_drum')
with xnano.new(width=8, height=1) as canvas:
canvas.play('kick_drum')
canvas.step(delta_seconds=0.5)
assert canvas.audio.render_sound().peak > 0.0
Source code in xnano/music.py
play
¶
play(playable: PlaySource, /, **options: Unpack[PlayOptions]) -> PlayHandle
Play a note, a sound, a symbol name, a melody or a sequence of those.
The sound goes to the running canvas (see active); with no canvas
running it goes to this computer's sound output. On a canvas from new,
which has a clock you move, the sound is recorded and makes no noise: read it with
canvas.audio.render_sound().
A str is a symbol name first, so play('kick') plays the note or sound registered
with symbol='kick'. Any other str is a note name such as 'C#4', a frequency such
as '440hz' or melody text: notes separated by spaces, :2 holds a note for two
beats, rest is a silence, + joins a chord and | marks a bar, as in
'C4 E4 G4:2 rest C5+E5+G5'. A sequence plays one after another. An option replaces
the same value on a Note, so play(note('C4'), instrument='violin')
plays the violin.
Parameters:
-
playable(PlaySource) –What to play.
-
**options(Unpack[PlayOptions], default:{}) –See
PlayOptions:instrument,velocity,effects,volume,pan,at_beatandbeats, the length in beats of a note name, a number or aNote.
Returns:
-
PlayHandle–A
PlayHandle.
Raises:
-
ImportError–xnano-audiois not installed. Install it withpip install "xnano[audio]". -
TerminalAudioUnavailableError–No canvas is running and this computer has no sound output device.
-
ValueError–An option is out of range, or a
stris neither a symbol, a note name nor melody text. The message lists the known sound symbols.
Examples:
import xnano
with xnano.new(width=8, height=1) as canvas:
xnano.play([xnano.note('C4'), xnano.note('E4'), xnano.note('G4')])
canvas.step(delta_seconds=1.5)
assert canvas.audio.render_sound().peak > 0.0
Source code in xnano/music.py
hook
¶
hook(function: Hook[DepsT, StateT]) -> ContextualOperation[DepsT, StateT]
hook(function: Hook[DepsT, StateT] | None = None, /, *, on: HookKind | None = None, when: When[DepsT, StateT] | None = None, every: float | None = None, after: float | None = None, keys: KeyName | Sequence[KeyName] | None = None, requires_deps: bool = False) -> ContextualOperation[DepsT, StateT] | Callable[[Hook[DepsT, StateT]], ContextualOperation[DepsT, StateT]]
Describe a hook once, to attach to any canvas or placement later.
It takes the same arguments as target.hook(...) and returns an operation: pipe it onto
a target with target | operation, or pass it to update. Each target gets its own
hook. The function may return an operation, a style or an effect, which is applied to the
target it runs on.
Parameters:
-
function(Hook[DepsT, StateT] | None, default:None) –The function to wrap when
@xnano.hookis used without parentheses: a function of theContext, or one with no parameters. -
on(HookKind | None, default:None) –What the hook listens to; see
HookKind. -
when(When[DepsT, StateT] | None, default:None) –A condition that must hold; see
When. -
every(float | None, default:None) –Repeat every this many seconds (
'tick') or beats ('beat'). -
after(float | None, default:None) –Run once after this many seconds (
'tick') or beats ('beat'). -
keys(KeyName | Sequence[KeyName] | None, default:None) –The key or keys an
on='key'hook reacts to. -
requires_deps(bool, default:False) –Whether the hook needs the dependencies given to
new(deps=...).
Raises:
-
TypeError–functioncannot be called with a context,keysis not a key name or a list of them, orwhenis not a condition. -
ValueError–on,every,after,keysorwhenis not valid, or they do not fit together.
Examples:
import xnano
readings = []
@xnano.hook(on='frame')
def clock_readout(context: xnano.Context) -> None:
readings.append(round(context.time.elapsed, 1))
with xnano.new(width=12, height=1) as canvas:
canvas | clock_readout
canvas.step(delta_seconds=0.5)
assert readings == [0.5]
Source code in xnano/operations.py
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 | |
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.
borderis'plain'unless you pass another kind orFalse.
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
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,paddingandmargin; seeAppearanceArguments.
Raises:
-
TypeError–textis not a string.
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
open
¶
open(canvas: Canvas[DepsT, StateT], /, *, title: str | None = None, width: int | Percentage | str | None = None, height: int | Percentage | str | None = None, **settings: Unpack[OpenSettings]) -> Terminal[DepsT, StateT]
open(content: Content | None = None, /, *, title: str | None = None, width: int | Percentage | str | None = None, height: int | Percentage | str | None = None, fps: float = 60.0, bpm: float = 120.0, effects: Sequence[RenderableEffectSpecification] = (), **settings: Unpack[CanvasSettings]) -> Terminal[None, None]
open(content: Content | None = None, /, *, title: str | None = None, width: int | Percentage | str | None = None, height: int | Percentage | str | None = None, fps: float = 60.0, bpm: float = 120.0, effects: Sequence[RenderableEffectSpecification] = (), state: StateT, **settings: Unpack[CanvasSettings]) -> Terminal[None, StateT]
open(content: Content | None = None, /, *, title: str | None = None, width: int | Percentage | str | None = None, height: int | Percentage | str | None = None, fps: float = 60.0, bpm: float = 120.0, effects: Sequence[RenderableEffectSpecification] = (), deps: DepsT, **settings: Unpack[CanvasSettings]) -> Terminal[DepsT, None]
open(content: Content | None = None, /, *, title: str | None = None, width: int | Percentage | str | None = None, height: int | Percentage | str | None = None, fps: float = 60.0, bpm: float = 120.0, effects: Sequence[RenderableEffectSpecification] = (), deps: DepsT, state: StateT, **settings: Unpack[CanvasSettings]) -> Terminal[DepsT, StateT]
open(canvas_or_content: Canvas[object, object] | Content | None = None, /, *, title: str | None = None, width: int | Percentage | str | None = None, height: int | Percentage | str | None = None, **settings: object) -> Terminal[DepsT, StateT]
Put a canvas on your screen and return it as a Terminal.
Given a canvas from new, this is Canvas.open:
the same object is attached to the screen and its time continues. Given content or
nothing, it creates the canvas with new() (the same keywords, except realtime)
and attaches that. From here on, anything you write, remove or draw appears at once, on a
loop of the canvas's own that your code never waits for. A with block closes it and
gives the screen back.
By default the canvas takes over the whole window, on the alternate screen so that your
shell's history comes back untouched; width='100%', height='100%' asks for the same.
Give height (and optionally width) to draw in a region of that size below the cursor
instead, in cells or as a percentage of the window such as '50%'; that region is erased
when the canvas closes, unless you pass clear=False. title is the window title.
The input gates say what the screen reports: mouse for buttons and drags, scroll
for the wheel, keyboard, paste, focus and interrupt (Ctrl-C), and
capture holds back what the program prints while the canvas is on the screen. See
GateSettings. mouse, scroll and paste are turned
on by themselves when a hook registered before opening needs them.
Parameters:
-
canvas_or_content(Canvas[object, object] | Content | None, default:None) –A canvas from
new(), or content to write into a new canvas. -
title(str | None, default:None) –The window title;
Nonekeeps the canvas's title. -
width(int | Percentage | str | None, default:None) –The width of the region to draw in, in cells or as a percentage of the window; the whole window when neither
widthnorheightis given. -
height(int | Percentage | str | None, default:None) –The height of the region to draw in, in cells or as a percentage of the window.
-
settings(object, default:{}) –The other keywords of
new()exceptrealtime: the gates, the canvas's look,fps,bpm,effects,depsandstate.
Returns:
-
Terminal[DepsT, StateT]–The open
Terminal, which is also the one module-level functions -
Terminal[DepsT, StateT]–such as
activefind.
Raises:
-
TerminalAlreadyOpenError–Another canvas is already on the screen.
-
TerminalError–There is no terminal to draw on.
-
TypeError–realtimewas given, an appearance keyword was given with content, or a keyword is unknown. -
ValueError–A
widthwas given without aheight, or a value is out of range.
Examples:
with xnano.open(height=3, mouse=True) as terminal:
terminal.write('hello')
terminal.run(quit_on='q')
Source code in xnano/terminal.py
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 | |