diff options
author | John Wiegley <johnw@newartisans.com> | 2009-02-05 21:18:37 -0400 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2009-02-05 21:20:09 -0400 |
commit | 408b819c6e087593ba61e82b91dda2369ef32f62 (patch) | |
tree | 68456c86187e00355d47c5794008b8226bd000e2 /src | |
parent | 7b24e8f8e33049fe533cce2d2d473c6122460954 (diff) | |
download | fork-ledger-408b819c6e087593ba61e82b91dda2369ef32f62.tar.gz fork-ledger-408b819c6e087593ba61e82b91dda2369ef32f62.tar.bz2 fork-ledger-408b819c6e087593ba61e82b91dda2369ef32f62.zip |
Greatly simplified the way option and command handlers are defined.
Diffstat (limited to 'src')
-rw-r--r-- | src/chain.cc | 150 | ||||
-rw-r--r-- | src/chain.h | 41 | ||||
-rw-r--r-- | src/csv.h | 3 | ||||
-rw-r--r-- | src/emacs.h | 3 | ||||
-rw-r--r-- | src/filters.h | 4 | ||||
-rw-r--r-- | src/global.cc | 83 | ||||
-rw-r--r-- | src/global.h | 19 | ||||
-rw-r--r-- | src/handler.h | 246 | ||||
-rw-r--r-- | src/item.cc | 2 | ||||
-rw-r--r-- | src/item.h | 2 | ||||
-rw-r--r-- | src/main.cc | 5 | ||||
-rw-r--r-- | src/output.cc | 6 | ||||
-rw-r--r-- | src/output.h | 1 | ||||
-rw-r--r-- | src/report.cc | 381 | ||||
-rw-r--r-- | src/report.h | 403 | ||||
-rw-r--r-- | src/session.cc | 1 | ||||
-rw-r--r-- | src/session.h | 1 | ||||
-rw-r--r-- | src/stream.cc | 2 | ||||
-rw-r--r-- | src/textual.cc | 4 | ||||
-rw-r--r-- | src/textual.h | 8 |
20 files changed, 723 insertions, 642 deletions
diff --git a/src/chain.cc b/src/chain.cc index f79da543..4956a237 100644 --- a/src/chain.cc +++ b/src/chain.cc @@ -30,6 +30,7 @@ */ #include "chain.h" +#include "report.h" #include "filters.h" #include "reconcile.h" @@ -43,14 +44,14 @@ xact_handler_ptr chain_xact_handlers(report_t& report, xact_handler_ptr handler(base_handler); - // format_xacts write each xact received to the - // output stream. + // format_xacts write each xact received to the output stream. if (handle_individual_xacts) { - // truncate_entries cuts off a certain number of _entries_ from - // being displayed. It does not affect calculation. - if (report.head_entries || report.tail_entries) - handler.reset(new truncate_entries(handler, report.head_entries, - report.tail_entries)); + // truncate_entries cuts off a certain number of _entries_ from being + // displayed. It does not affect calculation. + if (report.HANDLED(head_) || report.HANDLED(tail_)) + handler.reset(new truncate_entries(handler, + report.HANDLER(head_).value.to_long(), + report.HANDLER(tail_).value.to_long())); // filter_xacts will only pass through xacts matching the // `display_predicate'. @@ -59,15 +60,15 @@ xact_handler_ptr chain_xact_handlers(report_t& report, (handler, item_predicate<xact_t>(report.display_predicate, report.what_to_keep))); - // calc_xacts computes the running total. When this - // appears will determine, for example, whether filtered - // xacts are included or excluded from the running total. + // calc_xacts computes the running total. When this appears will + // determine, for example, whether filtered xacts are included or excluded + // from the running total. handler.reset(new calc_xacts(handler)); - // component_xacts looks for reported xact that - // match the given `descend_expr', and then reports the - // xacts which made up the total for that reported - // xact. +#if 0 + // component_xacts looks for reported xact that match the given + // `descend_expr', and then reports the xacts which made up the total for + // that reported xact. if (! report.descend_expr.empty()) { std::list<std::string> descend_exprs; @@ -90,9 +91,9 @@ xact_handler_ptr chain_xact_handlers(report_t& report, remember_components = true; } - // reconcile_xacts will pass through only those - // xacts which can be reconciled to a given balance - // (calculated against the xacts which it receives). + // reconcile_xacts will pass through only those xacts which can be + // reconciled to a given balance (calculated against the xacts which it + // receives). if (! report.reconcile_balance.empty()) { date_t cutoff = CURRENT_DATE(); if (! report.reconcile_date.empty()) @@ -100,57 +101,54 @@ xact_handler_ptr chain_xact_handlers(report_t& report, handler.reset(new reconcile_xacts (handler, value_t(report.reconcile_balance), cutoff)); } +#endif - // filter_xacts will only pass through xacts - // matching the `secondary_predicate'. + // filter_xacts will only pass through xacts matching the + // `secondary_predicate'. if (! report.secondary_predicate.empty()) handler.reset(new filter_xacts - (handler, item_predicate<xact_t>(report.secondary_predicate, - report.what_to_keep))); - - // sort_xacts will sort all the xacts it sees, based - // on the `sort_order' value expression. - if (! report.sort_string.empty()) { - if (report.entry_sort) - handler.reset(new sort_entries(handler, report.sort_string)); + (handler, item_predicate<xact_t> + (report.secondary_predicate, report.what_to_keep))); + + // sort_xacts will sort all the xacts it sees, based on the `sort_order' + // value expression. + if (report.HANDLED(sort_)) { + if (report.HANDLED(sort_entries_)) + handler.reset(new sort_entries(handler, report.HANDLER(sort_).str())); else - handler.reset(new sort_xacts(handler, report.sort_string)); + handler.reset(new sort_xacts(handler, report.HANDLER(sort_).str())); } - // changed_value_xacts adds virtual xacts to the - // list to account for changes in market value of commodities, - // which otherwise would affect the running total unpredictably. + // changed_value_xacts adds virtual xacts to the list to account for + // changes in market value of commodities, which otherwise would affect + // the running total unpredictably. if (report.show_revalued) handler.reset(new changed_value_xacts(handler, report.total_expr, report.show_revalued_only)); - // collapse_xacts causes entries with multiple xacts - // to appear as entries with a subtotaled xact for each - // commodity used. - if (report.show_collapsed) + // collapse_xacts causes entries with multiple xacts to appear as entries + // with a subtotaled xact for each commodity used. + if (report.HANDLED(collapse)) handler.reset(new collapse_xacts(handler, report.session)); - // subtotal_xacts combines all the xacts it receives - // into one subtotal entry, which has one xact for each - // commodity in each account. + // subtotal_xacts combines all the xacts it receives into one subtotal + // entry, which has one xact for each commodity in each account. // - // period_xacts is like subtotal_xacts, but it - // subtotals according to time periods rather than totalling - // everything. + // period_xacts is like subtotal_xacts, but it subtotals according to time + // periods rather than totalling everything. // - // dow_xacts is like period_xacts, except that it - // reports all the xacts that fall on each subsequent day - // of the week. - if (report.show_subtotal) + // dow_xacts is like period_xacts, except that it reports all the xacts + // that fall on each subsequent day of the week. + if (report.HANDLED(subtotal)) handler.reset(new subtotal_xacts(handler, remember_components)); - if (report.days_of_the_week) + if (report.HANDLED(dow)) handler.reset(new dow_xacts(handler, remember_components)); - else if (report.by_payee) + else if (report.HANDLED(by_payee)) handler.reset(new by_payee_xacts(handler, remember_components)); - // interval_xacts groups xacts together based on a - // time period, such as weekly or monthly. + // interval_xacts groups xacts together based on a time period, such as + // weekly or monthly. if (! report.report_period.empty()) { handler.reset(new interval_xacts(handler, report.report_period, remember_components)); @@ -158,27 +156,23 @@ xact_handler_ptr chain_xact_handlers(report_t& report, } } - // invert_xacts inverts the value of the xacts it - // receives. - if (report.show_inverted) + // invert_xacts inverts the value of the xacts it receives. + if (report.HANDLED(invert)) handler.reset(new invert_xacts(handler)); - // related_xacts will pass along all xacts related - // to the xact received. If `show_all_related' is true, - // then all the entry's xacts are passed; meaning that if - // one xact of an entry is to be printed, all the - // xact for that entry will be printed. - if (report.show_related) - handler.reset(new related_xacts(handler, report.show_all_related)); - - // anonymize_xacts removes all meaningful information from entry - // payee's and account names, for the sake of creating useful bug - // reports. - if (report.anonymize) + // related_xacts will pass along all xacts related to the xact received. If + // the `related_all' handler is on, then all the entry's xacts are passed; + // meaning that if one xact of an entry is to be printed, all the xact for + // that entry will be printed. + if (report.HANDLED(related)) + handler.reset(new related_xacts(handler, report.HANDLED(related_all))); + + // anonymize_xacts removes all meaningful information from entry payee's and + // account names, for the sake of creating useful bug reports. + if (report.HANDLED(anon)) handler.reset(new anonymize_xacts(handler)); - // This filter_xacts will only pass through xacts - // matching the `predicate'. + // This filter_xacts will only pass through xacts matching the `predicate'. if (! report.predicate.empty()) { DEBUG("report.predicate", "Report predicate expression = " << report.predicate); @@ -188,13 +182,12 @@ xact_handler_ptr chain_xact_handlers(report_t& report, } #if 0 - // budget_xacts takes a set of xacts from a data - // file and uses them to generate "budget xacts" which - // balance against the reported xacts. + // budget_xacts takes a set of xacts from a data file and uses them to + // generate "budget xacts" which balance against the reported xacts. // - // forecast_xacts is a lot like budget_xacts, except - // that it adds entries only for the future, and does not balance - // them against anything but the future balance. + // forecast_xacts is a lot like budget_xacts, except that it adds entries + // only for the future, and does not balance them against anything but the + // future balance. if (report.budget_flags) { budget_xacts * budget_handler = new budget_xacts(handler, @@ -202,11 +195,10 @@ xact_handler_ptr chain_xact_handlers(report_t& report, budget_handler->add_period_entries(journal->period_entries); handler.reset(budget_handler); - // Apply this before the budget handler, so that only matching - // xacts are calculated toward the budget. The use of - // filter_xacts above will further clean the results so - // that no automated xacts that don't match the filter get - // reported. + // Apply this before the budget handler, so that only matching xacts are + // calculated toward the budget. The use of filter_xacts above will + // further clean the results so that no automated xacts that don't match + // the filter get reported. if (! report.predicate.empty()) handler.reset(new filter_xacts(handler, report.predicate)); } @@ -222,9 +214,9 @@ xact_handler_ptr chain_xact_handlers(report_t& report, } #endif - if (report.comm_as_payee) + if (report.HANDLED(comm_as_payee)) handler.reset(new set_comm_as_payee(handler)); - else if (report.code_as_payee) + else if (report.HANDLED(code_as_payee)) handler.reset(new set_code_as_payee(handler)); return handler; diff --git a/src/chain.h b/src/chain.h index c9199f05..c6de088f 100644 --- a/src/chain.h +++ b/src/chain.h @@ -46,10 +46,49 @@ #ifndef _CHAIN_H #define _CHAIN_H -#include "report.h" +#include "xact.h" +#include "account.h" namespace ledger { +/** + * @brief Brief + * + * Long. + */ +template <typename T> +struct item_handler : public noncopyable +{ + shared_ptr<item_handler> handler; + +public: + item_handler() { + TRACE_CTOR(item_handler, ""); + } + item_handler(shared_ptr<item_handler> _handler) : handler(_handler) { + TRACE_CTOR(item_handler, "shared_ptr<item_handler>"); + } + virtual ~item_handler() { + TRACE_DTOR(item_handler); + } + + virtual void flush() { + if (handler.get()) + handler->flush(); + } + virtual void operator()(T& item) { + if (handler.get()) { + check_for_signal(); + (*handler.get())(item); + } + } +}; + +typedef shared_ptr<item_handler<xact_t> > xact_handler_ptr; +typedef shared_ptr<item_handler<account_t> > acct_handler_ptr; + +class report_t; + xact_handler_ptr chain_xact_handlers(report_t& report, xact_handler_ptr base_handler, @@ -46,8 +46,7 @@ #ifndef _CSV_H #define _CSV_H -#include "handler.h" -#include "format.h" +#include "output.h" namespace ledger { diff --git a/src/emacs.h b/src/emacs.h index fdb554ed..65aac7f6 100644 --- a/src/emacs.h +++ b/src/emacs.h @@ -46,8 +46,7 @@ #ifndef _EMACS_H #define _EMACS_H -#include "handler.h" -#include "format.h" +#include "output.h" namespace ledger { diff --git a/src/filters.h b/src/filters.h index c6ae1a4d..67b650dc 100644 --- a/src/filters.h +++ b/src/filters.h @@ -46,9 +46,11 @@ #ifndef _FILTERS_H #define _FILTERS_H -#include "handler.h" +#include "chain.h" #include "predicate.h" #include "entry.h" +#include "xact.h" +#include "account.h" namespace ledger { diff --git a/src/global.cc b/src/global.cc index 9dff9aac..b04b4498 100644 --- a/src/global.cc +++ b/src/global.cc @@ -168,8 +168,10 @@ void global_scope_t::execute_command(strings_list args, bool at_repl) // subprocess) and invoke the report command. The output stream is closed // by the caller of this function. - report().output_stream.initialize(report().output_file, - session().pager_path); + report().output_stream + .initialize(report().HANDLER(output_) ? + optional<path>(path(report().HANDLER(output_).str())) : + optional<path>(), session().pager_path); // Create an argument scope containing the report command's arguments, and // then invoke the command. The bound scope causes lookups to happen @@ -206,51 +208,42 @@ int global_scope_t::execute_command_wrapper(strings_list args, bool at_repl) return status; } +namespace { +} + expr_t::ptr_op_t global_scope_t::lookup(const string& name) { const char * p = name.c_str(); switch (*p) { - case 'l': - if (std::strncmp(p, "ledger_precmd_", 14) == 0) { - p = p + 14; - switch (*p) { - case 'p': - if (std::strcmp(p, "push") == 0) - return MAKE_FUNCTOR(global_scope_t::push_report_cmd); - else if (std::strcmp(p, "pop") == 0) - return MAKE_FUNCTOR(global_scope_t::pop_report_cmd); - break; - } - } - break; - case 'o': - if (std::strncmp(p, "opt_", 4) == 0) { - p = p + 4; + if (WANT_OPT()) { p += OPT_PREFIX_LEN; switch (*p) { case 'd': - if (std::strcmp(p, "debug_") == 0) - return MAKE_FUNCTOR(global_scope_t::ignore); + OPT(debug_); break; - case 's': - if (std::strcmp(p, "script_") == 0) - return MAKE_FUNCTOR(global_scope_t::option_script_); + OPT(script_); break; - case 't': - if (std::strcmp(p, "trace_") == 0) - return MAKE_FUNCTOR(global_scope_t::ignore); + OPT(trace_); break; - case 'v': - if (! *(p + 1) || std::strcmp(p, "verbose") == 0) - return MAKE_FUNCTOR(global_scope_t::ignore); - else if (std::strcmp(p, "verify") == 0) - return MAKE_FUNCTOR(global_scope_t::ignore); + OPT_(verbose); + else OPT(verify); break; } } + + case 'p': + if (WANT_PRECMD()) { p += PRECMD_PREFIX_LEN; + switch (*p) { + case 'p': + M_COMMAND(global_scope_t, push); + else M_COMMAND(global_scope_t, pop); + break; + } + } + break; } // If you're wondering how symbols from report() will be found, it's @@ -342,7 +335,7 @@ void normalize_session_options(session_t& session) function_t look_for_precommand(scope_t& scope, const string& verb) { - if (expr_t::ptr_op_t def = scope.lookup(string("ledger_precmd_") + verb)) + if (expr_t::ptr_op_t def = scope.lookup(string("precmd_") + verb)) return def->as_function(); else return function_t(); @@ -350,7 +343,7 @@ function_t look_for_precommand(scope_t& scope, const string& verb) function_t look_for_command(scope_t& scope, const string& verb) { - if (expr_t::ptr_op_t def = scope.lookup(string("ledger_cmd_") + verb)) + if (expr_t::ptr_op_t def = scope.lookup(string("cmd_") + verb)) return def->as_function(); else return function_t(); @@ -365,18 +358,18 @@ void normalize_report_options(report_t& report, const string& verb) // for 3.0. if (verb == "print" || verb == "entry" || verb == "dump") { - report.show_related = true; - report.show_all_related = true; + report.HANDLER(related).on(); + report.HANDLER(related_all).on(); } else if (verb == "equity") { - report.show_subtotal = true; + report.HANDLER(subtotal).on(); } - else if (report.show_related) { + else if (report.HANDLED(related)) { if (verb[0] == 'r') { - report.show_inverted = true; + report.HANDLER(invert).on(); } else { - report.show_subtotal = true; - report.show_all_related = true; + report.HANDLER(subtotal).on(); + report.HANDLER(related_all).on(); } } @@ -387,9 +380,9 @@ void normalize_report_options(report_t& report, const string& verb) if (report.display_predicate.empty()) { if (verb[0] == 'b') { - if (! report.show_empty) + if (! report.HANDLED(empty)) report.display_predicate = "total"; - if (! report.show_subtotal) { + if (! report.HANDLED(subtotal)) { if (! report.display_predicate.empty()) report.display_predicate += "&"; report.display_predicate += "depth<=1"; @@ -398,13 +391,13 @@ void normalize_report_options(report_t& report, const string& verb) else if (verb == "equity") { report.display_predicate = "amount_expr"; // jww (2008-08-14): ??? } - else if (verb[0] == 'r' && ! report.show_empty) { + else if (verb[0] == 'r' && ! report.HANDLED(empty)) { report.display_predicate = "amount"; } } - if (! report.report_period.empty() && ! report.sort_all) - report.entry_sort = true; + if (! report.report_period.empty() && ! report.HANDLED(sort_all_)) + report.HANDLER(sort_entries_).on(); } } // namespace ledger diff --git a/src/global.h b/src/global.h index f47967fb..9b9805a6 100644 --- a/src/global.h +++ b/src/global.h @@ -48,8 +48,6 @@ class global_scope_t : public noncopyable, public scope_t ptr_list<report_t> report_stack; public: - path script_file; - global_scope_t(char ** envp); ~global_scope_t(); @@ -81,7 +79,7 @@ public: void execute_command(strings_list args, bool at_repl); int execute_command_wrapper(strings_list args, bool at_repl); - value_t push_report_cmd(call_scope_t&) { + value_t push_command(call_scope_t&) { // Make a copy at position 2, because the topmost report object has an // open output stream at this point. We want it to get popped off as // soon as this command terminate so that the stream is closed cleanly. @@ -89,19 +87,16 @@ public: new report_t(report_stack.front())); return true; } - value_t pop_report_cmd(call_scope_t&) { + value_t pop_command(call_scope_t&) { pop_report(); return true; } - value_t option_script_(call_scope_t& args) { - script_file = args[0].as_string(); - return true; - } - - value_t ignore(call_scope_t&) { - return true; - } + OPTION(global_scope_t, debug_); + OPTION(global_scope_t, script_); + OPTION(global_scope_t, trace_); + OPTION(global_scope_t, verbose); + OPTION(global_scope_t, verify); virtual expr_t::ptr_op_t lookup(const string& name); }; diff --git a/src/handler.h b/src/handler.h index bfb1b08f..83d801a3 100644 --- a/src/handler.h +++ b/src/handler.h @@ -39,54 +39,244 @@ * * @ingroup report * - * @brief Brief + * @brief Defines a scheme for more easily handling commands and options via + * value expressions. * - * Long. + * The OPTION and OPTION_ macros are used to define an option handler within a + * scope_t derived class. The _ variant can specify a body in order to + * provide HELP(out) and DO() or DO_(args) methods. + * + * The other macros are used for looking up and referring to handlers, + * commands and functions. Typically they occur in the object's lookup + * method, for example: + * + * expr_t::ptr_op_t some_class_t::lookup(const string& name) + * { + * const char * p = name.c_str(); + * switch (*p) { + * case 'a': + * METHOD(some_class_t, my_method); // looks up a method by name + * break; + * + * case 'c': + * if (WANT_CMD()) { p += CMD_PREFIX_LEN; + * switch (*p) { + * case 'a': + * COMMAND(args); // looks up global func named "args_command" + * break; + * } + * } + * break; + * + * case 'o': + * if (WANT_OPT()) { p += OPT_PREFIX_LEN; + * switch (*p) { + * case 'f': + * OPT(foo); // look for a handler named "foo" + * else OPT(foo2_); // same, but foo2 wants an argument + * else OPT_(foo3); // match on "foo3" or 'f' + * else OPT_CH(foo4_); // match only on 'f' + * break; + * } + * } + * break; + * } + * + * return expr_t::ptr_op_t(); + * } */ #ifndef _HANDLER_H #define _HANDLER_H -#include "utils.h" -#include "xact.h" -#include "account.h" +#include "scope.h" namespace ledger { -/** - * @brief Brief - * - * Long. - */ template <typename T> -struct item_handler : public noncopyable +class handler_t { - shared_ptr<item_handler> handler; + const char * name; + std::size_t name_len; + const char ch; + bool handled; public: - item_handler() { - TRACE_CTOR(item_handler, ""); + T * parent; + value_t value; + + handler_t(const char * _name, const char _ch = '\0') + : name(_name), name_len(std::strlen(name)), ch(_ch), + handled(false), parent(NULL), value() { + TRACE_CTOR(handler_t, "const char *, const char"); } - item_handler(shared_ptr<item_handler> _handler) : handler(_handler) { - TRACE_CTOR(item_handler, "shared_ptr<item_handler>"); + handler_t(const handler_t& other) + : name(other.name), + name_len(other.name_len), + ch(other.ch), + handled(other.handled), + parent(NULL), + value(other.value) + { + TRACE_CTOR(handler_t, "copy"); } - virtual ~item_handler() { - TRACE_DTOR(item_handler); + + virtual ~handler_t() { + TRACE_DTOR(handler_t); + } + + string desc() const { + std::ostringstream out; + if (ch) + out << "--" << name << " (-" << ch << ")"; + else + out << "--" << name; + return out.str(); } - virtual void flush() { - if (handler.get()) - handler->flush(); + virtual void help(std::ostream& out) { + out << "No help for " << desc() << "\n"; } - virtual void operator()(T& item) { - if (handler.get()) { - check_for_signal(); - (*handler.get())(item); - } + + operator bool() const { + return handled; + } + + string str() const { + assert(handled); + return value.as_string(); + } + + void on() { + handled = true; + } + void on(const string& str) { + handled = true; + value = string_value(str); + } + void on(const value_t& val) { + handled = true; + value = val; + } + + void off() { + handled = false; + value = value_t(); + } + + virtual void handler(call_scope_t& args) { + if (name[name_len - 1] == '_') + value = args[0]; + } + + virtual value_t operator()(call_scope_t& args) { + handled = true; + handler(args); + return true; } }; -typedef shared_ptr<item_handler<xact_t> > xact_handler_ptr; -typedef shared_ptr<item_handler<account_t> > acct_handler_ptr; +#define BEGIN(type, name) \ + struct name ## _handler_t : public handler_t<type> + +#define CTOR(type, name) \ + name ## _handler_t() : handler_t<type>(#name) +#define DECL1(type, name, vartype, var, value) \ + vartype var ; \ + name ## _handler_t() : handler_t<type>(#name), var(value) + +#define HELP(var) virtual void help(std::ostream& var) +#define DO() virtual void handler(call_scope_t&) +#define DO_(var) virtual void handler(call_scope_t& var) + +#define END(name) name ## _handler + +#define COPY_OPT(name, other) name ## _handler(other.name ## _handler) + +#define CALL_FUNCTOR(x) \ + expr_t::op_t::wrap_functor(bind(&x ## _t::operator(), &x, _1)) + +inline bool optcmp(const char * p, const char * n) { + // Test whether p matches n, substituting - in p for _ in n. + for (; *p && *n; p++, n++) { + if (! (*p == '-' && *n == '_' ) && *p != *n) + return false; + } + return *p == *n; +} + +#define OPT(name) \ + if (optcmp(p, #name)) \ + return ((name ## _handler).parent = this, \ + CALL_FUNCTOR(name ## _handler)) + +#define OPT_(name) \ + if (! *(p + 1) || (*(p + 1) == '_' && ! *(p + 2)) || \ + optcmp(p, #name)) \ + return ((name ## _handler).parent = this, \ + CALL_FUNCTOR(name ## _handler)) + +#define OPT_CH(name) \ + if (! *(p + 1) || (*(p + 1) == '_' && ! *(p + 2))) \ + return ((name ## _handler).parent = this, \ + CALL_FUNCTOR(name ## _handler)) + +#define FUNCTION(name) \ + if (std::strcmp(p, #name) == 0) \ + return WRAP_FUNCTOR(fn_ ## name) + +#define METHOD(type, name) \ + if (std::strcmp(p, #name) == 0) \ + return MAKE_FUNCTOR(type::fn_ ## name) + +#define M_COMMAND(type, name) \ + if (std::strcmp(p, #name) == 0) \ + return MAKE_FUNCTOR(type::name ## _command) + +#define COMMAND(name) \ + if (std::strcmp(p, #name) == 0) \ + return WRAP_FUNCTOR(name ## _command) + +#define HANDLER(name) name ## _handler +#define HANDLED(name) HANDLER(name) + +#define OPTION(type, name) \ + BEGIN(type, name) \ + { \ + CTOR(type, name) {} \ + } \ + END(name) + +#define OPTION_(type, name, body) \ + BEGIN(type, name) \ + { \ + CTOR(type, name) {} \ + body \ + } \ + 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) } // namespace ledger diff --git a/src/item.cc b/src/item.cc index a4e2f2f1..6be3bae3 100644 --- a/src/item.cc +++ b/src/item.cc @@ -33,8 +33,6 @@ namespace ledger { -bool item_t::use_effective_date = false; - bool item_t::has_tag(const string& tag) const { if (! metadata) @@ -80,8 +80,6 @@ public: istream_pos_type end_pos; std::size_t end_line; - static bool use_effective_date; - item_t(flags_t _flags = ITEM_NORMAL, const optional<string>& _note = none) : supports_flags<>(_flags), _state(UNCLEARED), note(_note), beg_pos(0), beg_line(0), end_pos(0), end_line(0) diff --git a/src/main.cc b/src/main.cc index c8192082..72d84421 100644 --- a/src/main.cc +++ b/src/main.cc @@ -90,14 +90,13 @@ int main(int argc, char * argv[], char * envp[]) args = read_command_arguments(bound_scope, args); - if (! global_scope->script_file.empty() && - exists(global_scope->script_file)) { + if (global_scope->HANDLED(script_)) { // Ledger is being invoked as a script command interpreter global_scope->read_journal_files(); status = 0; - ifstream in(global_scope->script_file); + ifstream in(global_scope->HANDLER(script_).str()); while (status == 0 && ! in.eof()) { char line[1024]; in.getline(line, 1023); diff --git a/src/output.cc b/src/output.cc index da1f4bc5..a0db92b6 100644 --- a/src/output.cc +++ b/src/output.cc @@ -159,7 +159,7 @@ void format_accounts::flush() account_t::xdata_t& xdata(report.session.master->xdata()); - if (! report.show_collapsed && xdata.total) { + if (! report.HANDLED(collapse) && xdata.total) { out << "--------------------\n"; xdata.value = xdata.total; bind_scope_t bound_scope(report, *report.session.master); @@ -201,11 +201,11 @@ bool format_accounts::disp_subaccounts_p(account_t& account, bind_scope_t bound_scope(report, *pair.second); call_scope_t args(bound_scope); - result = report.get_total_expr(args); + result = report.fn_total_expr(args); if (! computed) { bind_scope_t account_scope(report, account); call_scope_t args(account_scope); - acct_total = report.get_total_expr(args); + acct_total = report.fn_total_expr(args); computed = true; } diff --git a/src/output.h b/src/output.h index af8e9e82..d3dd6560 100644 --- a/src/output.h +++ b/src/output.h @@ -47,7 +47,6 @@ #define _OUTPUT_H #include "report.h" -#include "handler.h" #include "format.h" namespace ledger { diff --git a/src/report.cc b/src/report.cc index 20c9e8e5..95add7a3 100644 --- a/src/report.cc +++ b/src/report.cc @@ -66,12 +66,12 @@ void report_t::accounts_report(acct_handler_ptr handler) { sum_all_accounts(); - if (sort_string.empty()) { + if (! HANDLED(sort_)) { basic_accounts_iterator walker(*session.master); pass_down_accounts(handler, walker, item_predicate<account_t>("total", what_to_keep)); } else { - sorted_accounts_iterator walker(*session.master, sort_string); + sorted_accounts_iterator walker(*session.master, HANDLER(sort_).str()); pass_down_accounts(handler, walker, item_predicate<account_t>("total", what_to_keep)); } @@ -84,43 +84,43 @@ void report_t::commodities_report(const string& format) { } -value_t report_t::get_amount_expr(call_scope_t& scope) +value_t report_t::fn_amount_expr(call_scope_t& scope) { return amount_expr.calc(scope); } -value_t report_t::get_total_expr(call_scope_t& scope) +value_t report_t::fn_total_expr(call_scope_t& scope) { return total_expr.calc(scope); } -value_t report_t::get_display_total(call_scope_t& scope) +value_t report_t::fn_display_total(call_scope_t& scope) { return display_total.calc(scope); } -value_t report_t::f_market_value(call_scope_t& args) -{ - var_t<datetime_t> date(args, 1); - var_t<string> in_terms_of(args, 2); +namespace { + value_t fn_market_value(call_scope_t& args) + { + var_t<datetime_t> date(args, 1); + var_t<string> in_terms_of(args, 2); - commodity_t * commodity = NULL; - if (in_terms_of) - commodity = amount_t::current_pool->find_or_create(*in_terms_of); + commodity_t * commodity = NULL; + if (in_terms_of) + commodity = amount_t::current_pool->find_or_create(*in_terms_of); - DEBUG("report.market", "getting market value of: " << args[0]); + DEBUG("report.market", "getting market value of: " << args[0]); - value_t result = - args[0].value(date ? optional<datetime_t>(*date) : optional<datetime_t>(), - commodity ? optional<commodity_t&>(*commodity) : - optional<commodity_t&>()); + value_t result = + args[0].value(date ? optional<datetime_t>(*date) : optional<datetime_t>(), + commodity ? optional<commodity_t&>(*commodity) : + optional<commodity_t&>()); - DEBUG("report.market", "result is: " << result); - return result; -} + DEBUG("report.market", "result is: " << result); + return result; + } -namespace { - value_t print_balance(call_scope_t& args) + value_t fn_print_balance(call_scope_t& args) { report_t& report(find_scope<report_t>(args)); @@ -136,13 +136,13 @@ namespace { return string_value(out.str()); } - value_t strip_annotations(call_scope_t& args) + value_t fn_strip(call_scope_t& args) { report_t& report(find_scope<report_t>(args)); return args[0].strip_annotations(report.what_to_keep); } - value_t truncate(call_scope_t& args) + value_t fn_truncate(call_scope_t& args) { report_t& report(find_scope<report_t>(args)); @@ -153,16 +153,24 @@ namespace { account_abbrev ? *account_abbrev : -1)); } - value_t display_date(call_scope_t& args) + value_t fn_display_date(call_scope_t& args) { report_t& report(find_scope<report_t>(args)); item_t& item(find_scope<item_t>(args)); - if (item.use_effective_date) { + date_t when; + if (report.HANDLED(effective)) { if (optional<date_t> date = item.effective_date()) - return string_value(format_date(*date, report.output_date_format)); + when = *date; + } else { + when = item.date(); } - return string_value(format_date(item.date(), report.output_date_format)); + + if (report.HANDLED(output_date_format_)) + return string_value + (format_date(when, report.HANDLER(output_date_format_).str())); + else + return string_value(format_date(when)); } template <class Type = xact_t, @@ -195,41 +203,29 @@ namespace { }; } +#if 0 +// Commands yet to implement: +// +// entry +// prices +// pricesdb +// csv +// emacs | lisp +#endif + +#define FORMAT(member) \ + (HANDLED(format_) ? HANDLER(format_).str() : session.member) + expr_t::ptr_op_t report_t::lookup(const string& name) { const char * p = name.c_str(); switch (*p) { case 'a': - if (std::strcmp(p, "amount_expr") == 0) - return MAKE_FUNCTOR(report_t::get_amount_expr); - break; - - case 'd': - if (std::strcmp(p, "display_total") == 0) - return MAKE_FUNCTOR(report_t::get_display_total); - else if (std::strcmp(p, "display_date") == 0) - return WRAP_FUNCTOR(display_date); + METHOD(report_t, amount_expr); break; - case 'l': - if (std::strncmp(p, "ledger_cmd_", 11) == 0) { - -#define FORMAT(str) (format_string.empty() ? session. str : format_string) - -#if 0 - // Commands yet to implement: - // - // entry - // dump - // output - // prices - // pricesdb - // csv - // emacs | lisp - // xml -#endif - - p = p + 11; + case 'c': + if (WANT_CMD()) { p += CMD_PREFIX_LEN; switch (*p) { case 'b': if (*(p + 1) == '\0' || @@ -262,297 +258,212 @@ expr_t::ptr_op_t report_t::lookup(const string& name) break; } } - else if (std::strncmp(p, "ledger_precmd_", 14) == 0) { - p = p + 14; - switch (*p) { - case 'a': - if (std::strcmp(p, "args") == 0) - return WRAP_FUNCTOR(args_command); - break; - - case 'p': - if (std::strcmp(p, "parse") == 0) - return WRAP_FUNCTOR(parse_command); - else if (std::strcmp(p, "period") == 0) - return WRAP_FUNCTOR(period_command); - break; - - case 'e': - if (std::strcmp(p, "eval") == 0) - return WRAP_FUNCTOR(eval_command); - break; + break; - case 'f': - if (std::strcmp(p, "format") == 0) - return WRAP_FUNCTOR(format_command); - break; - } - } + case 'd': + METHOD(report_t, display_total); + else FUNCTION(display_date); break; case 'm': - if (std::strcmp(p, "market_value") == 0) - return MAKE_FUNCTOR(report_t::f_market_value); + FUNCTION(market_value); break; case 'o': - if (std::strncmp(p, "opt_", 4) == 0) { - p = p + 4; + if (WANT_OPT()) { p += OPT_PREFIX_LEN; switch (*p) { case 'a': - if (std::strcmp(p, "amount_") == 0) - return MAKE_FUNCTOR(report_t::option_amount_); - else if (std::strcmp(p, "ansi") == 0) - return MAKE_FUNCTOR(report_t::option_ansi); - else if (std::strcmp(p, "ansi-invert") == 0) - return MAKE_FUNCTOR(report_t::option_ansi_invert); - else if (std::strcmp(p, "anon") == 0) - return MAKE_FUNCTOR(report_t::option_anon); + OPT(amount_); + else OPT(anon); break; case 'b': - if (std::strcmp(p, "b_") == 0 || - std::strcmp(p, "begin_") == 0) - return MAKE_FUNCTOR(report_t::option_begin_); - else if (std::strcmp(p, "base") == 0) - return MAKE_FUNCTOR(report_t::option_base); - else if (std::strcmp(p, "by-payee") == 0) - return MAKE_FUNCTOR(report_t::option_by_payee); + OPT_(begin_); + else OPT(base); + else OPT(by_payee); break; case 'c': - if (! *(p + 1) || std::strcmp(p, "current") == 0) - return MAKE_FUNCTOR(report_t::option_current); - else if (std::strcmp(p, "collapse") == 0) - return MAKE_FUNCTOR(report_t::option_collapse); - else if (std::strcmp(p, "cleared") == 0) - return MAKE_FUNCTOR(report_t::option_cleared); - else if (std::strcmp(p, "cost") == 0) - return MAKE_FUNCTOR(report_t::option_cost); - else if (std::strcmp(p, "comm-as-payee") == 0) - return MAKE_FUNCTOR(report_t::option_comm_as_payee); - else if (std::strcmp(p, "code-as-payee") == 0) - return MAKE_FUNCTOR(report_t::option_code_as_payee); + OPT_(current); + else OPT(collapse); + else OPT(cleared); + else OPT(cost); + else OPT(comm_as_payee); + else OPT(code_as_payee); break; case 'd': - if (std::strcmp(p, "daily") == 0) - return MAKE_FUNCTOR(report_t::option_daily); - else if (std::strcmp(p, "dow") == 0) - return MAKE_FUNCTOR(report_t::option_dow); - else if (std::strcmp(p, "date-format_") == 0) - return MAKE_FUNCTOR(report_t::option_date_format_); + OPT(daily); + else OPT(dow); + else OPT(date_format_); break; case 'e': - if (std::strcmp(p, "e_") == 0 || - std::strcmp(p, "end_") == 0) - return MAKE_FUNCTOR(report_t::option_end_); - else if (std::strcmp(p, "empty") == 0) - return MAKE_FUNCTOR(report_t::option_empty); + OPT_(end_); + else OPT(empty); + else OPT(effective); break; case 'f': - if (std::strcmp(p, "format_") == 0) - return MAKE_FUNCTOR(report_t::option_format_); + OPT(format_); break; case 'h': - if (std::strcmp(p, "head_") == 0) - return MAKE_FUNCTOR(report_t::option_head_); + OPT(head_); break; case 'i': - if (std::strcmp(p, "input-date-format_") == 0) - return MAKE_FUNCTOR(report_t::option_input_date_format_); + OPT(input_date_format_); + else OPT(invert); break; case 'j': - if (! *(p + 1)) - return MAKE_FUNCTOR(report_t::option_amount_data); + OPT_CH(amount_data); break; case 'l': - if (std::strcmp(p, "l_") == 0 - || std::strcmp(p, "limit_") == 0) - return MAKE_FUNCTOR(report_t::option_limit_); + OPT_(limit); break; case 'm': - if (std::strcmp(p, "monthly") == 0) - return MAKE_FUNCTOR(report_t::option_monthly); - else if (std::strcmp(p, "market") == 0) - return MAKE_FUNCTOR(report_t::option_market); + OPT(monthly); + else OPT(market); break; case 'n': - if (std::strcmp(p, "n") == 0) - return MAKE_FUNCTOR(report_t::option_collapse); + OPT_CH(collapse); + break; + + case 'o': + OPT_(output_); + else OPT(output_date_format_); break; case 'p': - if (std::strcmp(p, "p_") == 0 || - std::strcmp(p, "period_") == 0) - return MAKE_FUNCTOR(report_t::option_period_); - else if (std::strcmp(p, "period_sort_") == 0) - return MAKE_FUNCTOR(report_t::option_period_sort_); - else if (std::strcmp(p, "price") == 0) - return MAKE_FUNCTOR(report_t::option_price); - else if (std::strcmp(p, "price_db_") == 0) - return MAKE_FUNCTOR(report_t::option_price_db_); + OPT_(period_); + else OPT(period_sort_); + else OPT(price); + else OPT(price_db_); break; case 'q': - if (std::strcmp(p, "quarterly") == 0) - return MAKE_FUNCTOR(report_t::option_quarterly); - else if (std::strcmp(p, "quantity") == 0) - return MAKE_FUNCTOR(report_t::option_quantity); + OPT(quarterly); + else OPT(quantity); break; case 'r': - if (std::strcmp(p, "r") == 0 || - std::strcmp(p, "related") == 0) - return MAKE_FUNCTOR(report_t::option_related); + OPT_(related); + else OPT_(related_all); break; case 's': - if (std::strcmp(p, "s") == 0 || - std::strcmp(p, "subtotal") == 0) - return MAKE_FUNCTOR(report_t::option_subtotal); - else if (std::strcmp(p, "sort_") == 0) - return MAKE_FUNCTOR(report_t::option_sort_); - else if (std::strcmp(p, "sort_entries_") == 0) - return MAKE_FUNCTOR(report_t::option_sort_entries_); - else if (std::strcmp(p, "sort_all_") == 0) - return MAKE_FUNCTOR(report_t::option_sort_all_); + OPT_(subtotal); + else OPT(sort_); + else OPT(sort_all_); + else OPT(sort_entries_); break; case 't': - if (std::strcmp(p, "t_") == 0) - return MAKE_FUNCTOR(report_t::option_amount_); - else if (std::strcmp(p, "total_") == 0) - return MAKE_FUNCTOR(report_t::option_total_); - else if (std::strcmp(p, "totals") == 0) - return MAKE_FUNCTOR(report_t::option_totals); - else if (std::strcmp(p, "tail_") == 0) - return MAKE_FUNCTOR(report_t::option_tail_); + OPT_CH(amount_); + else OPT(total_); + else OPT(totals); + else OPT(tail_); break; case 'u': - if (std::strcmp(p, "uncleared") == 0) - return MAKE_FUNCTOR(report_t::option_uncleared); + OPT(uncleared); break; case 'w': - if (std::strcmp(p, "weekly") == 0) - return MAKE_FUNCTOR(report_t::option_weekly); + OPT(weekly); break; case 'x': - if (std::strcmp(p, "x")) - return MAKE_FUNCTOR(report_t::option_comm_as_payee); + OPT_CH(comm_as_payee); // jww (2009-02-05): ??? break; case 'y': - if (std::strcmp(p, "yearly") == 0) - return MAKE_FUNCTOR(report_t::option_yearly); - else if (std::strcmp(p, "y_") == 0) - return MAKE_FUNCTOR(report_t::option_date_format_); + OPT_CH(date_format_); + else OPT(yearly); break; case 'B': - if (! *(p + 1)) - return MAKE_FUNCTOR(report_t::option_cost); + OPT_CH(cost); break; - case 'C': - if (! *(p + 1)) - return MAKE_FUNCTOR(report_t::option_cleared); + OPT_CH(cleared); break; - case 'E': - if (! *(p + 1)) - return MAKE_FUNCTOR(report_t::option_empty); + OPT_CH(empty); break; - case 'F': - if (std::strcmp(p, "F_") == 0) - return MAKE_FUNCTOR(report_t::option_format_); + OPT_CH(format_); break; - case 'I': - if (! *(p + 1)) - return MAKE_FUNCTOR(report_t::option_price); + OPT_CH(price); break; - case 'J': - if (! *(p + 1)) - return MAKE_FUNCTOR(report_t::option_total_data); + OPT_CH(total_data); break; - case 'M': - if (! *(p + 1)) - return MAKE_FUNCTOR(report_t::option_monthly); + OPT_CH(monthly); break; - case 'O': - if (! *(p + 1)) - return MAKE_FUNCTOR(report_t::option_quantity); + OPT_CH(quantity); break; - case 'P': - if (! *(p + 1)) - return MAKE_FUNCTOR(report_t::option_by_payee); + OPT_CH(by_payee); break; - case 'S': - if (std::strcmp(p, "S_") == 0) - return MAKE_FUNCTOR(report_t::option_sort_); + OPT_CH(sort_); break; - case 'T': - if (std::strcmp(p, "T_") == 0) - return MAKE_FUNCTOR(report_t::option_total_); + OPT_CH(total_); break; - case 'U': - if (! *(p + 1)) - return MAKE_FUNCTOR(report_t::option_uncleared); + OPT_CH(uncleared); break; - case 'V': - if (! *(p + 1)) - return MAKE_FUNCTOR(report_t::option_market); + OPT_CH(market); break; - case 'W': - if (! *(p + 1)) - return MAKE_FUNCTOR(report_t::option_weekly); + OPT_CH(weekly); break; - case 'Y': - if (! *(p + 1)) - return MAKE_FUNCTOR(report_t::option_yearly); + OPT_CH(yearly); break; } } break; case 'p': - if (std::strcmp(p, "print_balance") == 0) - return WRAP_FUNCTOR(print_balance); + if (WANT_PRECMD()) { p += PRECMD_PREFIX_LEN; + switch (*p) { + case 'a': + COMMAND(args); + break; + case 'p': + COMMAND(parse); + else COMMAND(period); + break; + case 'e': + COMMAND(eval); + break; + case 'f': + COMMAND(format); + break; + } + } + else FUNCTION(print_balance); break; case 's': - if (std::strcmp(p, "strip") == 0) - return WRAP_FUNCTOR(strip_annotations); + FUNCTION(strip); break; case 't': - if (std::strcmp(p, "total_expr") == 0) - return MAKE_FUNCTOR(report_t::get_total_expr); - else if (std::strcmp(p, "truncate") == 0) - return WRAP_FUNCTOR(truncate); + FUNCTION(truncate); + else METHOD(report_t, total_expr); break; } diff --git a/src/report.h b/src/report.h index 541122a9..62664ba1 100644 --- a/src/report.h +++ b/src/report.h @@ -47,7 +47,7 @@ #define _REPORT_H #include "session.h" -#include "handler.h" +#include "chain.h" namespace ledger { @@ -105,144 +105,112 @@ class report_t : public scope_t report_t(); public: - optional<path> output_file; + session_t& session; + string account; output_stream_t output_stream; + keep_details_t what_to_keep; - string format_string; - string output_date_format; - string predicate; - string secondary_predicate; - string display_predicate; - string report_period; - string report_period_sort; - string sort_string; - string descend_expr; - string forecast_limit; - string reconcile_balance; - string reconcile_date; + uint_least8_t budget_flags; expr_t amount_expr; expr_t total_expr; expr_t display_total; - uint_least8_t budget_flags; + string predicate; + string secondary_predicate; + string display_predicate; + string report_period; + string report_period_sort; - long head_entries; - long tail_entries; - - bool show_collapsed; - bool show_subtotal; - bool show_totals; - bool show_related; - bool show_all_related; - bool show_inverted; - bool show_empty; - bool days_of_the_week; - bool by_payee; - bool comm_as_payee; - bool code_as_payee; bool show_revalued; bool show_revalued_only; - bool entry_sort; - bool sort_all; - bool anonymize; - bool use_effective_date; - - keep_details_t what_to_keep; - - string account; - - bool raw_mode; - - session_t& session; explicit report_t(session_t& _session) - : output_date_format("%y-%b-%d"), + : session(_session), amount_expr("amount"), total_expr("total"), display_total("total_expr"), - head_entries(0), - tail_entries(0), - - show_collapsed(false), - show_subtotal(false), - show_totals(false), - show_related(false), - show_all_related(false), - show_inverted(false), - show_empty(false), - days_of_the_week(false), - by_payee(false), - comm_as_payee(false), - code_as_payee(false), show_revalued(false), - show_revalued_only(false), - entry_sort(false), - sort_all(false), - anonymize(false), - use_effective_date(false), - - raw_mode(false), - - session(_session) + show_revalued_only(false) { TRACE_CTOR(report_t, "session_t&"); + + // Setup default values for some of the option handlers + HANDLER(output_date_format_).value = "%y-%b-%d"; } report_t(const report_t& other) : scope_t(), - output_file(other.output_file), + session(other.session), + account(other.account), + what_to_keep(other.what_to_keep), - format_string(other.format_string), - output_date_format(other.output_date_format), - predicate(other.predicate), - secondary_predicate(other.secondary_predicate), - display_predicate(other.display_predicate), - report_period(other.report_period), - report_period_sort(other.report_period_sort), - sort_string(other.sort_string), - descend_expr(other.descend_expr), - forecast_limit(other.forecast_limit), - reconcile_balance(other.reconcile_balance), - reconcile_date(other.reconcile_date), + budget_flags(other.budget_flags), amount_expr(other.amount_expr), total_expr(other.total_expr), display_total(other.display_total), - budget_flags(other.budget_flags), + predicate(other.predicate), + secondary_predicate(other.secondary_predicate), + display_predicate(other.display_predicate), + report_period(other.report_period), + report_period_sort(other.report_period_sort), - head_entries(other.head_entries), - tail_entries(other.tail_entries), - - show_collapsed(other.show_collapsed), - show_subtotal(other.show_subtotal), - show_totals(other.show_totals), - show_related(other.show_related), - show_all_related(other.show_all_related), - show_inverted(other.show_inverted), - show_empty(other.show_empty), - days_of_the_week(other.days_of_the_week), - by_payee(other.by_payee), - comm_as_payee(other.comm_as_payee), - code_as_payee(other.code_as_payee), show_revalued(other.show_revalued), show_revalued_only(other.show_revalued_only), - entry_sort(other.entry_sort), - sort_all(other.sort_all), - anonymize(other.anonymize), - use_effective_date(other.use_effective_date), - - what_to_keep(other.what_to_keep), - account(other.account), - - raw_mode(other.raw_mode), - - session(other.session) + COPY_OPT(amount_, other), + COPY_OPT(amount_data, other), + COPY_OPT(anon, other), + COPY_OPT(base, other), + COPY_OPT(by_payee, other), + COPY_OPT(cleared, other), + COPY_OPT(code_as_payee, other), + COPY_OPT(collapse, other), + COPY_OPT(comm_as_payee, other), + COPY_OPT(cost, other), + COPY_OPT(current, other), + COPY_OPT(daily, other), + COPY_OPT(date_format_, other), + COPY_OPT(dow, other), + COPY_OPT(effective, other), + COPY_OPT(empty, other), + COPY_OPT(format_, other), + COPY_OPT(head_, other), + COPY_OPT(input_date_format_, other), + COPY_OPT(invert, other), + COPY_OPT(limit, other), + COPY_OPT(market, other), + COPY_OPT(monthly, other), + COPY_OPT(output_, other), + COPY_OPT(output_date_format_, other), + COPY_OPT(period_, other), + COPY_OPT(period_sort_, other), + COPY_OPT(price, other), + COPY_OPT(price_db_, other), + COPY_OPT(quantity, other), + COPY_OPT(quarterly, other), + COPY_OPT(related, other), + COPY_OPT(related_all, other), + COPY_OPT(subtotal, other), + COPY_OPT(tail_, other), + COPY_OPT(total_, other), + COPY_OPT(total_data, other), + COPY_OPT(totals, other), + COPY_OPT(uncleared, other), + COPY_OPT(weekly, other), + COPY_OPT(yearly, other), + + COPY_OPT(begin_, other), + COPY_OPT(end_, other), + + COPY_OPT(sort_, other), + COPY_OPT(sort_all_, other), + COPY_OPT(sort_entries_, other) { TRACE_CTOR(report_t, "copy"); } @@ -262,6 +230,110 @@ public: void accounts_report(acct_handler_ptr handler); void commodities_report(const string& format); + value_t fn_amount_expr(call_scope_t& scope); + value_t fn_total_expr(call_scope_t& scope); + value_t fn_display_total(call_scope_t& scope); + + void append_predicate(const string& str) { + if (! predicate.empty()) + predicate = string("(") + predicate + ")&"; + predicate += str; + } + + /** + * Option handlers + */ + + OPTION(report_t, amount_); + OPTION(report_t, amount_data); + OPTION(report_t, anon); + OPTION(report_t, base); + OPTION(report_t, by_payee); + OPTION(report_t, cleared); + OPTION(report_t, code_as_payee); + OPTION(report_t, collapse); + OPTION(report_t, comm_as_payee); + OPTION(report_t, cost); + OPTION(report_t, current); + OPTION(report_t, daily); + OPTION(report_t, date_format_); + OPTION(report_t, dow); + OPTION(report_t, effective); + OPTION(report_t, empty); + OPTION(report_t, format_); + OPTION(report_t, head_); + OPTION(report_t, input_date_format_); + OPTION(report_t, invert); + OPTION(report_t, limit); + OPTION(report_t, market); + OPTION(report_t, monthly); + OPTION(report_t, output_); + OPTION(report_t, output_date_format_); + OPTION(report_t, period_); + OPTION(report_t, period_sort_); + OPTION(report_t, price); + OPTION(report_t, price_db_); + OPTION(report_t, quantity); + OPTION(report_t, quarterly); + OPTION(report_t, related); + OPTION(report_t, related_all); + OPTION(report_t, subtotal); + OPTION(report_t, tail_); + OPTION(report_t, total_); + OPTION(report_t, total_data); + OPTION(report_t, totals); + OPTION(report_t, uncleared); + OPTION(report_t, weekly); + OPTION(report_t, yearly); + + OPTION_(report_t, begin_, DO_(args) { + interval_t interval(args[0].to_string()); + if (! is_valid(interval.begin)) + throw_(std::invalid_argument, + "Could not determine beginning of period '" + << args[0].to_string() << "'"); + + if (! parent->predicate.empty()) + parent->predicate += "&"; + parent->predicate += "date>=["; + parent->predicate += to_iso_extended_string(interval.begin); + parent->predicate += "]"; + }); + + OPTION_(report_t, end_, DO_(args) { + interval_t interval(args[0].to_string()); + if (! is_valid(interval.begin)) + throw_(std::invalid_argument, + "Could not determine end of period '" + << args[0].to_string() << "'"); + + if (! parent->predicate.empty()) + parent->predicate += "&"; + parent->predicate += "date<["; + parent->predicate += to_iso_extended_string(interval.begin); + parent->predicate += "]"; + +#if 0 + terminus = interval.begin; +#endif + }); + + OPTION_(report_t, sort_, DO_(args) { + on(args[0].to_string()); + parent->HANDLER(sort_entries_).off(); + parent->HANDLER(sort_all_).off(); + }); + + OPTION_(report_t, sort_all_, DO_(args) { + parent->HANDLER(sort_).on(args[0].to_string()); + parent->HANDLER(sort_entries_).off(); + }); + + OPTION_(report_t, sort_entries_, DO_(args) { + parent->HANDLER(sort_).on(args[0].to_string()); + parent->HANDLER(sort_all_).off(); + }); + #if 0 ////////////////////////////////////////////////////////////////////// // @@ -292,11 +364,6 @@ public: throw int(0); } - value_t option_version(call_scope_t& args) { // v - show_version(std::cout); - throw int(0); - } - value_t option_init_file(call_scope_t& args) { // i: std::string path = resolve_path(optarg); if (access(path.c_str(), R_OK) != -1) @@ -306,66 +373,14 @@ public: "The init file '" << path << "' does not exist or is not readable"); } - value_t option_output(call_scope_t& args) { // o: - if (std::string(optarg) != "-") { - std::string path = resolve_path(optarg); - report->output_file = path; - } - } - value_t option_account(call_scope_t& args) { // a: config->account = optarg; } -#endif ////////////////////////////////////////////////////////////////////// // // Report filtering - value_t ignore(call_scope_t&) { - return true; - } - - value_t option_effective(call_scope_t&) { - use_effective_date = true; - return true; - } - - value_t option_begin_(call_scope_t& args) { // b: - interval_t interval(args[0].to_string()); - if (! is_valid(interval.begin)) - throw_(std::invalid_argument, - "Could not determine beginning of period '" - << args[0].to_string() << "'"); - - if (! predicate.empty()) - predicate += "&"; - predicate += "date>=["; - predicate += to_iso_extended_string(interval.begin); - predicate += "]"; - - return true; - } - - value_t option_end_(call_scope_t& args) { // e: - interval_t interval(args[0].to_string()); - if (! is_valid(interval.begin)) - throw_(std::invalid_argument, - "Could not determine end of period '" - << args[0].to_string() << "'"); - - if (! predicate.empty()) - predicate += "&"; - predicate += "date<["; - predicate += to_iso_extended_string(interval.begin); - predicate += "]"; - -#if 0 - terminus = interval.begin; -#endif - return true; - } - value_t option_current(call_scope_t& args) { // c if (! predicate.empty()) predicate += "&"; @@ -403,7 +418,7 @@ public: value_t option_lots(call_scope_t& args) { what_to_keep.keep_price = true; what_to_keep.keep_date = true; - what_to_keep.keep_tag = true; + what_to_keep.keep_tag = true; } value_t option_lot_prices(call_scope_t& args) { @@ -423,21 +438,6 @@ public: // // Output customization - value_t option_format_(call_scope_t& args) { // F: - format_string = args[0].as_string(); - return true; - } - - value_t option_date_format_(call_scope_t& args) { // y: - output_date_format = args[0].as_string(); - return true; - } - - value_t option_input_date_format_(call_scope_t& args) { // : - ledger::input_date_format = args[0].as_string(); - return true; - } - #if 0 value_t option_balance_format(call_scope_t& args) { // : config->balance_format = optarg; @@ -702,12 +702,6 @@ public: } #endif - void append_predicate(const string& str) { - if (! predicate.empty()) - predicate = string("(") + predicate + ")&"; - predicate += str; - } - value_t option_limit_(call_scope_t& args) { // l: append_predicate(args[0].as_string()); return true; @@ -732,21 +726,15 @@ public: #endif value_t option_amount_(call_scope_t& args) { // t: - amount_expr = args[0].as_string(); + _amount_expr = args[0].as_string(); return true; } value_t option_total_(call_scope_t& args) { // T: - total_expr = args[0].as_string(); + _total_expr = args[0].as_string(); return true; } - value_t get_amount_expr(call_scope_t& scope); - value_t get_total_expr(call_scope_t& scope); - value_t get_display_total(call_scope_t& scope); - - value_t f_market_value(call_scope_t& args); - value_t option_amount_data(call_scope_t&) { // j format_string = session.plot_amount_format; return true; @@ -757,22 +745,6 @@ public: return true; } - value_t option_ansi(call_scope_t& args) { -#if 0 - format_t::ansi_codes = true; - format_t::ansi_invert = false; -#endif - return true; - } - - value_t option_ansi_invert(call_scope_t& args) { -#if 0 - format_t::ansi_codes = - format_t::ansi_invert = true; -#endif - return true; - } - ////////////////////////////////////////////////////////////////////// // // Commodity reporting @@ -801,28 +773,28 @@ public: value_t option_quantity(call_scope_t& args) { // O show_revalued = false; - amount_expr = "amount"; - total_expr = "total"; + _amount_expr = "amount"; + _total_expr = "total"; return true; } value_t option_cost(call_scope_t& args) { // B show_revalued = false; - amount_expr = "cost"; - total_expr = "total_cost"; + _amount_expr = "cost"; + _total_expr = "total_cost"; return true; } value_t option_price(call_scope_t& args) { // I show_revalued = false; - amount_expr = "price"; - total_expr = "price_total"; + _amount_expr = "price"; + _total_expr = "price_total"; return true; } value_t option_market(call_scope_t& args) { // V - show_revalued = true; - display_total = "market_value(total_expr)"; + show_revalued = true; + _display_total = "market_value(total_expr)"; return true; } @@ -854,6 +826,7 @@ public: anonymize = true; return true; } +#endif // 0 // // Scope members diff --git a/src/session.cc b/src/session.cc index ce668bd9..38f15dc9 100644 --- a/src/session.cc +++ b/src/session.cc @@ -31,7 +31,6 @@ #include "session.h" #include "report.h" -#include "handler.h" #include "iterators.h" #include "filters.h" #include "textual.h" diff --git a/src/session.h b/src/session.h index 83a31b96..adf2f4b7 100644 --- a/src/session.h +++ b/src/session.h @@ -47,6 +47,7 @@ #define _SESSION_H #include "scope.h" +#include "handler.h" #include "journal.h" #include "account.h" #include "format.h" diff --git a/src/stream.cc b/src/stream.cc index 535a25a5..94282d2d 100644 --- a/src/stream.cc +++ b/src/stream.cc @@ -112,7 +112,7 @@ namespace { void output_stream_t::initialize(const optional<path>& output_file, const optional<path>& pager_path) { - if (output_file) + if (output_file && *output_file != "-") os = new ofstream(*output_file); else if (pager_path) pipe_to_pager_fd = do_fork(&os, *pager_path); diff --git a/src/textual.cc b/src/textual.cc index e22d1d28..d6fd966b 100644 --- a/src/textual.cc +++ b/src/textual.cc @@ -690,9 +690,9 @@ void textual_parser_t::instance_t::general_directive(char * line) break; } - static const std::size_t textdir_len = std::strlen("ledger_textdir_"); + static const std::size_t textdir_len = std::strlen("dir_"); scoped_array<char> directive(new char[std::strlen(p) + textdir_len + 1]); - std::strcpy(directive.get(), "ledger_textdir_"); + std::strcpy(directive.get(), "dir_"); std::strcpy(directive.get() + textdir_len, p); if (expr_t::ptr_op_t op = lookup(directive.get())) { diff --git a/src/textual.h b/src/textual.h index b6f67157..3565579a 100644 --- a/src/textual.h +++ b/src/textual.h @@ -47,7 +47,7 @@ #define _TEXTUAL_H #include "journal.h" -#include "handler.h" +#include "account.h" namespace ledger { @@ -166,12 +166,6 @@ protected: friend class instance_t; }; -void write_textual_journal(journal_t& journal, - const path& pathname, - xact_handler_ptr& formatter, - const string& write_hdr_format, - std::ostream& out); - } // namespace ledger #endif // _TEXTUAL_H |