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

@@ -8,9 +8,9 @@ include $(K)/env/makefile.env
# Source files
BASENAMES := util error locator file argv character ktype katom katom_list \
log show command argument argument_set argtype argtype_set \
state eval eval_python eval_cpp klammer klammer_set deftype \
target target_set machine font_store
log show command argument argument_set argtype argtype_registry \
state eval eval_python eval_cpp klammer klammer_registry klammerset klammerset_registry deftype \
target target_registry machine font_store
SOURCES := $(addsuffix .cpp,$(BASENAMES))
OBJECTS := $(addsuffix .o,$(BASENAMES))

View File

@@ -6,9 +6,10 @@
#include "error.h"
#include "util.h"
Argtype::Argtype(std::string name, std::string desc, std::string symbolic_pattern, std::string pattern,
std::string default_value, std::string alone_value,
std::string python_cast, modify_string_f python_format,
Argtype::Argtype(const std::string& name, const std::string& desc, const std::string& symbolic_pattern,
const std::string& pattern,
const std::string& default_value, const std::string& alone_value,
const std::string& python_cast, const modify_string_f& python_format,
const Locator& loc)
: m_name(name)
, m_desc(desc)

View File

@@ -25,9 +25,10 @@ public:
, m_loc()
{};
Argtype(std::string name, std::string desc, std::string symbolic_pattern, std::string pattern,
std::string default_value, std::string alone_value,
std::string python_cast, modify_string_f python_format,
Argtype(const std::string& name, const std::string& desc, const std::string& symbolic_pattern,
const std::string& pattern,
const std::string& default_value, const std::string& alone_value,
const std::string& python_cast, const modify_string_f& python_format,
const Locator& loc);
std::string python_value(const std::string& var_name, std::vector<std::string> value, size_t name_size);

View File

@@ -3,7 +3,7 @@
#include <algorithm>
#include <numeric>
#include "argtype_set.h"
#include "argtype_registry.h"
#include "error.h"
#include "show.h"
#include "log.h"
@@ -11,13 +11,13 @@
#include "character.h"
#include "katom.h"
Parameter_set& Argtype_set::parameters()
Parameter_set& Argtype_registry::parameters()
{
static Parameter_set instance("name | desc :pattern .* :python_cast str :default :alone");
return instance;
}
Argtype_set::Argtype_set()
Argtype_registry::Argtype_registry()
{
(void)(void)K::log(2);
Locator loc = current_locator();
@@ -33,7 +33,7 @@ Argtype_set::Argtype_set()
m_types["bool"].m_alone = "true";
}
std::string Argtype_set::replace_symbols(const std::string& pattern, const Locator& loc)
std::string Argtype_registry::replace_symbols(const std::string& pattern, const Locator& loc)
{
std::smatch match {};
std::regex symbol_pat(R"('(\w+)')");
@@ -54,7 +54,7 @@ std::string Argtype_set::replace_symbols(const std::string& pattern, const Locat
return expanded;
}
void Argtype_set::check_for_existing_definition(
void Argtype_registry::check_for_existing_definition(
const std::string& name, const Locator& loc)
{
if (count(m_names.begin(), m_names.end(), name) > 0) {
@@ -65,7 +65,7 @@ void Argtype_set::check_for_existing_definition(
}
}
void Argtype_set::add(const std::string& name, const std::string& desc,
void Argtype_registry::add(const std::string& name, const std::string& desc,
const std::string& pattern, const std::string& default_value,
const std::string& alone_value,
const std::string& python_cast, modify_string_f python_format,
@@ -130,15 +130,15 @@ void Argtype_set::add(const std::string& name, const std::string& desc,
m_names.push_back(name);
}
void Argtype_set::add(std::vector<Katom>::iterator begin, std::vector<Katom>::iterator end, std::vector<Katom>& katoms)
void Argtype_registry::add(std::vector<Katom>::iterator begin, std::vector<Katom>::iterator end, std::vector<Katom>& katoms)
{
(void)K::log(3);
auto [positional, optional, rest] =
argument_split(begin + 1, end - 1); //, Argtype_set::parameters.m_positional.size());
argument_split(begin + 1, end - 1); //, Argtype_registry::parameters.m_positional.size());
check_for_existing_definition(positional[0][0].m_text, begin->m_loc);
auto values = Argtype_set::parameters().value_map(positional, optional, rest, begin->m_loc);
auto values = Argtype_registry::parameters().value_map(positional, optional, rest, begin->m_loc);
// std::for_each(begin, end+1, [](Katom& k) { k.m_type = katom_t::replaced; });
@@ -151,7 +151,7 @@ void Argtype_set::add(std::vector<Katom>::iterator begin, std::vector<Katom>::it
ignore_whitespace(next_iter, katoms);
}
Argtype Argtype_set::get(const std::string& name, const Locator& loc) const
Argtype Argtype_registry::get(const std::string& name, const Locator& loc) const
{
if (is_not_in(name, m_names)) {
std::stringstream msg {};
@@ -162,7 +162,7 @@ Argtype Argtype_set::get(const std::string& name, const Locator& loc) const
}
std::string Argtype_set::eval(
std::string Argtype_registry::eval(
const std::string& value, const std::string& type_name, const Locator& loc)
{
std::regex re = m_types[type_name].m_regex;
@@ -193,7 +193,7 @@ static std::string values_note(const Argtype& type)
return note.str();
}
std::string Argtype_set::describe(bool long_form, int indent_width) const
std::string Argtype_registry::describe(bool long_form, int indent_width) const
{
std::string indent(' ', indent_width);
std::size_t name_width = std::accumulate(

View File

@@ -8,12 +8,12 @@
#include "katom.h"
#include "argument_set.h"
class Argtype_set
class Argtype_registry
{
public:
static Parameter_set& parameters();
Argtype_set();
Argtype_registry();
std::string replace_symbols(const std::string& pattern, const Locator& loc);
void check_for_existing_definition(const std::string& name, const Locator& loc);
@@ -29,7 +29,7 @@ public:
std::string eval(const std::string& value, const std::string& type_name, const Locator& loc);
std::string describe(bool long_form=false, int indent_width=4) const;
inline bool is_defined(std::string name) {
inline bool is_defined(const std::string& name) const {
return count(m_names.begin(), m_names.end(), name) > 0;
}
std::vector<std::string> m_names {};

View File

@@ -1,8 +1,8 @@
#include "argument.h"
#include "argtype.h"
Parameter::Parameter(const std::string& name, Argtype argtype, const Locator& loc,
bool optional, std::string default_value)
Parameter::Parameter(const std::string& name, const Argtype& argtype, const Locator& loc,
bool optional, const std::string& default_value)
: m_name(name)
, m_argtype(argtype)
, m_optional(optional)

View File

@@ -19,11 +19,10 @@ public:
, m_target()
{};
Parameter(const std::string& name, Argtype argtype, const Locator& loc,
bool optional=false, std::string default_value = "");
Parameter(const std::string& name, const Argtype& argtype, const Locator& loc,
bool optional=false, const std::string& default_value = "");
~Parameter() = default;
std::string python_value(std::string value);
bool undefined() const { return m_name == "_default"; };
std::string m_name {};

View File

@@ -5,7 +5,7 @@
#include "show.h"
#include "log.h"
#include "katom.h"
#include "argtype_set.h"
#include "argtype_registry.h"
#include "argument_set.h"
#include "util.h"
@@ -36,7 +36,7 @@ std::regex parameter_regex(bool optional=false)
// rest(2): the base type is copied, its type parameter set, and its
// display name extended, so kdesc signatures show rows.rest(2).
static Argtype resolve_argtype(
const std::string& type_text, const Argtype_set& argtypes, const Locator& loc)
const std::string& type_text, const Argtype_registry& argtypes, const Locator& loc)
{
static const std::regex parameterized(R"((\w+)\((\d+)\))");
std::smatch match {};
@@ -58,7 +58,7 @@ static bool is_rest(const Argtype& argtype)
Parameter_set::Parameter_set(const std::string parameter_string)
{
(void)K::log(3);
Argtype_set argtypes {};
Argtype_registry argtypes {};
parse_parameters(
katomize(line_split(parameter_string), Locator().str()),
argtypes);
@@ -69,11 +69,11 @@ Parameter_set::Parameter_set(const std::vector<Katom>& katoms)
: m_katoms(katoms)
{
(void)K::log(3);
Argtype_set argtypes {};
Argtype_registry argtypes {};
parse_parameters(m_katoms, argtypes);
}
Parameter_set::Parameter_set(const std::vector<Katom>& katoms, const Argtype_set& argtypes)
Parameter_set::Parameter_set(const std::vector<Katom>& katoms, const Argtype_registry& argtypes)
: m_katoms(katoms)
{
(void)K::log(3);
@@ -82,7 +82,7 @@ Parameter_set::Parameter_set(const std::vector<Katom>& katoms, const Argtype_set
// Parameter parsing
Parameter parse_positional_parameter(const katom_list& katoms, const Argtype_set& argtypes)
Parameter parse_positional_parameter(const katom_list& katoms, const Argtype_registry& argtypes)
{
// (void)K::log(3, katoms);
if (katoms.size() > 1) {
@@ -110,7 +110,7 @@ Parameter parse_positional_parameter(const katom_list& katoms, const Argtype_set
}
Parameter parse_optional_parameter(const katom_list& katoms, const Argtype_set& argtypes)
Parameter parse_optional_parameter(const katom_list& katoms, const Argtype_registry& argtypes)
{
//(void)K::log(3);
Katom k = katoms[0];
@@ -242,7 +242,7 @@ parameter_split(katom_list::const_iterator kbegin, katom_list::const_iterator ke
return {positional, optional};
}
void Parameter_set::parse_parameters(const katom_list& katoms, const Argtype_set& argtypes)
void Parameter_set::parse_parameters(const katom_list& katoms, const Argtype_registry& argtypes)
{
(void)K::log(3, trim(katoms));
if (katoms.empty()) {
@@ -274,10 +274,10 @@ void Parameter_set::parse_parameters(const katom_list& katoms, const Argtype_set
}
void describe_arguments(
std::string label,
std::vector<std::vector<Katom>> positional,
std::vector<std::vector<Katom>> optional,
std::vector<Katom> rest)
const std::string& label,
const std::vector<std::vector<Katom>>& positional,
const std::vector<std::vector<Katom>>& optional,
const std::vector<Katom>& rest)
{
std::cout << label << ":\n"
<< " positional: " << positional << "\n"

View File

@@ -7,7 +7,7 @@
#include "argument.h"
#include "locator.h"
class Argtype_set;
class Argtype_registry;
std::tuple<std::vector<std::vector<Katom>>,std::vector<std::vector<Katom>>,std::vector<Katom>>
argument_split(std::vector<Katom>::const_iterator kbegin, std::vector<Katom>::const_iterator kend,
@@ -20,9 +20,9 @@ public:
~Parameter_set() = default;
Parameter_set(const std::string parameter_string);
Parameter_set(const std::vector<Katom>& katoms);
Parameter_set(const std::vector<Katom>& katoms, const Argtype_set& argtypes);
Parameter_set(const std::vector<Katom>& katoms, const Argtype_registry& argtypes);
void parse_parameters(const std::vector<Katom>& katoms, const Argtype_set& argtypes);
void parse_parameters(const std::vector<Katom>& katoms, const Argtype_registry& argtypes);
void describe_parameters();
void check_positional(
@@ -40,7 +40,7 @@ public:
bool empty() const { return m_katoms.size() == 0; };
std::vector<Katom> m_katoms {};
//Argtype_set m_argtypes {};
//Argtype_registry m_argtypes {};
std::vector<Parameter> m_positional {};
std::vector<Parameter> m_optional {};
std::vector<std::string> m_optional_names {};
@@ -56,10 +56,10 @@ bool operator==(Parameter_set lhs, Parameter_set rhs);
using Argument_set = Parameter_set;
void describe_arguments(
std::string label,
std::vector<std::vector<Katom>> positional,
std::vector<std::vector<Katom>> optional,
std::vector<Katom> rest);
const std::string& label,
const std::vector<std::vector<Katom>>& positional,
const std::vector<std::vector<Katom>>& optional,
const std::vector<Katom>& rest);
std::string replace_arguments(
const std::map<std::string, std::string>& values,

View File

@@ -227,7 +227,7 @@ void Argv::usage(const std::string& command)
}
void Argv::check_flags_and_options(std::string command, strings_t& words)
void Argv::check_flags_and_options(const std::string& command, strings_t& words)
{
std::vector<std::string> not_defined {};
for (auto word : words) {
@@ -334,10 +334,10 @@ void Argv::parse_optional(strings_t& words, string_map& named_args)
// std::cout << "\n";
}
void Argv::parse_positional(std::string command, //strings_t words,
void Argv::parse_positional(const std::string& command, //strings_t words,
std::string pos_args, string_map& named_args)
{
for (std::string req : m_req_names) {
for (const std::string& req : m_req_names) {
auto arg = m_args[req];
auto [substring, rest, found] = regex_split_prefix(arg.m_rgx, pos_args);
if (!found) {

View File

@@ -62,7 +62,7 @@ public:
void update_width(Arg arg);
void check_flags_and_options(std::string command, std::vector<std::string>& words);
void check_flags_and_options(const std::string& command, std::vector<std::string>& words);
void parse_flags(std::vector<std::string>& words, std::map<std::string, std::string>& named_args);
void parse_optional(std::vector<std::string>& words, std::map<std::string, std::string>& named_args);
void parse_vars(std::vector<std::string>& words, std::map<std::string, std::string>& named_args);
@@ -72,7 +72,7 @@ public:
bool given(const std::string& name) { return m_given.contains(name); };
void parse_positional(
std::string command, // std::vector<std::string> words,
const std::string& command, // std::vector<std::string> words,
std::string pos_args, std::map<std::string, std::string>& named_args);
std::map<std::string, std::string> classify_arguments(int argc, char* argv[], bool full_parse=true);
@@ -96,11 +96,11 @@ public:
void describe();
// void describe(Argv original);
bool is_flag(std::string name) {
bool is_flag(const std::string& name) const {
return std::ranges::count(m_flag_names, name) > 0;
}
bool is_opt(std::string name) {
bool is_opt(const std::string& name) const {
return std::ranges::count(m_opt_names, name) > 0;
}

View File

@@ -1 +1 @@
BASENAMES := util error locator file argv character ktype katom katom_list log show command argument argument_set argtype argtype_set state eval eval_python eval_cpp klammer klammer_set target target_set machine
BASENAMES := util error locator file argv character ktype katom katom_list log show command argument argument_set argtype argtype_registry state eval eval_python eval_cpp klammer klammer_registry klammerset klammerset_registry target target_registry machine

View File

@@ -10,8 +10,8 @@ inline std::string command_pathname { "Pathname of command executed on the comma
class Error : std::exception {
public:
Error(std::string error_type, std::string description,
Locator locator = Locator(), bool do_justify = true)
Error(const std::string& error_type, const std::string& description,
const Locator& locator = Locator(), bool do_justify = true)
: m_type(error_type)
, m_desc(description)
, m_loc(locator)
@@ -48,6 +48,13 @@ public:
: Error("target", description, locator, do_justify) {};
};
class Klammerset_error : public Error {
public:
explicit Klammerset_error(
const std::string& description, const Locator& locator=Locator(), bool do_justify=true)
: Error("klammerset", description, locator, do_justify) {};
};
class Definition_error : public Error {
public:
explicit Definition_error(

View File

@@ -14,7 +14,7 @@ enum class eval_t {
class Eval
{
public:
explicit Eval(Machine& machine, Locator loc)
explicit Eval(Machine& machine, const Locator& loc)
: m_machine(machine),
m_loc(loc)
{};

View File

@@ -7,14 +7,14 @@
#include "file.h"
#include "show.h"
Eval_cpp::Eval_cpp(Machine& machine, Locator loc)
Eval_cpp::Eval_cpp(Machine& machine, const Locator& loc)
: m_machine(machine)
, m_loc(loc)
{
(void)K::log(3);
}
std::string Eval_cpp::eval(fs::path library_path, std::string function_name)
std::string Eval_cpp::eval(const fs::path& library_path, const std::string& function_name)
{
(void)K::log(3, library_path, function_name);
// msg() << "library path: " << library_path.string().c_str() << "\n";

View File

@@ -7,12 +7,12 @@
class Eval_cpp
{
public:
explicit Eval_cpp(Machine& machine, Locator loc);
explicit Eval_cpp(Machine& machine, const Locator& loc);
Eval_cpp(const Eval_cpp&) = delete;
Eval_cpp& operator=(const Eval_cpp&) = delete;
//~Eval_cpp();
std::string eval(fs::path library_path, std::string function_name);
std::string eval(const fs::path& library_path, const std::string& function_name);
Machine m_machine {};
Locator m_loc;

View File

@@ -5,7 +5,7 @@
std::regex Eval_python::statement_delimiter("\\s*;\\s*");
Eval_python::Eval_python(Machine& machine, Locator loc)
Eval_python::Eval_python(Machine& machine, const Locator& loc)
: m_machine(machine)
, m_loc(loc)
, m_globals(nullptr)
@@ -93,7 +93,7 @@ strings_t Eval_python::parse_modules(std::string code)
return modules;
}
void Eval_python::import_module(std::string module_name, bool verify)
void Eval_python::import_module(const std::string& module_name, bool verify)
{
(void)K::log(3, module_name);
@@ -176,12 +176,12 @@ std::string Eval_python::get_result(PyObject* result_object)
return result;
}
std::string Eval_python::eval_expression(std::string expression, bool import_modules)
std::string Eval_python::eval_expression(const std::string& expression, bool import_modules)
{
(void)K::log(3, expression);
// msg() << "expression: " << expression << "\n";
if (import_modules && expression.find('.') != std::string::npos) {
for (auto m : parse_modules(expression)) {
for (const auto& m : parse_modules(expression)) {
import_module(m);
}
}
@@ -191,7 +191,7 @@ std::string Eval_python::eval_expression(std::string expression, bool import_mod
Py_eval_input, m_globals, m_locals));
}
std::string Eval_python::eval_statements(std::string script)
std::string Eval_python::eval_statements(const std::string& script)
{
(void)K::log(3);
strings_t statements = regex_split(script, statement_delimiter);

View File

@@ -9,16 +9,16 @@ class Eval_python
{
public:
static std::regex statement_delimiter;
explicit Eval_python(Machine& machine, Locator loc);
explicit Eval_python(Machine& machine, const Locator& loc);
Eval_python(const Eval_python&) = delete;
Eval_python& operator=(const Eval_python&) = delete;
~Eval_python();
void add_module_path(const std::string& path);
std::vector<std::string> parse_modules(std::string code);
void import_module(std::string module_name, bool verify = true);
void import_module(const std::string& module_name, bool verify = true);
std::string get_result(PyObject* result_object);
std::string eval_expression(std::string expression, bool import_modules = true);
std::string eval_statements(std::string script);
std::string eval_expression(const std::string& expression, bool import_modules = true);
std::string eval_statements(const std::string& script);
std::string eval(std::string code);
//std::string eval_katom_list(const katom_iter& begin, const katom_iter& end);
std::string eval_katom_list(

View File

@@ -440,7 +440,7 @@ strings_t get_sks_directories(const std::string& s, bool include_argument)
return result;
}
std::string cache_directory(std::string subdirectory, std::string parent_directory)
std::string cache_directory(const std::string& subdirectory, std::string parent_directory)
{
if (parent_directory.empty()) {
// /dev/shm is a fast RAM-backed tmpfs on Linux; it does not exist on
@@ -475,7 +475,7 @@ bool in_modification_order(std::string filename1, std::string filename2)
}
}
void write_to_cache(std::string cache_dir, std::string basename, std::string text)
void write_to_cache(const std::string& cache_dir, const std::string& basename, const std::string& text)
{
if (!file_exists(cache_dir)) {
//std::cout << "Creating cache directory: " << cache_dir << "\n";
@@ -486,14 +486,14 @@ void write_to_cache(std::string cache_dir, std::string basename, std::string tex
string_to_file(output_filename, text);
}
std::string read_from_cache(std::string cache_dir, std::string basename)
std::string read_from_cache(const std::string& cache_dir, const std::string& basename)
{
std::string input_filename = cache_dir + "/" + basename;
// msg() << "Reading file from cache: " << input_filename << "\n";
return string_from_file(input_filename);
}
bool cache_requires_update(std::string cache_dir, std::string file_to_cache, std::string basename)
bool cache_requires_update(const std::string& cache_dir, const std::string& file_to_cache, const std::string& basename)
{
std::string cache_filename = cache_dir + "/" + basename;
return !in_modification_order(file_to_cache, cache_filename);
@@ -662,11 +662,12 @@ void copy_file_stream(const fs::path& src, const fs::path& dst)
}
void copy_preserving_basename(
strings_t filenames, std::string output_directory, std::string link_directory)
const strings_t& filenames, const std::string& output_directory,
const std::string& link_directory)
{
fs::path outdir(output_directory + "/" + link_directory);
fs::create_directories(outdir);
for (std::string filename : filenames) {
for (const std::string& filename : filenames) {
fs::path pname(filename);
auto out_path = outdir / pname.filename();
// Preserve the previous copy_options::update_existing behavior: skip

View File

@@ -45,12 +45,12 @@ fs::path klammertext_filename(
const std::string& basename, bool error_if_missing=true, bool make_directory_if_missing=false);
std::vector<std::string> sks_dirs();
std::vector<std::string> get_sks_directories(const std::string& s, bool include_argument=true);
std::string cache_directory(std::string subdirectory, std::string parent_directory="");
std::string cache_directory(const std::string& subdirectory, std::string parent_directory="");
std::time_t to_time_t(const fs::file_time_type& ftime);
bool in_modification_order(std::string filename1, std::string filename2);
void write_to_cache(std::string cache_dir, std::string basename, std::string text);
std::string read_from_cache(std::string cache_dir, std::string basename);
bool cache_requires_update(std::string cache_dir, std::string file_to_cache, std::string basename);
void write_to_cache(const std::string& cache_dir, const std::string& basename, const std::string& text);
std::string read_from_cache(const std::string& cache_dir, const std::string& basename);
bool cache_requires_update(const std::string& cache_dir, const std::string& file_to_cache, const std::string& basename);
std::vector<fs::path> pathnames_with_extension(
const fs::path& dir, const std::string extension
@@ -73,6 +73,7 @@ bool files_differ(const fs::path& p1,
void copy_file_stream(const fs::path& src, const fs::path& dst);
void copy_preserving_basename(
std::vector<std::string> filenames, std::string output_directory, std::string link_directory);
const std::vector<std::string>& filenames, const std::string& output_directory,
const std::string& link_directory);
fs::path resolve_relative_to(const fs::path& relative, const fs::path& base=std::filesystem::current_path());

View File

@@ -36,7 +36,7 @@ static std::string lower_extension(const fs::path& path)
}
std::string name_to_dirname(std::string name)
std::string name_to_dirname(const std::string& name)
{
std::string result {};
for (char c : name) {
@@ -206,7 +206,7 @@ static void extract_font_metrics(Resolved_font& font)
}
}
Resolved_font resolve_font(std::string family_name)
Resolved_font resolve_font(const std::string& family_name)
{
if (family_name.empty())
return {};

View File

@@ -19,7 +19,7 @@ struct Resolved_font {
float capheight_ratio = 0.0f; // cap-height / unitsPerEm from OS/2 table
};
std::string name_to_dirname(std::string name);
std::string name_to_dirname(const std::string& name);
// Directories searched for installed fonts (KLAMMERTEXT_FONTS, default
// ~/.klammertext/fonts); the default font set is searched after them.
std::vector<std::string> installed_font_dirs();
@@ -27,7 +27,7 @@ std::vector<std::string> installed_font_dirs();
std::string default_font_dir();
// Every installable font family found across those directories.
std::vector<std::string> available_font_families();
Resolved_font resolve_font(std::string family_name);
Resolved_font resolve_font(const std::string& family_name);
void install_resolved_font(const Resolved_font& font, std::string output_dir);
// One font file classified by its internal metadata (name table, OS/2).

View File

@@ -281,7 +281,7 @@ katom_list trim(const katom_list& katoms, bool trim_inactive)
return trim(result, trim_types);
}
strings_t line_split(std::string s)
strings_t line_split(const std::string& s)
{
std::istringstream is(s);
strings_t result {};
@@ -293,7 +293,7 @@ strings_t line_split(std::string s)
return result;
}
std::pair<std::string, strings_t> line_split(fs::path pathname)
std::pair<std::string, strings_t> line_split(const fs::path& pathname)
{
std::string source {};
strings_t lines {};

View File

@@ -99,8 +99,8 @@ std::vector<Katom> trim(const std::vector<Katom>& katoms, bool trim_inactive = f
std::vector<std::vector<Katom>> bar_split(std::vector<Katom>::iterator kbegin, std::vector<Katom>::iterator kend);
std::vector<std::string> line_split(std::string s);
std::pair<std::string, std::vector<std::string>> line_split(fs::path pathname);
std::vector<std::string> line_split(const std::string& s);
std::pair<std::string, std::vector<std::string>> line_split(const fs::path& pathname);
std::vector<Katom> katomize(const std::vector<std::string>& lines, const std::string& source_desc);
void warn_unparsed_katoms(std::vector<Katom>& katoms, bool warn = true);

View File

@@ -181,10 +181,10 @@ void check_named_katom_span(const Katom& begin, const Katom& end)
spans_t find_spans(
katom_iter begin, katom_iter end,
std::function<bool(const Katom&)> level_inc,
std::function<bool(const Katom&)> level_dec,
const std::function<bool(const Katom&)>& level_inc,
const std::function<bool(const Katom&)>& level_dec,
bool error_exit,
std::string name)
const std::string& name)
{
(void)K::log(4, name);
bool _dbg = false;
@@ -245,10 +245,10 @@ spans_t find_spans(
spans_t find_spans(
katom_list& katoms,
std::function<bool(const Katom&)> level_inc,
std::function<bool(const Katom&)> level_dec,
const std::function<bool(const Katom&)>& level_inc,
const std::function<bool(const Katom&)>& level_dec,
bool error_exit,
std::string name)
const std::string& name)
{
return find_spans(katoms.begin(), katoms.end(), level_inc, level_dec, error_exit, name);
}

View File

@@ -23,17 +23,17 @@ find_katom(const std::vector<Katom>::iterator begin, const std::vector<Katom>::i
std::vector<std::pair<Katom, Katom>>
find_spans(std::vector<Katom>::iterator begin, std::vector<Katom>::iterator end,
std::function<bool(const Katom&)> level_inc,
std::function<bool(const Katom&)> level_dec,
const std::function<bool(const Katom&)>& level_inc,
const std::function<bool(const Katom&)>& level_dec,
bool error_exit,
std::string name);
const std::string& name);
std::vector<std::pair<Katom, Katom>>
find_spans(std::vector<Katom>& katoms,
std::function<bool(const Katom&)> level_inc,
std::function<bool(const Katom&)> level_dec,
const std::function<bool(const Katom&)>& level_inc,
const std::function<bool(const Katom&)>& level_dec,
bool error_exit=true,
std::string name="all");
const std::string& name="all");
void describe_spans(const std::vector<Katom>& katoms);

View File

@@ -13,7 +13,7 @@ using namespace std::literals;
std::regex Klammer::name_re = std::regex(R"((\w+)(?:\.(\w+))?)");
std::tuple<std::string, std::string>
parse_name(Target_set targets, Katom name_katom)
parse_name(const Target_registry& targets, const Katom& name_katom)
{
std::string name_with_target = trim_char(name_katom.m_text, '@');
std::smatch match {};
@@ -29,7 +29,7 @@ parse_name(Target_set targets, Katom name_katom)
std::string klammer_name = match[1];
std::string target_name = match[2];
if (target_name.empty()) {
target_name = Target_set::general_name;
target_name = Target_registry::general_name;
}
if (!targets.has(target_name)) {
throw Target_error(
@@ -41,7 +41,7 @@ parse_name(Target_set targets, Katom name_katom)
}
std::tuple<Katom, Parameter_set, katom_list, Locator>
parse_definition_katoms(std::string klammer_name, Argtype_set argtypes, katom_iter& begin, katom_iter& end)
parse_definition_katoms(const std::string& klammer_name, const Argtype_registry& argtypes, katom_iter& begin, katom_iter& end)
{
(void)K::log(3, *begin, *(end - 1));
katom_iter deftype = std::find_if(
@@ -84,7 +84,7 @@ parse_definition_katoms(std::string klammer_name, Argtype_set argtypes, katom_it
}
void Klammer::add_target_definition(
std::string target_name, Argtype_set argtypes, katom_iter begin, katom_iter end)
const std::string& target_name, const Argtype_registry& argtypes, katom_iter begin, katom_iter end)
{
(void)K::log(3, *begin, *(end-1));
auto [deftype, parameters, body, loc] =
@@ -95,7 +95,7 @@ void Klammer::add_target_definition(
std::regex variable_re(R"(\*(\w+)\*)");
int i = 0;
variable_map_t varmap {};
for (auto k : body) {
for (const auto& k : body) {
std::smatch match {};
std::string txt = k.m_text;
while (std::regex_search(txt, match, variable_re) &&
@@ -127,23 +127,23 @@ void Klammer::remove_target_definition(const std::string& target_name)
// Rationalize multiple definitions
std::string error_list(std::string label, auto components, std::string after="")
std::string error_list(const std::string& label, const auto& components, const std::string& after="")
{
std::stringstream ss {};
ss << label << ":\n";
for (auto c : components) {
for (const auto& c : components) {
ss << " " << c.loc.desc() << "\n";
}
ss << after;
return ss.str();
}
auto Klammer::target_defs(std::vector<std::string> target_names)
auto Klammer::target_defs(const std::vector<std::string>& target_names)
{
std::vector<Klammer::components> defs {};
for (auto target : target_names) {
for (const auto& target : target_names) {
auto target_defs = collect_if(
m_defs, [target](const auto& def) { return def.target == target; });
m_defs, [&target](const auto& def) { return def.target == target; });
defs.insert(defs.end(), target_defs.begin(), target_defs.end());
}
return defs;
@@ -173,7 +173,7 @@ void Klammer::disallow_instances() //Klammer::components declaration)
}
}
bool Klammer::copy_to_instances(Target_set targets)
bool Klammer::copy_to_instances(const Target_registry& targets)
{
auto instances = instance_defs();
if (!instances.empty()) {
@@ -202,19 +202,20 @@ bool Klammer::copy_to_instances(Target_set targets)
}
void Klammer::copy_components(
Parameter_set parameters, std::vector<Klammer::components> cs, Target_set targets)
const Parameter_set& parameters, const std::vector<Klammer::components>& cs,
const Target_registry& targets)
{
(void)K::log(4);
for (auto target_name : targets.m_names) {
if (target_name == Target_set::declare_name ||
target_name == Target_set::general_name) {
for (const auto& target_name : targets.m_names) {
if (target_name == Target_registry::declare_name ||
target_name == Target_registry::general_name) {
continue;
}
m_parameters = parameters;
}
for (auto c : cs) {
for (const auto& c : cs) {
m_body[c.target] = c.body;
m_body_generic[c.target] = (c.target == Target_set::general_name);
m_body_generic[c.target] = (c.target == Target_registry::general_name);
m_varmap[c.target] = c.varmap;
}
}
@@ -223,7 +224,7 @@ void Klammer::copy_components(
void Klammer::check_for_multiple_general_klammers()
{
auto general_klammers = target_defs({Target_set::general_name});
auto general_klammers = target_defs({Target_registry::general_name});
if (general_klammers.size() > 1) {
throw Definition_error(
error_list(
@@ -235,11 +236,11 @@ void Klammer::check_for_multiple_general_klammers()
void Klammer::check_for_declaration_and_definitions()
{
auto declares = target_defs({Target_set::declare_name});
auto declares = target_defs({Target_registry::declare_name});
if (!declares.empty()) {
std::vector<Klammer::components> definitions {};
for (auto def : m_defs) {
if (def.target != Target_set::declare_name) {
for (const auto& def : m_defs) {
if (def.target != Target_registry::declare_name) {
if (def.deftype == katom_t::klammer_definition ||
def.deftype == katom_t::klammer_default) {
msg() << def << "\n";
@@ -261,11 +262,11 @@ void Klammer::check_for_declaration_and_definitions()
// If a general definition exists, use it for targets not defined, but check signatures
void Klammer::copy_general_klammer_to_undefined(Target_set targets)
void Klammer::copy_general_klammer_to_undefined(const Target_registry& targets)
{
(void)K::log(4);
auto general_klammers = target_defs({Target_set::general_name});
auto declares = target_defs({Target_set::declare_name});
auto general_klammers = target_defs({Target_registry::general_name});
auto declares = target_defs({Target_registry::declare_name});
// Check matching signatures (though this case already handled)
if (general_klammers.size() == 1) {
@@ -279,13 +280,13 @@ void Klammer::copy_general_klammer_to_undefined(Target_set targets)
m_parameters.m_katoms[0].m_loc, false);
}
}
auto [target, deftype, parameters, body, varmap, loc] = general_klammers[0];
const auto& [target, deftype, parameters, body, varmap, loc] = general_klammers[0];
if (m_parameters.m_katoms.empty()) {
m_parameters = parameters;
}
for (auto target_name : targets.m_names) {
for (const auto& target_name : targets.m_names) {
// std::cout << "General copy, considering " << target_name << "\n";
if (m_body.count(target_name) == 0 && target_name != Target_set::declare_name) {
if (m_body.count(target_name) == 0 && target_name != Target_registry::declare_name) {
// std::cout << " Copying to " << target_name << "\n";
m_body[target_name] = body;
m_body_generic[target_name] = true; // general body -> writer content
@@ -298,7 +299,7 @@ void Klammer::copy_general_klammer_to_undefined(Target_set targets)
// Three declaration cases: none, one, many
void Klammer::no_declarations(Target_set targets)
void Klammer::no_declarations(const Target_registry& targets)
{
(void)K::log(4);
// std::cout << boldblack << "No declarations\n" << black;
@@ -308,7 +309,7 @@ void Klammer::no_declarations(Target_set targets)
std::vector<std::string> target_names = targets.applicable();
std::vector<Parameter_set> all_parameter_sets {};
// Are all parameters the same?
for (auto def : m_defs) {
for (const auto& def : m_defs) {
if (std::ranges::find(target_names, def.target) != target_names.end()) {
// std::cout << " Found: " << def.target << "\n";
all_parameter_sets.push_back(def.parameters);
@@ -332,7 +333,7 @@ void Klammer::no_declarations(Target_set targets)
copy_general_klammer_to_undefined(targets);
}
void Klammer::one_declaration(Target_set targets, Klammer::components declare)
void Klammer::one_declaration(const Target_registry& targets, const Klammer::components& declare)
{
(void)K::log(4);
// std::cout << boldblack << "One declaration\n" << black;
@@ -342,7 +343,7 @@ void Klammer::one_declaration(Target_set targets, Klammer::components declare)
copy_general_klammer_to_undefined(targets);
}
void Klammer::many_declarations(std::vector<Klammer::components> declares)
void Klammer::many_declarations(const std::vector<Klammer::components>& declares)
{
(void)K::log(4);
// std::cout << boldblack << "Many declarations\n" << black;
@@ -353,10 +354,10 @@ void Klammer::many_declarations(std::vector<Klammer::components> declares)
void Klammer::rationalize(Target_set targets)
void Klammer::rationalize(const Target_registry& targets)
{
(void)K::log(3, m_name);
auto declares = target_defs({Target_set::declare_name});
auto declares = target_defs({Target_registry::declare_name});
auto declare_count = declares.size();
if (declare_count == 0) {
disallow_instances();
@@ -371,7 +372,7 @@ void Klammer::rationalize(Target_set targets)
}
std::string klammer_name_from_katom(std::string s, Locator loc)
std::string klammer_name_from_katom(const std::string& s, const Locator& loc)
{
std::regex rgx(R"(@(\w+).*)");
std::smatch match {};
@@ -389,11 +390,11 @@ void label(const std::string& s)
std::cout << std::right << std::setw(w) << std::setfill(' ') << s << ": ";
}
void show_args(const std::string& label_text, std::vector<Argument> arguments)
void show_args(const std::string& label_text, const std::vector<Argument>& arguments)
{
if (!arguments.empty()) {
label(label_text);
for (auto a : arguments) {
for (const auto& a : arguments) {
std::cout << a << " ";
}
std::cout << '\n';
@@ -403,7 +404,7 @@ void show_args(const std::string& label_text, std::vector<Argument> arguments)
strings_t Klammer::get_target_names() const
{
strings_t names {};
for (auto [target, body] : m_body) {
for (const auto& [target, body] : m_body) {
std::stringstream ss {};
// ss << name << target.m_loc.m_line;
ss << target;
@@ -422,12 +423,12 @@ strings_t Klammer::get_locations()
return {};
}
std::string Klammer::signature_text()
std::string Klammer::signature_text() const
{
std::string result {};
bool has_pos = false;
bool has_opt = false;
for (auto pos : m_parameters.m_positional) {
for (const auto& pos : m_parameters.m_positional) {
result += pos.m_name;
std::string type = pos.m_argtype.m_name;
if (type != default_argtype) {
@@ -442,7 +443,7 @@ std::string Klammer::signature_text()
if (opt_count <= 3 && !has_pos) {
result += " ";
}
for (auto opt : m_parameters.m_optional) {
for (const auto& opt : m_parameters.m_optional) {
if (opt_count > 3) {
result += "\n :" + opt.m_name;
} else {
@@ -473,18 +474,18 @@ std::string Klammer::signature_text()
}
std::string Klammer::description_text()
std::string Klammer::description_text() const
{
std::string result = " [" + m_name + ": no description]";
if (m_body.contains("k")) {
result = to_string(m_body["k"], true);
result = to_string(m_body.at("k"), true);
result = justify(result, 80, 1);
}
return result;
}
std::string Klammer::describe(int margin)
std::string Klammer::describe(int margin) const
{
std::string result {};
result += "@" + m_name + signature_text() + description_text();

View File

@@ -4,7 +4,7 @@
#include "deftype.h"
#include "argument_set.h"
#include "target_set.h"
#include "target_registry.h"
#include "locator.h"
class Klammer
@@ -31,37 +31,38 @@ public:
// target-name -> [variable -> index]
void add_target_definition(
std::string target_name, Argtype_set argtypes,
const std::string& target_name, const Argtype_registry& argtypes,
std::vector<Katom>::iterator begin, std::vector<Katom>::iterator end);
void remove_target_definition(const std::string& target_name);
auto target_defs(std::vector<std::string> target_names);
auto target_defs(const std::vector<std::string>& target_names);
auto instance_defs();
void disallow_instances(); //Klammer::components declaration);
bool copy_to_instances(Target_set targets);
bool copy_to_instances(const Target_registry& targets);
void copy_components(
Parameter_set parameters, std::vector<Klammer::components> cs, Target_set targets);
const Parameter_set& parameters, const std::vector<Klammer::components>& cs,
const Target_registry& targets);
void check_for_multiple_general_klammers();
void check_for_declaration_and_definitions();
void copy_general_klammer_to_undefined(Target_set targets);
void no_declarations(Target_set targets);
void one_declaration(Target_set targets, Klammer::components declare);
void many_declarations(std::vector<Klammer::components> declares);
void rationalize(Target_set target);
void copy_general_klammer_to_undefined(const Target_registry& targets);
void no_declarations(const Target_registry& targets);
void one_declaration(const Target_registry& targets, const Klammer::components& declare);
void many_declarations(const std::vector<Klammer::components>& declares);
void rationalize(const Target_registry& targets);
/*
void add_description(const std::string& desc, Katom definition_type);
auto user_defs();
auto klammer_defines_parameters();
auto klammer_uses_parameters();
void check_for_target_errors(Target_set targets);
void check_for_target_errors(Target_registry targets);
bool explicit_parameters_match();
void copy_components(Klammer::components cs, Target_set targets);
void copy_components(Klammer::components cs, Target_registry targets);
*/
std::string signature_text();
std::string description_text();
std::string describe(int margin=0);
std::string signature_text() const;
std::string description_text() const;
std::string describe(int margin=0) const;
bool has_literal_param() const {
for (const auto& p : m_parameters.m_positional)
@@ -91,18 +92,18 @@ public:
std::map<std::string, bool> m_body_generic {};
};
std::string klammer_name_from_katom(std::string s, Locator loc);
std::string klammer_name_from_katom(const std::string& s, const Locator& loc);
std::tuple<std::string,std::string>
parse_name(Target_set targets, Katom name_katom);
parse_name(const Target_registry& targets, const Katom& name_katom);
std::tuple<Katom, Parameter_set, std::vector<Katom>, Locator>
parse_definition_katoms(Argtype_set argtypes, //Target_set targets,
parse_definition_katoms(const std::string& klammer_name, const Argtype_registry& argtypes,
std::vector<Katom>::iterator& begin, std::vector<Katom>::iterator& end);
/*
klammer_definition_args parse_klammer_definition_katoms(
katom_list& katoms, Argtype_set& argtypes);
katom_list& katoms, Argtype_registry& argtypes);
void check_for_undefined_arguments(
std::string name, Parameters parameters, katom_list body_katoms, Locator loc);

View File

@@ -1,18 +1,18 @@
#include "klammer.h"
#include "klammer_set.h"
#include "klammer_registry.h"
#include "show.h"
#include "util.h"
#include "log.h"
#include "error.h"
/*
bool Klammer_set::has(std::string name, std::string target)
bool Klammer_registry::has(std::string name, std::string target)
{
return m_klammers.count(name) > 0;
}
*/
void Klammer_set::add(Argtype_set argtypes, Target_set& targets, katom_iter begin, katom_iter end, katom_list& katoms)
void Klammer_registry::add(const Argtype_registry& argtypes, const Target_registry& targets, katom_iter begin, katom_iter end, katom_list& katoms)
{
(void)K::log(3, *begin, *(end - 1));
restore_initial_type(begin, end);
@@ -62,7 +62,7 @@ void Klammer_set::add(Argtype_set argtypes, Target_set& targets, katom_iter begi
// This add's target:
Target target = targets.get(target_name, begin->m_loc);
if (!target.m_provides.empty()) {
for (auto provide_name : target.m_provides) {
for (const auto& provide_name : target.m_provides) {
if (m_klammers[klammer_name].m_defloc.count(provide_name) > 0) {
m_klammers[klammer_name].remove_target_definition(provide_name);
}
@@ -80,30 +80,30 @@ void Klammer_set::add(Argtype_set argtypes, Target_set& targets, katom_iter begi
ignore_whitespace(next_iter, katoms);
}
void Klammer_set::rationalize(Target_set targets)
void Klammer_registry::rationalize(const Target_registry& targets)
{
(void)K::log(3);
for (auto k : m_klammers) {
m_klammers[k.first].rationalize(targets);
for (auto& [name, klammer] : m_klammers) {
klammer.rationalize(targets);
}
}
/*
bool Klammer_set::has(std::string name, std::string target)
bool Klammer_registry::has(std::string name, std::string target)
{
return m_klammers.count(name) > 0;
}
*/
void Klammer_set::check_klammer(std::string name, std::string target, Locator loc)
void Klammer_registry::check_klammer(const std::string& name, const std::string& target, const Locator& loc) const
{
if (m_klammers.count(name) == 0) {
throw Definition_error("The klammer " + q_(name) + " is not defined for an unspecified target", loc);
}
Klammer k = m_klammers[name];
const Klammer& k = m_klammers.at(name);
if (k.m_defloc.count(target) == 0) {
std::string desc;
if (target == Target_set::general_name) {
if (target == Target_registry::general_name) {
desc = "an unspecified target";
} else {
desc = "target " + q_(target);
@@ -113,7 +113,7 @@ void Klammer_set::check_klammer(std::string name, std::string target, Locator lo
}
const std::vector<Katom>* Klammer_set::constant_body(const std::string& name) const
const std::vector<Katom>* Klammer_registry::constant_body(const std::string& name) const
{
auto it = m_klammers.find(name);
if (it == m_klammers.end()) return nullptr;
@@ -126,14 +126,14 @@ const std::vector<Katom>* Klammer_set::constant_body(const std::string& name) co
if (!d.parameters.empty()) return nullptr;
}
for (const auto& d : k.m_defs) {
if (d.target == Target_set::general_name && d.parameters.empty()) {
if (d.target == Target_registry::general_name && d.parameters.empty()) {
return &d.body;
}
}
return nullptr;
}
int max_length(std::map<std::string, Klammer> ss)
int max_length(const std::map<std::string, Klammer>& ss)
{
size_t result = 0;
for_each(ss.begin(), ss.end(),
@@ -141,19 +141,19 @@ int max_length(std::map<std::string, Klammer> ss)
return result;
}
std::string Klammer_set::instance_list(int margin) const
std::string Klammer_registry::instance_list(int margin) const
{
std::stringstream ss {};
std::string tab(margin, ' ');
auto name_width = max_length(m_klammers);
for (auto [name, k] : m_klammers) {
for (const auto& [name, k] : m_klammers) {
ss << tab << std::setfill(' ') << std::setw(name_width) << name
<< sp_arrow << k << "\n";
}
return ss.str();
}
std::string Klammer_set::describe(int margin) const
std::string Klammer_registry::describe(int margin) const
{
/*
strings_t names {};
@@ -161,7 +161,7 @@ std::string Klammer_set::describe(int margin) const
strings_t locations {};
*/
std::string result;
for (auto [name, k] : m_klammers) {
for (const auto& [name, k] : m_klammers) {
result += k.describe(margin) + "\n";
/*
names.push_back(name);

View File

@@ -1,16 +1,16 @@
#pragma once
#include "klammer.h"
#include "target_set.h"
#include "target_registry.h"
class Klammer_set
class Klammer_registry
{
public:
Klammer_set() = default;
void add(Argtype_set argtypes, Target_set& targets,
Klammer_registry() = default;
void add(const Argtype_registry& argtypes, const Target_registry& targets,
std::vector<Katom>::iterator begin, std::vector<Katom>::iterator end, std::vector<Katom>& katoms);
void rationalize(Target_set targets);
void check_klammer(std::string name, std::string target, Locator loc);
void rationalize(const Target_registry& targets);
void check_klammer(const std::string& name, const std::string& target, const Locator& loc) const;
const std::vector<Katom>* constant_body(const std::string& name) const;
std::string instance_list(int margin) const;
std::string describe(int margin=0) const;

8
mac/klammerset.cpp Normal file
View File

@@ -0,0 +1,8 @@
#include "klammerset.h"
Klammerset::Klammerset(const std::string& symbol, const std::string& desc, const Locator& loc)
: m_symbol(symbol)
, m_desc(desc)
, m_loc(loc)
{
}

28
mac/klammerset.h Normal file
View File

@@ -0,0 +1,28 @@
#pragma once
#include <string>
#include <vector>
#include "locator.h"
// A Klammerset is the formal construct declared by the @@@klammerset system
// command: a named, logically related group of klammer definitions loaded
// together. The instance holds metadata and the file list only -- the
// klammers themselves live in the Machine's Klammer_registry (one flat,
// additive namespace; the definition modes govern collisions). Membership
// is provenance, not containment.
class Klammerset
{
public:
Klammerset() = default;
Klammerset(const std::string& symbol, const std::string& desc, const Locator& loc);
std::string m_symbol {}; // registry key and command-line name (e.g. "sks")
std::string m_desc {}; // the logical relationship that makes this a set
std::string m_name {}; // display name (e.g. "Standard Klammer Set")
std::string m_author {};
std::string m_date {}; // last update; a date serves as the version
std::vector<std::string> m_requires {}; // klammerset declaration files, loaded first
std::vector<std::string> m_files {}; // definition files, loaded in list order
Locator m_loc {}; // the declaring file; relative names resolve against it
};

225
mac/klammerset_registry.cpp Normal file
View File

@@ -0,0 +1,225 @@
#include <cctype>
#include <cstdlib>
#include <iomanip>
#include <sstream>
#include "klammerset_registry.h"
#include "error.h"
#include "file.h"
#include "log.h"
#include "util.h"
#include "show.h"
#include "katom.h"
Klammerset_registry::Klammerset_registry()
: m_parameters(Parameter_set("symbol | desc :name :author :date :requires :files"))
{
}
void Klammerset_registry::add(Klammerset klammerset)
{
(void)K::log(3, klammerset.m_symbol);
m_klammersets[klammerset.m_symbol] = klammerset;
m_symbols.push_back(klammerset.m_symbol);
}
std::optional<Klammerset> Klammerset_registry::add(
std::vector<Katom>::iterator begin, std::vector<Katom>::iterator end, std::vector<Katom>& katoms)
{
(void)K::log(3, *begin, *(end - 1));
auto [positional, optional, rest] =
argument_split(begin + 1, end - 1, m_parameters.m_positional.size());
auto values = m_parameters.value_map(positional, optional, rest, begin->m_loc);
modify_type(katom_t::replaced, begin, end);
auto next_iter = end;
ignore_whitespace(next_iter, katoms);
std::string symbol = values["symbol"];
check_symbol(symbol, begin->m_loc);
if (has(symbol)) {
(void)K::log(2, "Klammerset \"" + symbol + "\" is already loaded; declaration skipped");
return std::nullopt;
}
// The filename lists follow the standard conventions (spaces allowed,
// standalone "/" separator). The existence rescue tests names against
// the declaring file's directory, where relative names are later
// resolved by Machine::load_klammerset_files.
fs::path declaring(begin->m_loc.m_filename);
std::string base_dir =
fs::exists(declaring) ? declaring.parent_path().string() : "";
Klammerset klammerset(symbol, values["desc"], begin->m_loc);
klammerset.m_name = values["name"];
klammerset.m_author = values["author"];
klammerset.m_date = values["date"];
klammerset.m_requires = resolve_filename_list(values["requires"], base_dir);
klammerset.m_files = resolve_filename_list(values["files"], base_dir);
add(klammerset);
return klammerset;
}
void Klammerset_registry::check_symbol(const std::string& symbol, const Locator& loc) const
{
bool valid = !symbol.empty() && std::isalpha(static_cast<unsigned char>(symbol[0]));
for (char c : symbol) {
if (!std::isalnum(static_cast<unsigned char>(c)) && c != '_') {
valid = false;
}
}
if (!valid) {
throw Klammerset_error(
"The klammerset symbol \"" + symbol + "\" is not valid. A symbol begins "
"with a letter and contains only letters, digits, and underscores.",
loc);
}
}
bool Klammerset_registry::has(const std::string& symbol) const
{
return m_klammersets.count(symbol) > 0;
}
Klammerset Klammerset_registry::get(const std::string& symbol, const Locator& loc) const
{
if (has(symbol)) {
return m_klammersets.at(symbol);
} else {
throw Klammerset_error("Klammerset " + symbol + " does not exist", loc);
}
}
// --- The klammerset search path ---
bool is_klammerset_symbol(const std::string& name)
{
if (name.empty() || !std::isalpha(static_cast<unsigned char>(name[0]))) {
return false;
}
for (char c : name) {
if (!std::isalnum(static_cast<unsigned char>(c)) && c != '_') {
return false;
}
}
return true;
}
std::vector<std::string> klammerset_search_dirs(const std::string& local_dir)
{
std::vector<std::string> result {};
// A repeated directory (e.g. the local stage already IS
// $KLAMMERTEXT_HOME) adds nothing and clutters error messages.
auto push_unique = [&result](const std::string& dir) {
std::string canonical = fs::weakly_canonical(dir).string();
if (!is_in(canonical, result)) {
result.push_back(canonical);
}
};
if (!local_dir.empty()) {
push_unique(local_dir);
}
std::string paths {};
const char* env = std::getenv("KLAMMERTEXT_KLAMMERSETS");
if (env && *env) {
paths = env;
} else if (const char* home = std::getenv("HOME"); home && *home) {
paths = std::string(home) + "/.klammertext/klammersets";
}
std::stringstream ss(paths);
std::string dir;
while (std::getline(ss, dir, ':')) {
if (!dir.empty()) {
push_unique(dir);
}
}
if (const char* kthome = std::getenv(klammertext_home_var.c_str()); kthome && *kthome) {
push_unique(kthome);
}
return result;
}
fs::path resolve_klammerset_symbol(
const std::string& symbol, const std::string& local_dir, const Locator& loc)
{
std::vector<std::string> dirs = klammerset_search_dirs(local_dir);
for (const std::string& dir : dirs) {
fs::path candidate = fs::path(dir) / symbol / (symbol + ".k");
if (fs::exists(candidate) && fs::is_regular_file(candidate)) {
return fs::weakly_canonical(candidate);
}
}
throw Klammerset_error(
"The klammerset \"" + symbol + "\" was not found. A symbol x names the "
"declaration file x/x.k in one of the search directories: "
+ join(dirs, ", ")
+ ". Enter \"kdesc --klammerset\" to list the available klammersets.",
loc);
}
std::string describe_klammerset_search(const std::string& local_dir, int margin)
{
std::string tab(margin, ' ');
std::stringstream ss {};
std::map<std::string, std::string> first_hit {};
for (const std::string& dir : klammerset_search_dirs(local_dir)) {
if (!fs::is_directory(dir)) {
continue;
}
for (const auto& entry : fs::directory_iterator(dir)) {
if (!entry.is_directory()) {
continue;
}
std::string symbol = entry.path().filename().string();
fs::path declaration = entry.path() / (symbol + ".k");
if (!is_klammerset_symbol(symbol) || !fs::is_regular_file(declaration)) {
continue;
}
ss << tab << symbol << sp_arrow << declaration.string();
if (first_hit.count(symbol)) {
ss << " (shadowed by " << first_hit[symbol] << ")";
} else {
first_hit[symbol] = declaration.string();
}
ss << "\n";
}
}
if (first_hit.empty()) {
ss << tab << "(no klammersets found)\n";
}
return ss.str();
}
std::string Klammerset_registry::describe(int margin, bool long_format) const
{
std::string tab(margin, ' ');
std::stringstream ss {};
std::vector<std::string> descs {};
for (const std::string& symbol : m_symbols) {
descs.push_back(m_klammersets.at(symbol).m_desc);
}
auto symbol_width = max_length(m_symbols);
auto desc_width = max_length(descs);
for (const std::string& symbol : m_symbols) {
const Klammerset& ks = m_klammersets.at(symbol);
if (long_format) {
ss << tab << std::setfill(' ') << std::setw(symbol_width) << std::left << symbol << " "
<< std::setw(desc_width) << std::left << ks.m_desc << " "
<< ks.m_loc.str() << "\n";
if (!ks.m_name.empty())
ss << tab << std::string(symbol_width, ' ') << " name: " << ks.m_name << "\n";
if (!ks.m_author.empty())
ss << tab << std::string(symbol_width, ' ') << " author: " << ks.m_author << "\n";
if (!ks.m_date.empty())
ss << tab << std::string(symbol_width, ' ') << " date: " << ks.m_date << "\n";
if (!ks.m_requires.empty())
ss << tab << std::string(symbol_width, ' ') << " requires: " << join(ks.m_requires, " / ") << "\n";
if (!ks.m_files.empty())
ss << tab << std::string(symbol_width, ' ') << " files: " << join(ks.m_files, " / ") << "\n";
} else {
ss << tab << std::setfill(' ') << std::setw(symbol_width) << std::left << symbol
<< sp_arrow << ks << "\n";
}
}
return ss.str();
}

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);

View File

@@ -28,7 +28,7 @@ std::string abbreviate_location(
}
Locator::Locator(fs::path filename, int line, int chr)
Locator::Locator(const fs::path& filename, int line, int chr)
: m_filename(filename)
, m_line(line)
, m_chr(chr)

View File

@@ -23,7 +23,7 @@ public:
, m_line(int(location.line()))
, m_chr(int(location.column()))
{};
Locator(fs::path filename, int line, int chr);
Locator(const fs::path& filename, int line, int chr);
std::string str(bool relative = false) const;
std::string desc(bool relative = false) const;
std::string abbrev(bool include_chr=true) const;

View File

@@ -9,10 +9,10 @@
#include "eval.h"
Machine::Machine()
: m_argtypes(Argtype_set())
: m_argtypes(Argtype_registry())
, m_state(State())
, m_targets(Target_set())
, m_klammers(Klammer_set())
, m_targets(Target_registry())
, m_klammers(Klammer_registry())
{
(void)K::log(3);
m_state.add_environment_frame();
@@ -352,20 +352,80 @@ void Machine::extract_machine_definitions()
if (m_katoms.empty()) {
return;
}
for (const auto& [op, cl] : find_spans(m_katoms, begin_machine_def, end_machine_def, true, command_name)) {
auto [begin, end] = find_span_katoms(m_katoms, op, cl);
//std::string name = trim_char(begin->m_text, '@');
std::string name = begin->m_text;
if (name == "@@@target") {
m_targets.add(begin, end, m_katoms);
} else if (name == "@@@argtype") {
m_argtypes.add(begin, end, m_katoms);
} else if (name == "@@@state") {
m_state.parse_state_katoms(begin, end, m_katoms);
// A @@@klammerset declaration inserts its files' katoms into the stream
// at the declaration point, invalidating the span list, so the scan
// restarts. Processed spans are marked replaced and are never found
// again, which also bounds the restarts.
bool rescan = true;
while (rescan) {
rescan = false;
for (const auto& [op, cl] : find_spans(m_katoms, begin_machine_def, end_machine_def, true, command_name)) {
auto [begin, end] = find_span_katoms(m_katoms, op, cl);
//std::string name = trim_char(begin->m_text, '@');
std::string name = begin->m_text;
if (name == "@@@target") {
m_targets.add(begin, end, m_katoms);
} else if (name == "@@@argtype") {
m_argtypes.add(begin, end, m_katoms);
} else if (name == "@@@state") {
m_state.parse_state_katoms(begin, end, m_katoms);
} else if (name == "@@@klammerset") {
if (auto klammerset = m_klammersets.add(begin, end, m_katoms)) {
load_klammerset_files(*klammerset, end);
rescan = true;
break;
}
}
}
}
}
void Machine::load_klammerset_files(const Klammerset& klammerset, katom_iter insert_at)
{
(void)K::log(2, "Loading klammerset \"" + klammerset.m_symbol + "\"");
// Relative names resolve against the declaring file's directory, never
// the cwd. :requires files are read before the set's own files; each
// holds its own @@@klammerset declaration, whose already-loaded guard
// makes repeated requirements a no-op.
fs::path declaring(klammerset.m_loc.m_filename);
fs::path base = fs::exists(declaring) ? declaring : fs::current_path();
std::string base_dir = (is_directory(base) ? base : base.parent_path()).string();
// A :requires entry may be a bare symbol, resolved on the klammerset
// search path with the declaring directory as the local stage; :files
// entries are always filenames (this set's own definition files).
std::vector<std::string> filenames {};
for (const auto& required : klammerset.m_requires) {
if (is_klammerset_symbol(required)) {
filenames.push_back(
resolve_klammerset_symbol(required, base_dir, klammerset.m_loc).string());
} else {
filenames.push_back(required);
}
}
filenames.insert(filenames.end(), klammerset.m_files.begin(), klammerset.m_files.end());
// Collect all files into one list and insert once: insert_at is
// invalidated by the first insertion into m_katoms.
katom_list loaded {};
for (const auto& filename : filenames) {
fs::path pathname = resolve_relative_to(filename, base);
if (!fs::exists(pathname)) {
throw Klammerset_error(
"Klammerset \"" + klammerset.m_symbol + "\" lists the file \"" + filename
+ "\", which does not exist (resolved to \"" + pathname.string() + "\")",
klammerset.m_loc);
}
pathname = fs::canonical(pathname);
m_state.add_search_dir(pathname.parent_path().string());
std::string text = trim_right(string_from_file(pathname.string()));
katom_list ks = katomize(line_split(text), pathname);
process_katoms(ks, pathname);
loaded.insert(loaded.end(), ks.begin(), ks.end());
}
m_katoms.insert(insert_at, loaded.begin(), loaded.end());
}
void Machine::extract_klammer_definitions(katom_list katoms)
{
fmsg() << katoms << "\n";
@@ -489,12 +549,12 @@ katom_list Machine::apply_klammer(
return result;
}
void Machine::apply_klammer_set(
Klammer_set& klammer_set, katom_list& katoms, const std::string& target, katom_iter begin, katom_iter end)
void Machine::apply_klammer_registry(
Klammer_registry& klammer_registry, katom_list& katoms, const std::string& target, katom_iter begin, katom_iter end)
{
(void)K::log(3, "Klammer");
std::string name = trim_char(begin->m_text, '@');
katom_list applied_katoms = apply_klammer(klammer_set.m_klammers[name], target, begin, end);
katom_list applied_katoms = apply_klammer(klammer_registry.m_klammers[name], target, begin, end);
for (auto& k : applied_katoms) {
if (k.m_type == katom_t::bar || k.m_type == katom_t::double_bar || k.m_type == katom_t::option_name) {
k.m_type = katom_t::text;
@@ -504,16 +564,16 @@ void Machine::apply_klammer_set(
}
void Machine::apply(
Klammer_set& klammer_set, katom_list& katoms, const std::string& target)
Klammer_registry& klammer_registry, katom_list& katoms, const std::string& target)
{
(void)K::log(3, "Klammer_set");
(void)K::log(3, "Klammer_registry");
for (const auto& [op, cl] : find_spans(
katoms, begin_klammer_apply, end_klammer_apply, true, command_name)) {
auto [begin, end] = find_span_katoms(katoms, op, cl);
klammer_set.check_klammer(
klammer_registry.check_klammer(
klammer_name_from_katom(begin->m_text, begin->m_loc),
target, begin->m_loc);
apply_klammer_set(klammer_set, katoms, target, begin, end);
apply_klammer_registry(klammer_registry, katoms, target, begin, end);
}
}

View File

@@ -4,9 +4,10 @@
// #include "source.h"
#include "katom_list.h"
#include "klammer_set.h"
#include "target_set.h"
#include "argtype_set.h"
#include "klammer_registry.h"
#include "klammerset_registry.h"
#include "target_registry.h"
#include "argtype_registry.h"
#include "state.h"
#include "error.h"
@@ -20,11 +21,12 @@ public:
Machine();
// Copy constructor
Machine(const Machine& other)
Machine(const Machine& other)
: m_argtypes(other.m_argtypes)
, m_state(other.m_state)
, m_targets(other.m_targets)
, m_klammers(other.m_klammers)
, m_klammersets(other.m_klammersets)
, m_result(other.m_result)
{}
@@ -35,6 +37,7 @@ public:
m_state = other.m_state;
m_targets = other.m_targets;
m_klammers = other.m_klammers;
m_klammersets = other.m_klammersets;
m_result = other.m_result;
}
return *this;
@@ -65,6 +68,7 @@ public:
bool klammers=true, bool eval=true, bool cond=true, bool read=true);
void expand_constant_klammers(katom_list& katoms, const Katom& op, const Katom& cl);
void load_klammerset_files(const Klammerset& klammerset, katom_iter insert_at);
void extract_machine_definitions();
void extract_klammer_definitions();
void extract_klammer_definitions(katom_list katoms);
@@ -72,18 +76,19 @@ public:
katom_list apply_klammer(Klammer& klammer, const std::string& target, katom_iter arguments_begin, katom_iter arguments_end);
void apply_klammer_set(Klammer_set& klammer_set,
void apply_klammer_registry(Klammer_registry& klammer_registry,
katom_list& katoms, const std::string& target, katom_iter begin, katom_iter end);
void apply(Klammer_set& klammer_set, katom_list& katoms, const std::string& target);
void apply(Klammer_registry& klammer_registry, katom_list& katoms, const std::string& target);
std::string run_phase_functions();
std::string apply(const std::string& target_name, bool final_processing=true, bool escape_characters=true);
Argtype_set m_argtypes {};
Argtype_registry m_argtypes {};
State m_state {};
Target_set m_targets {};
Klammer_set m_klammers {};
Target_registry m_targets {};
Klammer_registry m_klammers {};
Klammerset_registry m_klammersets {};
input_sources_t m_sources {};
std::string m_result {};
std::vector<Katom> m_katoms {};

View File

@@ -461,12 +461,12 @@ std::ostream& operator<<(std::ostream& os, const Klammer::components& kc)
}
// Klammer_set
// Klammer_registry
std::ostream& operator<<(std::ostream& os, const Klammer_set& ks)
std::ostream& operator<<(std::ostream& os, const Klammer_registry& ks)
{
for (auto klam : ks.m_klammers) {
for (auto [k,v] : klam.second.m_defloc) {
for (const auto& klam : ks.m_klammers) {
for (const auto& [k,v] : klam.second.m_defloc) {
os << " " << k << sp_arrow << v << "\n";
}
//klam.second.m_defloc.str() << "\n";
@@ -485,30 +485,62 @@ void show_arrow_pair(std::ostream& os, std::pair<std::string,std::string> transf
std::ostream& operator<<(std::ostream& os, const Target& t)
{
os << "<\U0001D517" << broken_bar << t.m_name << broken_bar << t.m_desc << broken_bar;
for (auto i : t.m_includes) {
for (const auto& i : t.m_includes) {
os << i << right_arrow << t.m_name << broken_bar;
}
for (auto p : t.m_provides) {
for (const auto& p : t.m_provides) {
os << t.m_name << right_arrow << p << broken_bar;
}
os << ">";
return os;
}
// Target_set
// Target_registry
std::ostream& operator<<(std::ostream& os, const Target_set& ts)
std::ostream& operator<<(std::ostream& os, const Target_registry& ts)
{
size_t width = 0;
for (auto t : ts.m_targets) {
for (const auto& t : ts.m_targets) {
width = std::max(width, t.first.size());
}
for (auto [name, target] : ts.m_targets) {
for (const auto& [name, target] : ts.m_targets) {
os << std::setw(width) << name << sp_arrow << target << "\n";
}
return os;
}
// Klammerset
std::ostream& operator<<(std::ostream& os, const Klammerset& ks)
{
os << "<\U0001D516" << broken_bar << ks.m_symbol << broken_bar << ks.m_desc;
if (!ks.m_date.empty()) {
os << broken_bar << ks.m_date;
}
if (!ks.m_requires.empty()) {
os << broken_bar << "requires " << join(ks.m_requires, " / ");
}
if (!ks.m_files.empty()) {
os << broken_bar << join(ks.m_files, " / ");
}
os << ">";
return os;
}
// Klammerset_registry
std::ostream& operator<<(std::ostream& os, const Klammerset_registry& kr)
{
size_t width = 0;
for (const auto& k : kr.m_klammersets) {
width = std::max(width, k.first.size());
}
for (const auto& [symbol, klammerset] : kr.m_klammersets) {
os << std::setw(width) << symbol << sp_arrow << klammerset << "\n";
}
return os;
}
// Machine
@@ -537,6 +569,7 @@ std::ostream& operator<<(std::ostream& os, const Machine& m)
std::string argtypes_desc = m.m_argtypes.describe(false, 8);
std::string state_desc = m.m_state.describe(false, 3);
std::string targets_desc = m.m_targets.describe(4);
std::string klammersets_desc = m.m_klammersets.describe(4);
std::string klammer_desc = m.m_klammers.describe(2);
std::string source_desc = describe_sources(m);
@@ -544,12 +577,13 @@ std::ostream& operator<<(std::ostream& os, const Machine& m)
<< label("Sources", m.m_sources.size()) << source_desc << "\n"
<< label("Argtypes", m.m_argtypes.m_names.size()) << argtypes_desc << "\n"
<< label("Targets", m.m_targets.m_names.size()) << targets_desc << "\n"
<< label("Klammersets", m.m_klammersets.m_symbols.size()) << klammersets_desc << "\n"
<< label("Klammers", m.m_klammers.m_klammers.size()) << klammer_desc << "\n"
<< label("State", m.m_state.m_frames.size()) << state_desc;
<< label("State", m.m_state.m_frames.size()) << state_desc;
return os;
}
void modify_stream(std::string name)
void modify_stream(const std::string& name)
{
if (name == "all") std::cout << kall;
if (name == "type") std::cout << ktype;

View File

@@ -8,9 +8,10 @@
#include "argtype.h"
#include "argument.h"
#include "klammer.h"
#include "klammer_set.h"
#include "klammer_registry.h"
#include "klammerset_registry.h"
#include "state.h"
#include "target_set.h"
#include "target_registry.h"
#include "machine.h"
#include "file.h"
@@ -143,16 +144,22 @@ std::ostream& operator<<(std::ostream& os, const Klammer::variable_map_t& vm);
// Klammer::components
std::ostream& operator<<(std::ostream& os, const Klammer::components& kc);
// Klammer_set
std::ostream& operator<<(std::ostream& os, const Klammer_set& ks);
// Klammer_registry
std::ostream& operator<<(std::ostream& os, const Klammer_registry& ks);
// Target
std::ostream& operator<<(std::ostream& os, const Target& t);
// Target_set
std::ostream& operator<<(std::ostream& os, const Target_set& ts);
// Target_registry
std::ostream& operator<<(std::ostream& os, const Target_registry& ts);
// Klammerset
std::ostream& operator<<(std::ostream& os, const Klammerset& ks);
// Klammerset_registry
std::ostream& operator<<(std::ostream& os, const Klammerset_registry& kr);
// Machine
std::ostream& operator<<(std::ostream& os, const Machine& m);
void modify_stream(std::string name);
void modify_stream(const std::string& name);

View File

@@ -10,7 +10,7 @@
int State::class_id = 0;
bool Var::defined()
bool Var::defined() const
{
return !m_name.empty();
}
@@ -24,18 +24,19 @@ std::vector<std::string> Frame::names() const
return result;
}
void Frame::set(std::string name, std::string value,
std::string delim, std::string desc, Locator loc, Argtype argtype)
void Frame::set(const std::string& name, const std::string& value,
const std::string& delim, const std::string& desc, const Locator& loc,
const Argtype& argtype)
{
Var v(name, value, delim, desc, loc, argtype);
m_vars[name] = v;
}
std::pair<Var, bool> Frame::get(std::string name)
std::pair<Var, bool> Frame::get(const std::string& name) const
{
std::pair<Var, bool> result {Var(), false};
if (m_vars.contains(name)) {
result = {m_vars[name], true};
result = {m_vars.at(name), true};
}
return result;
}
@@ -43,7 +44,7 @@ std::pair<Var, bool> Frame::get(std::string name)
// State
void State::open_frame(std::string name)
void State::open_frame(const std::string& name)
{
Frame f(name);
// m_frames.push_back(f);
@@ -58,19 +59,20 @@ void State::close_frame()
}
// Preserve altered machine state:
string_map machine_state {};
for (auto [name, var] : m_frames[0].m_vars) {
for (const auto& [name, var] : m_frames[0].m_vars) {
if (contains(name, "K_")) {
machine_state[name] = var.m_value;
}
}
m_frames.erase(m_frames.begin());
for (auto [name, value] : machine_state) {
for (const auto& [name, value] : machine_state) {
set(name, value, true);
}
}
void State::set(std::string name, std::string value, bool update,
std::string delim, std::string desc, Locator loc, Argtype argtype)
void State::set(const std::string& name, const std::string& value, bool update,
const std::string& delim, const std::string& desc, const Locator& loc,
const Argtype& argtype)
{
if (m_frames.empty()) {
std::stringstream ss {};
@@ -89,9 +91,9 @@ void State::set(std::string name, std::string value, bool update,
m_frames[0].set(name, value, delim, desc, loc, argtype);
}
void State::set(std::map<std::string, std::string> varmap)
void State::set(const std::map<std::string, std::string>& varmap)
{
for (auto [k, v] : varmap) {
for (const auto& [k, v] : varmap) {
set(k, v);
}
}
@@ -107,7 +109,7 @@ void State::set(const std::map<std::string, std::string>& varmap,
}
void State::replace(std::string name, std::string value, bool error_if_not_defined)
void State::replace(const std::string& name, const std::string& value, bool error_if_not_defined)
{
if (error_if_not_defined && !get(name).defined()) {
std::stringstream ss {};
@@ -120,14 +122,14 @@ void State::replace(std::string name, std::string value, bool error_if_not_defin
void State::add_environment_frame()
{
open_frame(klammerstate::shell_environment_name);
for (auto [name, value] : environment_variables()) {
for (const auto& [name, value] : environment_variables()) {
set(name, value);
}
}
Var State::get(std::string name, bool error_if_not_defined, Locator loc)
Var State::get(const std::string& name, bool error_if_not_defined, const Locator& loc) const
{
for (auto f : m_frames) {
for (const auto& f : m_frames) {
auto [result, found] = f.get(name);
if (found) {
return result;
@@ -141,12 +143,12 @@ Var State::get(std::string name, bool error_if_not_defined, Locator loc)
}
}
std::string State::value(std::string name, bool error_if_not_defined, Locator loc)
std::string State::value(const std::string& name, bool error_if_not_defined, const Locator& loc) const
{
return get(name, error_if_not_defined, loc).m_value;
}
std::string State::subst(std::string text, bool quote_values)
std::string State::subst(const std::string& text, bool quote_values) const
{
(void)K::log(3);
std::string result = text;
@@ -198,7 +200,8 @@ void State::subst(katom_iter begin, katom_iter end)
}
void prohibit_change_of_description(
std::string name, bool defined, std::string old_desc, std::string new_desc, Locator old_loc, Locator loc)
const std::string& name, bool defined, const std::string& old_desc,
const std::string& new_desc, const Locator& old_loc, const Locator& loc)
{
if (defined && !old_desc.empty() && !new_desc.empty()) {
std::stringstream ss {};
@@ -216,7 +219,7 @@ void prohibit_change_of_description(
// Parameter_set m_parameters = Parameter_set("name :value :append :replace :delim :desc");
void State::parse_state_katoms(katom_iter begin, katom_iter end, katom_list katoms)
void State::parse_state_katoms(katom_iter begin, katom_iter end, katom_list& katoms)
{
(void)K::log(3, *begin, *(end-1));
// std::cout << "parse_katoms: " << std::pair(begin + 1, end - 1) << "\n";
@@ -246,11 +249,11 @@ void State::parse_state_katoms(katom_iter begin, katom_iter end, katom_list kato
ignore_whitespace(next_iter, katoms);
}
std::vector<std::string> State::all_names()
std::vector<std::string> State::all_names() const
{
std::vector<std::string> result {};
for (Frame f : m_frames) {
for (auto [name, var] : f.m_vars) {
for (const Frame& f : m_frames) {
for (const auto& [name, var] : f.m_vars) {
// std::cout << "Name: " << name << "\n";
result.push_back(name);
}
@@ -282,7 +285,7 @@ std::string State::python_code()
// the file whose @eval names it is found regardless of the cwd.
python_dirs.insert(python_dirs.end(),
m_search_dirs.begin(), m_search_dirs.end());
for (auto d : python_dirs) {
for (const auto& d : python_dirs) {
auto python_files = pathnames_with_extension(d, "py");
if (!python_files.empty()) {
ss << "sys.path.append('" << d << "')\n";
@@ -308,12 +311,12 @@ std::string State::describe(bool show_environment, int margin_size) const
std::string margin(margin_size, ' ');
int i = m_frames.size() - 1;
std::stringstream ss {};
for (auto f : m_frames) {
for (const auto& f : m_frames) {
int width = max_key_length(f.m_vars);
ss << margin << "Frame " << i-- << ": " << f.m_name << "\n";
if ((f.m_name != klammerstate::shell_environment_name) ||
(show_environment && f.m_name == klammerstate::shell_environment_name)) {
for (auto [key, value] : f.m_vars) {
for (const auto& [key, value] : f.m_vars) {
std::string print_value = value.m_value;
if (print_value == klammerstate::no_value) {
print_value = "<no-value>";

View File

@@ -14,9 +14,9 @@ class Var
{
public:
Var() = default;
Var(std::string name, std::string value=klammerstate::no_value,
std::string delim=":", std::string desc="", Locator loc=Locator(),
Argtype argtype=Argtype())
Var(const std::string& name, const std::string& value=klammerstate::no_value,
const std::string& delim=":", const std::string& desc="", const Locator& loc=Locator(),
const Argtype& argtype=Argtype())
: m_name(name)
, m_value(value)
, m_delim(delim)
@@ -24,7 +24,7 @@ public:
, m_loc(loc)
, m_argtype(argtype)
{};
bool defined();
bool defined() const;
std::string m_name {};
std::string m_value {};
@@ -41,15 +41,15 @@ inline std::string shell_environment_name = "Shell environment";
class Frame
{
public:
Frame(std::string name)
Frame(const std::string& name)
: m_name(name)
{};
std::vector<std::string> names() const;
void set(std::string name, std::string value,
std::string delim=":", std::string desc="", Locator loc=Locator(),
Argtype argtype=Argtype());
std::pair<Var, bool> get(std::string name);
void set(const std::string& name, const std::string& value,
const std::string& delim=":", const std::string& desc="", const Locator& loc=Locator(),
const Argtype& argtype=Argtype());
std::pair<Var, bool> get(const std::string& name) const;
std::string m_name {};
std::map<std::string, Var> m_vars {};
@@ -59,24 +59,24 @@ class State
{
public:
static int class_id;
void open_frame(std::string name);
void open_frame(const std::string& name);
void close_frame();
void set(std::string name, std::string value, bool update=false,
std::string delim=" ", std::string desc="", Locator loc=Locator(),
Argtype argtype=Argtype());
void set(std::map<std::string, std::string> varmap);
void set(const std::string& name, const std::string& value, bool update=false,
const std::string& delim=" ", const std::string& desc="", const Locator& loc=Locator(),
const Argtype& argtype=Argtype());
void set(const std::map<std::string, std::string>& varmap);
void set(const std::map<std::string, std::string>& varmap,
const Parameter_set& parameters);
void replace(std::string name, std::string value, bool error_if_not_defined=true);
void replace(const std::string& name, const std::string& value, bool error_if_not_defined=true);
void add_environment_frame();
Var get(std::string name, bool error_if_not_defined=false, Locator loc=Locator());
std::string value(std::string name, bool error_if_not_defined=true, Locator loc=Locator());
Var get(const std::string& name, bool error_if_not_defined=false, const Locator& loc=Locator()) const;
std::string value(const std::string& name, bool error_if_not_defined=true, const Locator& loc=Locator()) const;
std::string subst(std::string text, bool quote_values=false);
std::string subst(const std::string& text, bool quote_values=false) const;
void subst(std::vector<Katom>::iterator begin, std::vector<Katom>::iterator end);
void parse_state_katoms(std::vector<Katom>::iterator begin, std::vector<Katom>::iterator end, katom_list katoms);
std::vector<std::string> all_names();
void parse_state_katoms(std::vector<Katom>::iterator begin, std::vector<Katom>::iterator end, katom_list& katoms);
std::vector<std::string> all_names() const;
void add_search_dir(const std::string& dir);
std::string python_code();
std::string describe(bool show_environment=false, int margin_size=2) const;

View File

@@ -7,32 +7,32 @@
//#include "text.h"
#include "util.h"
void Target::add_transform(std::string original, std::string transformed)
void Target::add_transform(const std::string& original, const std::string& transformed)
{
m_transforms.push_back({original, transformed});
}
void Target::add_transforms(std::string transforms)
void Target::add_transforms(const std::string& transforms)
{
add_transforms(parse_transforms(transforms));
}
void Target::add_transforms(string_pairs transforms)
void Target::add_transforms(const string_pairs& transforms)
{
for (auto [old_str, new_str] : transforms) {
for (const auto& [old_str, new_str] : transforms) {
add_transform(old_str, new_str);
}
}
void Target::transform(katom_list& katoms)
void Target::transform(katom_list& katoms) const
{
(void)K::log(3);
std::for_each(
katoms.begin(), katoms.end(),
[this] (Katom& k) {
katoms.begin(), katoms.end(),
[this] (Katom& k) {
// std::cout << "transform: " << k << "\n";
if (k.m_type != katom_t::literal) {
for (auto [a, b] : this->m_transforms) {
for (const auto& [a, b] : this->m_transforms) {
// std::cout << " " << a << right_arrow << b << "\n";
k.m_text = string_replace(k.m_text, a, b);
}
@@ -41,7 +41,7 @@ void Target::transform(katom_list& katoms)
}
std::vector<std::pair<std::string, std::string>>
parse_transforms(std::string transform_string)
parse_transforms(const std::string& transform_string)
{
(void)K::log(3);
if (trim(transform_string).empty()) return {};
@@ -59,7 +59,7 @@ parse_transforms(std::string transform_string)
return result;
}
void Target::add_escapes(std::string escape_spec)
void Target::add_escapes(const std::string& escape_spec)
{
auto words = word_split(escape_spec);
for (size_t i = 0; i + 1 < words.size(); i += 2) {
@@ -142,9 +142,9 @@ std::string hide_structural_characters(const std::string& s)
return result;
}
void Target::add_after_apply(std::string function_specs)
void Target::add_after_apply(const std::string& function_specs)
{
for (auto f : regex_split(function_specs, std::regex(R"(\s+;\s+)"), true)) {
for (const auto& f : regex_split(function_specs, std::regex(R"(\s+;\s+)"), true)) {
// msg() << "Add " << m_name << " after-apply: " << f << "\n";
m_after_apply.push_back(f);
}

View File

@@ -11,25 +11,25 @@ class Target
{
public:
Target() = default;
// Target(std::vector<Katom>::iterator begin, std::vector<Katom>::iterator end, Argtype_set argtypes);
Target(std::string name, std::string desc, Locator loc)
// Target(std::vector<Katom>::iterator begin, std::vector<Katom>::iterator end, Argtype_registry argtypes);
Target(const std::string& name, const std::string& desc, const Locator& loc)
: m_name(name)
, m_desc(desc)
, m_loc(loc)
{};
void add_transform(std::string original, std::string transformed);
void add_transforms(std::string transforms);
void add_transforms(std::vector<std::pair<std::string, std::string>> transforms);
void transform(std::vector<Katom>& katoms);
void add_transform(const std::string& original, const std::string& transformed);
void add_transforms(const std::string& transforms);
void add_transforms(const std::vector<std::pair<std::string, std::string>>& transforms);
void transform(std::vector<Katom>& katoms) const;
void add_escapes(std::string escape_spec);
void add_escapes(const std::string& escape_spec);
std::string escape_text(std::string text) const;
std::string unescape_text(std::string text) const;
std::string resolve_escapes(std::string text) const;
static std::string escape_marker(const std::string& ch);
void add_after_apply(std::string function_specs);
void add_after_apply(const std::string& function_specs);
std::string m_name {};
std::string m_desc {};
@@ -40,13 +40,13 @@ public:
Locator m_loc {};
std::vector<std::pair<std::string, std::string>> m_transforms {};
std::vector<std::pair<std::string, std::string>> m_escapes {};
// Argtype_set m_argtypes {};
// Argtype_registry m_argtypes {};
};
std::vector<std::pair<std::string, std::string>>
parse_transforms(std::string transform_string);
parse_transforms(const std::string& transform_string);
// Decode every KTESC<hex>KTESC marker in text back to its original
// characters. Used for the final output (after target-declared escapes have

View File

@@ -1,8 +1,7 @@
#include <sstream>
#include <iterator>
#include <algorithm>
#include "target_set.h"
#include "target_registry.h"
#include "error.h"
#include "log.h"
#include "util.h"
@@ -10,10 +9,10 @@
#include "log.h"
#include "katom.h"
std::string Target_set::declare_name = "k";
std::string Target_set::general_name = "*";
std::string Target_registry::declare_name = "k";
std::string Target_registry::general_name = "*";
Target_set::Target_set()
Target_registry::Target_registry()
: m_parameters(Parameter_set("name | desc :after_apply :after_write :includes :escape | transforms.rest"))
{
Target k(declare_name, "Description of parameters and klammer result", Locator());
@@ -22,16 +21,15 @@ Target_set::Target_set()
add(general);
}
void Target_set::add(Target target)
void Target_registry::add(Target target)
{
(void)K::log(3, target);
check_for_previous_definition(target.m_name, target.m_loc);
m_targets[target.m_name] = target;
m_names.push_back(target.m_name);
m_descs.push_back(target.m_desc);
}
void Target_set::add(std::vector<Katom>::iterator begin, std::vector<Katom>::iterator end, std::vector<Katom>& katoms)
void Target_registry::add(std::vector<Katom>::iterator begin, std::vector<Katom>::iterator end, std::vector<Katom>& katoms)
{
(void)K::log(3, *begin, *(end - 1));
auto [positional, optional, rest] =
@@ -40,14 +38,10 @@ void Target_set::add(std::vector<Katom>::iterator begin, std::vector<Katom>::ite
//std::cout << ktype << "Transformed: " << kreplaced << std::pair(begin, end) << "\n";
//std::cout << values << "\n";
check_for_previous_definition(values["name"], begin->m_loc);
Target target(values["name"], values["desc"], begin->m_loc);
target.add_transforms(values["transforms"]);
target.add_escapes(values["escape"]);
target.add_after_apply(values["after_apply"]);
// for (auto included_target : word_split(values["includes"])) {
// msg() << "Include: " << included_target << "\n";
// }
target.m_includes = word_split(values["includes"]);
// Inherit escapes from included targets
for (const auto& included : target.m_includes) {
@@ -57,15 +51,13 @@ void Target_set::add(std::vector<Katom>::iterator begin, std::vector<Katom>::ite
}
}
}
m_targets[target.m_name] = target;
m_names.push_back(target.m_name);
// Registration (and the previous-definition check) goes through
// add(Target) -- the single registration path.
add(target);
for (auto [name, defined_target] : m_targets) {
// msg() << name << sp_arrow << defined_target << "\n";
for (auto& [name, defined_target] : m_targets) {
if (is_in(name, target.m_includes)) {
defined_target.m_provides.push_back(target.m_name);
// msg() << " " << name << " provides " << target.m_name << "\n " << defined_target.m_provides << "\n";
m_targets[name] = defined_target;
}
}
@@ -76,56 +68,62 @@ void Target_set::add(std::vector<Katom>::iterator begin, std::vector<Katom>::ite
}
void Target_set::check_for_previous_definition(std::string name, Locator loc)
void Target_registry::check_for_previous_definition(const std::string& name, const Locator& loc) const
{
if (has(name)) {
Target current = m_targets[name];
const Target& current = m_targets.at(name);
throw Target_error("Target \"" + name + "\" is already defined:\n " + current.m_loc.desc(),
loc, false);
}
}
bool Target_set::has(std::string target_name)
bool Target_registry::has(const std::string& target_name) const
{
return std::ranges::find(m_names, target_name) != m_names.end();
// Membership comes from the map; m_names exists only to preserve
// definition order for describe().
return m_targets.count(target_name) > 0;
}
Target Target_set::get(std::string target_name, Locator loc)
Target Target_registry::get(const std::string& target_name, const Locator& loc) const
{
if (has(target_name) || target_name == Target_set::general_name) {
if (has(target_name) || target_name == Target_registry::general_name) {
return m_targets.at(target_name);
} else {
throw Target_error("Target " + target_name + " does not exist", loc);
}
}
void Target_set::transform(std::string target_name, katom_list& katoms)
void Target_registry::transform(const std::string& target_name, katom_list& katoms) const
{
(void)K::log(3);
m_targets[target_name].transform(katoms);
m_targets.at(target_name).transform(katoms);
}
std::vector<std::string> Target_set::user_defined()
std::vector<std::string> Target_registry::user_defined() const
{
return collect_if(
m_names, [](auto name) {
return name != Target_set::declare_name && name != Target_set::general_name; });
m_names, [](const auto& name) {
return name != Target_registry::declare_name && name != Target_registry::general_name; });
}
std::vector<std::string> Target_set::applicable()
std::vector<std::string> Target_registry::applicable() const
{
return collect_if(
m_names, [](auto name) {
return name != Target_set::declare_name; });
m_names, [](const auto& name) {
return name != Target_registry::declare_name; });
}
std::string Target_set::describe(int margin, bool long_format) const
std::string Target_registry::describe(int margin, bool long_format) const
{
std::string tab(margin, ' ');
std::stringstream ss {};
std::vector<std::string> descs {};
for (const std::string& name : m_names) {
descs.push_back(m_targets.at(name).m_desc);
}
auto name_width = max_length(m_names);
auto desc_width = max_length(m_descs);
auto desc_width = max_length(descs);
for (const std::string& name : m_names) {
const Target& t = m_targets.at(name);
if (long_format) {

View File

@@ -6,17 +6,17 @@
#include "argument_set.h"
#include "katom.h"
class Target_set
class Target_registry
{
public:
static std::string declare_name;
static std::string general_name;
Target_set();
Target_registry();
void add(Target target);
void add(std::vector<Katom>::iterator begin, std::vector<Katom>::iterator end, std::vector<Katom>& katoms);
void check_for_previous_definition(std::string name, Locator loc);
void check_for_previous_definition(const std::string& name, const Locator& loc) const;
/*
@@ -27,19 +27,18 @@ public:
*/
bool has(std::string target_name);
Target get(std::string target_name, Locator loc);
void transform(std::string target_name, std::vector<Katom>& katoms);
bool has(const std::string& target_name) const;
Target get(const std::string& target_name, const Locator& loc) const;
void transform(const std::string& target_name, std::vector<Katom>& katoms) const;
std::vector<std::string> user_defined();
std::vector<std::string> applicable();
std::vector<std::string> user_defined() const;
std::vector<std::string> applicable() const;
std::string describe(int margin=2, bool long_format=false) const;
//Argtype_set m_argtypes {};
//Argtype_registry m_argtypes {};
std::map<std::string, Target> m_targets {};
std::vector<std::string> m_names {};
std::vector<std::string> m_descs {};
Parameter_set m_parameters {};
@@ -51,7 +50,7 @@ public:
//Parameter_set m_parameters =
// Parameter_set(katomize({"name :desc | transforms.rest"}, "target_set"));
// Parameter_set(katomize({"name :desc | transforms.rest"}, "target_registry"));
/*
// Targets(Statevar_set& statevars);

View File

@@ -111,7 +111,7 @@ std::string regex_escape(const std::string& s)
return result;
}
strings_t regex_split(std::string s, std::regex re, bool trim_parts)
strings_t regex_split(const std::string& s, const std::regex& re, bool trim_parts)
{
strings_t result = {};
if (s.size() == 0) {
@@ -134,17 +134,17 @@ strings_t word_split(const std::string& s)
return regex_split(s, std::regex("\\s+"));
}
bool is_in(std::string s, strings_t v)
bool is_in(const std::string& s, const strings_t& v)
{
return find(v.begin(), v.end(), s) != v.end();
}
bool is_not_in(std::string s, strings_t v)
bool is_not_in(const std::string& s, const strings_t& v)
{
return find(v.begin(), v.end(), s) == v.end();
}
strings_t find_all(std::string str, std::regex pattern, int match_group)
strings_t find_all(const std::string& str, const std::regex& pattern, int match_group)
{
std::sregex_iterator end {};
strings_t result;
@@ -153,7 +153,7 @@ strings_t find_all(std::string str, std::regex pattern, int match_group)
return result;
}
strings_t find_all(std::string str, std::string pattern, int match_group)
strings_t find_all(const std::string& str, const std::string& pattern, int match_group)
{
return find_all(str, std::regex(pattern), match_group);
}
@@ -168,7 +168,7 @@ strings_t split_into_paragraphs(const std::string& s)
}
std::string add_margin(std::string s, unsigned int margin_size)
std::string add_margin(const std::string& s, unsigned int margin_size)
{
auto margin = std::string(margin_size, ' ');
return trim_right(
@@ -297,7 +297,7 @@ std::string to_be(int count, bool present)
return result;
}
int max_length(strings_t ss)
int max_length(const strings_t& ss)
{
size_t result = 0;
for_each(ss.begin(), ss.end(),
@@ -349,7 +349,7 @@ std::vector<std::pair<std::string, std::string>> environment_variables(bool allo
return result;
}
std::string replace_environment_variables(std::string str)
std::string replace_environment_variables(const std::string& str)
{
if (str.find('{') == std::string::npos || str.find('}') == std::string::npos) {
return str;
@@ -398,10 +398,10 @@ std::string abbrev(const std::string& s, unsigned int max_length, bool remove_ne
return result;
}
void remove_element(std::vector<std::string>& ss, std::string removed)
void remove_element(std::vector<std::string>& ss, const std::string& removed)
{
ss.erase(std::remove_if(ss.begin(), ss.end(),
[&removed](std::string s) { return s == removed; }),
[&removed](const std::string& s) { return s == removed; }),
ss.end());
}
@@ -428,7 +428,7 @@ std::string display_string(const std::string& s, unsigned int width, bool replac
return result;
}
std::pair<std::string,std::string> extract_parameter_type(std::string parameter_name)
std::pair<std::string,std::string> extract_parameter_type(const std::string& parameter_name)
{
std::regex name_pat { R"((\w+)\.(\w+))" };
std::smatch match {};
@@ -487,7 +487,8 @@ std::string get_env_var(const std::string& var) {
return val ? std::string(val) : "";
}
std::string freplace(const std::string src, std::regex pattern, std::function<std::string(std::smatch)> func)
std::string freplace(const std::string& src, const std::regex& pattern,
const std::function<std::string(std::smatch)>& func)
{
std::string result {};
std::smatch match;

View File

@@ -36,13 +36,13 @@ std::string string_replace(const std::string& source, const std::string& old_str
std::string regex_escape(const std::string& s);
bool contains(const std::string& str, const std::string& substr);
bool contains(const std::vector<std::string>& strings, const std::string& element);
std::vector<std::string> regex_split(std::string s, std::regex re, bool trim_parts=true);
std::vector<std::string> regex_split(const std::string& s, const std::regex& re, bool trim_parts=true);
std::vector<std::string> word_split(const std::string& s);
bool is_in(std::string s, std::vector<std::string> v);
bool is_not_in(std::string s, std::vector<std::string> v);
std::vector<std::string> find_all(std::string str, std::regex pattern, int match_group=0);
std::vector<std::string> find_all(std::string str, std::string pattern, int match_group=0);
std::string add_margin(std::string s, unsigned int margin_size);
bool is_in(const std::string& s, const std::vector<std::string>& v);
bool is_not_in(const std::string& s, const std::vector<std::string>& v);
std::vector<std::string> find_all(const std::string& str, const std::regex& pattern, int match_group=0);
std::vector<std::string> find_all(const std::string& str, const std::string& pattern, int match_group=0);
std::string add_margin(const std::string& s, unsigned int margin_size);
std::string justify(const std::string& input_text, unsigned int text_width=80, unsigned int margin_width=0);
std::string join(const std::vector<std::string>& ss, const std::string& separator = " ");
std::string join(int argc, char* array[], const std::string& separator = " ");
@@ -50,26 +50,27 @@ std::string argv_to_string(int argc, char* argv[]);
std::string plural(const std::string& word, int count);
std::string plural(const std::string& word, const std::vector<std::string>& things);
std::string to_be(int count, bool present = true);
int max_length(std::vector<std::string> ss);
int max_length(const std::vector<std::string>& ss);
std::vector<std::pair<std::string, std::string>> environment_variables(bool allow_empty_definitions=true);
std::string replace_environment_variables(std::string str);
std::string replace_environment_variables(const std::string& str);
std::string abbrev(const std::string& s, unsigned int max_length=65, bool remove_newlines=true);
void remove_element(std::vector<std::string>& ss, std::string removed);
void remove_element(std::vector<std::string>& ss, const std::string& removed);
void remove_duplicates(std::vector<std::string>& ss);
std::string display_string(const std::string& s, unsigned int width=40, bool replace_newlines=true);
std::pair<std::string,std::string> extract_parameter_type(std::string parameter_name);
std::pair<std::string,std::string> extract_parameter_type(const std::string& parameter_name);
std::tuple<std::string, std::string, bool> regex_split_prefix(const std::regex& pattern, const std::string& text);
std::vector<std::string> dlist_split(const std::string& s);
std::string get_env_var(const std::string& var);
std::string freplace(const std::string src, std::regex pattern, std::function<std::string(std::smatch)> func);
std::string freplace(const std::string& src, const std::regex& pattern,
const std::function<std::string(std::smatch)>& func);
std::string exec(const char* cmd);
inline std::string q_(std::string s)
inline std::string q_(const std::string& s)
{
return "\"" + s + "\"";
}
inline std::string qq_(std::string s)
inline std::string qq_(const std::string& s)
{
if (s.find('\n') == std::string::npos) {
return "\"" + s + "\"";
@@ -97,7 +98,7 @@ bool all_equal(const std::vector<T>& v) {
}
template <typename T>
int max_key_length(std::map<std::string, T> map)
int max_key_length(const std::map<std::string, T>& map)
{
size_t result = 0;
for_each(map.begin(), map.end(),