Verbatim-safe typography, ^-punctuation quoting, full-range ^UUUU^, polyglot html

Typographic transforms (---, quote pairs, ~) no longer touch verbatim
text: @c/@code/@source_listing content and ^'...'^ spans show exactly the
characters written. "^" before any punctuation character quotes it in
every target (the apostrophe excepted: ^' opens a literal span), with the
new :resolve option on @@@target declaring per-target renderings. The
^UUUU^ code-point form accepts 4-6 hex digits, the full Unicode range.
The html output and transform spellings are polyglot (XML-valid), in
preparation for an EPUB target. New suites: transform_test, character_test
(engine), typography_test (SKS).

(from dev 07ce5ea86a0a)
This commit is contained in:
2026-08-23 20:48:26 +02:00
parent d982c0d6cc
commit 37b6ba1c4f
77 changed files with 1665 additions and 1608 deletions

View File

@@ -27,7 +27,7 @@ void Option_set_registry::add(
if (deftype.m_initial_type == katom_t::klammer_instance) {
throw Definition_error(
"The option set " + q_(name) + " is declared with \"::\", which takes its "
"parameters from a \".k\" declaration. An option set IS a declaration: "
"parameters from a \".k\" declaration. An option set is a declaration; "
"it declares its parameters itself, after \":\".",
begin->m_loc);
}
@@ -68,16 +68,16 @@ void Option_set_registry::add(
throw Definition_error(
"The option set " + q_(name) + " declares the positional "
+ plural("parameter", static_cast<int>(names.size())) + " "
+ join(names, ", ") + ".\n"
+ join(names, ", ") + ".\n\n"
"An option set declares only optional parameters -- names written with "
"a leading \":\".",
begin->m_loc, false);
begin->m_loc);
}
if (parameters.m_optional.empty()) {
throw Definition_error(
"The option set " + q_(name) + " declares no parameters.\n"
"The option set " + q_(name) + " declares no parameters.\n\n"
"The form is: @@" + name + ".o :name.argtype default ... : <description> @@",
begin->m_loc, false);
begin->m_loc);
}
// The members as written: these katoms are what is spliced into the
@@ -201,14 +201,14 @@ std::string definition_name(const std::string& klammer_name, const std::string&
std::stringstream ss {};
if (option_sets.has(name) && target_name == Target_registry::optionset_name) {
ss << "The option set " << q_(name) << " is used in the declaration of the option "
<< "set " << q_(klammer_name) << ".\n"
<< "set " << q_(klammer_name) << ".\n\n"
<< "An option set is used only in the parameter list of a \".k\" declaration, "
<< "so a set does not include another set: a klammer that needs two "
<< "vocabularies names two sets, and each set stays a vocabulary that can "
<< "be learned whole.";
} else if (option_sets.has(name)) {
ss << "The option set " << q_(name) << " is used in the parameter list of "
<< definition_name(klammer_name, target_name) << ".\n"
<< definition_name(klammer_name, target_name) << ".\n\n"
<< "An option set may be used only in the parameter list of a \".k\" "
<< "declaration, which is where a klammer's interface is declared once "
<< "for all of its targets. Declare "
@@ -216,15 +216,15 @@ std::string definition_name(const std::string& klammer_name, const std::string&
<< "an instance (\"::\"), which inherits the declared parameters.";
} else {
ss << "The klammer " << q_(name) << " is applied in the parameter list of "
<< definition_name(klammer_name, target_name) << ".\n"
<< definition_name(klammer_name, target_name) << ".\n\n"
<< "A klammer application in a parameter list is not allowed: it is "
<< "resolved after the parameters are parsed, so the parameter list it "
<< "was meant to contribute is not there when the list is read. An "
<< "option set, declared with a \".o\" target, is how parameters are "
<< "shared between klammers. Declared option sets: "
<< "shared between klammers.\n\nDeclared option sets: "
<< option_sets.available() << ".";
}
throw Definition_error(ss.str(), loc, false);
throw Definition_error(ss.str(), loc);
}
// The default written for each member at the use site:
@@ -237,10 +237,10 @@ std::map<std::string, std::string> use_site_defaults(
if (!positional.empty() || active(rest)) {
throw Definition_error(
"The use of the option set " + q_(option_set.m_name) +
" gives a value that is not an option.\n"
" gives a value that is not an option.\n\n"
"A set's names and types are fixed where the set is declared; only a "
"default may be given where it is used, written as \":name value\".",
begin->m_loc, false);
begin->m_loc);
}
std::map<std::string, std::string> defaults {};
for (const auto& option : optional) {
@@ -248,17 +248,17 @@ std::map<std::string, std::string> use_site_defaults(
if (name.size() + 1 != option[0].m_text.size()) {
throw Definition_error(
"The use of the option set " + q_(option_set.m_name) + " gives a type for \":"
+ name + "\".\n"
+ name + "\".\n\n"
"A set's names and types are declared where the set is; only a default "
"may be given where it is used.",
option[0].m_loc, false);
option[0].m_loc);
}
const Parameter* member = option_set.find(name);
if (member == nullptr) {
throw Definition_error(
"The option set " + q_(option_set.m_name) + " has no parameter \":"
+ name + "\".\n It declares: " + option_set.member_names(),
option[0].m_loc, false);
+ name + "\". It declares:\n " + option_set.member_names(),
option[0].m_loc);
}
if (defaults.count(name) > 0) {
throw Definition_error(
@@ -297,7 +297,7 @@ option_set_uses_t expand_option_sets(
throw Definition_error(
"The parameter \":" + name + "\" of " + q_(klammer_name) +
" is declared twice:\n " + previous->second + "\n " + from,
loc, false);
loc);
}
origin[name] = from;
};