Skip to content

Commit 2e8efdd

Browse files
committed
Merge Console.print_box into Console.print method and modernize
Changes are mostly backwards compatible expect for a slight change in text placement. Also update some old docs which were not using correct directives.
1 parent 07ea8ac commit 2e8efdd

File tree

4 files changed

+163
-42
lines changed

4 files changed

+163
-42
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@ This project adheres to [Semantic Versioning](https://semver.org/) since version
66

77
## [Unreleased]
88

9+
### Changed
10+
11+
- `Console.print` now accepts `height` and `width` keywords and has renamed `string` to `text`.
12+
- Text printed with `Console.print` using right-alignment has been shifted to the left by 1-tile.
13+
14+
### Deprecated
15+
16+
- Using `Console.print` without keywords for only the `x`, `y`, and `text` parameters has been deprecated.
17+
The `string` parameter has been renamed to `text`.
18+
- `Console.print_box` has been replaced by `Console.print`.
19+
920
## [17.1.0] - 2025-03-29
1021

1122
### Added

docs/tcod/getting-started.rst

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ console will be stretched to fit the window. You can add arguments to
1919
:any:`Context.present` to fix the aspect ratio or only scale the console by
2020
integer increments.
2121

22-
Example::
22+
.. code-block:: python
2323
2424
#!/usr/bin/env python
2525
# Make sure 'dejavu10x10_gs_tc.png' is in the same directory as this script.
@@ -38,23 +38,24 @@ Example::
3838
"dejavu10x10_gs_tc.png", 32, 8, tcod.tileset.CHARMAP_TCOD,
3939
)
4040
# Create the main console.
41-
console = tcod.console.Console(WIDTH, HEIGHT, order="F")
41+
console = tcod.console.Console(WIDTH, HEIGHT)
4242
# Create a window based on this console and tileset.
4343
with tcod.context.new( # New window for a console of size columns×rows.
4444
columns=console.width, rows=console.height, tileset=tileset,
4545
) as context:
4646
while True: # Main loop, runs until SystemExit is raised.
4747
console.clear()
48-
console.print(x=0, y=0, string="Hello World!")
48+
console.print(x=0, y=0, text="Hello World!")
4949
context.present(console) # Show the console.
5050
5151
# This event loop will wait until at least one event is processed before exiting.
5252
# For a non-blocking event loop replace `tcod.event.wait` with `tcod.event.get`.
5353
for event in tcod.event.wait():
5454
context.convert_event(event) # Sets tile coordinates for mouse events.
5555
print(event) # Print event names and attributes.
56-
if isinstance(event, tcod.event.Quit):
57-
raise SystemExit()
56+
match event:
57+
case tcod.event.Quit():
58+
raise SystemExit()
5859
# The window will be closed after the above with-block exits.
5960
6061
@@ -87,7 +88,7 @@ You can call :any:`Context.new_console` every frame or only when the window
8788
is resized. This example creates a new console every frame instead of
8889
clearing the console every frame and replacing it only on resizing the window.
8990

90-
Example::
91+
.. code-block:: python
9192
9293
#!/usr/bin/env python
9394
import tcod.context
@@ -103,17 +104,18 @@ Example::
103104
width=WIDTH, height=HEIGHT, sdl_window_flags=FLAGS
104105
) as context:
105106
while True:
106-
console = context.new_console(order="F") # Console size based on window resolution and tile size.
107+
console = context.new_console() # Console size based on window resolution and tile size.
107108
console.print(0, 0, "Hello World")
108109
context.present(console, integer_scaling=True)
109110
110111
for event in tcod.event.wait():
111-
context.convert_event(event) # Sets tile coordinates for mouse events.
112+
event = context.convert_event(event) # Sets tile coordinates for mouse events.
112113
print(event) # Print event names and attributes.
113-
if isinstance(event, tcod.event.Quit):
114-
raise SystemExit()
115-
elif isinstance(event, tcod.event.WindowResized) and event.type == "WindowSizeChanged":
116-
pass # The next call to context.new_console may return a different size.
114+
match event:
115+
case tcod.event.Quit():
116+
raise SystemExit()
117+
case tcod.event.WindowResized(type="WindowSizeChanged"):
118+
pass # The next call to context.new_console may return a different size.
117119
118120
119121
if __name__ == "__main__":

tcod/console.py

Lines changed: 134 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import warnings
1111
from os import PathLike
1212
from pathlib import Path
13-
from typing import Any, Iterable
13+
from typing import Any, Iterable, overload
1414

1515
import numpy as np
1616
from numpy.typing import ArrayLike, NDArray
@@ -552,6 +552,7 @@ def __deprecate_defaults( # noqa: C901, PLR0912
552552
stacklevel=3,
553553
)
554554

