Files
klammertext/mac/argtype.h
Andy Kopra cacff229a1 feat(argtype): :alone - the value of an option written without one
An optional argument has three values: the default (the name is absent),
the argument type's :alone value (the name is written alone), and a
written value.

:alone is declared by the argument type only, never by a klammer's
parameter declaration -- a default is what one klammer means by silence,
but a bare option name must read the same way in every klammer.  The bool
type declares :alone true, which is the whole of the convention that a
bare boolean option means true; there is no boolean special case in the
engine.  A type whose pattern matches running text cannot declare :alone,
since an option's value runs to the next bar or option name and would
swallow the following text.

kdesc and `ktext -m` now show [default: X] and [alone: Y] per argument
type.

In the Standard Klammer Set: @code :number becomes a bool (it was an
untyped string tested only for truthiness, so a bare :number was a
no-op); decimal_mark declares :alone comma; table_hline and table_vline
declare :alone all.  The 35 bools that default false gained the bare form
for free.

Tests: tst/alone_test.sh (21 cases) joins the shipped suite.

(from dev 6024f49c2859)
2026-07-28 22:24:32 +02:00

84 lines
3.4 KiB
C++

#pragma once
#include <string>
#include <variant>
#include <functional>
#include <regex>
#include "locator.h"
using argtype_t = std::variant<bool,double,std::string,std::vector<std::string>>;
using modify_string_f = std::function<std::string(std::vector<std::string>)>;
class Argtype
{
public:
Argtype()
: m_name("default")
, m_desc("default argument type")
, m_symbolic_pattern(R"((?:.|\n)*)")
, m_pattern(R"((?:.|\n)*)")
, m_python_cast("str")
, m_python_format()
, m_regex(std::regex(R"((?:.|\n)*)"))
, 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,
const Locator& loc);
std::string python_value(const std::string& var_name, std::vector<std::string> value, size_t name_size);
// True for the match-everything pattern shared by the string family
// (string, rest, literal, and the default type). Validating against
// it is pointless, and running std::regex over a large value (e.g.
// @document's :text holding a whole document) overflows the regex
// executor's recursion stack.
bool matches_all() const { return m_pattern == R"((?:.|\n)*)"; };
std::string m_name {};
std::string m_desc {};
std::string m_symbolic_pattern {};
std::string m_pattern {};
// Default value for parameters of this type; a default given in a
// klammer's parameter declaration overrides it (see
// parse_optional_parameter). Useful for single-purpose types
// (cell_hpos, column_width); general types (bool, float) have no
// sensible universal default and leave it empty.
std::string m_default {};
// Value for an optional argument whose name is written alone, with no
// value after it (:number rather than :number 10). Declared by the
// argument type, never by a klammer's parameter declaration: the
// default is what a klammer means by silence and is properly
// per-klammer, but a bare option name must read the same way in every
// klammer or the writer cannot know what it means without consulting
// each signature. bool declares "true", which is where the
// presence-means-true convention comes from; a type whose pattern
// matches everything cannot declare it (the value would swallow the
// following text instead). Empty means the type has no alone value,
// and a bare option name yields the empty string as before.
std::string m_alone {};
// Type parameter for parameterized types like rest(2): the value N
// is bound around the python cast as (lambda N: <cast>)(2)(...).
// Empty means unparameterized; a type with a default parameter
// (rest -> "1") is specialized by writing type(N) in a declaration.
std::string m_parameter {};
std::string m_python_cast {};
modify_string_f m_python_format {};
std::regex m_regex {};
int m_count {1};
int m_mincount {1};
int m_maxcount {1};
Locator m_loc;
};
std::string pyformat_string(const std::vector<std::string>& value);
std::string pyformat_bool(const std::vector<std::string>& value);
std::string pyformat_number(const std::vector<std::string>& value);
std::string pyformat_list(const std::vector<std::string>& value);
std::string pyformat_dlist(const std::vector<std::string>& value);