diff options
Diffstat (limited to 'src/global.cc')
-rw-r--r-- | src/global.cc | 159 |
1 files changed, 126 insertions, 33 deletions
diff --git a/src/global.cc b/src/global.cc index a258d0bb..1c94cfcb 100644 --- a/src/global.cc +++ b/src/global.cc @@ -39,9 +39,12 @@ #endif #include "item.h" #include "journal.h" +#include "pool.h" namespace ledger { +static bool args_only = false; + global_scope_t::global_scope_t(char ** envp) { TRACE_CTOR(global_scope_t, ""); @@ -74,7 +77,7 @@ global_scope_t::global_scope_t(char ** envp) // Before processing command-line options, we must notify the session object // that such options are beginning, since options like -f cause a complete // override of files found anywhere else. - if (! HANDLED(args_only)) { + if (! args_only) { session().set_flush_on_next_data_file(true); read_environment_settings(envp); session().set_flush_on_next_data_file(true); @@ -138,7 +141,7 @@ void global_scope_t::report_error(const std::exception& err) string context = error_context(); if (! context.empty()) std::cerr << context << std::endl; - + std::cerr << _("Error: ") << err.what() << std::endl; } else { caught_signal = NONE_CAUGHT; @@ -179,8 +182,6 @@ void global_scope_t::execute_command(strings_list args, bool at_repl) if (bool(command = look_for_precommand(bound_scope, verb))) is_precommand = true; - else if (! bool(command = look_for_command(bound_scope, verb))) - throw_(std::logic_error, _("Unrecognized command '%1'") << verb); // If it is not a pre-command, then parse the user's ledger data at this // time if not done alreday (i.e., if not at a REPL). Then patch up the @@ -189,7 +190,11 @@ void global_scope_t::execute_command(strings_list args, bool at_repl) if (! is_precommand) { if (! at_repl) session().read_journal_files(); + normalize_report_options(verb); + + if (! bool(command = look_for_command(bound_scope, verb))) + throw_(std::logic_error, _("Unrecognized command '%1'") << verb); } // Create the output stream (it might be a file, the console or a PAGER @@ -204,6 +209,12 @@ void global_scope_t::execute_command(strings_list args, bool at_repl) optional<path>(path(report().HANDLER(pager_).str())) : optional<path>()); + // Now that the output stream is initialized, report the options that will + // participate in this report, if the user specified --options + + if (HANDLED(options)) + report_options(report(), report().output_stream); + // Create an argument scope containing the report command's arguments, and // then invoke the command. The bound scope causes lookups to happen // first in the global scope, and then in the report scope. @@ -239,6 +250,29 @@ int global_scope_t::execute_command_wrapper(strings_list args, bool at_repl) return status; } +void global_scope_t::report_options(report_t& report, std::ostream& out) +{ + out << "<=============================================================================>" + << std::endl; + out << "[Global scope options]" << std::endl; + + HANDLER(args_only).report(out); + HANDLER(debug_).report(out); + HANDLER(init_file_).report(out); + HANDLER(script_).report(out); + HANDLER(trace_).report(out); + HANDLER(verbose).report(out); + HANDLER(verify).report(out); + + out << std::endl << "[Session scope options]" << std::endl; + report.session.report_options(out); + + out << std::endl << "[Report scope options]" << std::endl; + report.report_options(out); + out << "<=============================================================================>" + << std::endl; +} + option_t<global_scope_t> * global_scope_t::lookup_option(const char * p) { switch (*p) { @@ -260,6 +294,9 @@ option_t<global_scope_t> * global_scope_t::lookup_option(const char * p) case 'i': OPT(init_file_); break; + case 'o': + OPT(options); + break; case 's': OPT(script_); break; @@ -287,13 +324,13 @@ expr_t::ptr_op_t global_scope_t::lookup(const string& name) break; case 'p': - if (WANT_PRECMD()) { p += PRECMD_PREFIX_LEN; - switch (*p) { + if (WANT_PRECMD()) { const char * q = p + PRECMD_PREFIX_LEN; + switch (*q) { case 'p': - if (is_eq(p, "push")) - MAKE_FUNCTOR(global_scope_t::push_command); - else if (is_eq(p, "pop")) - MAKE_FUNCTOR(global_scope_t::pop_command); + if (is_eq(q, "push")) + return MAKE_FUNCTOR(global_scope_t::push_command); + else if (is_eq(q, "pop")) + return MAKE_FUNCTOR(global_scope_t::pop_command); break; } } @@ -316,18 +353,18 @@ void global_scope_t::read_environment_settings(char * envp[]) if (const char * p = std::getenv("LEDGER")) { if (! std::getenv("LEDGER_FILE")) - process_option("file", report(), p, "LEDGER"); + process_option("environ", "file", report(), p, "LEDGER"); } if (const char * p = std::getenv("LEDGER_INIT")) { if (! std::getenv("LEDGER_INIT_FILE")) - process_option("init-file", report(), p, "LEDGER_INIT"); + process_option("environ", "init-file", report(), p, "LEDGER_INIT"); } if (const char * p = std::getenv("PRICE_HIST")) { if (! std::getenv("LEDGER_PRICEDB")) - process_option("price-db", report(), p, "PRICE_HIST"); + process_option("environ", "price-db", report(), p, "PRICE_HIST"); } if (const char * p = std::getenv("PRICE_EXP")) - process_option("price-exp", report(), p, "PRICE_EXP"); + process_option("environ", "price-exp", report(), p, "PRICE_EXP"); #endif TRACE_FINISH(environment, 1); @@ -379,9 +416,19 @@ void global_scope_t::normalize_report_options(const string& verb) report_t& rep(report()); - // jww (2009-02-09): These global are a hack, but hard to avoid. - item_t::use_effective_date = rep.HANDLED(effective); - rep.session.commodity_pool->keep_base = rep.HANDLED(base); + // jww (2009-02-09): These globals are a hack, but hard to avoid. + item_t::use_effective_date = rep.HANDLED(effective); + rep.session.commodity_pool->keep_base = rep.HANDLED(base); + rep.session.commodity_pool->get_quotes = rep.session.HANDLED(download); + + if (rep.session.HANDLED(price_exp_)) + rep.session.commodity_pool->quote_leeway = + rep.session.HANDLER(price_exp_).value.as_long(); + + if (rep.session.HANDLED(price_db_)) + rep.session.commodity_pool->price_db = rep.session.HANDLER(price_db_).str(); + else + rep.session.commodity_pool->price_db = none; if (rep.HANDLED(date_format_)) { output_datetime_format = rep.HANDLER(date_format_).str() + " %H:%M:%S"; @@ -397,29 +444,72 @@ void global_scope_t::normalize_report_options(const string& verb) // I might be able to do it with command objects, like register_t, which // each know how to adjust the report based on its current option settings. if (verb == "print" || verb == "xact" || verb == "dump") { - rep.HANDLER(related).on_only(); - rep.HANDLER(related_all).on_only(); + rep.HANDLER(related).on_only(string("?normalize")); + rep.HANDLER(related_all).on_only(string("?normalize")); } else if (verb == "equity") { - rep.HANDLER(equity).on_only(); + rep.HANDLER(equity).on_only(string("?normalize")); } else if (rep.HANDLED(related)) { if (verb[0] == 'r') { - rep.HANDLER(invert).on_only(); + rep.HANDLER(invert).on_only(string("?normalize")); } else { - rep.HANDLER(subtotal).on_only(); - rep.HANDLER(related_all).on_only(); + rep.HANDLER(subtotal).on_only(string("?normalize")); + rep.HANDLER(related_all).on_only(string("?normalize")); } } if (! rep.HANDLED(empty)) - rep.HANDLER(display_).on("amount|(!post&total)"); + rep.HANDLER(display_).on(string("?normalize"), "amount|(!post&total)"); if (verb[0] != 'b' && verb[0] != 'r') - rep.HANDLER(base).on_only(); + rep.HANDLER(base).on_only(string("?normalize")); + + // If a time period was specified with -p, check whether it also gave a + // begin and/or end to the report period (though these can be overridden + // using -b or -e). Then, if no _duration_ was specified (such as monthly), + // then ignore the period since the begin/end are the only interesting + // details. + if (rep.HANDLED(period_)) { + if (! rep.HANDLED(sort_all_)) + rep.HANDLER(sort_xacts_).on_only(string("?normalize")); + + date_interval_t interval(rep.HANDLER(period_).str()); + + if (! rep.HANDLED(begin_) && interval.start) { + string predicate = + "date>=[" + to_iso_extended_string(*interval.start) + "]"; + rep.HANDLER(limit_).on(string("?normalize"), predicate); + } + if (! rep.HANDLED(end_) && interval.end) { + string predicate = + "date<[" + to_iso_extended_string(*interval.end) + "]"; + rep.HANDLER(limit_).on(string("?normalize"), predicate); + } - if (rep.HANDLED(period_) && ! rep.HANDLED(sort_all_)) - rep.HANDLER(sort_xacts_).on_only(); + if (! interval.duration) + rep.HANDLER(period_).off(); + } + + // If -j or -J were specified, set the appropriate format string now so as + // to avoid option ordering issues were we to have done it during the + // initial parsing of the options. + if (rep.HANDLED(amount_data)) { + rep.HANDLER(format_) + .on_with(string("?normalize"), rep.HANDLER(plot_amount_format_).value); + } + else if (rep.HANDLED(total_data)) { + rep.HANDLER(format_) + .on_with(string("?normalize"), rep.HANDLER(plot_total_format_).value); + } + + // If the --exchange (-X) option was used, parse out any final price + // settings that may be there. + if (rep.HANDLED(exchange_) && + rep.HANDLER(exchange_).str().find('=') != string::npos) { + value_t(0L).exchange_commodities(rep.HANDLER(exchange_).str(), true, + rep.terminus); + } long cols = 0; if (rep.HANDLED(columns_)) @@ -465,15 +555,15 @@ void global_scope_t::normalize_report_options(const string& verb) } if (! rep.HANDLER(date_width_).specified) - rep.HANDLER(date_width_).on_with(date_width); + rep.HANDLER(date_width_).on_with(string("?normalize"), date_width); if (! rep.HANDLER(payee_width_).specified) - rep.HANDLER(payee_width_).on_with(payee_width); + rep.HANDLER(payee_width_).on_with(string("?normalize"), payee_width); if (! rep.HANDLER(account_width_).specified) - rep.HANDLER(account_width_).on_with(account_width); + rep.HANDLER(account_width_).on_with(string("?normalize"), account_width); if (! rep.HANDLER(amount_width_).specified) - rep.HANDLER(amount_width_).on_with(amount_width); + rep.HANDLER(amount_width_).on_with(string("?normalize"), amount_width); if (! rep.HANDLER(total_width_).specified) - rep.HANDLER(total_width_).on_with(total_width); + rep.HANDLER(total_width_).on_with(string("?normalize"), total_width); } } @@ -500,7 +590,10 @@ void handle_debug_options(int argc, char * argv[]) { for (int i = 1; i < argc; i++) { if (argv[i][0] == '-') { - if (std::strcmp(argv[i], "--verify") == 0) { + if (std::strcmp(argv[i], "--args-only") == 0) { + args_only = true; + } + else if (std::strcmp(argv[i], "--verify") == 0) { #if defined(VERIFY_ON) verify_enabled = true; // global in utils.h #endif |