555+
@deprecated("Switch to using keywords and then replace with 'console.print(...)'")
555556
def print_(
556557
self,
557558
x: int,
@@ -579,6 +580,7 @@ def print_(
579580
alignment = self.default_alignment if alignment is None else alignment
580581
lib.TCOD_console_printf_ex(self.console_c, x, y, bg_blend, alignment, _fmt(string))
581582

583+
@deprecated("Switch to using keywords and then replace with 'console.print(...)'")
582584
def print_rect( # noqa: PLR0913
583585
self,
584586
x: int,
@@ -973,55 +975,159 @@ def __str__(self) -> str:
973975
"""Return a simplified representation of this consoles contents."""
974976
return "<{}>".format("\n ".join("".join(chr(c) for c in line) for line in self._tiles["ch"]))
975977

978+
@overload
979+
@deprecated(
980+
"Switch all parameters to keywords such as 'console.print(x=..., y=..., text=..., width=..., height=..., fg=..., bg=..., bg_blend=..., alignment=...)'"
981+
"\n'string' keyword should be renamed to `text`"
982+
)
983+
def print(
984+
self,
985+
x: int,
986+
y: int,
987+
text: str,
988+
fg: tuple[int, int, int] | None = None,
989+
bg: tuple[int, int, int] | None = None,
990+
bg_blend: int = tcod.constants.BKGND_SET,
991+
alignment: int = tcod.constants.LEFT,
992+
*,
993+
string: str = "",
994+
) -> int: ...
995+
996+
@overload
997+
def print(
998+
self,
999+
x: int,
1000+
y: int,
1001+
text: str,
1002+
*,
1003+
width: int | None = None,
1004+
height: int | None = None,
1005+
fg: tuple[int, int, int] | None = None,
1006+
bg: tuple[int, int, int] | None = None,
1007+
bg_blend: int = tcod.constants.BKGND_SET,
1008+
alignment: int = tcod.constants.LEFT,
1009+
) -> int: ...
1010+
9761011
def print( # noqa: PLR0913
9771012
self,
9781013
x: int,
9791014
y: int,
980-
string: str,
1015+
text: str = "",
9811016
fg: tuple[int, int, int] | None = None,
9821017
bg: tuple[int, int, int] | None = None,
9831018
bg_blend: int = tcod.constants.BKGND_SET,
9841019
alignment: int = tcod.constants.LEFT,
985-
) -> None:
986-
r"""Print a string on a console with manual line breaks.
1020+
*,
1021+
width: int | None = None,
1022+
height: int | None = None,
1023+
string: str = "",
1024+
) -> int:
1025+
r"""Print a string of Unicode text on this console.
9871026
988-
`x` and `y` are the starting tile, with ``0,0`` as the upper-left
989-
corner of the console.
1027+
Prefer using keywords for this method call to avoid ambiguous parameters.
9901028
991-
`string` is a Unicode string which may include color control
992-
characters. Strings which are too long will be truncated until the
993-
next newline character ``"\n"``.
1029+
Args:
1030+
x: Starting X coordinate, with the left-most tile as zero.
1031+
y: Starting Y coordinate, with the top-most tile as zero.
1032+
text: A Unicode string which may include color control characters.
1033+
width: Width in tiles to constrain the printing region.
1034+
If a `width` is given then `text` will have automatic word wrapping applied to it.
1035+
A `width` of `None` means `text` will only have manual line breaks.
1036+
height: Height in tiles to constrain the printing region.
1037+
fg: RGB tuple to use as the foreground color, or `None` to leave the foreground unchanged.
1038+
Tuple values should be 0-255.
1039+
bg: RGB tuple to use as the background color, or `None` to leave the foreground unchanged.
1040+
Tuple values should be 0-255.
1041+
bg_blend: Background blend type used by libtcod.
1042+
Typically starts with `libtcodpy.BKGND_*`.
1043+
alignment: One of `libtcodpy.LEFT`, `libtcodpy.CENTER`, or `libtcodpy.RIGHT`
1044+
string: Older deprecated name of the `text` parameter.
9941045
995-
`fg` and `bg` are the foreground text color and background tile color
996-
respectfully. This is a 3-item tuple with (r, g, b) color values from
997-
0 to 255. These parameters can also be set to `None` to leave the
998-
colors unchanged.
1046+
Returns:
1047+
The height of `text` in lines via word wrapping and line breaks.
9991048
1000-
`bg_blend` is the blend type used by libtcod.
1049+
Example::
10011050
1002-
`alignment` can be `tcod.LEFT`, `tcod.CENTER`, or `tcod.RIGHT`.
1051+
>>> from tcod import libtcodpy
1052+
>>> console = tcod.console.Console(20, 1)
1053+
>>> console.clear(ch=ord('·'))
1054+
>>> console.print(x=0, y=0, text="left")
1055+
1
1056+
>>> console.print(x=console.width, y=0, text="right", alignment=libtcodpy.RIGHT)
1057+
1
1058+
>>> console.print(x=10, y=0, text="center", alignment=libtcodpy.CENTER)
1059+
1
1060+
>>> print(console)
1061+
<left···center··right>
1062+
1063+
>>> console = tcod.console.Console(20, 4)
1064+
>>> console.clear(ch=ord('·'))
1065+
>>> console.print(x=1, y=1, text="words within bounds", width=8)
1066+
3
1067+
>>> print(console)
1068+
<····················
1069+
·words··············
1070+
·within·············
1071+
·bounds·············>
1072+
>>> WHITE = (255, 255, 255)
1073+
>>> BLACK = (0, 0, 0)
1074+
>>> console.print(x=0, y=0, text="Black text on white background", fg=BLACK, bg=WHITE)
1075+
1
10031076
10041077
.. versionadded:: 8.5
10051078
10061079
.. versionchanged:: 9.0
1080+
10071081
`fg` and `bg` now default to `None` instead of white-on-black.
10081082
10091083
.. versionchanged:: 13.0
1084+
10101085
`x` and `y` are now always used as an absolute position for negative values.
1086+
1087+
.. versionchanged:: Unreleased
1088+
1089+
Added `text` parameter to replace `string`.
1090+
1091+
Added `width` and `height` keyword parameters to bind text to a rectangle and replace other print functions.
1092+
Right-aligned text with `width=None` now treats the `x` coordinate as a past-the-end index, this will shift
1093+
the text of older calls to the left by 1 tile.
1094+
1095+
Now returns the number of lines printed via word wrapping.
10111096
"""
1012-
string_ = string.encode("utf-8")
1013-
lib.TCOD_console_printn(
1014-
self.console_c,
1015-
x,
1016-
y,
1017-
len(string_),
1018-
string_,
1019-
(fg,) if fg is not None else ffi.NULL,
1020-
(bg,) if bg is not None else ffi.NULL,
1021-
bg_blend,
1022-
alignment,
1097+
if width is not None and width <= 0:
1098+
return 0
1099+
if width is None and alignment == tcod.constants.LEFT: # Fix alignment
1100+
width = 0x100000
1101+
if width is None and alignment == tcod.constants.CENTER: # Fix center alignment
1102+
x -= 0x100000
1103+
width = 0x200000
1104+
if width is None and alignment == tcod.constants.RIGHT: # Fix right alignment
1105+
x -= 0x100000
1106+
width = 0x100000
1107+
rgb_fg = ffi.new("TCOD_ColorRGB*", fg) if fg is not None else ffi.NULL
1108+
rgb_bg = ffi.new("TCOD_ColorRGB*", bg) if bg is not None else ffi.NULL
1109+
utf8 = (string or text).encode("utf-8")
1110+
return _check(
1111+
int(
1112+
lib.TCOD_printn_rgb(
1113+
self.console_c,
1114+
{
1115+
"x": x,
1116+
"y": y,
1117+
"width": width or 0,
1118+
"height": height or 0,
1119+
"fg": rgb_fg,
1120+
"bg": rgb_bg,
1121+
"flag": bg_blend,
1122+
"alignment": alignment,
1123+
},
1124+
len(utf8),
1125+
utf8,
1126+
)
1127+
)
10231128
)
10241129

1130+
@deprecated("Switch to using keywords and then replace with 'console.print(...)'")
10251131
def print_box( # noqa: PLR0913
10261132
self,
10271133
x: int,
@@ -1144,9 +1250,9 @@ def draw_frame( # noqa: PLR0913
11441250
>>> console.draw_frame(x=6, y=0, width=3, height=3, decoration="123456789")
11451251
>>> console.draw_frame(x=9, y=0, width=3, height=3, decoration="/-\\| |\\-/")
11461252
>>> console.draw_frame(x=0, y=3, width=12, height=3)
1147-
>>> console.print_box(x=0, y=3, width=12, height=1, string=" Title ", alignment=libtcodpy.CENTER)
1253+
>>> console.print(x=0, y=3, width=12, height=1, string=" Title ", alignment=libtcodpy.CENTER)
11481254
1
1149-
>>> console.print_box(x=0, y=5, width=12, height=1, string="┤Lower├", alignment=libtcodpy.CENTER)
1255+
>>> console.print(x=0, y=5, width=12, height=1, string="┤Lower├", alignment=libtcodpy.CENTER)
11501256
1
11511257
>>> print(console)
11521258
<┌─┐╔═╗123/-\

tests/test_console.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,10 @@ def test_console_defaults() -> None:
7070
def test_console_methods() -> None:
7171
console = tcod.console.Console(width=12, height=10)
7272
console.put_char(0, 0, ord("@"))
73-
console.print_(0, 0, "Test")
74-
console.print_rect(0, 0, 2, 8, "a b c d e f")
73+
with pytest.deprecated_call():
74+
console.print_(0, 0, "Test")
75+
with pytest.deprecated_call():
76+
console.print_rect(0, 0, 2, 8, "a b c d e f")
7577
console.get_height_rect(0, 0, 2, 8, "a b c d e f")
7678
with pytest.deprecated_call():
7779
console.rect(0, 0, 2, 2, True)

0 commit comments

Comments
 (0)