Initial commit: Klammertext source distribution
Curated source subset assembled by klammertext-dev's doc/make_dist.sh: the Klammermachine (mac), the Standard Klammer Set (sks), the commands (com), editor plugins and install guides (doc), a test subset (tst), and lib/bin placeholders. Builds with 'make -C com'. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
160
mac/target_set.cpp
Normal file
160
mac/target_set.cpp
Normal file
@@ -0,0 +1,160 @@
|
||||
#include <sstream>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
|
||||
#include "target_set.h"
|
||||
#include "error.h"
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
#include "show.h"
|
||||
#include "log.h"
|
||||
#include "katom.h"
|
||||
|
||||
std::string Target_set::declare_name = "k";
|
||||
std::string Target_set::general_name = "*";
|
||||
|
||||
Target_set::Target_set()
|
||||
: 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());
|
||||
Target general(general_name, "General target, used when a target is not specified", Locator());
|
||||
add(k);
|
||||
add(general);
|
||||
}
|
||||
|
||||
void Target_set::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)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);
|
||||
|
||||
//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) {
|
||||
if (m_targets.count(included)) {
|
||||
for (const auto& esc : m_targets[included].m_escapes) {
|
||||
target.m_escapes.push_back(esc);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_targets[target.m_name] = target;
|
||||
m_names.push_back(target.m_name);
|
||||
|
||||
for (auto [name, defined_target] : m_targets) {
|
||||
// msg() << name << sp_arrow << defined_target << "\n";
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// std::for_each(begin, end, [](Katom& k) { k.m_type = katom_t::replaced; });
|
||||
modify_type(katom_t::replaced, begin, end);
|
||||
auto next_iter = end;
|
||||
ignore_whitespace(next_iter, katoms);
|
||||
}
|
||||
|
||||
|
||||
void Target_set::check_for_previous_definition(std::string name, Locator loc)
|
||||
{
|
||||
if (has(name)) {
|
||||
Target current = m_targets[name];
|
||||
throw Target_error("Target \"" + name + "\" is already defined:\n " + current.m_loc.desc(),
|
||||
loc, false);
|
||||
}
|
||||
}
|
||||
|
||||
bool Target_set::has(std::string target_name)
|
||||
{
|
||||
return std::ranges::find(m_names, target_name) != m_names.end();
|
||||
}
|
||||
|
||||
|
||||
Target Target_set::get(std::string target_name, Locator loc)
|
||||
{
|
||||
if (has(target_name) || target_name == Target_set::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)K::log(3);
|
||||
m_targets[target_name].transform(katoms);
|
||||
}
|
||||
|
||||
std::vector<std::string> Target_set::user_defined()
|
||||
{
|
||||
return collect_if(
|
||||
m_names, [](auto name) {
|
||||
return name != Target_set::declare_name && name != Target_set::general_name; });
|
||||
}
|
||||
|
||||
std::vector<std::string> Target_set::applicable()
|
||||
{
|
||||
return collect_if(
|
||||
m_names, [](auto name) {
|
||||
return name != Target_set::declare_name; });
|
||||
}
|
||||
|
||||
std::string Target_set::describe(int margin, bool long_format) const
|
||||
{
|
||||
std::string tab(margin, ' ');
|
||||
std::stringstream ss {};
|
||||
auto name_width = max_length(m_names);
|
||||
auto desc_width = max_length(m_descs);
|
||||
for (const std::string& name : m_names) {
|
||||
const Target& t = m_targets.at(name);
|
||||
if (long_format) {
|
||||
ss << tab << std::setfill(' ') << std::setw(name_width) << std::right << name << " "
|
||||
<< std::setw(desc_width) << std::left << t.m_desc << " "
|
||||
<< t.m_loc.str() << "\n";
|
||||
} else {
|
||||
ss << tab << std::setfill(' ') << std::setw(name_width) << name << sp_arrow << t << "\n";
|
||||
}
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/*
|
||||
void Targets::describe()
|
||||
{
|
||||
std::string intro =
|
||||
"A \"target\" specifies the output format of Klammertext processing. "
|
||||
"Targets are identified by the typical filename extension of the format. "
|
||||
"A klammer defines how it converts its arguments to the appropriate structure for one or more targets. "
|
||||
"The special target \"k\" is used for a klammer definition that describes that klammer's "
|
||||
"arguments and purpose in the various targets for which it is defined. "
|
||||
"If the klammer definition does not specify a target, the klammer can be used for any target.";
|
||||
std::cout << "Klammertext targets\n\n" << justify(intro) << "\n\n";
|
||||
for (std::string name : names) {
|
||||
if (name == Target::any_target_name)
|
||||
continue;
|
||||
targets[name]->describe();
|
||||
std::cout << "\n";
|
||||
}
|
||||
}
|
||||
*/
|
||||
Reference in New Issue
Block a user