Files
klammertext/mac/show.h

195 lines
6.4 KiB
C
Raw Normal View History

#pragma once
#include <iostream>
#include <vector>
#include "locator.h"
#include "katom.h"
#include "argtype.h"
#include "argument.h"
#include "klammer.h"
#include "klammer_registry.h"
#include "klammerset_registry.h"
#include "state.h"
#include "target_registry.h"
#include "machine.h"
#include "file.h"
using namespace std::string_literals;
const std::string middle_dot { "\uFF65" };
const std::string broken_bar { "\u00A6" };
const std::string right_arrow { "\uFFEB" };
const std::string sp_arrow { " \u2192 " };
const std::string right_bracket { "\u27E9" };
const std::string left_bracket { "\u27E8" };
const std::string bbar { "¦" };
const std::string left_double_bracket { "\u27E6" };
const std::string right_double_bracket { "\u27E7" };
const std::string left_square_bracket { "\u2045" };
const std::string right_square_bracket { "\u2046" };
const std::string check { "\u2713" };
An output policy for the three commands, and @cond as a true special form A snapshot of the development tree. The substantial changes since the last one: COMMAND OUTPUT POLICY. The three commands display text in exactly three cases, and each owns a stream: LOGGING under "-v" greater than 0 and an ERROR before termination go to STDERR; OUTPUT THE USER ASKED FOR goes to STDOUT. For ktext that output is a document, so "ktext doc.kt -d | ..." is now safe -- logging used to share the stream and land inside the document. A bare command prints its usage and succeeds rather than failing. Colour is emitted only to a terminal, per stream, and NO_COLOR is honoured. "-v 1" reports every decision whose outcome you could not have read off your own input: the klammerset that was loaded and from which file, a font's directory, a ":files" name's file, how "-o" was expanded. Higher levels are the trace. The commands no longer warn and continue: an anomaly is an error, described with its location. Two exceptions remain, each for a stated reason -- a condition that is expected and temporary by design, and a judgment that is a heuristic rather than exact. @cond IS NOW A TRUE SPECIAL FORM, resolved at APPLICATION time rather than when the file is read. Two consequences for a writer: * a state variable reaches the predicate. "@@@state Flag :value true @@@ @cond *Flag* | T | F @" renders "T"; it used to see the literal "*Flag*" and silently take the false branch. The document now behaves like a klammer body, whose arguments are bound before its conditionals are decided. * nothing in a discarded branch happens -- it is not read, not evaluated, not expanded. An @eval in the branch not taken used to run anyway. Its predicate relation is total and strict: true, True, 1; false, False, 0, and empty; anything else is an error at the @cond rather than silently false. @eval REACHING OUTSIDE. ":shell" and ":haskell" now keep the command's standard error out of the document (it appears under "-v 1") and treat a nonzero exit as an error naming what the command reported. A command that exits nonzero on purpose -- "grep" finding no match -- says so with "|| true". KLAMMER SETS. Several combine: "--klammersets a b c" loads all three in the order given, sharing one namespace, with the definition modes deciding collisions. "none" means none and may not be combined with other symbols. A klammerset with symbol X is declared in a file X/X.k, which is what lets two sets require the same third set without loading it twice. TESTS. Four new suites: the kdiag command's interface, the @eval primitive's contract with the outside world, and verbosity at both tiers. Three suites that could not run on macOS at all now do. Assembled from dev commit 6c8ee6c22fca.
2026-08-16 01:37:59 +02:00
// A colour is a STREAM-AWARE object, not a string, because the same name is
// written to two streams whose destinations differ: "ktext -d > doc.txt" has a
// file on stdout and a terminal on stderr at the same time, so one global
// on/off cannot be right for both. Inserting a Color emits its escape
// sequence only when THAT stream is a terminal, so escape codes can never
// reach a redirected document, a pipe, or a captured log.
//
// Streams other than std::cout/std::cerr -- a stringstream building an error
// message, a file -- are never coloured. That is the conservative reading and
// it also stops escapes from being baked into strings whose length is then
// measured (abbreviate() in util.cpp counted them).
class Color {
public:
explicit Color(const std::string& code) : m_code(code) {}
// The raw sequence, for the rare place that needs a string rather than an
// insertion. Prefer inserting the Color: this form cannot be suppressed.
const std::string& code() const { return m_code; }
private:
std::string m_code {};
};
// True when colour should be emitted on this stream: it is a terminal and the
// NO_COLOR environment variable is unset. NO_COLOR (https://no-color.org) is
// honoured for ANY non-empty value, which is what the convention specifies; it
// is the escape hatch for the case isatty cannot see, such as a pager or a CI
// capture that does want, or does not want, colour.
bool color_enabled(const std::ostream& os);
std::ostream& operator<<(std::ostream& os, const Color& color);
const Color black("\033[0;30m");
const Color boldblack("\033[1;30m");
const Color green("\033[0;32m");
const Color boldgreen("\033[1;32m");
const Color cyan("\033[0;36m");
const Color blue("\033[0;34m");
const Color boldblue("\033[1;34m");
const Color magenta("\033[0;35m");
const Color red("\033[31m");
const Color yellow("\033[0;33m");
const Color reset("\033[0m");
const auto seqout = [](auto x) { std::cout << "seq: " << x << "\n"; };
//const auto mapout = [](auto m) { auto const& key std::cout << m.first << sp_arrow << m.second << "\n"; };
const auto mapout = [](auto const& kv){
auto const& [k, v] = kv;
std::cout << k << sp_arrow << v << "\n";
};
inline const
std::set sks_commands = {
"ktext"s,
"kdesc"s,
"kdiag"s,
"argument_test"s,
"argtype_test"s
};
std::ostream& msg(Locator loc=Locator());
std::ostream& fmsg(Locator loc=Locator());
std::vector<Katom> abbrev(const std::vector<Katom>& ks, unsigned int max_length=16);
// std::vector<int>
std::ostream& operator<<(std::ostream& os, const std::vector<int>& ns);
// std::vector<std::string>
std::ostream& operator<<(std::ostream& os, const std::vector<std::string>& ss);
// std::vector<fs::path>
std::ostream& operator<<(std::ostream& os, const std::vector<fs::path>& pp);
// std::map<std::string,std::string>
std::ostream& operator<<(std::ostream& os, const std::map<std::string,std::string>& sm);
// Katom iterator pair
std::ostream& operator<<(
std::ostream& os,
const std::pair<std::vector<Katom>::iterator, std::vector<Katom>::iterator>& iters);
// Locator
std::ostream& operator<<(std::ostream& os, const Locator& loc);
// Katom
std::ostream& operator<<(std::ostream& os, const Katom& k);
std::ostream& operator<<(std::ostream& os, const std::vector<std::vector<Katom>>& ks);
std::ostream& operator<<(std::ostream& os, const std::shared_ptr<Katom>& k);
std::ostream& operator<<(std::ostream& os, const std::vector<Katom>::iterator& k);
std::ostream& operator<<(std::ostream& os, const std::vector<Katom>& ks);
std::ostream& operator<<(std::ostream& os, const std::vector<std::vector<Katom>::iterator>& ks);
std::ostream& kindex(std::ostream& os);
std::ostream& ktype(std::ostream& os);
std::ostream& klevel(std::ostream& os);
// std::ostream& kspans(std::ostream& os);
std::ostream& kws(std::ostream& os);
std::ostream& kall(std::ostream& os);
std::ostream& kreplaced(std::ostream& os);
std::ostream& kignored(std::ostream& os);
std::ostream& kreset(std::ostream& os);
inline static std::string newline_symbol = "/";
std::ostream& operator<<(std::ostream& os, const std::vector<Katom>& ks);
std::ostream& operator<<(std::ostream& os, const std::vector<Katom>& ks);
// Argtype
std::ostream& operator<<(std::ostream& os, const Argtype& a);
// Parameter (aliased as Argument at application sites)
std::ostream& operator<<(std::ostream& os, const Parameter& p);
// Parameter_set (aliased as Argument_set at application sites)
std::ostream& operator<<(std::ostream& os, const Parameter_set& as);
// std::vector<Parameter>
std::ostream& operator<<(std::ostream& os, const std::vector<Parameter>& as);
// Var
std::ostream& operator<<(std::ostream& os, const Var& v);
// Frame
std::ostream& operator<<(std::ostream& os, const Frame& f);
// State
std::ostream& operator<<(std::ostream& os, const State& s);
// Klammer
std::ostream& operator<<(std::ostream& os, const Klammer& k);
// Klammer::variable_map_t
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_registry
std::ostream& operator<<(std::ostream& os, const Klammer_registry& ks);
// Target
std::ostream& operator<<(std::ostream& os, const Target& t);
// 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(const std::string& name);