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
@@ -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
@@ -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, \
|
||||
|
||||
Reference in new issue
Block a user