Greatly simplified the way option and command handlers are defined.
This commit is contained in:
parent
7b24e8f8e3
commit
408b819c6e
20 changed files with 730 additions and 649 deletions
146
src/chain.cc
146
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)));
|
||||
(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));
|
||||
// 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));
|
||||
// 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.anonymize)
|
||||
// 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;
|
||||
|
|
|
|||
41
src/chain.h
41
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 {
|
||||
|
||||
|
|
|
|||
|
|
@ -46,8 +46,7 @@
|
|||
#ifndef _EMACS_H
|
||||
#define _EMACS_H
|
||||
|
||||
#include "handler.h"
|
||||
#include "format.h"
|
||||
#include "output.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
case 'o':
|
||||
if (WANT_OPT()) { p += OPT_PREFIX_LEN;
|
||||
switch (*p) {
|
||||
case 'd':
|
||||
OPT(debug_);
|
||||
break;
|
||||
case 's':
|
||||
OPT(script_);
|
||||
break;
|
||||
case 't':
|
||||
OPT(trace_);
|
||||
break;
|
||||
case 'v':
|
||||
OPT_(verbose);
|
||||
else OPT(verify);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case 'p':
|
||||
if (WANT_PRECMD()) { p += PRECMD_PREFIX_LEN;
|
||||
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);
|
||||
M_COMMAND(global_scope_t, push);
|
||||
else M_COMMAND(global_scope_t, pop);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
if (std::strncmp(p, "opt_", 4) == 0) {
|
||||
p = p + 4;
|
||||
switch (*p) {
|
||||
case 'd':
|
||||
if (std::strcmp(p, "debug_") == 0)
|
||||
return MAKE_FUNCTOR(global_scope_t::ignore);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if (std::strcmp(p, "script_") == 0)
|
||||
return MAKE_FUNCTOR(global_scope_t::option_script_);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (std::strcmp(p, "trace_") == 0)
|
||||
return MAKE_FUNCTOR(global_scope_t::ignore);
|
||||
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);
|
||||
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
|
||||
|
|
|
|||
19
src/global.h
19
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);
|
||||
};
|
||||
|
|
|
|||
248
src/handler.h
248
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>");
|
||||
}
|
||||
virtual ~item_handler() {
|
||||
TRACE_DTOR(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 void flush() {
|
||||
if (handler.get())
|
||||
handler->flush();
|
||||
virtual ~handler_t() {
|
||||
TRACE_DTOR(handler_t);
|
||||
}
|
||||
virtual void operator()(T& item) {
|
||||
if (handler.get()) {
|
||||
check_for_signal();
|
||||
(*handler.get())(item);
|
||||
}
|
||||
|
||||
string desc() const {
|
||||
std::ostringstream out;
|
||||
if (ch)
|
||||
out << "--" << name << " (-" << ch << ")";
|
||||
else
|
||||
out << "--" << name;
|
||||
return out.str();
|
||||
}
|
||||
|
||||
virtual void help(std::ostream& out) {
|
||||
out << "No help for " << desc() << "\n";
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@
|
|||
#define _OUTPUT_H
|
||||
|
||||
#include "report.h"
|
||||
#include "handler.h"
|
||||
#include "format.h"
|
||||
|
||||
namespace ledger {
|
||||
|
|
|
|||
389
src/report.cc
389
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);
|
||||
|
||||
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]);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
namespace {
|
||||
value_t print_balance(call_scope_t& args)
|
||||
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);
|
||||
|
||||
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&>());
|
||||
|
||||
DEBUG("report.market", "result is: " << result);
|
||||
return result;
|
||||
}
|
||||
|
||||
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);
|
||||
METHOD(report_t, 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);
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
399
src/report.h
399
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),
|
||||
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),
|
||||
|
||||
account(other.account),
|
||||
COPY_OPT(begin_, other),
|
||||
COPY_OPT(end_, other),
|
||||
|
||||
raw_mode(other.raw_mode),
|
||||
|
||||
session(other.session)
|
||||
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
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
#include "session.h"
|
||||
#include "report.h"
|
||||
#include "handler.h"
|
||||
#include "iterators.h"
|
||||
#include "filters.h"
|
||||
#include "textual.h"
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
#define _SESSION_H
|
||||
|
||||
#include "scope.h"
|
||||
#include "handler.h"
|
||||
#include "journal.h"
|
||||
#include "account.h"
|
||||
#include "format.h"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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())) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue