katom types from ref/ in groups, @table :leading in lines of text and :rulesep, @code under txt, one table style attribute, literal-klammer options (from dev 2e453744f5e9)

kdesc --katoms is Klammertext rendered from ref/, the types in titled groups,
with --katoms full for the regex column.  @table :leading L is L lines of the
surrounding text in html as in pdf (default 1), and :rulesep spaces the
horizontal rules.  The html table has one style attribute, so :column_width
fractions take effect again.  @code and @source_listing render in plain
text; captions are numbered per kind there, and a table needs no blank line
around it.  @c takes :nd, and an option-shaped word before a bar inside
literal code is code.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
ackandClaude Fable 5.1 committed 2026-09-21 22:37:13 +02:00
1 parent 63956c00e5
commit 217c0f3fc5
23 files changed
+625 -290

No files matched your search

+99
View File
@@ -5,6 +5,7 @@
#include "error.h"
#include "show.h"
#include "font_store.h"
#include "ktype.h"
// extern "C" is needed for dlsym name lookup. Returning std::string from
// C-linkage functions is technically non-standard but works correctly on
@@ -191,3 +192,101 @@ std::string argtype_definitions(Machine& machine)
kt << "define@\n\n";
return kt.str();
}
// The Regex cell of a katom type. A type the Machine assigns is matched by
// no regex and its cell is empty -- ws_added among them, whose m_pattern is a
// description and not a regex (see the note in mac/katom_matching.cpp). The
// two whitespace types are named, since "@c c@" would show nothing.
static std::string katom_regex_cell(const Ktype& k)
{
if (k.m_pattern.empty() || k.m_type == katom_t::ws_added) {
return "";
}
if (k.m_type == katom_t::space) {
return "@symb-space";
}
if (k.m_type == katom_t::newline) {
return "@t \\n @";
}
// A literal value has its caret forms processed as it is built, so a
// caret is written quoted: bare, "[^^@#|]+" would display as "[^@#|]+"
// and "[@|#^:*]" would lose its caret to the colon.
// The exception is a caret before an apostrophe: "^'" is not a quoting
// form (it opens a literal span elsewhere) and passes through as written.
std::string quoted {};
for (size_t i = 0; i < k.m_pattern.size(); i++) {
const char c = k.m_pattern[i];
const bool before_apostrophe = i + 1 < k.m_pattern.size() && k.m_pattern[i + 1] == '\'';
quoted += (c == '^' && !before_apostrophe) ? "^^" : std::string(1, c);
}
return "@c :nd | " + quoted + " c@";
}
extern "C"
std::string katom_descriptions([[maybe_unused]] Machine& machine)
{
std::stringstream kt {};
kt << R"(
A ``katom'' is an individual element in the Klammertext input text. Each katom
has a type, listed below. You can see how Klammertext divides up text into
katoms with the @t-kdiag command.
In the katom patterns, @symb-name is a word that begins with a letter and only
contains letters, numbers, or the underscore (_) or period (.) characters. The
@symb-n symbol is an integer greater than or equal to 1. The @symb-code symbol
is one of the codes used with the @t ^^ @ character to create characters that
are not available in the English alphabet. The codes for producing those
characters can be displayed by the @t-kdesc command: @t kdesc -c -u @
)";
// ":txt_width N" widens the TABLE alone. This text is re-read by a
// Machine of its own (Eval::eval), so a @@@state here changes the width
// the @table below is laid out to and nothing else: the prose above
// leaves that Machine as plain text and is filled to the caller's width
// by the caller's phases, which skip the table because it is laid out.
const std::string txt_width = machine.m_state.value("txt_width", false);
if (!txt_width.empty()) {
kt << "@@@state Target_txt_width :replace " << txt_width << " @@@\n";
}
const bool show_regex = machine.m_state.value("regex", false) == "true";
// The rows first, so that the rules can be placed by the number of rows
// before them (the header is the first): one above each group's title
// and one below it, which is what marks the row as a title. The first
// group needs none above: "head" already rules the header off.
const std::string b = " | ";
const std::string title_cells = show_regex ? b + b + b + b : b + b + b;
std::stringstream rows {};
std::stringstream hlines {};
int row_count = 1;
for (const auto& group : katom_type_groups) {
if (row_count > 1) {
hlines << " " << row_count;
}
rows << title_cells << "@i " << group.m_title << " @ ||\n";
row_count++;
hlines << " " << row_count; // ... and one below the title
for (const auto& type : group.m_types) {
const Ktype& k = type_to_katom_instance(type.m_type);
rows << static_cast<int>(k.m_type) << b << k.m_name << b << type.m_pattern << b;
if (show_regex) {
rows << katom_regex_cell(k) << b;
}
rows << type.m_description << " ||\n";
row_count++;
}
}
kt << "@table "
<< ":number false "
<< ":hline head bottom" << hlines.str() << " :leading .95 ";
if (show_regex) {
kt << ":cell_hpos c l :style r r t t r :column_width fit fit fit fit fill |\n"
<< "Index | Name | Pattern | Regex | Description ||\n";
} else {
kt << ":cell_hpos c l :style r r t r :column_width fit fit fit fill |\n"
<< "Index | Name | Pattern | Description ||\n";
}
kt << rows.str() << "table@\n";
return kt.str();
}