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

63
mac/klammerset_registry.h Normal file
View File

@@ -0,0 +1,63 @@
#pragma once
#include <map>
#include <optional>
#include <string>
#include "klammerset.h"
#include "argument_set.h"
#include "katom.h"
class Klammerset_registry
{
public:
Klammerset_registry();
void add(Klammerset klammerset);
// Parse a @@@klammerset span. Returns the new Klammerset so the
// Machine can load its files, or nullopt when the symbol is already
// registered: a klammerset is loaded once, and a repeated declaration
// (typically reached through :requires) is skipped, not an error.
std::optional<Klammerset> add(std::vector<Katom>::iterator begin, std::vector<Katom>::iterator end, std::vector<Katom>& katoms);
void check_symbol(const std::string& symbol, const Locator& loc) const;
bool has(const std::string& symbol) const;
Klammerset get(const std::string& symbol, const Locator& loc) const;
std::string describe(int margin=2, bool long_format=false) const;
std::map<std::string, Klammerset> m_klammersets {};
std::vector<std::string> m_symbols {};
Parameter_set m_parameters {};
};
// --- The klammerset search path (symbol -> declaration file) ---
// A bare identifier (letters, digits, underscores; starts with a letter)
// names a klammerset symbol; anything else -- a path component, an
// extension, a space -- is a filename used as given.
bool is_klammerset_symbol(const std::string& name);
// The directories searched for a klammerset symbol, most specific first:
// 1. local_dir -- the directory of whatever names the symbol: the input
// document's directory (ktext -k), the declaring file's directory
// (:requires), or the cwd when there is no document
// 2. the KLAMMERTEXT_KLAMMERSETS directories (colon-separated; default
// ~/.klammertext/klammersets), in listed order
// 3. $KLAMMERTEXT_HOME (the distribution's sets, e.g. sks/sks.k)
// A symbol x resolves to the first <dir>/x/x.k found, so a document-local
// set shadows an installed one, which shadows a distributed one. (This is
// deliberately the OPPOSITE order from the @eval module path, which puts
// the SKS directories first: a stray util.py next to a document shadowing
// an SKS module is an everyday accident, while a directory named sks/
// holding an sks.k next to a manuscript is not.)
std::vector<std::string> klammerset_search_dirs(const std::string& local_dir);
// Resolve a symbol to its declaration file; first hit wins. Throws a
// Klammerset_error naming the searched directories when nothing matches.
fs::path resolve_klammerset_symbol(
const std::string& symbol, const std::string& local_dir, const Locator& loc);
// The symbols available on the search path, with provenance; a symbol
// found again in a later directory is marked as shadowed. For
// kdesc --klammerset.
std::string describe_klammerset_search(const std::string& local_dir, int margin=2);