Klammerset: the @@@klammerset construct, its search path, and const correctness

The @@@klammerset system command formally declares a klammerset — a
named, logically related group of klammer definitions — with an
operative, idempotent declaration (:requires and :files load in order
at the declaration point, relative to the declaring file). A bare
symbol given to ktext -k, kdesc --input, or :requires resolves to
x/x.k on the search path: the document's directory, then
KLAMMERTEXT_KLAMMERSETS, then KLAMMERTEXT_HOME; kdesc --klammerset
lists the available sets. sks/sks.k is the first declared klammerset,
so `-k sks` loads the SKS by name. The engine's lookup classes were
renamed *_set → *_registry to keep the two concepts apart, and the
whole C++ tree now follows standard const-correctness conventions.
tst/ gains klammerset_test.sh (18 cases).

(from dev 64b1abf23e56)
This commit is contained in:
2026-07-30 23:50:07 +02:00
parent c42981f7e2
commit ef77f03584
83 changed files with 1429 additions and 594 deletions

View File

@@ -5,7 +5,8 @@
#include "font_store.h"
#include "ktype.h"
#include "log.h"
#include "argtype_set.h"
#include "argtype_registry.h"
#include "klammerset_registry.h"
#include "character.h"
#include "show.h"
#include "util.h"
@@ -32,6 +33,37 @@ static void font_usage()
"and then in the default font set.\n";
}
static void klammerset_usage()
{
std::cout <<
"Klammerset commands:\n"
" --klammerset List the klammersets on the search path\n"
" --klammerset list The same\n"
" --klammerset help This description\n"
"\n"
"A klammerset symbol x names the declaration file x/x.k, searched for in:\n"
"the current directory (for ktext, the input document's directory), the\n"
"KLAMMERTEXT_KLAMMERSETS directories (colon-separated; default\n"
"$HOME/.klammertext/klammersets), and $KLAMMERTEXT_HOME. The first hit\n"
"wins, so a document-local klammerset shadows an installed one, which\n"
"shadows a distributed one.\n";
}
static void klammerset_command(const strings_t& words)
{
std::string verb = words.empty() ? "list" : words[0];
if (verb == "list") {
std::cout << boldblack << "Klammersets\n" << black
<< describe_klammerset_search(fs::current_path().string());
} else if (verb == "help") {
klammerset_usage();
} else {
std::cout << "Unrecognized klammerset command: --klammerset "
<< join(words, " ") << "\n\n";
klammerset_usage();
}
}
static void font_command(const strings_t& words)
{
std::string verb = words.empty() ? "list" : words[0];
@@ -70,13 +102,14 @@ int main(int argc, char* argv[])
args.flag("targets", "Show targets defined by the input file");
args.flag("klammers", "Show klammers defined by the input file");
args.var("font", "List installed fonts. Enter \"--font help\" for font maintenance commands.");
args.var("klammerset", "List the klammersets on the search path. Enter \"--klammerset help\" for details.");
args.opt("v", "'verbosity'", "n", "0", "'verbosity'");
if (show_usage(argc, argv)) {
args.usage(file_basename(argv[0]));
exit(1);
}
auto p = [&](std::string name) { return args.get(name) == "true"; };
auto p = [&](const std::string& name) { return args.get(name) == "true"; };
args.parse(argc, argv);
verbose_level = stoi(args.get("v"));
@@ -90,7 +123,7 @@ int main(int argc, char* argv[])
}
if (p("a")) {
Argtype_set argtypes;
Argtype_registry argtypes;
std::cout << boldblack << "\nStandard klammer argument types\n" << black;
std::cout << argtypes.describe() << "\n";
}
@@ -116,6 +149,19 @@ int main(int argc, char* argv[])
return 0;
}
// The --klammerset subcommands operate on the search path
// (filesystem enumeration) and load no klammer set.
if (args.given("klammerset")) {
strings_t words {};
for (const std::string& w : args.as_vector("klammerset")) {
if (!w.empty()) {
words.push_back(w);
}
}
klammerset_command(words);
return 0;
}
Machine M;
strings_t input_filenames = resolve_filename_list(args.get("input"));
@@ -124,6 +170,13 @@ int main(int argc, char* argv[])
M.read(fs::path(M.m_state.value("KLAMMERTEXT_HOME") + "/sks/sks.k"));
} else {
for (auto fname : input_filenames) {
if (is_klammerset_symbol(fname)) {
// A bare symbol resolves on the klammerset search
// path; kdesc has no input document, so the local
// stage is the cwd.
fname = resolve_klammerset_symbol(
fname, fs::current_path().string(), Locator()).string();
}
std::cout << "Read " << fname << "\n";
M.read(fs::path(absolute_pathname(fname)));
}

View File

@@ -45,7 +45,7 @@ int main(int argc, char* argv[])
args.usage(file_basename(argv[0]));
exit(1);
}
auto p = [&](std::string name) { return args.get(name) == "true"; };
auto p = [&](const std::string& name) { return args.get(name) == "true"; };
args.parse(argc, argv);
verbose_level = args.as_int("v");

View File

@@ -7,7 +7,8 @@
#include "util.h"
#include "machine.h"
#include "show.h"
#include "target_set.h"
#include "target_registry.h"
#include "klammerset_registry.h"
int main(int argc, char* argv[])
{
@@ -17,10 +18,10 @@ int main(int argc, char* argv[])
args.req("filenames", "Input files in Klammertext format. ", "'list'");
args.opt("s", "Text processed before input files.", "input-string", "", "'text'");
args.opt("t","Output target; default is general (unspecified)", "target",
Target_set::general_name, "'word'");
Target_registry::general_name, "'word'");
args.opt("o", "Output basename; meaning and default defined by target.", "basename",
"", "'word'");
args.opt("k", "File containing the klammerset definition; default is the Standard Klammer Set. With a value of \"none\", no klammerset is loaded.",
args.opt("k", "Klammerset symbol (resolved on the klammerset search path) or the pathname of a klammerset definition file; default is the Standard Klammer Set. With a value of \"none\", no klammerset is loaded.",
"pathname", "", "'word'");
args.flag("d", "Display the output to the screen, rather than writing files.");
args.flag("m", "Show the Klammermachine state at the beginning of processing.");
@@ -83,6 +84,12 @@ int main(int argc, char* argv[])
if (klammerset_filename != "none") {
if (klammerset_filename.empty()) {
klammerset_filename = M.m_state.value("KLAMMERTEXT_HOME") + "/sks/sks.k";
} else if (is_klammerset_symbol(klammerset_filename)) {
// A bare symbol resolves on the klammerset search path;
// the local stage is the input document's directory (the
// cwd when the input is a string).
klammerset_filename = resolve_klammerset_symbol(
klammerset_filename, M.m_state.value("K_input_dir"), Locator()).string();
}
K::log(1, "Reading klammerset filename: " + klammerset_filename);
M.read(fs::path(klammerset_filename));