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

+7
View File
@@ -232,3 +232,10 @@ column.
@@tbl.k spec.figure_id : The caption title for a table @@
@@tbl.html,tex,txt :: @reference *spec* | Table @ @@
#[
@@columns.k rows.rest : A minimal table without a caption, header, or lines @@
@@columns.html,tex,txt ::
@table rows :number false :header false @
@@
]#
+61 -22
View File
@@ -978,32 +978,71 @@ class Table(klammer_base.Klammer_base):
return (phases.txt_style_marker(STYLE[code]) + cell
+ phases.txt_style_marker(STYLE[code], False))
return cell
widths = self.txt_column_widths()
# A cell is one line of text: a newline written inside it is
# whitespace, as it is in html and tex.
rows = [[re.sub(r"\s*\n\s*", " ", cell) for cell in row] for row in self.rows]
widest = self.txt_column_widths()
pos = [hpos(p) for p in self.cell_hpos]
result = ""
indent = txt_util.NBSP * int(self.Target_txt_indent)
colsep = " "
# Horizontal lines are the same rule as the other targets (:hline,
# defaulting to under the header row and at the bottom when the
# table has a header): a rule of hyphens the width of the table at
# each boundary that has a line. A line over part of the columns
# is drawn full width here -- a partial rule in a plain-text table
# reads as an accident. Vertical lines have no plain-text form.
# The hyphens are HIDDEN (KTESC markers): a klammer's result is
# re-read as Klammertext and the txt target's dash transforms turn
# "--" into "-", so a bare run of hyphens came out a fraction of
# its length. (The caption rule escapes this by being drawn in a
# phase, after the transforms.)
rule = (indent + klammer_base.hide_typographic(
# Placement under txt (2026-09-16): an explicit :hpos left takes its
# indent from :offset (characters; 0 = flush), :hpos none flows with
# no indent, and anything else -- including the default, center --
# keeps the block convention, Target_txt_indent. (Centering and
# right-alignment are not attempted: a block that shifts with the
# width of its widest row reads as an accident in plain text.)
if self.hpos == "left":
indent = txt_util.NBSP * int(kutil.parse_width("txt", self.offset)[0])
elif self.hpos == "none":
indent = ""
else:
indent = txt_util.NBSP * int(self.Target_txt_indent)
colsep = " "
# Column widths, by the same rules as the other targets
# (:column_width): 'fit' is the widest entry; a fraction is that part
# of the text width; '*' takes the remaining width; 'fill' takes the
# remaining width but no more than its widest entry -- and, unlike a
# 'fit' column, its cells WRAP to that width (2026-09-13; until then
# the txt table never wrapped a cell, so a description column ran off
# the page). Several fill/'*' columns share the remainder in
# proportion to their widest entries.
text_width = (int(self.Target_txt_width) - int(self.Target_txt_indent)
- len(colsep) * (self.row_size - 1))
specs = extend(self.column_width, self.row_size)
widths = [0] * self.row_size
for i, w in enumerate(specs):
if w in ("fit", "f"):
widths[i] = widest[i]
elif w not in ("fill", "*"):
widths[i] = max(1, int(float(w) * text_width))
flexible = [i for i, w in enumerate(specs) if w in ("fill", "*")]
if flexible:
remaining = max(len(flexible), text_width - sum(widths))
total = sum(max(1, widest[i]) for i in flexible)
for i in flexible:
share = max(1, remaining * max(1, widest[i]) // total)
widths[i] = min(share, widest[i]) if specs[i] == "fill" else share
wrapped = {i for i, w in enumerate(specs) if w not in ("fit", "f")}
mark = phases.txt_verbatim_marker() # each line: already laid out
rule = (mark + indent + klammer_base.hide_typographic(
"-" * (sum(widths) + len(colsep) * (len(widths) - 1))) + "\n")
for row_i, row in enumerate(self.rows):
result = ""
for row_i, row in enumerate(rows):
if row_i in self.s_hline.by_index:
result += rule
result += indent + colsep.join(
[pad(styled(elt, row_i, cell_i), width, align)
for cell_i, (elt, width, align) in enumerate(zip(row, widths, pos))])
result += "\n"
if len(self.rows) in self.s_hline.by_index:
# Each cell becomes its lines: wrapped to the column's width in a
# wrapping column, one line otherwise; the row is as tall as its
# tallest cell, short cells padded with empty lines.
cell_lines = []
for cell_i, (elt, width) in enumerate(zip(row, widths)):
text = styled(elt, row_i, cell_i)
lines = phases.txt_wrap(text, width) if cell_i in wrapped and text else [text]
cell_lines.append(lines or [""])
height = max(len(lines) for lines in cell_lines)
for n in range(height):
result += mark + indent + colsep.join(
[pad(lines[n] if n < len(lines) else "", width, align)
for lines, width, align in zip(cell_lines, widths, pos)])
result += "\n"
if len(rows) in self.s_hline.by_index:
result += rule
result = txt_util.add_caption(
result, "Table", self.number, self.caption, self.caption_side, \