Typed arguments, calculated tables, spans, closed-world fonts, top-level fnt/ and env/
Sync with klammertext-dev through b90b0e09: - Argument types end to end: :python_cast values are applied (Python @eval receives real bools/numbers/lists), argument values are validated against their argtype patterns with the argtype's description as the error message, argtypes can declare :default (overridable per declaration), and parameterized type families are supported: rest(N) casts a rest argument to an N-dimensional list (bar-count = dimension). - Unified indexed_range syntax (selector with parenthesized subsets, composable mnemonic names) for table lines and spans. - Table klammer: caption fonts fixed in both targets, :column_width / :leading / :colsep wired, :colspan and :rowspan render (HTML attributes; \multicolumn / \multirow), calculated cell values (:calc) with prefix operators, display-precision semantics, :calc_format and :decimal period|comma. - Fonts: closed-world resolution on the Klammertext font store (infrastructure in mac/font_store; no Google Fonts links or fetch). Default fonts live in the top-level fnt/; additional fonts install into KLAMMERTEXT_FONTS directories via kdesc --font (list, samples, preview, install — classification by font metadata). CSS font family names are quoted (digit-initial families were silently lost). - Environment files moved from mac/env/ to the top-level env/; shell profiles source env/runtime.env. Dead per-host variants removed. - Container: fnt/ ships in the image; curl removed (no network use).
This commit is contained in:
@@ -7,12 +7,13 @@
|
||||
#include "util.h"
|
||||
|
||||
Argtype::Argtype(std::string name, std::string desc, std::string symbolic_pattern, std::string pattern,
|
||||
std::string python_cast, modify_string_f python_format,
|
||||
std::string default_value, std::string python_cast, modify_string_f python_format,
|
||||
const Locator& loc)
|
||||
: m_name(name)
|
||||
, m_desc(desc)
|
||||
, m_symbolic_pattern(symbolic_pattern)
|
||||
, m_pattern(pattern)
|
||||
, m_default(default_value)
|
||||
, m_python_cast(python_cast)
|
||||
, m_python_format(python_format)
|
||||
, m_regex(std::regex(pattern))
|
||||
@@ -20,22 +21,25 @@ Argtype::Argtype(std::string name, std::string desc, std::string symbolic_patter
|
||||
{
|
||||
}
|
||||
|
||||
static bool empty_value(const strings_t& v)
|
||||
{
|
||||
return v.empty() || (v.size() == 1 && v[0].empty());
|
||||
}
|
||||
|
||||
std::string pyformat_string(const strings_t& v)
|
||||
{
|
||||
std::string p = v[0];
|
||||
std::string delim = "\"";
|
||||
if (contains(p, "\"\"\"")) {
|
||||
delim = "'''";
|
||||
} else if (contains(p, "'''")) {
|
||||
delim = "\"\"\"";
|
||||
} else if (contains(p, "\"")) {
|
||||
delim = "'";
|
||||
}
|
||||
return delim + p + delim;
|
||||
std::string p = v.empty() ? "" : v[0];
|
||||
p = string_replace(p, "\\", "\\\\");
|
||||
p = string_replace(p, "\"", "\\\"");
|
||||
p = string_replace(p, "\n", "\\n");
|
||||
return "\"" + p + "\"";
|
||||
}
|
||||
|
||||
std::string pyformat_bool(const strings_t& v)
|
||||
{
|
||||
if (empty_value(v)) {
|
||||
return "None";
|
||||
}
|
||||
std::string value = v[0];
|
||||
std::set<std::string> true_values { "1", "true", "True", "yes" };
|
||||
std::set<std::string> false_values { "0", "false", "False", "no" };
|
||||
@@ -50,6 +54,9 @@ std::string pyformat_bool(const strings_t& v)
|
||||
|
||||
std::string pyformat_number(const strings_t& value)
|
||||
{
|
||||
if (empty_value(value)) {
|
||||
return "None";
|
||||
}
|
||||
return value[0];
|
||||
}
|
||||
|
||||
@@ -62,12 +69,29 @@ std::string pylist(strings_t words)
|
||||
|
||||
std::string pyformat_list(const strings_t& value)
|
||||
{
|
||||
return pylist(value);
|
||||
strings_t words {};
|
||||
for (const std::string& v : value) {
|
||||
for (const std::string& word : word_split(v)) {
|
||||
if (!word.empty()) {
|
||||
words.push_back(word);
|
||||
}
|
||||
}
|
||||
}
|
||||
return pylist(words);
|
||||
}
|
||||
|
||||
std::string pyformat_dlist(const strings_t& value)
|
||||
{
|
||||
return pylist(value);
|
||||
strings_t items {};
|
||||
for (const std::string& v : value) {
|
||||
if (v.empty()) {
|
||||
continue;
|
||||
}
|
||||
for (const std::string& item : dlist_split(v)) {
|
||||
items.push_back(item);
|
||||
}
|
||||
}
|
||||
return pylist(items);
|
||||
}
|
||||
|
||||
std::string Argtype::python_value(const std::string& var_name, std::vector<std::string> value, size_t name_size)
|
||||
@@ -76,7 +100,18 @@ std::string Argtype::python_value(const std::string& var_name, std::vector<std::
|
||||
ss << " " << std::left << std::setw(name_size) << var_name << " = ";
|
||||
if (m_python_format) {
|
||||
ss << m_python_format(value);
|
||||
} else if (m_python_cast.empty() || m_python_cast == "str") {
|
||||
// String-family types (and untyped variables): plain quoted string.
|
||||
ss << pyformat_string(value);
|
||||
} else if (!m_parameter.empty()) {
|
||||
// Parameterized type: bind the type parameter as N around the
|
||||
// cast, e.g. (lambda N: <cast>)(2)("A | B || C | D").
|
||||
ss << "(lambda N: " << m_python_cast << ")(" << m_parameter << ")("
|
||||
<< pyformat_string(value) << ")";
|
||||
} else {
|
||||
// User-defined :python_cast expression, applied to the raw value.
|
||||
// The cast is applied to an empty value too, so e.g. a split lambda
|
||||
// yields [] for an unsupplied argument.
|
||||
ss << m_python_cast << "(" << pyformat_string(value) << ")";
|
||||
}
|
||||
return ss.str();
|
||||
|
||||
Reference in New Issue
Block a user