Files
klammertext/ref/reflect.cpp
T
ackandClaude Fable 5.1 0ead40f272 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>
2026-09-16 16:59:49 +02:00

167 lines
6.5 KiB
C++

#include <set>
#include "machine.h"
#include "character.h"
#include "error.h"
#include "show.h"
// extern "C" is needed for dlsym name lookup. Returning std::string from
// C-linkage functions is technically non-standard but works correctly on
// Linux (Itanium ABI) where C and C++ calling conventions are identical.
#if defined(__clang__)
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
#endif
extern "C"
std::string diacritics_examples([[maybe_unused]] Machine& machine)
{
if (diacritics.size() != diacritic_symbols_order.size()) {
throw Internal_error("Mismatch between diacritics order list and their definitions");
}
//std::cout << machine;
std::stringstream kt {};
kt << "@table :caption Diacritics (with typical base characters) :cell_hpos c c l |\n"
<< "@i-Displayed | @i-Written | @i-Name ||\n";
for (char symbol : diacritic_symbols_order) {
std::string sym { symbol };
auto [code, name] = diacritics[sym];
std::string letter = diacritic_example_letter[sym];
std::string written = "^" + letter + sym;
if (sym == "~") {
written = "^" + letter + "^~";
}
std::string display = "^" + letter + sym;
kt << display << " | @t ^" << written << " @ | " << name << " ||\n";
}
kt << "table@";
return kt.str();
}
extern "C"
std::string extended_latin_examples([[maybe_unused]] Machine& machine)
{
std::stringstream kt {};
kt << "@table :caption Extended Latin characters and ligatures :cell_hpos c c l |\n"
<< "@i-Displayed | @i-Written | @i-Name ||\n";
for (const std::string& symbol : extended_latin_symbols) {
auto [code, name] = extended_latin[symbol];
std::string coded = "^" + symbol + "^";
std::string file_literal = "^^ #- " + symbol + " #- ^^";
kt << coded << " | @t " << file_literal << " @ | " << name << " ||\n";
}
kt << "table@";
return kt.str();
}
extern "C"
std::string pinyin_examples([[maybe_unused]] Machine& machine)
{
std::stringstream kt {};
kt << "@table :caption Mandarin pinyin tones (using vowel ``a'') :cell_hpos c c l |\n"
<< " @i-Displayed | @i-Written | @i-Name ||\n";
for (auto [symbol, codename] : pinyin_tones) {
auto [code, name] = codename;
std::string literal = "^a" + symbol;
kt << literal << " | @t ^" << literal << " @ | " << name << " ||\n";
}
kt << "table@";
return kt.str();
}
extern "C"
std::string unicode_examples([[maybe_unused]] Machine& machine)
{
std::stringstream kt {};
kt << "\n@s2 Including Unicode in Klammertext files @\n\n"
<< "To specify a wide variety of different letter forms, the Unicode Standard "
<< "defines a large set of \"code points\" organized by groups. To include a "
<< "Unicode character in Klammertext, you surround its hexadecimal number with "
<< "the \"^^\" character. For example, the Cyrillic captial letter \"I\" is \"И\", "
<< "included in Klammertext as ^^0418^^.\n\n"
<< "To search for Unicode characters by their description, see: @nl@\n"
<< "@link https://www.fileformat.info/info/unicode/char/search.htm @\n\n";
kt << "@table :caption Examples of Chinese characters :cell_hpos c c l |\n"
<< " Character | Written | Pinyin ||\n";
for (auto chr : dao) {
std::string code = "^" + chr[1] + "^";
kt << process_unicode_codepoint(code) << " | "
<< "^" << code << "^" << " | "
<< chr[0] << " ||\n";
}
kt << "table@\n\n";
kt << "@table :caption Examples of Egyptian hieroglyphs :cell_hpos c c c l |\n"
<< "Hieroglyph | Written | Sound | Gardiner ||\n";
// The body font carries no hieroglyphs, so the glyph names the
// typeface it needs (shipped in fnt/); @document declares and localizes
// it. Under txt @typeface passes the text through unchanged.
for (auto glyph : ptolemy) {
kt << "@typeface noto-sans-egyptian-hieroglyphs :scale 1.5 | "
<< process_unicode_codepoint("^" + glyph[2] + "^") << " @ | "
<< "^^" + glyph[2] + "^^ | "
<< glyph[1] << " | "
<< glyph[0] << " ||\n";
}
kt << "table@\n\n"
<< "\nIn @link https://en.wikipedia.org/wiki/List_of_Egyptian_hieroglyphs @, "
<< "the Unicode codepoint in the second column of the \"List of hieroglyphs\" "
<< "table is the number in the ^^...^^ code used by Klammertext.\n\n";
return kt.str();
}
extern "C"
std::string argtype_definitions(Machine& machine)
{
auto argtypes = machine.m_argtypes;
std::stringstream kt {};
std::set<std::string> custom {};
std::map<std::string, std::vector<std::string>> custom_types {};
kt << "@s2 Types of klammer arguments @\n\n"
<< "@define :style r | \n";
// Hack to make the "Pattern:" label line up vertically;
// there should be a klammer that aligns text at "tab stops".
auto name_width = std::string("klammertext").size() + 1;
for (const auto& name : argtypes.m_names) {
auto argtype = argtypes.m_types.at(name);
auto filename = argtype.m_loc.m_filename;
if (contains(filename, "argtype_registry")) {
std::string fill(name_width - name.size(), '~');
kt << "\n@c " << name << " c@ @t " << fill << " t@ @i Pattern: i@ @c "
<< argtype.m_symbolic_pattern << " c@ |\n"
<< capitalize(trim(argtype.m_desc)) << " ||\n";
} else {
custom.insert(filename);
custom_types[filename].push_back(name);
}
}
kt << "\ndefine@\n\n"
<< "@vspace .5 @\n@s3 Reusing argtype symbols @\n\n"
<< "A previously defined type can be included in the definition of a new type "
<< "by surrounding the name of the existing type in single quotation marks. "
<< "For example, the @c uint c@ type (unsigned integer) is used to define an integer with a "
<< "`+' or `-' character before it.\n\n"
<< "@vspace .5 @\n@s3 Custom argument types @\n\n"
<< "Other argtypes are defined for special purposes for klammers defined in the following files:\n\n";
kt << "@define :style t |\n";
for (auto [filename, types] : custom_types) {
auto type_count = types.size();
int column_count = type_count < 4 ? 1 : int(float(type_count)/3);
// auto count = int(float(types.size()) / 3);
kt << symbolic_klammertext_filename(filename) << " |\n"
<< "@columns :style c :n " << column_count << " | " << join(types, " ") << " @ ||\n\n";
}
kt << "define@\n\n";
return kt.str();
}