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 "chain.h"
|
||||||
|
#include "report.h"
|
||||||
#include "filters.h"
|
#include "filters.h"
|
||||||
#include "reconcile.h"
|
#include "reconcile.h"
|
||||||
|
|
||||||
|
|
@ -43,14 +44,14 @@ xact_handler_ptr chain_xact_handlers(report_t& report,
|
||||||
|
|
||||||
xact_handler_ptr handler(base_handler);
|
xact_handler_ptr handler(base_handler);
|
||||||
|
|
||||||
// format_xacts write each xact received to the
|
// format_xacts write each xact received to the output stream.
|
||||||
// output stream.
|
|
||||||
if (handle_individual_xacts) {
|
if (handle_individual_xacts) {
|
||||||
// truncate_entries cuts off a certain number of _entries_ from
|
// truncate_entries cuts off a certain number of _entries_ from being
|
||||||
// being displayed. It does not affect calculation.
|
// displayed. It does not affect calculation.
|
||||||
if (report.head_entries || report.tail_entries)
|
if (report.HANDLED(head_) || report.HANDLED(tail_))
|
||||||
handler.reset(new truncate_entries(handler, report.head_entries,
|
handler.reset(new truncate_entries(handler,
|
||||||
report.tail_entries));
|
report.HANDLER(head_).value.to_long(),
|
||||||
|
report.HANDLER(tail_).value.to_long()));
|
||||||
|
|
||||||
// filter_xacts will only pass through xacts matching the
|
// filter_xacts will only pass through xacts matching the
|
||||||
// `display_predicate'.
|
// `display_predicate'.
|
||||||
|
|
@ -59,15 +60,15 @@ xact_handler_ptr chain_xact_handlers(report_t& report,
|
||||||
(handler, item_predicate<xact_t>(report.display_predicate,
|
(handler, item_predicate<xact_t>(report.display_predicate,
|
||||||
report.what_to_keep)));
|
report.what_to_keep)));
|
||||||
|
|
||||||
// calc_xacts computes the running total. When this
|
// calc_xacts computes the running total. When this appears will
|
||||||
// appears will determine, for example, whether filtered
|
// determine, for example, whether filtered xacts are included or excluded
|
||||||
// xacts are included or excluded from the running total.
|
// from the running total.
|
||||||
handler.reset(new calc_xacts(handler));
|
handler.reset(new calc_xacts(handler));
|
||||||
|
|
||||||
// component_xacts looks for reported xact that
|
#if 0
|
||||||
// match the given `descend_expr', and then reports the
|
// component_xacts looks for reported xact that match the given
|
||||||
// xacts which made up the total for that reported
|
// `descend_expr', and then reports the xacts which made up the total for
|
||||||
// xact.
|
// that reported xact.
|
||||||
if (! report.descend_expr.empty()) {
|
if (! report.descend_expr.empty()) {
|
||||||
std::list<std::string> descend_exprs;
|
std::list<std::string> descend_exprs;
|
||||||
|
|
||||||
|
|
@ -90,9 +91,9 @@ xact_handler_ptr chain_xact_handlers(report_t& report,
|
||||||
remember_components = true;
|
remember_components = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reconcile_xacts will pass through only those
|
// reconcile_xacts will pass through only those xacts which can be
|
||||||
// xacts which can be reconciled to a given balance
|
// reconciled to a given balance (calculated against the xacts which it
|
||||||
// (calculated against the xacts which it receives).
|
// receives).
|
||||||
if (! report.reconcile_balance.empty()) {
|
if (! report.reconcile_balance.empty()) {
|
||||||
date_t cutoff = CURRENT_DATE();
|
date_t cutoff = CURRENT_DATE();
|
||||||
if (! report.reconcile_date.empty())
|
if (! report.reconcile_date.empty())
|
||||||
|
|
@ -100,57 +101,54 @@ xact_handler_ptr chain_xact_handlers(report_t& report,
|
||||||
handler.reset(new reconcile_xacts
|
handler.reset(new reconcile_xacts
|
||||||
(handler, value_t(report.reconcile_balance), cutoff));
|
(handler, value_t(report.reconcile_balance), cutoff));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// filter_xacts will only pass through xacts
|
// filter_xacts will only pass through xacts matching the
|
||||||
// matching the `secondary_predicate'.
|
// `secondary_predicate'.
|
||||||
if (! report.secondary_predicate.empty())
|
if (! report.secondary_predicate.empty())
|
||||||
handler.reset(new filter_xacts
|
handler.reset(new filter_xacts
|
||||||
(handler, item_predicate<xact_t>(report.secondary_predicate,
|
(handler, item_predicate<xact_t>
|
||||||
report.what_to_keep)));
|
(report.secondary_predicate, report.what_to_keep)));
|
||||||
|
|
||||||
// sort_xacts will sort all the xacts it sees, based
|
// sort_xacts will sort all the xacts it sees, based on the `sort_order'
|
||||||
// on the `sort_order' value expression.
|
// value expression.
|
||||||
if (! report.sort_string.empty()) {
|
if (report.HANDLED(sort_)) {
|
||||||
if (report.entry_sort)
|
if (report.HANDLED(sort_entries_))
|
||||||
handler.reset(new sort_entries(handler, report.sort_string));
|
handler.reset(new sort_entries(handler, report.HANDLER(sort_).str()));
|
||||||
else
|
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
|
// changed_value_xacts adds virtual xacts to the list to account for
|
||||||
// list to account for changes in market value of commodities,
|
// changes in market value of commodities, which otherwise would affect
|
||||||
// which otherwise would affect the running total unpredictably.
|
// the running total unpredictably.
|
||||||
if (report.show_revalued)
|
if (report.show_revalued)
|
||||||
handler.reset(new changed_value_xacts(handler, report.total_expr,
|
handler.reset(new changed_value_xacts(handler, report.total_expr,
|
||||||
report.show_revalued_only));
|
report.show_revalued_only));
|
||||||
|
|
||||||
// collapse_xacts causes entries with multiple xacts
|
// collapse_xacts causes entries with multiple xacts to appear as entries
|
||||||
// to appear as entries with a subtotaled xact for each
|
// with a subtotaled xact for each commodity used.
|
||||||
// commodity used.
|
if (report.HANDLED(collapse))
|
||||||
if (report.show_collapsed)
|
|
||||||
handler.reset(new collapse_xacts(handler, report.session));
|
handler.reset(new collapse_xacts(handler, report.session));
|
||||||
|
|
||||||
// subtotal_xacts combines all the xacts it receives
|
// subtotal_xacts combines all the xacts it receives into one subtotal
|
||||||
// into one subtotal entry, which has one xact for each
|
// entry, which has one xact for each commodity in each account.
|
||||||
// commodity in each account.
|
|
||||||
//
|
//
|
||||||
// period_xacts is like subtotal_xacts, but it
|
// period_xacts is like subtotal_xacts, but it subtotals according to time
|
||||||
// subtotals according to time periods rather than totalling
|
// periods rather than totalling everything.
|
||||||
// everything.
|
|
||||||
//
|
//
|
||||||
// dow_xacts is like period_xacts, except that it
|
// dow_xacts is like period_xacts, except that it reports all the xacts
|
||||||
// reports all the xacts that fall on each subsequent day
|
// that fall on each subsequent day of the week.
|
||||||
// of the week.
|
if (report.HANDLED(subtotal))
|
||||||
if (report.show_subtotal)
|
|
||||||
handler.reset(new subtotal_xacts(handler, remember_components));
|
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));
|
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));
|
handler.reset(new by_payee_xacts(handler, remember_components));
|
||||||
|
|
||||||
// interval_xacts groups xacts together based on a
|
// interval_xacts groups xacts together based on a time period, such as
|
||||||
// time period, such as weekly or monthly.
|
// weekly or monthly.
|
||||||
if (! report.report_period.empty()) {
|
if (! report.report_period.empty()) {
|
||||||
handler.reset(new interval_xacts(handler, report.report_period,
|
handler.reset(new interval_xacts(handler, report.report_period,
|
||||||
remember_components));
|
remember_components));
|
||||||
|
|
@ -158,27 +156,23 @@ xact_handler_ptr chain_xact_handlers(report_t& report,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// invert_xacts inverts the value of the xacts it
|
// invert_xacts inverts the value of the xacts it receives.
|
||||||
// receives.
|
if (report.HANDLED(invert))
|
||||||
if (report.show_inverted)
|
|
||||||
handler.reset(new invert_xacts(handler));
|
handler.reset(new invert_xacts(handler));
|
||||||
|
|
||||||
// related_xacts will pass along all xacts related
|
// related_xacts will pass along all xacts related to the xact received. If
|
||||||
// to the xact received. If `show_all_related' is true,
|
// the `related_all' handler is on, then all the entry's xacts are passed;
|
||||||
// then all the entry's xacts are passed; meaning that if
|
// meaning that if one xact of an entry is to be printed, all the xact for
|
||||||
// one xact of an entry is to be printed, all the
|
// that entry will be printed.
|
||||||
// xact for that entry will be printed.
|
if (report.HANDLED(related))
|
||||||
if (report.show_related)
|
handler.reset(new related_xacts(handler, report.HANDLED(related_all)));
|
||||||
handler.reset(new related_xacts(handler, report.show_all_related));
|
|
||||||
|
|
||||||
// anonymize_xacts removes all meaningful information from entry
|
// anonymize_xacts removes all meaningful information from entry payee's and
|
||||||
// payee's and account names, for the sake of creating useful bug
|
// account names, for the sake of creating useful bug reports.
|
||||||
// reports.
|
if (report.HANDLED(anon))
|
||||||
if (report.anonymize)
|
|
||||||
handler.reset(new anonymize_xacts(handler));
|
handler.reset(new anonymize_xacts(handler));
|
||||||
|
|
||||||
// This filter_xacts will only pass through xacts
|
// This filter_xacts will only pass through xacts matching the `predicate'.
|
||||||
// matching the `predicate'.
|
|
||||||
if (! report.predicate.empty()) {
|
if (! report.predicate.empty()) {
|
||||||
DEBUG("report.predicate",
|
DEBUG("report.predicate",
|
||||||
"Report predicate expression = " << report.predicate);
|
"Report predicate expression = " << report.predicate);
|
||||||
|
|
@ -188,13 +182,12 @@ xact_handler_ptr chain_xact_handlers(report_t& report,
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// budget_xacts takes a set of xacts from a data
|
// budget_xacts takes a set of xacts from a data file and uses them to
|
||||||
// file and uses them to generate "budget xacts" which
|
// generate "budget xacts" which balance against the reported xacts.
|
||||||
// balance against the reported xacts.
|
|
||||||
//
|
//
|
||||||
// forecast_xacts is a lot like budget_xacts, except
|
// forecast_xacts is a lot like budget_xacts, except that it adds entries
|
||||||
// that it adds entries only for the future, and does not balance
|
// only for the future, and does not balance them against anything but the
|
||||||
// them against anything but the future balance.
|
// future balance.
|
||||||
|
|
||||||
if (report.budget_flags) {
|
if (report.budget_flags) {
|
||||||
budget_xacts * budget_handler = new budget_xacts(handler,
|
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);
|
budget_handler->add_period_entries(journal->period_entries);
|
||||||
handler.reset(budget_handler);
|
handler.reset(budget_handler);
|
||||||
|
|
||||||
// Apply this before the budget handler, so that only matching
|
// Apply this before the budget handler, so that only matching xacts are
|
||||||
// xacts are calculated toward the budget. The use of
|
// calculated toward the budget. The use of filter_xacts above will
|
||||||
// filter_xacts above will further clean the results so
|
// further clean the results so that no automated xacts that don't match
|
||||||
// that no automated xacts that don't match the filter get
|
// the filter get reported.
|
||||||
// reported.
|
|
||||||
if (! report.predicate.empty())
|
if (! report.predicate.empty())
|
||||||
handler.reset(new filter_xacts(handler, report.predicate));
|
handler.reset(new filter_xacts(handler, report.predicate));
|
||||||
}
|
}
|
||||||
|
|
@ -222,9 +214,9 @@ xact_handler_ptr chain_xact_handlers(report_t& report,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (report.comm_as_payee)
|
if (report.HANDLED(comm_as_payee))
|
||||||
handler.reset(new set_comm_as_payee(handler));
|
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));
|
handler.reset(new set_code_as_payee(handler));
|
||||||
|
|
||||||
return handler;
|
return handler;
|
||||||
|
|
|
||||||
41
src/chain.h
41
src/chain.h
|
|
@ -46,10 +46,49 @@
|
||||||
#ifndef _CHAIN_H
|
#ifndef _CHAIN_H
|
||||||
#define _CHAIN_H
|
#define _CHAIN_H
|
||||||
|
|
||||||
#include "report.h"
|
#include "xact.h"
|
||||||
|
#include "account.h"
|
||||||
|
|
||||||
namespace ledger {
|
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
|
xact_handler_ptr
|
||||||
chain_xact_handlers(report_t& report,
|
chain_xact_handlers(report_t& report,
|
||||||
xact_handler_ptr base_handler,
|
xact_handler_ptr base_handler,
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,7 @@
|
||||||
#ifndef _CSV_H
|
#ifndef _CSV_H
|
||||||
#define _CSV_H
|
#define _CSV_H
|
||||||
|
|
||||||
#include "handler.h"
|
#include "output.h"
|
||||||
#include "format.h"
|
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,7 @@
|
||||||
#ifndef _EMACS_H
|
#ifndef _EMACS_H
|
||||||
#define _EMACS_H
|
#define _EMACS_H
|
||||||
|
|
||||||
#include "handler.h"
|
#include "output.h"
|
||||||
#include "format.h"
|
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,9 +46,11 @@
|
||||||
#ifndef _FILTERS_H
|
#ifndef _FILTERS_H
|
||||||
#define _FILTERS_H
|
#define _FILTERS_H
|
||||||
|
|
||||||
#include "handler.h"
|
#include "chain.h"
|
||||||
#include "predicate.h"
|
#include "predicate.h"
|
||||||
#include "entry.h"
|
#include "entry.h"
|
||||||
|
#include "xact.h"
|
||||||
|
#include "account.h"
|
||||||
|
|
||||||
namespace ledger {
|
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
|
// subprocess) and invoke the report command. The output stream is closed
|
||||||
// by the caller of this function.
|
// by the caller of this function.
|
||||||
|
|
||||||
report().output_stream.initialize(report().output_file,
|
report().output_stream
|
||||||
session().pager_path);
|
.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
|
// Create an argument scope containing the report command's arguments, and
|
||||||
// then invoke the command. The bound scope causes lookups to happen
|
// 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;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
}
|
||||||
|
|
||||||
expr_t::ptr_op_t global_scope_t::lookup(const string& name)
|
expr_t::ptr_op_t global_scope_t::lookup(const string& name)
|
||||||
{
|
{
|
||||||
const char * p = name.c_str();
|
const char * p = name.c_str();
|
||||||
switch (*p) {
|
switch (*p) {
|
||||||
case 'l':
|
case 'o':
|
||||||
if (std::strncmp(p, "ledger_precmd_", 14) == 0) {
|
if (WANT_OPT()) { p += OPT_PREFIX_LEN;
|
||||||
p = p + 14;
|
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) {
|
switch (*p) {
|
||||||
case 'p':
|
case 'p':
|
||||||
if (std::strcmp(p, "push") == 0)
|
M_COMMAND(global_scope_t, push);
|
||||||
return MAKE_FUNCTOR(global_scope_t::push_report_cmd);
|
else M_COMMAND(global_scope_t, pop);
|
||||||
else if (std::strcmp(p, "pop") == 0)
|
|
||||||
return MAKE_FUNCTOR(global_scope_t::pop_report_cmd);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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
|
// 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)
|
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();
|
return def->as_function();
|
||||||
else
|
else
|
||||||
return function_t();
|
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)
|
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();
|
return def->as_function();
|
||||||
else
|
else
|
||||||
return function_t();
|
return function_t();
|
||||||
|
|
@ -365,18 +358,18 @@ void normalize_report_options(report_t& report, const string& verb)
|
||||||
// for 3.0.
|
// for 3.0.
|
||||||
|
|
||||||
if (verb == "print" || verb == "entry" || verb == "dump") {
|
if (verb == "print" || verb == "entry" || verb == "dump") {
|
||||||
report.show_related = true;
|
report.HANDLER(related).on();
|
||||||
report.show_all_related = true;
|
report.HANDLER(related_all).on();
|
||||||
}
|
}
|
||||||
else if (verb == "equity") {
|
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') {
|
if (verb[0] == 'r') {
|
||||||
report.show_inverted = true;
|
report.HANDLER(invert).on();
|
||||||
} else {
|
} else {
|
||||||
report.show_subtotal = true;
|
report.HANDLER(subtotal).on();
|
||||||
report.show_all_related = true;
|
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 (report.display_predicate.empty()) {
|
||||||
if (verb[0] == 'b') {
|
if (verb[0] == 'b') {
|
||||||
if (! report.show_empty)
|
if (! report.HANDLED(empty))
|
||||||
report.display_predicate = "total";
|
report.display_predicate = "total";
|
||||||
if (! report.show_subtotal) {
|
if (! report.HANDLED(subtotal)) {
|
||||||
if (! report.display_predicate.empty())
|
if (! report.display_predicate.empty())
|
||||||
report.display_predicate += "&";
|
report.display_predicate += "&";
|
||||||
report.display_predicate += "depth<=1";
|
report.display_predicate += "depth<=1";
|
||||||
|
|
@ -398,13 +391,13 @@ void normalize_report_options(report_t& report, const string& verb)
|
||||||
else if (verb == "equity") {
|
else if (verb == "equity") {
|
||||||
report.display_predicate = "amount_expr"; // jww (2008-08-14): ???
|
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";
|
report.display_predicate = "amount";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! report.report_period.empty() && ! report.sort_all)
|
if (! report.report_period.empty() && ! report.HANDLED(sort_all_))
|
||||||
report.entry_sort = true;
|
report.HANDLER(sort_entries_).on();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ledger
|
} // 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;
|
ptr_list<report_t> report_stack;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
path script_file;
|
|
||||||
|
|
||||||
global_scope_t(char ** envp);
|
global_scope_t(char ** envp);
|
||||||
~global_scope_t();
|
~global_scope_t();
|
||||||
|
|
||||||
|
|
@ -81,7 +79,7 @@ public:
|
||||||
void execute_command(strings_list args, bool at_repl);
|
void execute_command(strings_list args, bool at_repl);
|
||||||
int execute_command_wrapper(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
|
// 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
|
// 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.
|
// soon as this command terminate so that the stream is closed cleanly.
|
||||||
|
|
@ -89,19 +87,16 @@ public:
|
||||||
new report_t(report_stack.front()));
|
new report_t(report_stack.front()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
value_t pop_report_cmd(call_scope_t&) {
|
value_t pop_command(call_scope_t&) {
|
||||||
pop_report();
|
pop_report();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t option_script_(call_scope_t& args) {
|
OPTION(global_scope_t, debug_);
|
||||||
script_file = args[0].as_string();
|
OPTION(global_scope_t, script_);
|
||||||
return true;
|
OPTION(global_scope_t, trace_);
|
||||||
}
|
OPTION(global_scope_t, verbose);
|
||||||
|
OPTION(global_scope_t, verify);
|
||||||
value_t ignore(call_scope_t&) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
virtual expr_t::ptr_op_t lookup(const string& name);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
248
src/handler.h
248
src/handler.h
|
|
@ -39,54 +39,244 @@
|
||||||
*
|
*
|
||||||
* @ingroup report
|
* @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
|
#ifndef _HANDLER_H
|
||||||
#define _HANDLER_H
|
#define _HANDLER_H
|
||||||
|
|
||||||
#include "utils.h"
|
#include "scope.h"
|
||||||
#include "xact.h"
|
|
||||||
#include "account.h"
|
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Brief
|
|
||||||
*
|
|
||||||
* Long.
|
|
||||||
*/
|
|
||||||
template <typename T>
|
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:
|
public:
|
||||||
item_handler() {
|
T * parent;
|
||||||
TRACE_CTOR(item_handler, "");
|
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) {
|
handler_t(const handler_t& other)
|
||||||
TRACE_CTOR(item_handler, "shared_ptr<item_handler>");
|
: name(other.name),
|
||||||
}
|
name_len(other.name_len),
|
||||||
virtual ~item_handler() {
|
ch(other.ch),
|
||||||
TRACE_DTOR(item_handler);
|
handled(other.handled),
|
||||||
|
parent(NULL),
|
||||||
|
value(other.value)
|
||||||
|
{
|
||||||
|
TRACE_CTOR(handler_t, "copy");
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void flush() {
|
virtual ~handler_t() {
|
||||||
if (handler.get())
|
TRACE_DTOR(handler_t);
|
||||||
handler->flush();
|
|
||||||
}
|
}
|
||||||
virtual void operator()(T& item) {
|
|
||||||
if (handler.get()) {
|
string desc() const {
|
||||||
check_for_signal();
|
std::ostringstream out;
|
||||||
(*handler.get())(item);
|
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;
|
#define BEGIN(type, name) \
|
||||||
typedef shared_ptr<item_handler<account_t> > acct_handler_ptr;
|
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
|
} // namespace ledger
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,6 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
bool item_t::use_effective_date = false;
|
|
||||||
|
|
||||||
bool item_t::has_tag(const string& tag) const
|
bool item_t::has_tag(const string& tag) const
|
||||||
{
|
{
|
||||||
if (! metadata)
|
if (! metadata)
|
||||||
|
|
|
||||||
|
|
@ -80,8 +80,6 @@ public:
|
||||||
istream_pos_type end_pos;
|
istream_pos_type end_pos;
|
||||||
std::size_t end_line;
|
std::size_t end_line;
|
||||||
|
|
||||||
static bool use_effective_date;
|
|
||||||
|
|
||||||
item_t(flags_t _flags = ITEM_NORMAL, const optional<string>& _note = none)
|
item_t(flags_t _flags = ITEM_NORMAL, const optional<string>& _note = none)
|
||||||
: supports_flags<>(_flags), _state(UNCLEARED), note(_note),
|
: supports_flags<>(_flags), _state(UNCLEARED), note(_note),
|
||||||
beg_pos(0), beg_line(0), end_pos(0), end_line(0)
|
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);
|
args = read_command_arguments(bound_scope, args);
|
||||||
|
|
||||||
if (! global_scope->script_file.empty() &&
|
if (global_scope->HANDLED(script_)) {
|
||||||
exists(global_scope->script_file)) {
|
|
||||||
// Ledger is being invoked as a script command interpreter
|
// Ledger is being invoked as a script command interpreter
|
||||||
global_scope->read_journal_files();
|
global_scope->read_journal_files();
|
||||||
|
|
||||||
status = 0;
|
status = 0;
|
||||||
|
|
||||||
ifstream in(global_scope->script_file);
|
ifstream in(global_scope->HANDLER(script_).str());
|
||||||
while (status == 0 && ! in.eof()) {
|
while (status == 0 && ! in.eof()) {
|
||||||
char line[1024];
|
char line[1024];
|
||||||
in.getline(line, 1023);
|
in.getline(line, 1023);
|
||||||
|
|
|
||||||
|
|
@ -159,7 +159,7 @@ void format_accounts::flush()
|
||||||
|
|
||||||
account_t::xdata_t& xdata(report.session.master->xdata());
|
account_t::xdata_t& xdata(report.session.master->xdata());
|
||||||
|
|
||||||
if (! report.show_collapsed && xdata.total) {
|
if (! report.HANDLED(collapse) && xdata.total) {
|
||||||
out << "--------------------\n";
|
out << "--------------------\n";
|
||||||
xdata.value = xdata.total;
|
xdata.value = xdata.total;
|
||||||
bind_scope_t bound_scope(report, *report.session.master);
|
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);
|
bind_scope_t bound_scope(report, *pair.second);
|
||||||
call_scope_t args(bound_scope);
|
call_scope_t args(bound_scope);
|
||||||
result = report.get_total_expr(args);
|
result = report.fn_total_expr(args);
|
||||||
if (! computed) {
|
if (! computed) {
|
||||||
bind_scope_t account_scope(report, account);
|
bind_scope_t account_scope(report, account);
|
||||||
call_scope_t args(account_scope);
|
call_scope_t args(account_scope);
|
||||||
acct_total = report.get_total_expr(args);
|
acct_total = report.fn_total_expr(args);
|
||||||
computed = true;
|
computed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,6 @@
|
||||||
#define _OUTPUT_H
|
#define _OUTPUT_H
|
||||||
|
|
||||||
#include "report.h"
|
#include "report.h"
|
||||||
#include "handler.h"
|
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
|
|
||||||
namespace ledger {
|
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();
|
sum_all_accounts();
|
||||||
|
|
||||||
if (sort_string.empty()) {
|
if (! HANDLED(sort_)) {
|
||||||
basic_accounts_iterator walker(*session.master);
|
basic_accounts_iterator walker(*session.master);
|
||||||
pass_down_accounts(handler, walker,
|
pass_down_accounts(handler, walker,
|
||||||
item_predicate<account_t>("total", what_to_keep));
|
item_predicate<account_t>("total", what_to_keep));
|
||||||
} else {
|
} else {
|
||||||
sorted_accounts_iterator walker(*session.master, sort_string);
|
sorted_accounts_iterator walker(*session.master, HANDLER(sort_).str());
|
||||||
pass_down_accounts(handler, walker,
|
pass_down_accounts(handler, walker,
|
||||||
item_predicate<account_t>("total", what_to_keep));
|
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);
|
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);
|
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);
|
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 {
|
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));
|
report_t& report(find_scope<report_t>(args));
|
||||||
|
|
||||||
|
|
@ -136,13 +136,13 @@ namespace {
|
||||||
return string_value(out.str());
|
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));
|
report_t& report(find_scope<report_t>(args));
|
||||||
return args[0].strip_annotations(report.what_to_keep);
|
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));
|
report_t& report(find_scope<report_t>(args));
|
||||||
|
|
||||||
|
|
@ -153,16 +153,24 @@ namespace {
|
||||||
account_abbrev ? *account_abbrev : -1));
|
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));
|
report_t& report(find_scope<report_t>(args));
|
||||||
item_t& item(find_scope<item_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())
|
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,
|
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)
|
expr_t::ptr_op_t report_t::lookup(const string& name)
|
||||||
{
|
{
|
||||||
const char * p = name.c_str();
|
const char * p = name.c_str();
|
||||||
switch (*p) {
|
switch (*p) {
|
||||||
case 'a':
|
case 'a':
|
||||||
if (std::strcmp(p, "amount_expr") == 0)
|
METHOD(report_t, amount_expr);
|
||||||
return MAKE_FUNCTOR(report_t::get_amount_expr);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd':
|
case 'c':
|
||||||
if (std::strcmp(p, "display_total") == 0)
|
if (WANT_CMD()) { p += CMD_PREFIX_LEN;
|
||||||
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;
|
|
||||||
switch (*p) {
|
switch (*p) {
|
||||||
case 'b':
|
case 'b':
|
||||||
if (*(p + 1) == '\0' ||
|
if (*(p + 1) == '\0' ||
|
||||||
|
|
@ -262,297 +258,212 @@ expr_t::ptr_op_t report_t::lookup(const string& name)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (std::strncmp(p, "ledger_precmd_", 14) == 0) {
|
break;
|
||||||
p = p + 14;
|
|
||||||
switch (*p) {
|
|
||||||
case 'a':
|
|
||||||
if (std::strcmp(p, "args") == 0)
|
|
||||||
return WRAP_FUNCTOR(args_command);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'p':
|
case 'd':
|
||||||
if (std::strcmp(p, "parse") == 0)
|
METHOD(report_t, display_total);
|
||||||
return WRAP_FUNCTOR(parse_command);
|
else FUNCTION(display_date);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'm':
|
case 'm':
|
||||||
if (std::strcmp(p, "market_value") == 0)
|
FUNCTION(market_value);
|
||||||
return MAKE_FUNCTOR(report_t::f_market_value);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'o':
|
case 'o':
|
||||||
if (std::strncmp(p, "opt_", 4) == 0) {
|
if (WANT_OPT()) { p += OPT_PREFIX_LEN;
|
||||||
p = p + 4;
|
|
||||||
switch (*p) {
|
switch (*p) {
|
||||||
case 'a':
|
case 'a':
|
||||||
if (std::strcmp(p, "amount_") == 0)
|
OPT(amount_);
|
||||||
return MAKE_FUNCTOR(report_t::option_amount_);
|
else OPT(anon);
|
||||||
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);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'b':
|
case 'b':
|
||||||
if (std::strcmp(p, "b_") == 0 ||
|
OPT_(begin_);
|
||||||
std::strcmp(p, "begin_") == 0)
|
else OPT(base);
|
||||||
return MAKE_FUNCTOR(report_t::option_begin_);
|
else OPT(by_payee);
|
||||||
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);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
if (! *(p + 1) || std::strcmp(p, "current") == 0)
|
OPT_(current);
|
||||||
return MAKE_FUNCTOR(report_t::option_current);
|
else OPT(collapse);
|
||||||
else if (std::strcmp(p, "collapse") == 0)
|
else OPT(cleared);
|
||||||
return MAKE_FUNCTOR(report_t::option_collapse);
|
else OPT(cost);
|
||||||
else if (std::strcmp(p, "cleared") == 0)
|
else OPT(comm_as_payee);
|
||||||
return MAKE_FUNCTOR(report_t::option_cleared);
|
else OPT(code_as_payee);
|
||||||
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);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd':
|
case 'd':
|
||||||
if (std::strcmp(p, "daily") == 0)
|
OPT(daily);
|
||||||
return MAKE_FUNCTOR(report_t::option_daily);
|
else OPT(dow);
|
||||||
else if (std::strcmp(p, "dow") == 0)
|
else OPT(date_format_);
|
||||||
return MAKE_FUNCTOR(report_t::option_dow);
|
|
||||||
else if (std::strcmp(p, "date-format_") == 0)
|
|
||||||
return MAKE_FUNCTOR(report_t::option_date_format_);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'e':
|
case 'e':
|
||||||
if (std::strcmp(p, "e_") == 0 ||
|
OPT_(end_);
|
||||||
std::strcmp(p, "end_") == 0)
|
else OPT(empty);
|
||||||
return MAKE_FUNCTOR(report_t::option_end_);
|
else OPT(effective);
|
||||||
else if (std::strcmp(p, "empty") == 0)
|
|
||||||
return MAKE_FUNCTOR(report_t::option_empty);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
if (std::strcmp(p, "format_") == 0)
|
OPT(format_);
|
||||||
return MAKE_FUNCTOR(report_t::option_format_);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
if (std::strcmp(p, "head_") == 0)
|
OPT(head_);
|
||||||
return MAKE_FUNCTOR(report_t::option_head_);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
if (std::strcmp(p, "input-date-format_") == 0)
|
OPT(input_date_format_);
|
||||||
return MAKE_FUNCTOR(report_t::option_input_date_format_);
|
else OPT(invert);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'j':
|
case 'j':
|
||||||
if (! *(p + 1))
|
OPT_CH(amount_data);
|
||||||
return MAKE_FUNCTOR(report_t::option_amount_data);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
if (std::strcmp(p, "l_") == 0
|
OPT_(limit);
|
||||||
|| std::strcmp(p, "limit_") == 0)
|
|
||||||
return MAKE_FUNCTOR(report_t::option_limit_);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'm':
|
case 'm':
|
||||||
if (std::strcmp(p, "monthly") == 0)
|
OPT(monthly);
|
||||||
return MAKE_FUNCTOR(report_t::option_monthly);
|
else OPT(market);
|
||||||
else if (std::strcmp(p, "market") == 0)
|
|
||||||
return MAKE_FUNCTOR(report_t::option_market);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'n':
|
case 'n':
|
||||||
if (std::strcmp(p, "n") == 0)
|
OPT_CH(collapse);
|
||||||
return MAKE_FUNCTOR(report_t::option_collapse);
|
break;
|
||||||
|
|
||||||
|
case 'o':
|
||||||
|
OPT_(output_);
|
||||||
|
else OPT(output_date_format_);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
if (std::strcmp(p, "p_") == 0 ||
|
OPT_(period_);
|
||||||
std::strcmp(p, "period_") == 0)
|
else OPT(period_sort_);
|
||||||
return MAKE_FUNCTOR(report_t::option_period_);
|
else OPT(price);
|
||||||
else if (std::strcmp(p, "period_sort_") == 0)
|
else OPT(price_db_);
|
||||||
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_);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'q':
|
case 'q':
|
||||||
if (std::strcmp(p, "quarterly") == 0)
|
OPT(quarterly);
|
||||||
return MAKE_FUNCTOR(report_t::option_quarterly);
|
else OPT(quantity);
|
||||||
else if (std::strcmp(p, "quantity") == 0)
|
|
||||||
return MAKE_FUNCTOR(report_t::option_quantity);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
if (std::strcmp(p, "r") == 0 ||
|
OPT_(related);
|
||||||
std::strcmp(p, "related") == 0)
|
else OPT_(related_all);
|
||||||
return MAKE_FUNCTOR(report_t::option_related);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
if (std::strcmp(p, "s") == 0 ||
|
OPT_(subtotal);
|
||||||
std::strcmp(p, "subtotal") == 0)
|
else OPT(sort_);
|
||||||
return MAKE_FUNCTOR(report_t::option_subtotal);
|
else OPT(sort_all_);
|
||||||
else if (std::strcmp(p, "sort_") == 0)
|
else OPT(sort_entries_);
|
||||||
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_);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
if (std::strcmp(p, "t_") == 0)
|
OPT_CH(amount_);
|
||||||
return MAKE_FUNCTOR(report_t::option_amount_);
|
else OPT(total_);
|
||||||
else if (std::strcmp(p, "total_") == 0)
|
else OPT(totals);
|
||||||
return MAKE_FUNCTOR(report_t::option_total_);
|
else OPT(tail_);
|
||||||
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_);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'u':
|
case 'u':
|
||||||
if (std::strcmp(p, "uncleared") == 0)
|
OPT(uncleared);
|
||||||
return MAKE_FUNCTOR(report_t::option_uncleared);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'w':
|
case 'w':
|
||||||
if (std::strcmp(p, "weekly") == 0)
|
OPT(weekly);
|
||||||
return MAKE_FUNCTOR(report_t::option_weekly);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'x':
|
case 'x':
|
||||||
if (std::strcmp(p, "x"))
|
OPT_CH(comm_as_payee); // jww (2009-02-05): ???
|
||||||
return MAKE_FUNCTOR(report_t::option_comm_as_payee);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'y':
|
case 'y':
|
||||||
if (std::strcmp(p, "yearly") == 0)
|
OPT_CH(date_format_);
|
||||||
return MAKE_FUNCTOR(report_t::option_yearly);
|
else OPT(yearly);
|
||||||
else if (std::strcmp(p, "y_") == 0)
|
|
||||||
return MAKE_FUNCTOR(report_t::option_date_format_);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'B':
|
case 'B':
|
||||||
if (! *(p + 1))
|
OPT_CH(cost);
|
||||||
return MAKE_FUNCTOR(report_t::option_cost);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'C':
|
case 'C':
|
||||||
if (! *(p + 1))
|
OPT_CH(cleared);
|
||||||
return MAKE_FUNCTOR(report_t::option_cleared);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'E':
|
case 'E':
|
||||||
if (! *(p + 1))
|
OPT_CH(empty);
|
||||||
return MAKE_FUNCTOR(report_t::option_empty);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'F':
|
case 'F':
|
||||||
if (std::strcmp(p, "F_") == 0)
|
OPT_CH(format_);
|
||||||
return MAKE_FUNCTOR(report_t::option_format_);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'I':
|
case 'I':
|
||||||
if (! *(p + 1))
|
OPT_CH(price);
|
||||||
return MAKE_FUNCTOR(report_t::option_price);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'J':
|
case 'J':
|
||||||
if (! *(p + 1))
|
OPT_CH(total_data);
|
||||||
return MAKE_FUNCTOR(report_t::option_total_data);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'M':
|
case 'M':
|
||||||
if (! *(p + 1))
|
OPT_CH(monthly);
|
||||||
return MAKE_FUNCTOR(report_t::option_monthly);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'O':
|
case 'O':
|
||||||
if (! *(p + 1))
|
OPT_CH(quantity);
|
||||||
return MAKE_FUNCTOR(report_t::option_quantity);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'P':
|
case 'P':
|
||||||
if (! *(p + 1))
|
OPT_CH(by_payee);
|
||||||
return MAKE_FUNCTOR(report_t::option_by_payee);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'S':
|
case 'S':
|
||||||
if (std::strcmp(p, "S_") == 0)
|
OPT_CH(sort_);
|
||||||
return MAKE_FUNCTOR(report_t::option_sort_);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'T':
|
case 'T':
|
||||||
if (std::strcmp(p, "T_") == 0)
|
OPT_CH(total_);
|
||||||
return MAKE_FUNCTOR(report_t::option_total_);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'U':
|
case 'U':
|
||||||
if (! *(p + 1))
|
OPT_CH(uncleared);
|
||||||
return MAKE_FUNCTOR(report_t::option_uncleared);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'V':
|
case 'V':
|
||||||
if (! *(p + 1))
|
OPT_CH(market);
|
||||||
return MAKE_FUNCTOR(report_t::option_market);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'W':
|
case 'W':
|
||||||
if (! *(p + 1))
|
OPT_CH(weekly);
|
||||||
return MAKE_FUNCTOR(report_t::option_weekly);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'Y':
|
case 'Y':
|
||||||
if (! *(p + 1))
|
OPT_CH(yearly);
|
||||||
return MAKE_FUNCTOR(report_t::option_yearly);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
if (std::strcmp(p, "print_balance") == 0)
|
if (WANT_PRECMD()) { p += PRECMD_PREFIX_LEN;
|
||||||
return WRAP_FUNCTOR(print_balance);
|
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;
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
if (std::strcmp(p, "strip") == 0)
|
FUNCTION(strip);
|
||||||
return WRAP_FUNCTOR(strip_annotations);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
if (std::strcmp(p, "total_expr") == 0)
|
FUNCTION(truncate);
|
||||||
return MAKE_FUNCTOR(report_t::get_total_expr);
|
else METHOD(report_t, total_expr);
|
||||||
else if (std::strcmp(p, "truncate") == 0)
|
|
||||||
return WRAP_FUNCTOR(truncate);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
399
src/report.h
399
src/report.h
|
|
@ -47,7 +47,7 @@
|
||||||
#define _REPORT_H
|
#define _REPORT_H
|
||||||
|
|
||||||
#include "session.h"
|
#include "session.h"
|
||||||
#include "handler.h"
|
#include "chain.h"
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
|
|
@ -105,144 +105,112 @@ class report_t : public scope_t
|
||||||
report_t();
|
report_t();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
optional<path> output_file;
|
session_t& session;
|
||||||
|
string account;
|
||||||
output_stream_t output_stream;
|
output_stream_t output_stream;
|
||||||
|
keep_details_t what_to_keep;
|
||||||
|
|
||||||
string format_string;
|
uint_least8_t budget_flags;
|
||||||
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;
|
|
||||||
|
|
||||||
expr_t amount_expr;
|
expr_t amount_expr;
|
||||||
expr_t total_expr;
|
expr_t total_expr;
|
||||||
expr_t display_total;
|
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;
|
||||||
bool show_revalued_only;
|
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)
|
explicit report_t(session_t& _session)
|
||||||
: output_date_format("%y-%b-%d"),
|
: session(_session),
|
||||||
|
|
||||||
amount_expr("amount"),
|
amount_expr("amount"),
|
||||||
total_expr("total"),
|
total_expr("total"),
|
||||||
display_total("total_expr"),
|
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(false),
|
||||||
show_revalued_only(false),
|
show_revalued_only(false)
|
||||||
entry_sort(false),
|
|
||||||
sort_all(false),
|
|
||||||
anonymize(false),
|
|
||||||
use_effective_date(false),
|
|
||||||
|
|
||||||
raw_mode(false),
|
|
||||||
|
|
||||||
session(_session)
|
|
||||||
{
|
{
|
||||||
TRACE_CTOR(report_t, "session_t&");
|
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)
|
report_t(const report_t& other)
|
||||||
: scope_t(),
|
: 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),
|
budget_flags(other.budget_flags),
|
||||||
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),
|
|
||||||
|
|
||||||
amount_expr(other.amount_expr),
|
amount_expr(other.amount_expr),
|
||||||
total_expr(other.total_expr),
|
total_expr(other.total_expr),
|
||||||
display_total(other.display_total),
|
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(other.show_revalued),
|
||||||
show_revalued_only(other.show_revalued_only),
|
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),
|
COPY_OPT(sort_, other),
|
||||||
|
COPY_OPT(sort_all_, other),
|
||||||
session(other.session)
|
COPY_OPT(sort_entries_, other)
|
||||||
{
|
{
|
||||||
TRACE_CTOR(report_t, "copy");
|
TRACE_CTOR(report_t, "copy");
|
||||||
}
|
}
|
||||||
|
|
@ -262,6 +230,110 @@ public:
|
||||||
void accounts_report(acct_handler_ptr handler);
|
void accounts_report(acct_handler_ptr handler);
|
||||||
void commodities_report(const string& format);
|
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
|
#if 0
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
|
@ -292,11 +364,6 @@ public:
|
||||||
throw int(0);
|
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:
|
value_t option_init_file(call_scope_t& args) { // i:
|
||||||
std::string path = resolve_path(optarg);
|
std::string path = resolve_path(optarg);
|
||||||
if (access(path.c_str(), R_OK) != -1)
|
if (access(path.c_str(), R_OK) != -1)
|
||||||
|
|
@ -306,66 +373,14 @@ public:
|
||||||
"The init file '" << path << "' does not exist or is not readable");
|
"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:
|
value_t option_account(call_scope_t& args) { // a:
|
||||||
config->account = optarg;
|
config->account = optarg;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Report filtering
|
// 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
|
value_t option_current(call_scope_t& args) { // c
|
||||||
if (! predicate.empty())
|
if (! predicate.empty())
|
||||||
predicate += "&";
|
predicate += "&";
|
||||||
|
|
@ -403,7 +418,7 @@ public:
|
||||||
value_t option_lots(call_scope_t& args) {
|
value_t option_lots(call_scope_t& args) {
|
||||||
what_to_keep.keep_price = true;
|
what_to_keep.keep_price = true;
|
||||||
what_to_keep.keep_date = 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) {
|
value_t option_lot_prices(call_scope_t& args) {
|
||||||
|
|
@ -423,21 +438,6 @@ public:
|
||||||
//
|
//
|
||||||
// Output customization
|
// 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
|
#if 0
|
||||||
value_t option_balance_format(call_scope_t& args) { // :
|
value_t option_balance_format(call_scope_t& args) { // :
|
||||||
config->balance_format = optarg;
|
config->balance_format = optarg;
|
||||||
|
|
@ -702,12 +702,6 @@ public:
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void append_predicate(const string& str) {
|
|
||||||
if (! predicate.empty())
|
|
||||||
predicate = string("(") + predicate + ")&";
|
|
||||||
predicate += str;
|
|
||||||
}
|
|
||||||
|
|
||||||
value_t option_limit_(call_scope_t& args) { // l:
|
value_t option_limit_(call_scope_t& args) { // l:
|
||||||
append_predicate(args[0].as_string());
|
append_predicate(args[0].as_string());
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -732,21 +726,15 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
value_t option_amount_(call_scope_t& args) { // t:
|
value_t option_amount_(call_scope_t& args) { // t:
|
||||||
amount_expr = args[0].as_string();
|
_amount_expr = args[0].as_string();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t option_total_(call_scope_t& args) { // T:
|
value_t option_total_(call_scope_t& args) { // T:
|
||||||
total_expr = args[0].as_string();
|
_total_expr = args[0].as_string();
|
||||||
return true;
|
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
|
value_t option_amount_data(call_scope_t&) { // j
|
||||||
format_string = session.plot_amount_format;
|
format_string = session.plot_amount_format;
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -757,22 +745,6 @@ public:
|
||||||
return true;
|
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
|
// Commodity reporting
|
||||||
|
|
@ -801,28 +773,28 @@ public:
|
||||||
|
|
||||||
value_t option_quantity(call_scope_t& args) { // O
|
value_t option_quantity(call_scope_t& args) { // O
|
||||||
show_revalued = false;
|
show_revalued = false;
|
||||||
amount_expr = "amount";
|
_amount_expr = "amount";
|
||||||
total_expr = "total";
|
_total_expr = "total";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t option_cost(call_scope_t& args) { // B
|
value_t option_cost(call_scope_t& args) { // B
|
||||||
show_revalued = false;
|
show_revalued = false;
|
||||||
amount_expr = "cost";
|
_amount_expr = "cost";
|
||||||
total_expr = "total_cost";
|
_total_expr = "total_cost";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t option_price(call_scope_t& args) { // I
|
value_t option_price(call_scope_t& args) { // I
|
||||||
show_revalued = false;
|
show_revalued = false;
|
||||||
amount_expr = "price";
|
_amount_expr = "price";
|
||||||
total_expr = "price_total";
|
_total_expr = "price_total";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t option_market(call_scope_t& args) { // V
|
value_t option_market(call_scope_t& args) { // V
|
||||||
show_revalued = true;
|
show_revalued = true;
|
||||||
display_total = "market_value(total_expr)";
|
_display_total = "market_value(total_expr)";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -854,6 +826,7 @@ public:
|
||||||
anonymize = true;
|
anonymize = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif // 0
|
||||||
|
|
||||||
//
|
//
|
||||||
// Scope members
|
// Scope members
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@
|
||||||
|
|
||||||
#include "session.h"
|
#include "session.h"
|
||||||
#include "report.h"
|
#include "report.h"
|
||||||
#include "handler.h"
|
|
||||||
#include "iterators.h"
|
#include "iterators.h"
|
||||||
#include "filters.h"
|
#include "filters.h"
|
||||||
#include "textual.h"
|
#include "textual.h"
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@
|
||||||
#define _SESSION_H
|
#define _SESSION_H
|
||||||
|
|
||||||
#include "scope.h"
|
#include "scope.h"
|
||||||
|
#include "handler.h"
|
||||||
#include "journal.h"
|
#include "journal.h"
|
||||||
#include "account.h"
|
#include "account.h"
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ namespace {
|
||||||
void output_stream_t::initialize(const optional<path>& output_file,
|
void output_stream_t::initialize(const optional<path>& output_file,
|
||||||
const optional<path>& pager_path)
|
const optional<path>& pager_path)
|
||||||
{
|
{
|
||||||
if (output_file)
|
if (output_file && *output_file != "-")
|
||||||
os = new ofstream(*output_file);
|
os = new ofstream(*output_file);
|
||||||
else if (pager_path)
|
else if (pager_path)
|
||||||
pipe_to_pager_fd = do_fork(&os, *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;
|
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]);
|
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);
|
std::strcpy(directive.get() + textdir_len, p);
|
||||||
|
|
||||||
if (expr_t::ptr_op_t op = lookup(directive.get())) {
|
if (expr_t::ptr_op_t op = lookup(directive.get())) {
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@
|
||||||
#define _TEXTUAL_H
|
#define _TEXTUAL_H
|
||||||
|
|
||||||
#include "journal.h"
|
#include "journal.h"
|
||||||
#include "handler.h"
|
#include "account.h"
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
|
|
@ -166,12 +166,6 @@ protected:
|
||||||
friend class instance_t;
|
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
|
} // namespace ledger
|
||||||
|
|
||||||
#endif // _TEXTUAL_H
|
#endif // _TEXTUAL_H
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue