Width and height argtypes, kdesc --argtypes from ref/, txt @define/@left_right/@columns, kdiag --check value validation (from dev d6993110e9b3)

Also: the klammertext argtype (descriptions kept as source), txt table
wrapping and :hpos/:offset, @c between ‹ ›, txt section headings, the
ktext newline-only trim, capitalize(), and the argtype test suite.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
ackandClaude Fable 5.1 committed 2026-09-16 16:59:49 +02:00
1 parent 9b0d0d7897
commit 0ead40f272
39 files changed
+734 -158

No files matched your search

+49 -4
View File
@@ -112,10 +112,27 @@ def _rest_split_level(s, dimensions):
def rest_args(s, dimensions=1):
return rest_split(s, dimensions)
def parse_length(target, s, rel_fraction):
def choose(html_value, tex_value):
def parse_length(target, s, rel_fraction=1, axis="width"):
"""A length argument as the target's own length.
Returns (text, number, unit). `axis` is "width" or "height" and gives
a BARE number its meaning -- characters or lines, the natural unit of
the axis in every target (sks/kutil/kutil.k, the width and height
argtypes): under txt the integer count itself; under html "ch" and
"lh" (a consumer of "lh" writes the em fallback first, see
css_height); under tex the width of a digit in the current font
(\\fontcharwd) and \\baselineskip. `target` "txt" is accepted for the
bare units only, since plain text has no other.
"""
def choose(html_value, tex_value, txt_value=None):
if target == "txt" or target == "ansi":
if txt_value is None:
unit = "characters" if axis == "width" else "lines"
raise Exception(f'The {axis} "{s}" has no meaning in plain text: '
f'give a bare number of {unit}')
return txt_value
return html_value if target == "html" else tex_value
pat = re.compile(r'(?:([0-9.]+)([a-z]+))|(none|f)|(?:"([^"]+)")')
pat = re.compile(r'(?:([0-9.]+)([a-z]*))|(none|f)|(?:"([^"]+)")')
#pat = re.compile(r'(?:([0-9.]+)([a-z]+))|(none|f)|(?:{([^}]+)})')
@@ -138,6 +155,14 @@ def parse_length(target, s, rel_fraction):
result = choose("", f"\\textwidth - \\widthof{{ {text[1:]}}}")
else:
result = choose("", f"\\widthof{{ {text}}}")
elif units == "":
# The natural unit of the axis.
if axis == "height":
result = choose(f"{num}lh", f"{num}\\baselineskip", str(round(num)))
units = "lines"
else:
result = choose(f"{num}ch", f"{num}\\fontcharwd\\font`0 ", str(round(num)))
units = "ch"
elif units == "w":
result = choose(f"{100 * num}vw", f"{num}\\textwidth")
elif units == "h":
@@ -149,11 +174,31 @@ def parse_length(target, s, rel_fraction):
elif units == "px":
result = choose(f"{round(num)}", f"{num}px")
else:
result = f"{num}{units}"
# em, pt: the same text in html and tex; none in plain text.
result = choose(f"{num}{units}", f"{num}{units}")
result = re.sub("\t", "\\t", result)
return result, num, units
def parse_width(target, s, rel_fraction=1):
return parse_length(target, s, rel_fraction, "width")
def parse_height(target, s, rel_fraction=1):
return parse_length(target, s, rel_fraction, "height")
def css_height(prop, value):
"""A CSS declaration for a height from parse_height's html text. The
"lh" unit is recent (2023 in every major browser); an older browser
ignores a declaration it cannot parse and keeps the previous one, so
the em equivalent is written FIRST and lh second -- the standard
fallback idiom, no detection needed."""
if value.endswith("lh"):
# A short decimal, not the float's full expansion (1.5 * 1.2 is
# 1.7999999999999998 in binary).
em = f"{float(value[:-2]) * 1.2:.4g}"
return f"{prop}: {em}em; {prop}: {value}"
return f"{prop}: {value}"
def old_parse_length(target, s):
pat = re.compile(r'(?:([0-9.]+)([a-z]+))|(none|f)|("([^"]+)")')
match = pat.match(s)