Images in plain text and the terminal; bounded build parallelism (from dev 16f82cc887af)
- @image under txt and ansi is a picture in characters, in five styles (Image_txt_style: halfblock the default, shade, ascii, quadrant, braille), sized to the terminal's width less a margin when ktext runs in one, every cell in its own colours under ansi; a figure's caption is centred under it and no txt caption is ruled off any more. - The build compiles as many files at once as the machine has cores (JOBS; make -C com JOBS=1 for a small machine): the sub-makes' bare -j meant unlimited parallelism and exhausted 8 GB machines. The three install pages say "make -C com". Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
d14da90bbf
commit
ed7bedf5a7
13 files changed
+335
-41
No files matched your search
+37
-6
@@ -75,20 +75,43 @@ _STYLE_MARKER_RGX = re.compile(
|
||||
"|".join(re.escape(txt_style_marker(s, on))
|
||||
for s in TXT_STYLES for on in (True, False)))
|
||||
|
||||
# A COLOUR marker carries its colour: __KTEXTFG<rrggbb>__ opens a foreground
|
||||
# colour, __KTEXTFGOFF__ restores the default (SGR 39, never a blanket reset).
|
||||
# Used by @image under txt/ansi (2026-09-27, Andy's terminal images): the
|
||||
# character carries the luminance and the colour the hue, so stripping the
|
||||
# escapes still leaves a monochrome picture -- the invariant kept.
|
||||
def txt_color_marker(rgb=None, background=False):
|
||||
"""A foreground colour marker, or with background=True a background one
|
||||
(__KTEXTBG<rrggbb>__ / __KTEXTBGOFF__, SGR 48;2 and 49): the quadrant
|
||||
and halfblock image styles set two colours per cell."""
|
||||
ground = "BG" if background else "FG"
|
||||
if rgb is None:
|
||||
return f"__KTEXT{ground}OFF__"
|
||||
r, g, b = rgb
|
||||
return f"__KTEXT{ground}{int(r):02X}{int(g):02X}{int(b):02X}__"
|
||||
|
||||
_COLOR_MARKER_RGX = re.compile(r"__KTEXT(FG|BG)(?:([0-9A-F]{6})|OFF)__")
|
||||
|
||||
def txt_strip_styles(text, K):
|
||||
return _STYLE_MARKER_RGX.sub("", text)
|
||||
return _COLOR_MARKER_RGX.sub("", _STYLE_MARKER_RGX.sub("", text))
|
||||
|
||||
def ansi_resolve_styles(text, K):
|
||||
for style, (on, off) in TXT_STYLES.items():
|
||||
text = text.replace(txt_style_marker(style), on)
|
||||
text = text.replace(txt_style_marker(style, False), off)
|
||||
return text
|
||||
def color(m):
|
||||
ground, hex6 = m.group(1), m.group(2)
|
||||
code = 38 if ground == "FG" else 48
|
||||
if hex6 is None:
|
||||
return f"\033[{code + 1}m" # 39 / 49: the default fore-/background
|
||||
return f"\033[{code};2;{int(hex6[0:2], 16)};{int(hex6[2:4], 16)};{int(hex6[4:6], 16)}m"
|
||||
return _COLOR_MARKER_RGX.sub(color, text)
|
||||
|
||||
def txt_visible_length(s):
|
||||
"""How many columns s occupies once its markers resolve: a KTESC
|
||||
marker is one glyph, an nbsp marker one space, a style marker nothing.
|
||||
len() is the wrong measure for anything laid out (see txt_util)."""
|
||||
s = _STYLE_MARKER_RGX.sub("", s).replace(txt_verbatim_marker(), "")
|
||||
s = _COLOR_MARKER_RGX.sub("", _STYLE_MARKER_RGX.sub("", s)).replace(txt_verbatim_marker(), "")
|
||||
return len(klammer_base.unescape_ktesc(s).replace(txt_nbsp_marker(), " "))
|
||||
|
||||
def txt_wrap(text, width, subsequent_indent=""):
|
||||
@@ -257,6 +280,10 @@ def txt_insert_captions(text, K):
|
||||
return widest
|
||||
def replace(m):
|
||||
indent_run, name, text = m.groups()
|
||||
# The name may carry flags after "+": "center" sets the caption
|
||||
# centred on its block (a figure's, as in html and tex).
|
||||
name, _, flags = name.partition("+")
|
||||
centered = "center" in flags.split("+")
|
||||
indent = len(indent_run) // len(nbsp)
|
||||
indented_width = max(1, width - indent)
|
||||
# The block the caption belongs to: below a top caption, above a
|
||||
@@ -278,12 +305,16 @@ def txt_insert_captions(text, K):
|
||||
else:
|
||||
caption = text
|
||||
# Visible widths throughout: a caption may carry style markers.
|
||||
# NO RULE under (or over) a caption: none of the targets draws one
|
||||
# (Andy, 2026-09-28 -- the rule this pass drew since 2026-08 was a
|
||||
# txt invention; a table's rules are its own :hline, a listing's its
|
||||
# own frame). A centred caption is set on the block's width.
|
||||
lines = [caption]
|
||||
if txt_visible_length(caption) > indented_width:
|
||||
lines = txt_wrap(caption, indented_width)
|
||||
line_length = max(txt_visible_length(e) for e in lines)
|
||||
line_length = max(line_length, block - indent)
|
||||
lines.append("-" * line_length)
|
||||
if centered:
|
||||
measure = max(block - indent, max(txt_visible_length(e) for e in lines))
|
||||
lines = [" " * max(0, (measure - txt_visible_length(e)) // 2) + e for e in lines]
|
||||
lead = txt_verbatim_marker() + indent_run
|
||||
# The first line's marker is already in the text, before the indent
|
||||
# run this match begins with (add_caption); the others get theirs.
|
||||
|
||||
Reference in new issue
Block a user