summaryrefslogtreecommitdiff
path: root/src/global.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/global.cc')
-rw-r--r--src/global.cc159
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