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:
1 parent
9b0d0d7897
commit
0ead40f272
39 files changed
+734
-158
No files matched your search
+74
-13
@@ -11,35 +11,56 @@ from html_util import E
|
||||
import color
|
||||
|
||||
class Indent(klammer_base.Klammer_base):
|
||||
"""An indented block (@indent). :left and :right are widths: a bare
|
||||
number is characters in every target (2026-09-16); :right defaults to
|
||||
:left."""
|
||||
def __init__(self, K):
|
||||
super().__init__(K)
|
||||
# Doesn't do anything now:
|
||||
# self.s = kutil.escape(self.s)
|
||||
if self.right < 0:
|
||||
if not self.right:
|
||||
self.right = self.left
|
||||
self.reduce = self.left + self.right
|
||||
|
||||
def html(self):
|
||||
text_align = "justify" if not self.ragged else "left"
|
||||
left = kutil.parse_width("html", self.left)[0]
|
||||
right = kutil.parse_width("html", self.right)[0]
|
||||
return E("div").body(self.s)\
|
||||
.sty("margin", f"0.5rem {self.right}ex 0.5rem {self.left}ex")\
|
||||
.sty("margin", f"0.5rem {right} 0.5rem {left}")\
|
||||
.sty("text-align", text_align)\
|
||||
.str()
|
||||
def tex(self):
|
||||
if self.ragged:
|
||||
self.s = "\\raggedright " + self.s
|
||||
result = rf"\hspace*{{{self.left}ex}}" + latex_util.minipage(
|
||||
self.s, rf"\linewidth - {self.reduce}ex", center=False)
|
||||
left = kutil.parse_width("tex", self.left)[0]
|
||||
right = kutil.parse_width("tex", self.right)[0]
|
||||
result = rf"\hspace*{{{left}}}" + latex_util.minipage(
|
||||
self.s, rf"\linewidth - {left} - {right}", center=False)
|
||||
result = latex_util.block(result)
|
||||
return result
|
||||
|
||||
def txt(self):
|
||||
indent = phases.txt_nbsp_marker() * self.left # a space that survives
|
||||
width = int(self.Target_txt_width) - self.left - self.right + 1 # Off-by one for textwrap
|
||||
result = self.s
|
||||
result = re.sub("KK0022", '"', result)
|
||||
result = indent + f"\n{indent}".join(textwrap.wrap(result, width=width, break_on_hyphens=True))
|
||||
return result
|
||||
left = int(kutil.parse_width("txt", self.left)[0])
|
||||
right = int(kutil.parse_width("txt", self.right)[0])
|
||||
indent = phases.txt_nbsp_marker() * left # a space that survives
|
||||
width = int(self.Target_txt_width) - left - right
|
||||
result = re.sub("KK0022", '"', self.s)
|
||||
return phases.txt_lay_out(indent + f"\n{indent}".join(phases.txt_wrap(result, width)))
|
||||
|
||||
class Hspace(klammer_base.Klammer_base):
|
||||
"""Horizontal space (@hspace): a width, so a bare number is characters
|
||||
in every target."""
|
||||
def __init__(self, K):
|
||||
super().__init__(K)
|
||||
|
||||
def html(self):
|
||||
return f'<span style="display: inline-block; width: {kutil.parse_width("html", self.width)[0]}"></span>'
|
||||
|
||||
def tex(self):
|
||||
return f"\\hspace{{{kutil.parse_width('tex', self.width)[0]}}}"
|
||||
|
||||
def txt(self):
|
||||
# The nbsp marker, not spaces: an @eval result of only whitespace
|
||||
# is trimmed away entirely.
|
||||
return phases.txt_nbsp_marker() * int(kutil.parse_width("txt", self.width)[0])
|
||||
|
||||
|
||||
class Note(klammer_base.Klammer_base):
|
||||
@@ -106,6 +127,26 @@ class Lines(klammer_base.Klammer_base):
|
||||
def txt(self):
|
||||
return self.lines
|
||||
|
||||
class Vspace(klammer_base.Klammer_base):
|
||||
"""Vertical space (@vspace): the first parameter of the height type. A
|
||||
bare number is lines in every target, as it always was here; a unit
|
||||
(2em, 12pt) is now accepted as well, under html and tex."""
|
||||
def __init__(self, K):
|
||||
super().__init__(K)
|
||||
|
||||
def html(self):
|
||||
height = kutil.parse_height("html", self.lines)[0]
|
||||
return f'<div style="{kutil.css_height("height", height)}"></div>'
|
||||
|
||||
def tex(self):
|
||||
return f"\\vspace{{{kutil.parse_height('tex', self.lines)[0]}}}"
|
||||
|
||||
def txt(self):
|
||||
# One marker per line; the justification phase turns them into
|
||||
# blank lines after paragraph normalization (a whitespace-only
|
||||
# @eval result would be trimmed away, hence the markers).
|
||||
return phases.txt_vspace_marker() * int(kutil.parse_height("txt", self.lines)[0])
|
||||
|
||||
class Left_right(klammer_base.Klammer_base):
|
||||
def __init__(self, K):
|
||||
super().__init__(K)
|
||||
@@ -126,3 +167,23 @@ class Left_right(klammer_base.Klammer_base):
|
||||
result += rf"\parbox{{\linewidth}}{{{left} \hfill {right}}}" + " \\\\\n"
|
||||
result = result[:-3]
|
||||
return result
|
||||
|
||||
def txt(self):
|
||||
# Plain text: the left text at the block indent, the right text ending
|
||||
# at Target_txt_width, the gap filled with the nbsp marker (the only
|
||||
# space that survives to the output, and what marks the block as laid
|
||||
# out). A pair that cannot share a line -- less than two columns
|
||||
# between them -- goes on two lines, the right text still flush right.
|
||||
nbsp = phases.txt_nbsp_marker()
|
||||
indent = int(self.Target_txt_indent)
|
||||
width = int(self.Target_txt_width)
|
||||
lines = []
|
||||
for left, right in self.rows:
|
||||
left, right = left.strip(), right.strip()
|
||||
gap = width - indent - phases.txt_visible_length(left) - phases.txt_visible_length(right)
|
||||
if gap >= 2:
|
||||
lines.append(nbsp * indent + left + nbsp * gap + right)
|
||||
else:
|
||||
lines.append(nbsp * indent + left)
|
||||
lines.append(nbsp * max(indent, width - phases.txt_visible_length(right)) + right)
|
||||
return phases.txt_lay_out("\n".join(lines))
|
||||
Reference in new issue
Block a user