Segregated symbols into 5 separate namespaces
The different namespaces are:
Function Value expression functions, which receive a "context"
Option Command-line options
Precommand Commands which are invoked before reading the journal
Command Commands which are invoked after reading the journal
Directive Directives that occur at column 0 in a data file
This greatly eases the ability for Python uses to add intercept hooks to
change how the basic Ledger module functions. An example of what should
be possible soon:
import ledger
def my_foo_handler(value):
print "--foo received:", value
ledger.add_handler(ledger.Option, "foo=", my_foo_handler)
This commit is contained in:
parent
4a14f3224b
commit
78e6770c4c
23 changed files with 509 additions and 423 deletions
|
|
@ -241,8 +241,12 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_t::ptr_op_t account_t::lookup(const string& name)
|
expr_t::ptr_op_t account_t::lookup(const symbol_t::kind_t kind,
|
||||||
|
const string& name)
|
||||||
{
|
{
|
||||||
|
if (kind != symbol_t::FUNCTION)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
switch (name[0]) {
|
switch (name[0]) {
|
||||||
case 'a':
|
case 'a':
|
||||||
if (name == "amount")
|
if (name == "amount")
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,8 @@ public:
|
||||||
}
|
}
|
||||||
bool remove_post(post_t * post);
|
bool remove_post(post_t * post);
|
||||||
|
|
||||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||||
|
const string& name);
|
||||||
|
|
||||||
bool valid() const;
|
bool valid() const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -314,28 +314,32 @@ option_t<global_scope_t> * global_scope_t::lookup_option(const char * p)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_t::ptr_op_t global_scope_t::lookup(const string& name)
|
expr_t::ptr_op_t global_scope_t::lookup(const symbol_t::kind_t kind,
|
||||||
|
const string& name)
|
||||||
{
|
{
|
||||||
const char * p = name.c_str();
|
switch (kind) {
|
||||||
switch (*p) {
|
case symbol_t::FUNCTION:
|
||||||
case 'o':
|
if (option_t<global_scope_t> * handler = lookup_option(name.c_str()))
|
||||||
if (WANT_OPT()) { p += OPT_PREFIX_LEN;
|
return MAKE_OPT_FUNCTOR(global_scope_t, handler);
|
||||||
if (option_t<global_scope_t> * handler = lookup_option(p))
|
|
||||||
return MAKE_OPT_HANDLER(global_scope_t, handler);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p':
|
case symbol_t::OPTION:
|
||||||
if (WANT_PRECMD()) { const char * q = p + PRECMD_PREFIX_LEN;
|
if (option_t<global_scope_t> * handler = lookup_option(name.c_str()))
|
||||||
switch (*q) {
|
return MAKE_OPT_HANDLER(global_scope_t, handler);
|
||||||
case 'p':
|
break;
|
||||||
if (is_eq(q, "push"))
|
|
||||||
return MAKE_FUNCTOR(global_scope_t::push_command);
|
case symbol_t::PRECOMMAND: {
|
||||||
else if (is_eq(q, "pop"))
|
const char * p = name.c_str();
|
||||||
return MAKE_FUNCTOR(global_scope_t::pop_command);
|
switch (*p) {
|
||||||
break;
|
case 'p':
|
||||||
}
|
if (is_eq(p, "push"))
|
||||||
|
return MAKE_FUNCTOR(global_scope_t::push_command);
|
||||||
|
else if (is_eq(p, "pop"))
|
||||||
|
return MAKE_FUNCTOR(global_scope_t::pop_command);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -396,7 +400,7 @@ void global_scope_t::normalize_session_options()
|
||||||
function_t global_scope_t::look_for_precommand(scope_t& scope,
|
function_t global_scope_t::look_for_precommand(scope_t& scope,
|
||||||
const string& verb)
|
const string& verb)
|
||||||
{
|
{
|
||||||
if (expr_t::ptr_op_t def = scope.lookup(string(PRECMD_PREFIX) + verb))
|
if (expr_t::ptr_op_t def = scope.lookup(symbol_t::PRECOMMAND, verb))
|
||||||
return def->as_function();
|
return def->as_function();
|
||||||
else
|
else
|
||||||
return function_t();
|
return function_t();
|
||||||
|
|
@ -405,7 +409,7 @@ function_t global_scope_t::look_for_precommand(scope_t& scope,
|
||||||
function_t global_scope_t::look_for_command(scope_t& scope,
|
function_t global_scope_t::look_for_command(scope_t& scope,
|
||||||
const string& verb)
|
const string& verb)
|
||||||
{
|
{
|
||||||
if (expr_t::ptr_op_t def = scope.lookup(string(CMD_PREFIX) + verb))
|
if (expr_t::ptr_op_t def = scope.lookup(symbol_t::COMMAND, verb))
|
||||||
return def->as_function();
|
return def->as_function();
|
||||||
else
|
else
|
||||||
return function_t();
|
return function_t();
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,8 @@ See LICENSE file included with the distribution for details and disclaimer.");
|
||||||
|
|
||||||
option_t<global_scope_t> * lookup_option(const char * p);
|
option_t<global_scope_t> * lookup_option(const char * p);
|
||||||
|
|
||||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||||
|
const string& name);
|
||||||
|
|
||||||
OPTION(global_scope_t, args_only);
|
OPTION(global_scope_t, args_only);
|
||||||
OPTION(global_scope_t, debug_);
|
OPTION(global_scope_t, debug_);
|
||||||
|
|
|
||||||
|
|
@ -304,8 +304,12 @@ value_t get_comment(item_t& item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_t::ptr_op_t item_t::lookup(const string& name)
|
expr_t::ptr_op_t item_t::lookup(const symbol_t::kind_t kind,
|
||||||
|
const string& name)
|
||||||
{
|
{
|
||||||
|
if (kind != symbol_t::FUNCTION)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
switch (name[0]) {
|
switch (name[0]) {
|
||||||
case 'a':
|
case 'a':
|
||||||
if (name == "actual")
|
if (name == "actual")
|
||||||
|
|
|
||||||
|
|
@ -189,7 +189,8 @@ public:
|
||||||
return _state;
|
return _state;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||||
|
const string& name);
|
||||||
|
|
||||||
bool valid() const;
|
bool valid() const;
|
||||||
|
|
||||||
|
|
|
||||||
14
src/op.cc
14
src/op.cc
|
|
@ -43,7 +43,7 @@ expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth)
|
||||||
if (is_ident()) {
|
if (is_ident()) {
|
||||||
DEBUG("expr.compile", "lookup: " << as_ident());
|
DEBUG("expr.compile", "lookup: " << as_ident());
|
||||||
|
|
||||||
if (ptr_op_t def = scope.lookup(as_ident())) {
|
if (ptr_op_t def = scope.lookup(symbol_t::FUNCTION, as_ident())) {
|
||||||
// Identifier references are first looked up at the point of
|
// Identifier references are first looked up at the point of
|
||||||
// definition, and then at the point of every use if they could
|
// definition, and then at the point of every use if they could
|
||||||
// not be found there.
|
// not be found there.
|
||||||
|
|
@ -65,11 +65,11 @@ expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth)
|
||||||
if (kind == O_DEFINE) {
|
if (kind == O_DEFINE) {
|
||||||
switch (left()->kind) {
|
switch (left()->kind) {
|
||||||
case IDENT:
|
case IDENT:
|
||||||
scope.define(left()->as_ident(), right());
|
scope.define(symbol_t::FUNCTION, left()->as_ident(), right());
|
||||||
break;
|
break;
|
||||||
case O_CALL:
|
case O_CALL:
|
||||||
if (left()->left()->is_ident())
|
if (left()->left()->is_ident())
|
||||||
scope.define(left()->left()->as_ident(), this);
|
scope.define(symbol_t::FUNCTION, left()->left()->as_ident(), this);
|
||||||
else
|
else
|
||||||
throw_(compile_error, _("Invalid function definition"));
|
throw_(compile_error, _("Invalid function definition"));
|
||||||
break;
|
break;
|
||||||
|
|
@ -152,9 +152,10 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth)
|
||||||
if (! varname->is_ident())
|
if (! varname->is_ident())
|
||||||
throw_(calc_error, _("Invalid function definition"));
|
throw_(calc_error, _("Invalid function definition"));
|
||||||
else if (args_index == args_count)
|
else if (args_index == args_count)
|
||||||
local_scope.define(varname->as_ident(), wrap_value(false));
|
local_scope.define(symbol_t::FUNCTION, varname->as_ident(),
|
||||||
|
wrap_value(false));
|
||||||
else
|
else
|
||||||
local_scope.define(varname->as_ident(),
|
local_scope.define(symbol_t::FUNCTION, varname->as_ident(),
|
||||||
wrap_value(call_args[args_index++]));
|
wrap_value(call_args[args_index++]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -178,7 +179,8 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth)
|
||||||
_("Left operand of . operator is NULL"));
|
_("Left operand of . operator is NULL"));
|
||||||
} else {
|
} else {
|
||||||
scope_t& objscope(*obj.as_scope());
|
scope_t& objscope(*obj.as_scope());
|
||||||
if (ptr_op_t member = objscope.lookup(right()->as_ident())) {
|
if (ptr_op_t member =
|
||||||
|
objscope.lookup(symbol_t::FUNCTION, right()->as_ident())) {
|
||||||
result = member->calc(objscope, NULL, depth + 1);
|
result = member->calc(objscope, NULL, depth + 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,7 @@ namespace {
|
||||||
op_bool_tuple find_option(scope_t& scope, const string& name)
|
op_bool_tuple find_option(scope_t& scope, const string& name)
|
||||||
{
|
{
|
||||||
char buf[128];
|
char buf[128];
|
||||||
std::strcpy(buf, "opt_");
|
char * p = buf;
|
||||||
char * p = &buf[4];
|
|
||||||
foreach (char ch, name) {
|
foreach (char ch, name) {
|
||||||
if (ch == '-')
|
if (ch == '-')
|
||||||
*p++ = '_';
|
*p++ = '_';
|
||||||
|
|
@ -52,28 +51,27 @@ namespace {
|
||||||
*p++ = '_';
|
*p++ = '_';
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
|
|
||||||
if (expr_t::ptr_op_t op = scope.lookup(buf))
|
if (expr_t::ptr_op_t op = scope.lookup(symbol_t::OPTION, buf))
|
||||||
return op_bool_tuple(op, true);
|
return op_bool_tuple(op, true);
|
||||||
|
|
||||||
*--p = '\0';
|
*--p = '\0';
|
||||||
|
|
||||||
return op_bool_tuple(scope.lookup(buf), false);
|
return op_bool_tuple(scope.lookup(symbol_t::OPTION, buf), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
op_bool_tuple find_option(scope_t& scope, const char letter)
|
op_bool_tuple find_option(scope_t& scope, const char letter)
|
||||||
{
|
{
|
||||||
char buf[10];
|
char buf[4];
|
||||||
std::strcpy(buf, "opt_");
|
buf[0] = letter;
|
||||||
buf[4] = letter;
|
buf[1] = '_';
|
||||||
buf[5] = '_';
|
buf[2] = '\0';
|
||||||
buf[6] = '\0';
|
|
||||||
|
|
||||||
if (expr_t::ptr_op_t op = scope.lookup(buf))
|
if (expr_t::ptr_op_t op = scope.lookup(symbol_t::OPTION, buf))
|
||||||
return op_bool_tuple(op, true);
|
return op_bool_tuple(op, true);
|
||||||
|
|
||||||
buf[5] = '\0';
|
buf[1] = '\0';
|
||||||
|
|
||||||
return op_bool_tuple(scope.lookup(buf), false);
|
return op_bool_tuple(scope.lookup(symbol_t::OPTION, buf), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void process_option(const string& whence, const function_t& opt,
|
void process_option(const string& whence, const function_t& opt,
|
||||||
|
|
|
||||||
24
src/option.h
24
src/option.h
|
|
@ -283,30 +283,6 @@ inline bool is_eq(const char * p, const char * n) {
|
||||||
} \
|
} \
|
||||||
END(name)
|
END(name)
|
||||||
|
|
||||||
#define OPT_PREFIX "opt_"
|
|
||||||
#define OPT_PREFIX_LEN 4
|
|
||||||
|
|
||||||
#define WANT_OPT() \
|
|
||||||
(std::strncmp(p, OPT_PREFIX, OPT_PREFIX_LEN) == 0)
|
|
||||||
|
|
||||||
#define PRECMD_PREFIX "precmd_"
|
|
||||||
#define PRECMD_PREFIX_LEN 7
|
|
||||||
|
|
||||||
#define WANT_PRECMD() \
|
|
||||||
(std::strncmp(p, PRECMD_PREFIX, PRECMD_PREFIX_LEN) == 0)
|
|
||||||
|
|
||||||
#define CMD_PREFIX "cmd_"
|
|
||||||
#define CMD_PREFIX_LEN 4
|
|
||||||
|
|
||||||
#define WANT_CMD() \
|
|
||||||
(std::strncmp(p, CMD_PREFIX, CMD_PREFIX_LEN) == 0)
|
|
||||||
|
|
||||||
#define DIR_PREFIX "dir_"
|
|
||||||
#define DIR_PREFIX_LEN 4
|
|
||||||
|
|
||||||
#define WANT_DIR() \
|
|
||||||
(std::strncmp(p, DIR_PREFIX, DIR_PREFIX_LEN) == 0)
|
|
||||||
|
|
||||||
bool process_option(const string& whence, const string& name, scope_t& scope,
|
bool process_option(const string& whence, const string& name, scope_t& scope,
|
||||||
const char * arg, const string& varname);
|
const char * arg, const string& varname);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -271,8 +271,12 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_t::ptr_op_t post_t::lookup(const string& name)
|
expr_t::ptr_op_t post_t::lookup(const symbol_t::kind_t kind,
|
||||||
|
const string& name)
|
||||||
{
|
{
|
||||||
|
if (kind != symbol_t::FUNCTION)
|
||||||
|
return item_t::lookup(kind, name);
|
||||||
|
|
||||||
switch (name[0]) {
|
switch (name[0]) {
|
||||||
case 'a':
|
case 'a':
|
||||||
if (name[1] == '\0' || name == "amount")
|
if (name[1] == '\0' || name == "amount")
|
||||||
|
|
@ -366,7 +370,7 @@ expr_t::ptr_op_t post_t::lookup(const string& name)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return item_t::lookup(name);
|
return item_t::lookup(kind, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool post_t::valid() const
|
bool post_t::valid() const
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,8 @@ public:
|
||||||
return ! has_flags(POST_VIRTUAL) || has_flags(POST_MUST_BALANCE);
|
return ! has_flags(POST_VIRTUAL) || has_flags(POST_MUST_BALANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||||
|
const string& name);
|
||||||
|
|
||||||
bool valid() const;
|
bool valid() const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ namespace {
|
||||||
{
|
{
|
||||||
if (value.is_scope()) {
|
if (value.is_scope()) {
|
||||||
if (scope_t * scope = value.as_scope())
|
if (scope_t * scope = value.as_scope())
|
||||||
return expr_t(scope->lookup(name), scope);
|
return expr_t(scope->lookup(symbol_t::FUNCTION, name), scope);
|
||||||
}
|
}
|
||||||
throw_(value_error, _("Cannot lookup attributes in %1") << value.label());
|
throw_(value_error, _("Cannot lookup attributes in %1") << value.label());
|
||||||
return expr_t();
|
return expr_t();
|
||||||
|
|
|
||||||
|
|
@ -285,38 +285,40 @@ python_interpreter_t::lookup_option(const char * p)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_t::ptr_op_t python_interpreter_t::lookup(const string& name)
|
expr_t::ptr_op_t python_interpreter_t::lookup(const symbol_t::kind_t kind,
|
||||||
|
const string& name)
|
||||||
{
|
{
|
||||||
// Give our superclass first dibs on symbol definitions
|
// Give our superclass first dibs on symbol definitions
|
||||||
if (expr_t::ptr_op_t op = session_t::lookup(name))
|
if (expr_t::ptr_op_t op = session_t::lookup(kind, name))
|
||||||
return op;
|
return op;
|
||||||
|
|
||||||
const char * p = name.c_str();
|
switch (kind) {
|
||||||
switch (*p) {
|
case symbol_t::FUNCTION:
|
||||||
case 'o':
|
if (is_initialized && main_nspace.has_key(name.c_str())) {
|
||||||
if (WANT_OPT()) { const char * q = p + OPT_PREFIX_LEN;
|
DEBUG("python.interp", "Python lookup: " << name);
|
||||||
if (option_t<python_interpreter_t> * handler = lookup_option(q))
|
|
||||||
return MAKE_OPT_HANDLER(python_interpreter_t, handler);
|
if (python::object obj = main_nspace.get(name.c_str()))
|
||||||
|
return WRAP_FUNCTOR(functor_t(name, obj));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p':
|
case symbol_t::OPTION:
|
||||||
if (WANT_PRECMD()) { const char * q = p + PRECMD_PREFIX_LEN;
|
if (option_t<python_interpreter_t> * handler = lookup_option(name.c_str()))
|
||||||
switch (*q) {
|
return MAKE_OPT_HANDLER(python_interpreter_t, handler);
|
||||||
case 'p':
|
|
||||||
if (is_eq(q, "python"))
|
|
||||||
return MAKE_FUNCTOR(python_interpreter_t::python_command);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case symbol_t::PRECOMMAND: {
|
||||||
|
const char * p = name.c_str();
|
||||||
|
switch (*p) {
|
||||||
|
case 'p':
|
||||||
|
if (is_eq(p, "python"))
|
||||||
|
return MAKE_FUNCTOR(python_interpreter_t::python_command);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_initialized && main_nspace.has_key(name.c_str())) {
|
default:
|
||||||
DEBUG("python.interp", "Python lookup: " << name);
|
break;
|
||||||
|
|
||||||
if (python::object obj = main_nspace.get(name.c_str()))
|
|
||||||
return WRAP_FUNCTOR(functor_t(name, obj));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,8 @@ public:
|
||||||
|
|
||||||
option_t<python_interpreter_t> * lookup_option(const char * p);
|
option_t<python_interpreter_t> * lookup_option(const char * p);
|
||||||
|
|
||||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||||
|
const string& name);
|
||||||
|
|
||||||
#if BOOST_VERSION >= 103700
|
#if BOOST_VERSION >= 103700
|
||||||
OPTION_(python_interpreter_t, import_, DO_(scope) {
|
OPTION_(python_interpreter_t, import_, DO_(scope) {
|
||||||
|
|
|
||||||
566
src/report.cc
566
src/report.cc
|
|
@ -464,8 +464,8 @@ value_t report_t::echo_command(call_scope_t& scope)
|
||||||
|
|
||||||
bool report_t::maybe_import(const string& module)
|
bool report_t::maybe_import(const string& module)
|
||||||
{
|
{
|
||||||
if (lookup(string(OPT_PREFIX) + "import_")) {
|
if (lookup(symbol_t::OPTION, "import_")) {
|
||||||
expr_t(string(OPT_PREFIX) + "import_(\"" + module + "\")").calc(*this);
|
expr_t(string("import_(\"") + module + "\")").calc(*this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -707,304 +707,316 @@ option_t<report_t> * report_t::lookup_option(const char * p)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void report_t::define(const string& name, expr_t::ptr_op_t def)
|
void report_t::define(const symbol_t::kind_t kind, const string& name,
|
||||||
|
expr_t::ptr_op_t def)
|
||||||
{
|
{
|
||||||
session.define(name, def);
|
session.define(kind, name, def);
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_t::ptr_op_t report_t::lookup(const string& name)
|
expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
|
||||||
|
const string& name)
|
||||||
{
|
{
|
||||||
if (expr_t::ptr_op_t def = session.lookup(name))
|
if (expr_t::ptr_op_t def = session.lookup(kind, name))
|
||||||
return def;
|
return def;
|
||||||
|
|
||||||
const char * p = name.c_str();
|
const char * p = name.c_str();
|
||||||
switch (*p) {
|
|
||||||
case 'a':
|
switch (kind) {
|
||||||
if (is_eq(p, "amount_expr"))
|
case symbol_t::FUNCTION:
|
||||||
return MAKE_FUNCTOR(report_t::fn_amount_expr);
|
switch (*p) {
|
||||||
else if (is_eq(p, "ansify_if"))
|
case 'a':
|
||||||
return MAKE_FUNCTOR(report_t::fn_ansify_if);
|
if (is_eq(p, "amount_expr"))
|
||||||
else if (is_eq(p, "abs"))
|
return MAKE_FUNCTOR(report_t::fn_amount_expr);
|
||||||
return MAKE_FUNCTOR(report_t::fn_abs);
|
else if (is_eq(p, "ansify_if"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_ansify_if);
|
||||||
|
else if (is_eq(p, "abs"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_abs);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'b':
|
||||||
|
if (is_eq(p, "black"))
|
||||||
|
return WRAP_FUNCTOR(fn_black);
|
||||||
|
else if (is_eq(p, "blink"))
|
||||||
|
return WRAP_FUNCTOR(fn_blink);
|
||||||
|
else if (is_eq(p, "blue"))
|
||||||
|
return WRAP_FUNCTOR(fn_blue);
|
||||||
|
else if (is_eq(p, "bold"))
|
||||||
|
return WRAP_FUNCTOR(fn_bold);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
if (is_eq(p, "cyan"))
|
||||||
|
return WRAP_FUNCTOR(fn_cyan);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
if (is_eq(p, "display_amount"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_display_amount);
|
||||||
|
else if (is_eq(p, "display_total"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_display_total);
|
||||||
|
else if (is_eq(p, "date"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_now);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
if (is_eq(p, "format_date"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_format_date);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'g':
|
||||||
|
if (is_eq(p, "get_at"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_get_at);
|
||||||
|
else if (is_eq(p, "green"))
|
||||||
|
return WRAP_FUNCTOR(fn_green);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'i':
|
||||||
|
if (is_eq(p, "is_seq"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_is_seq);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'j':
|
||||||
|
if (is_eq(p, "justify"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_justify);
|
||||||
|
else if (is_eq(p, "join"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_join);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'm':
|
||||||
|
if (is_eq(p, "market"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_market);
|
||||||
|
else if (is_eq(p, "magenta"))
|
||||||
|
return WRAP_FUNCTOR(fn_magenta);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'n':
|
||||||
|
if (is_eq(p, "null"))
|
||||||
|
return WRAP_FUNCTOR(fn_null);
|
||||||
|
else if (is_eq(p, "now"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_now);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'o':
|
||||||
|
if (is_eq(p, "options"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_options);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
if (is_eq(p, "post"))
|
||||||
|
return WRAP_FUNCTOR(fn_false);
|
||||||
|
else if (is_eq(p, "percent"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_percent);
|
||||||
|
else if (is_eq(p, "price"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_price);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'q':
|
||||||
|
if (is_eq(p, "quoted"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_quoted);
|
||||||
|
else if (is_eq(p, "quantity"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_quantity);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'r':
|
||||||
|
if (is_eq(p, "rounded"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_rounded);
|
||||||
|
else if (is_eq(p, "red"))
|
||||||
|
return WRAP_FUNCTOR(fn_red);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
if (is_eq(p, "scrub"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_scrub);
|
||||||
|
else if (is_eq(p, "strip"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_strip);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 't':
|
||||||
|
if (is_eq(p, "truncated"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_truncated);
|
||||||
|
else if (is_eq(p, "total_expr"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_total_expr);
|
||||||
|
else if (is_eq(p, "today"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_today);
|
||||||
|
else if (is_eq(p, "t"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_display_amount);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'T':
|
||||||
|
if (is_eq(p, "T"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_display_total);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'u':
|
||||||
|
if (is_eq(p, "underline"))
|
||||||
|
return WRAP_FUNCTOR(fn_underline);
|
||||||
|
else if (is_eq(p, "unrounded"))
|
||||||
|
return MAKE_FUNCTOR(report_t::fn_unrounded);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'w':
|
||||||
|
if (is_eq(p, "white"))
|
||||||
|
return WRAP_FUNCTOR(fn_white);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'y':
|
||||||
|
if (is_eq(p, "yellow"))
|
||||||
|
return WRAP_FUNCTOR(fn_yellow);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if they are trying to access an option's setting or value.
|
||||||
|
if (option_t<report_t> * handler = lookup_option(p))
|
||||||
|
return MAKE_OPT_FUNCTOR(report_t, handler);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'b':
|
case symbol_t::OPTION:
|
||||||
if (is_eq(p, "black"))
|
if (option_t<report_t> * handler = lookup_option(p))
|
||||||
return WRAP_FUNCTOR(fn_black);
|
return MAKE_OPT_HANDLER(report_t, handler);
|
||||||
else if (is_eq(p, "blink"))
|
|
||||||
return WRAP_FUNCTOR(fn_blink);
|
|
||||||
else if (is_eq(p, "blue"))
|
|
||||||
return WRAP_FUNCTOR(fn_blue);
|
|
||||||
else if (is_eq(p, "bold"))
|
|
||||||
return WRAP_FUNCTOR(fn_bold);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c':
|
case symbol_t::COMMAND:
|
||||||
if (WANT_CMD()) { const char * q = p + CMD_PREFIX_LEN;
|
switch (*p) {
|
||||||
switch (*q) {
|
case 'b':
|
||||||
case 'b':
|
if (*(p + 1) == '\0' || is_eq(p, "bal") || is_eq(p, "balance")) {
|
||||||
if (*(q + 1) == '\0' || is_eq(q, "bal") || is_eq(q, "balance")) {
|
return expr_t::op_t::wrap_functor
|
||||||
return expr_t::op_t::wrap_functor
|
(reporter<account_t, acct_handler_ptr, &report_t::accounts_report>
|
||||||
(reporter<account_t, acct_handler_ptr, &report_t::accounts_report>
|
(new format_accounts(*this, report_format(HANDLER(balance_format_))),
|
||||||
(new format_accounts(*this, report_format(HANDLER(balance_format_))),
|
*this, "#balance"));
|
||||||
*this, "#balance"));
|
|
||||||
}
|
|
||||||
else if (is_eq(q, "budget")) {
|
|
||||||
HANDLER(amount_).set_expr(string("#budget"), "(amount, 0)");
|
|
||||||
|
|
||||||
budget_flags |= BUDGET_WRAP_VALUES;
|
|
||||||
if (! (budget_flags & ~BUDGET_WRAP_VALUES))
|
|
||||||
budget_flags |= BUDGET_BUDGETED;
|
|
||||||
|
|
||||||
return expr_t::op_t::wrap_functor
|
|
||||||
(reporter<account_t, acct_handler_ptr, &report_t::accounts_report>
|
|
||||||
(new format_accounts(*this, report_format(HANDLER(budget_format_))),
|
|
||||||
*this, "#budget"));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'c':
|
|
||||||
if (is_eq(q, "csv")) {
|
|
||||||
return WRAP_FUNCTOR
|
|
||||||
(reporter<>
|
|
||||||
(new format_posts(*this, report_format(HANDLER(csv_format_))),
|
|
||||||
*this, "#csv"));
|
|
||||||
}
|
|
||||||
else if (is_eq(q, "cleared")) {
|
|
||||||
HANDLER(amount_).set_expr(string("#cleared"),
|
|
||||||
"(amount, cleared ? amount : 0)");
|
|
||||||
|
|
||||||
return expr_t::op_t::wrap_functor
|
|
||||||
(reporter<account_t, acct_handler_ptr, &report_t::accounts_report>
|
|
||||||
(new format_accounts(*this, report_format(HANDLER(cleared_format_))),
|
|
||||||
*this, "#cleared"));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'e':
|
|
||||||
if (is_eq(q, "equity"))
|
|
||||||
return WRAP_FUNCTOR
|
|
||||||
(reporter<>
|
|
||||||
(new format_posts(*this, report_format(HANDLER(print_format_))),
|
|
||||||
*this, "#equity"));
|
|
||||||
else if (is_eq(q, "entry"))
|
|
||||||
return WRAP_FUNCTOR(xact_command);
|
|
||||||
else if (is_eq(q, "emacs"))
|
|
||||||
return WRAP_FUNCTOR
|
|
||||||
(reporter<>(new format_emacs_posts(output_stream), *this, "#emacs"));
|
|
||||||
else if (is_eq(q, "echo"))
|
|
||||||
return MAKE_FUNCTOR(report_t::echo_command);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'p':
|
|
||||||
if (*(q + 1) == '\0' || is_eq(q, "print"))
|
|
||||||
return WRAP_FUNCTOR
|
|
||||||
(reporter<>
|
|
||||||
(new format_posts(*this, report_format(HANDLER(print_format_)),
|
|
||||||
HANDLED(raw)), *this, "#print"));
|
|
||||||
else if (is_eq(q, "prices"))
|
|
||||||
return expr_t::op_t::wrap_functor
|
|
||||||
(reporter<post_t, post_handler_ptr, &report_t::commodities_report>
|
|
||||||
(new format_posts(*this, report_format(HANDLER(prices_format_))),
|
|
||||||
*this, "#prices"));
|
|
||||||
else if (is_eq(q, "pricesdb"))
|
|
||||||
return expr_t::op_t::wrap_functor
|
|
||||||
(reporter<post_t, post_handler_ptr, &report_t::commodities_report>
|
|
||||||
(new format_posts(*this, report_format(HANDLER(pricesdb_format_))),
|
|
||||||
*this, "#pricesdb"));
|
|
||||||
else if (is_eq(q, "python") && maybe_import("ledger.interp"))
|
|
||||||
return session.lookup(string(CMD_PREFIX) + "python");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'r':
|
|
||||||
if (*(q + 1) == '\0' || is_eq(q, "reg") || is_eq(q, "register"))
|
|
||||||
return WRAP_FUNCTOR
|
|
||||||
(reporter<>
|
|
||||||
(new format_posts(*this, report_format(HANDLER(register_format_))),
|
|
||||||
*this, "#register"));
|
|
||||||
else if (is_eq(q, "reload"))
|
|
||||||
return MAKE_FUNCTOR(report_t::reload_command);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 's':
|
|
||||||
if (is_eq(q, "stats") || is_eq(q, "stat"))
|
|
||||||
return WRAP_FUNCTOR(report_statistics);
|
|
||||||
else
|
|
||||||
if (is_eq(q, "server") && maybe_import("ledger.server"))
|
|
||||||
return session.lookup(string(CMD_PREFIX) + "server");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'x':
|
|
||||||
if (is_eq(q, "xact"))
|
|
||||||
return WRAP_FUNCTOR(xact_command);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
else if (is_eq(p, "budget")) {
|
||||||
else if (is_eq(p, "cyan"))
|
HANDLER(amount_).set_expr(string("#budget"), "(amount, 0)");
|
||||||
return WRAP_FUNCTOR(fn_cyan);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'd':
|
budget_flags |= BUDGET_WRAP_VALUES;
|
||||||
if (is_eq(p, "display_amount"))
|
if (! (budget_flags & ~BUDGET_WRAP_VALUES))
|
||||||
return MAKE_FUNCTOR(report_t::fn_display_amount);
|
budget_flags |= BUDGET_BUDGETED;
|
||||||
else if (is_eq(p, "display_total"))
|
|
||||||
return MAKE_FUNCTOR(report_t::fn_display_total);
|
|
||||||
else if (is_eq(p, "date"))
|
|
||||||
return MAKE_FUNCTOR(report_t::fn_now);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'f':
|
return expr_t::op_t::wrap_functor
|
||||||
if (is_eq(p, "format_date"))
|
(reporter<account_t, acct_handler_ptr, &report_t::accounts_report>
|
||||||
return MAKE_FUNCTOR(report_t::fn_format_date);
|
(new format_accounts(*this, report_format(HANDLER(budget_format_))),
|
||||||
break;
|
*this, "#budget"));
|
||||||
|
|
||||||
case 'g':
|
|
||||||
if (is_eq(p, "get_at"))
|
|
||||||
return MAKE_FUNCTOR(report_t::fn_get_at);
|
|
||||||
else if (is_eq(p, "green"))
|
|
||||||
return WRAP_FUNCTOR(fn_green);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'i':
|
|
||||||
if (is_eq(p, "is_seq"))
|
|
||||||
return MAKE_FUNCTOR(report_t::fn_is_seq);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'j':
|
|
||||||
if (is_eq(p, "justify"))
|
|
||||||
return MAKE_FUNCTOR(report_t::fn_justify);
|
|
||||||
else if (is_eq(p, "join"))
|
|
||||||
return MAKE_FUNCTOR(report_t::fn_join);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'm':
|
|
||||||
if (is_eq(p, "market"))
|
|
||||||
return MAKE_FUNCTOR(report_t::fn_market);
|
|
||||||
else if (is_eq(p, "magenta"))
|
|
||||||
return WRAP_FUNCTOR(fn_magenta);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'n':
|
|
||||||
if (is_eq(p, "null"))
|
|
||||||
return WRAP_FUNCTOR(fn_null);
|
|
||||||
else if (is_eq(p, "now"))
|
|
||||||
return MAKE_FUNCTOR(report_t::fn_now);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'o':
|
|
||||||
if (WANT_OPT()) { const char * q = p + OPT_PREFIX_LEN;
|
|
||||||
if (option_t<report_t> * handler = lookup_option(q))
|
|
||||||
return MAKE_OPT_HANDLER(report_t, handler);
|
|
||||||
}
|
|
||||||
else if (is_eq(p, "options")) {
|
|
||||||
return MAKE_FUNCTOR(report_t::fn_options);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'p':
|
|
||||||
if (WANT_PRECMD()) { const char * q = p + PRECMD_PREFIX_LEN;
|
|
||||||
switch (*q) {
|
|
||||||
case 'a':
|
|
||||||
if (is_eq(q, "args"))
|
|
||||||
return WRAP_FUNCTOR(args_command);
|
|
||||||
break;
|
|
||||||
case 'e':
|
|
||||||
if (is_eq(q, "eval"))
|
|
||||||
return WRAP_FUNCTOR(eval_command);
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
if (is_eq(q, "format"))
|
|
||||||
return WRAP_FUNCTOR(format_command);
|
|
||||||
break;
|
|
||||||
case 'g':
|
|
||||||
if (is_eq(q, "generate"))
|
|
||||||
return expr_t::op_t::wrap_functor
|
|
||||||
(reporter<post_t, post_handler_ptr, &report_t::generate_report>
|
|
||||||
(new format_posts(*this, report_format(HANDLER(print_format_)),
|
|
||||||
false), *this, "#generate"));
|
|
||||||
case 'h':
|
|
||||||
if (is_eq(q, "hello") && maybe_import("ledger.hello"))
|
|
||||||
return session.lookup(string(PRECMD_PREFIX) + "hello");
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
if (is_eq(q, "parse"))
|
|
||||||
return WRAP_FUNCTOR(parse_command);
|
|
||||||
else if (is_eq(q, "period"))
|
|
||||||
return WRAP_FUNCTOR(period_command);
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
if (is_eq(q, "template"))
|
|
||||||
return WRAP_FUNCTOR(template_command);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
if (is_eq(p, "csv")) {
|
||||||
|
return WRAP_FUNCTOR
|
||||||
|
(reporter<>
|
||||||
|
(new format_posts(*this, report_format(HANDLER(csv_format_))),
|
||||||
|
*this, "#csv"));
|
||||||
|
}
|
||||||
|
else if (is_eq(p, "cleared")) {
|
||||||
|
HANDLER(amount_).set_expr(string("#cleared"),
|
||||||
|
"(amount, cleared ? amount : 0)");
|
||||||
|
|
||||||
|
return expr_t::op_t::wrap_functor
|
||||||
|
(reporter<account_t, acct_handler_ptr, &report_t::accounts_report>
|
||||||
|
(new format_accounts(*this, report_format(HANDLER(cleared_format_))),
|
||||||
|
*this, "#cleared"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'e':
|
||||||
|
if (is_eq(p, "equity"))
|
||||||
|
return WRAP_FUNCTOR
|
||||||
|
(reporter<>
|
||||||
|
(new format_posts(*this, report_format(HANDLER(print_format_))),
|
||||||
|
*this, "#equity"));
|
||||||
|
else if (is_eq(p, "entry"))
|
||||||
|
return WRAP_FUNCTOR(xact_command);
|
||||||
|
else if (is_eq(p, "emacs"))
|
||||||
|
return WRAP_FUNCTOR
|
||||||
|
(reporter<>(new format_emacs_posts(output_stream), *this, "#emacs"));
|
||||||
|
else if (is_eq(p, "echo"))
|
||||||
|
return MAKE_FUNCTOR(report_t::echo_command);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
if (*(p + 1) == '\0' || is_eq(p, "print"))
|
||||||
|
return WRAP_FUNCTOR
|
||||||
|
(reporter<>
|
||||||
|
(new format_posts(*this, report_format(HANDLER(print_format_)),
|
||||||
|
HANDLED(raw)), *this, "#print"));
|
||||||
|
else if (is_eq(p, "prices"))
|
||||||
|
return expr_t::op_t::wrap_functor
|
||||||
|
(reporter<post_t, post_handler_ptr, &report_t::commodities_report>
|
||||||
|
(new format_posts(*this, report_format(HANDLER(prices_format_))),
|
||||||
|
*this, "#prices"));
|
||||||
|
else if (is_eq(p, "pricesdb"))
|
||||||
|
return expr_t::op_t::wrap_functor
|
||||||
|
(reporter<post_t, post_handler_ptr, &report_t::commodities_report>
|
||||||
|
(new format_posts(*this, report_format(HANDLER(pricesdb_format_))),
|
||||||
|
*this, "#pricesdb"));
|
||||||
|
else if (is_eq(p, "python") && maybe_import("ledger.interp"))
|
||||||
|
return session.lookup(symbol_t::COMMAND, "python");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'r':
|
||||||
|
if (*(p + 1) == '\0' || is_eq(p, "reg") || is_eq(p, "register"))
|
||||||
|
return WRAP_FUNCTOR
|
||||||
|
(reporter<>
|
||||||
|
(new format_posts(*this, report_format(HANDLER(register_format_))),
|
||||||
|
*this, "#register"));
|
||||||
|
else if (is_eq(p, "reload"))
|
||||||
|
return MAKE_FUNCTOR(report_t::reload_command);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
if (is_eq(p, "stats") || is_eq(p, "stat"))
|
||||||
|
return WRAP_FUNCTOR(report_statistics);
|
||||||
|
else
|
||||||
|
if (is_eq(p, "server") && maybe_import("ledger.server"))
|
||||||
|
return session.lookup(symbol_t::COMMAND, "server");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'x':
|
||||||
|
if (is_eq(p, "xact"))
|
||||||
|
return WRAP_FUNCTOR(xact_command);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (is_eq(p, "post"))
|
|
||||||
return WRAP_FUNCTOR(fn_false);
|
|
||||||
else if (is_eq(p, "percent"))
|
|
||||||
return MAKE_FUNCTOR(report_t::fn_percent);
|
|
||||||
else if (is_eq(p, "price"))
|
|
||||||
return MAKE_FUNCTOR(report_t::fn_price);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'q':
|
case symbol_t::PRECOMMAND:
|
||||||
if (is_eq(p, "quoted"))
|
switch (*p) {
|
||||||
return MAKE_FUNCTOR(report_t::fn_quoted);
|
case 'a':
|
||||||
else if (is_eq(p, "quantity"))
|
if (is_eq(p, "args"))
|
||||||
return MAKE_FUNCTOR(report_t::fn_quantity);
|
return WRAP_FUNCTOR(args_command);
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
if (is_eq(p, "eval"))
|
||||||
|
return WRAP_FUNCTOR(eval_command);
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
if (is_eq(p, "format"))
|
||||||
|
return WRAP_FUNCTOR(format_command);
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
if (is_eq(p, "generate"))
|
||||||
|
return expr_t::op_t::wrap_functor
|
||||||
|
(reporter<post_t, post_handler_ptr, &report_t::generate_report>
|
||||||
|
(new format_posts(*this, report_format(HANDLER(print_format_)),
|
||||||
|
false), *this, "#generate"));
|
||||||
|
case 'h':
|
||||||
|
if (is_eq(p, "hello") && maybe_import("ledger.hello"))
|
||||||
|
return session.lookup(symbol_t::PRECOMMAND, "hello");
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
if (is_eq(p, "parse"))
|
||||||
|
return WRAP_FUNCTOR(parse_command);
|
||||||
|
else if (is_eq(p, "period"))
|
||||||
|
return WRAP_FUNCTOR(period_command);
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
if (is_eq(p, "template"))
|
||||||
|
return WRAP_FUNCTOR(template_command);
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'r':
|
default:
|
||||||
if (is_eq(p, "rounded"))
|
|
||||||
return MAKE_FUNCTOR(report_t::fn_rounded);
|
|
||||||
else if (is_eq(p, "red"))
|
|
||||||
return WRAP_FUNCTOR(fn_red);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 's':
|
|
||||||
if (is_eq(p, "scrub"))
|
|
||||||
return MAKE_FUNCTOR(report_t::fn_scrub);
|
|
||||||
else if (is_eq(p, "strip"))
|
|
||||||
return MAKE_FUNCTOR(report_t::fn_strip);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 't':
|
|
||||||
if (is_eq(p, "truncated"))
|
|
||||||
return MAKE_FUNCTOR(report_t::fn_truncated);
|
|
||||||
else if (is_eq(p, "total_expr"))
|
|
||||||
return MAKE_FUNCTOR(report_t::fn_total_expr);
|
|
||||||
else if (is_eq(p, "today"))
|
|
||||||
return MAKE_FUNCTOR(report_t::fn_today);
|
|
||||||
else if (is_eq(p, "t"))
|
|
||||||
return MAKE_FUNCTOR(report_t::fn_display_amount);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'T':
|
|
||||||
if (is_eq(p, "T"))
|
|
||||||
return MAKE_FUNCTOR(report_t::fn_display_total);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'u':
|
|
||||||
if (is_eq(p, "underline"))
|
|
||||||
return WRAP_FUNCTOR(fn_underline);
|
|
||||||
else if (is_eq(p, "unrounded"))
|
|
||||||
return MAKE_FUNCTOR(report_t::fn_unrounded);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'w':
|
|
||||||
if (is_eq(p, "white"))
|
|
||||||
return WRAP_FUNCTOR(fn_white);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'y':
|
|
||||||
if (is_eq(p, "yellow"))
|
|
||||||
return WRAP_FUNCTOR(fn_yellow);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if they are trying to access an option's setting or value.
|
|
||||||
if (option_t<report_t> * handler = lookup_option(p))
|
|
||||||
return MAKE_OPT_FUNCTOR(report_t, handler);
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -311,9 +311,11 @@ public:
|
||||||
|
|
||||||
option_t<report_t> * lookup_option(const char * p);
|
option_t<report_t> * lookup_option(const char * p);
|
||||||
|
|
||||||
virtual void define(const string& name, expr_t::ptr_op_t def);
|
virtual void define(const symbol_t::kind_t kind, const string& name,
|
||||||
|
expr_t::ptr_op_t def);
|
||||||
|
|
||||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||||
|
const string& name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Option handlers
|
* Option handlers
|
||||||
|
|
|
||||||
23
src/scope.cc
23
src/scope.cc
|
|
@ -35,31 +35,34 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
void symbol_scope_t::define(const string& name, expr_t::ptr_op_t def)
|
void symbol_scope_t::define(const symbol_t::kind_t kind,
|
||||||
|
const string& name, expr_t::ptr_op_t def)
|
||||||
{
|
{
|
||||||
DEBUG("scope.symbols", "Defining '" << name << "' = " << def);
|
DEBUG("scope.symbols", "Defining '" << name << "' = " << def);
|
||||||
|
|
||||||
std::pair<symbol_map::iterator, bool> result
|
std::pair<symbol_map::iterator, bool> result
|
||||||
= symbols.insert(symbol_map::value_type(name, def));
|
= symbols.insert(symbol_map::value_type(symbol_t(kind, name, def), def));
|
||||||
if (! result.second) {
|
if (! result.second) {
|
||||||
symbol_map::iterator i = symbols.find(name);
|
symbol_map::iterator i = symbols.find(symbol_t(kind, name));
|
||||||
assert(i != symbols.end());
|
assert(i != symbols.end());
|
||||||
symbols.erase(i);
|
symbols.erase(i);
|
||||||
|
|
||||||
std::pair<symbol_map::iterator, bool> result2
|
result = symbols.insert(symbol_map::value_type(symbol_t(kind, name, def),
|
||||||
= symbols.insert(symbol_map::value_type(name, def));
|
def));
|
||||||
if (! result2.second)
|
if (! result.second)
|
||||||
throw_(compile_error, _("Redefinition of '%1' in same scope") << name);
|
throw_(compile_error,
|
||||||
|
_("Redefinition of '%1' in the same scope") << name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_t::ptr_op_t symbol_scope_t::lookup(const string& name)
|
expr_t::ptr_op_t symbol_scope_t::lookup(const symbol_t::kind_t kind,
|
||||||
|
const string& name)
|
||||||
{
|
{
|
||||||
symbol_map::const_iterator i = symbols.find(name);
|
symbol_map::const_iterator i = symbols.find(symbol_t(kind, name));
|
||||||
if (i != symbols.end())
|
if (i != symbols.end())
|
||||||
return (*i).second;
|
return (*i).second;
|
||||||
|
|
||||||
return child_scope_t::lookup(name);
|
return child_scope_t::lookup(kind, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
|
||||||
93
src/scope.h
93
src/scope.h
|
|
@ -50,6 +50,61 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Brief
|
||||||
|
*
|
||||||
|
* Long.
|
||||||
|
*/
|
||||||
|
struct symbol_t
|
||||||
|
{
|
||||||
|
enum kind_t {
|
||||||
|
UNKNOWN,
|
||||||
|
FUNCTION,
|
||||||
|
OPTION,
|
||||||
|
PRECOMMAND,
|
||||||
|
COMMAND,
|
||||||
|
DIRECTIVE
|
||||||
|
};
|
||||||
|
|
||||||
|
kind_t kind;
|
||||||
|
string name;
|
||||||
|
expr_t::ptr_op_t definition;
|
||||||
|
|
||||||
|
symbol_t() : kind(UNKNOWN), name(""), definition(NULL) {
|
||||||
|
TRACE_CTOR(symbol_t, "");
|
||||||
|
}
|
||||||
|
symbol_t(kind_t _kind, string _name, expr_t::ptr_op_t _definition = NULL)
|
||||||
|
: kind(_kind), name(_name), definition(_definition) {
|
||||||
|
TRACE_CTOR(symbol_t, "symbol_t::kind_t, string");
|
||||||
|
}
|
||||||
|
symbol_t(const symbol_t& sym)
|
||||||
|
: kind(sym.kind), name(sym.name),
|
||||||
|
definition(sym.definition) {
|
||||||
|
TRACE_CTOR(symbol_t, "copy");
|
||||||
|
}
|
||||||
|
~symbol_t() throw() {
|
||||||
|
TRACE_DTOR(symbol_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const symbol_t& sym) const {
|
||||||
|
return kind < sym.kind || name < sym.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||||
|
private:
|
||||||
|
/** Serialization. */
|
||||||
|
|
||||||
|
friend class boost::serialization::access;
|
||||||
|
|
||||||
|
template<class Archive>
|
||||||
|
void serialize(Archive& ar, const unsigned int /* version */) {
|
||||||
|
ar & kind;
|
||||||
|
ar & name;
|
||||||
|
ar & definition;
|
||||||
|
}
|
||||||
|
#endif // HAVE_BOOST_SERIALIZATION
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Brief
|
* @brief Brief
|
||||||
*
|
*
|
||||||
|
|
@ -65,8 +120,10 @@ public:
|
||||||
TRACE_DTOR(scope_t);
|
TRACE_DTOR(scope_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void define(const string&, expr_t::ptr_op_t) {}
|
virtual void define(const symbol_t::kind_t, const string&,
|
||||||
virtual expr_t::ptr_op_t lookup(const string& name) = 0;
|
expr_t::ptr_op_t) {}
|
||||||
|
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||||
|
const string& name) = 0;
|
||||||
|
|
||||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||||
private:
|
private:
|
||||||
|
|
@ -100,14 +157,16 @@ public:
|
||||||
TRACE_DTOR(child_scope_t);
|
TRACE_DTOR(child_scope_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void define(const string& name, expr_t::ptr_op_t def) {
|
virtual void define(const symbol_t::kind_t kind,
|
||||||
|
const string& name, expr_t::ptr_op_t def) {
|
||||||
if (parent)
|
if (parent)
|
||||||
parent->define(name, def);
|
parent->define(kind, name, def);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual expr_t::ptr_op_t lookup(const string& name) {
|
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||||
|
const string& name) {
|
||||||
if (parent)
|
if (parent)
|
||||||
return parent->lookup(name);
|
return parent->lookup(kind, name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -132,7 +191,7 @@ private:
|
||||||
*/
|
*/
|
||||||
class symbol_scope_t : public child_scope_t
|
class symbol_scope_t : public child_scope_t
|
||||||
{
|
{
|
||||||
typedef std::map<const string, expr_t::ptr_op_t> symbol_map;
|
typedef std::map<symbol_t, expr_t::ptr_op_t> symbol_map;
|
||||||
|
|
||||||
symbol_map symbols;
|
symbol_map symbols;
|
||||||
|
|
||||||
|
|
@ -147,9 +206,11 @@ public:
|
||||||
TRACE_DTOR(symbol_scope_t);
|
TRACE_DTOR(symbol_scope_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void define(const string& name, expr_t::ptr_op_t def);
|
virtual void define(const symbol_t::kind_t kind, const string& name,
|
||||||
|
expr_t::ptr_op_t def);
|
||||||
|
|
||||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||||
|
const string& name);
|
||||||
|
|
||||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||||
private:
|
private:
|
||||||
|
|
@ -259,15 +320,17 @@ public:
|
||||||
TRACE_DTOR(bind_scope_t);
|
TRACE_DTOR(bind_scope_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void define(const string& name, expr_t::ptr_op_t def) {
|
virtual void define(const symbol_t::kind_t kind, const string& name,
|
||||||
parent->define(name, def);
|
expr_t::ptr_op_t def) {
|
||||||
grandchild.define(name, def);
|
parent->define(kind, name, def);
|
||||||
|
grandchild.define(kind, name, def);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual expr_t::ptr_op_t lookup(const string& name) {
|
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||||
if (expr_t::ptr_op_t def = grandchild.lookup(name))
|
const string& name) {
|
||||||
|
if (expr_t::ptr_op_t def = grandchild.lookup(kind, name))
|
||||||
return def;
|
return def;
|
||||||
return child_scope_t::lookup(name);
|
return child_scope_t::lookup(kind, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||||
|
|
|
||||||
|
|
@ -284,23 +284,26 @@ option_t<session_t> * session_t::lookup_option(const char * p)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_t::ptr_op_t session_t::lookup(const string& name)
|
expr_t::ptr_op_t session_t::lookup(const symbol_t::kind_t kind,
|
||||||
|
const string& name)
|
||||||
{
|
{
|
||||||
const char * p = name.c_str();
|
switch (kind) {
|
||||||
switch (*p) {
|
case symbol_t::FUNCTION:
|
||||||
case 'o':
|
// Check if they are trying to access an option's setting or value.
|
||||||
if (WANT_OPT()) { p += OPT_PREFIX_LEN;
|
if (option_t<session_t> * handler = lookup_option(name.c_str()))
|
||||||
if (option_t<session_t> * handler = lookup_option(p))
|
return MAKE_OPT_FUNCTOR(session_t, handler);
|
||||||
return MAKE_OPT_HANDLER(session_t, handler);
|
break;
|
||||||
}
|
|
||||||
|
case symbol_t::OPTION:
|
||||||
|
if (option_t<session_t> * handler = lookup_option(name.c_str()))
|
||||||
|
return MAKE_OPT_HANDLER(session_t, handler);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if they are trying to access an option's setting or value.
|
return symbol_scope_t::lookup(kind, name);
|
||||||
if (option_t<session_t> * handler = lookup_option(p))
|
|
||||||
return MAKE_OPT_FUNCTOR(session_t, handler);
|
|
||||||
|
|
||||||
return symbol_scope_t::lookup(name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,8 @@ public:
|
||||||
|
|
||||||
option_t<session_t> * lookup_option(const char * p);
|
option_t<session_t> * lookup_option(const char * p);
|
||||||
|
|
||||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||||
|
const string& name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Option handlers
|
* Option handlers
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,8 @@ namespace {
|
||||||
std::streamsize len,
|
std::streamsize len,
|
||||||
account_t * account);
|
account_t * account);
|
||||||
|
|
||||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||||
|
const string& name);
|
||||||
};
|
};
|
||||||
|
|
||||||
void parse_amount_expr(scope_t& scope,
|
void parse_amount_expr(scope_t& scope,
|
||||||
|
|
@ -749,11 +750,7 @@ void instance_t::general_directive(char * line)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
scoped_array<char> directive(new char[std::strlen(p) + DIR_PREFIX_LEN + 1]);
|
if (expr_t::ptr_op_t op = lookup(symbol_t::DIRECTIVE, p)) {
|
||||||
std::strcpy(directive.get(), DIR_PREFIX);
|
|
||||||
std::strcpy(directive.get() + DIR_PREFIX_LEN, p);
|
|
||||||
|
|
||||||
if (expr_t::ptr_op_t op = lookup(directive.get())) {
|
|
||||||
call_scope_t args(*this);
|
call_scope_t args(*this);
|
||||||
args.push_back(string_value(p));
|
args.push_back(string_value(p));
|
||||||
op->as_function()(args);
|
op->as_function()(args);
|
||||||
|
|
@ -1233,9 +1230,10 @@ xact_t * instance_t::parse_xact(char * line,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_t::ptr_op_t instance_t::lookup(const string& name)
|
expr_t::ptr_op_t instance_t::lookup(const symbol_t::kind_t kind,
|
||||||
|
const string& name)
|
||||||
{
|
{
|
||||||
return scope.lookup(name);
|
return scope.lookup(kind, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t journal_t::parse(std::istream& in,
|
std::size_t journal_t::parse(std::istream& in,
|
||||||
|
|
|
||||||
|
|
@ -422,8 +422,12 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_t::ptr_op_t xact_t::lookup(const string& name)
|
expr_t::ptr_op_t xact_t::lookup(const symbol_t::kind_t kind,
|
||||||
|
const string& name)
|
||||||
{
|
{
|
||||||
|
if (kind != symbol_t::FUNCTION)
|
||||||
|
return item_t::lookup(kind, name);
|
||||||
|
|
||||||
switch (name[0]) {
|
switch (name[0]) {
|
||||||
case 'c':
|
case 'c':
|
||||||
if (name == "code")
|
if (name == "code")
|
||||||
|
|
@ -448,7 +452,7 @@ expr_t::ptr_op_t xact_t::lookup(const string& name)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return item_t::lookup(name);
|
return item_t::lookup(kind, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool xact_t::valid() const
|
bool xact_t::valid() const
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,8 @@ public:
|
||||||
string idstring() const;
|
string idstring() const;
|
||||||
string id() const;
|
string id() const;
|
||||||
|
|
||||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||||
|
const string& name);
|
||||||
|
|
||||||
virtual bool valid() const;
|
virtual bool valid() const;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue