summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.cc73
-rw-r--r--config.h6
-rw-r--r--main.cc115
-rw-r--r--main.py108
-rw-r--r--walk.cc77
5 files changed, 228 insertions, 151 deletions
diff --git a/config.cc b/config.cc
index 108a9e5d..a92d6ab2 100644
--- a/config.cc
+++ b/config.cc
@@ -284,6 +284,69 @@ void config_t::process_options(const std::string& command,
nformat.reset(next_lines_format);
}
+void parse_ledger_data(journal_t * journal,
+ parser_t * text_parser,
+ parser_t * cache_parser)
+{
+ int entry_count = 0;
+
+ if (! config.init_file.empty()) {
+ if (parse_journal_file(config.init_file, journal))
+ throw error("Entries not allowed in initialization file");
+ journal->sources.pop_front(); // remove init file
+ }
+
+ if (cache_parser && config.use_cache &&
+ ! config.cache_file.empty() && ! config.data_file.empty()) {
+ config.cache_dirty = true;
+ if (access(config.cache_file.c_str(), R_OK) != -1) {
+ std::ifstream stream(config.cache_file.c_str());
+ if (cache_parser->test(stream)) {
+ entry_count += cache_parser->parse(stream, journal, NULL,
+ &config.data_file);
+ if (entry_count > 0)
+ config.cache_dirty = false;
+ }
+ }
+ }
+
+ if (entry_count == 0 && ! config.data_file.empty()) {
+ account_t * account = NULL;
+ if (! config.account.empty())
+ account = journal->find_account(config.account);
+
+ if (config.data_file == "-") {
+ config.use_cache = false;
+ entry_count += parse_journal(std::cin, journal, account);
+ } else {
+ entry_count += parse_journal_file(config.data_file, journal, account);
+ }
+
+ if (! config.price_db.empty())
+ if (parse_journal_file(config.price_db, journal))
+ throw error("Entries not allowed in price history file");
+ }
+
+ for (strings_list::iterator i = config.price_settings.begin();
+ i != config.price_settings.end();
+ i++) {
+ std::string conversion = "C ";
+ conversion += *i;
+ int i = conversion.find('=');
+ if (i != -1) {
+ conversion[i] = ' ';
+ std::istringstream stream(conversion);
+ text_parser->parse(stream, journal, journal->master);
+ }
+ }
+
+ if (entry_count == 0)
+ throw error("Please specify ledger file using -f,"
+ " or LEDGER_FILE environment variable.");
+
+ VALIDATE(journal->valid());
+}
+
static void show_version(std::ostream& out)
{
out
@@ -644,6 +707,14 @@ void py_add_config_option_handlers()
add_other_option_handlers(config_options);
}
+BOOST_PYTHON_FUNCTION_OVERLOADS(parse_ledger_data_overloads,
+ parse_ledger_data, 2, 3)
+
+void py_option_help()
+{
+ option_help(std::cout);
+}
+
void export_config()
{
class_< config_t > ("Config")
@@ -691,6 +762,8 @@ void export_config()
scope().attr("config") = ptr(&config);
+ def("option_help", py_option_help);
+ def("parse_ledger_data", parse_ledger_data, parse_ledger_data_overloads());
def("add_config_option_handlers", py_add_config_option_handlers);
}
diff --git a/config.h b/config.h
index d481757d..7f2a7707 100644
--- a/config.h
+++ b/config.h
@@ -6,6 +6,7 @@
#include "valexpr.h"
#include "datetime.h"
#include "format.h"
+#include "parser.h"
#include <iostream>
#include <memory>
@@ -84,6 +85,11 @@ extern std::list<option_t> config_options;
void option_help(std::ostream& out);
+// Parse what ledger data can be determined from the config settings
+void parse_ledger_data(journal_t * journal,
+ parser_t * text_parser,
+ parser_t * cache_parser = NULL);
+
struct declared_option_handler : public option_handler {
declared_option_handler(const std::string& label,
const std::string& opt_chars) {
diff --git a/main.cc b/main.cc
index a2640a90..8dd3d9c6 100644
--- a/main.cc
+++ b/main.cc
@@ -33,9 +33,7 @@ using namespace ledger;
namespace {
TIMER_DEF(write_cache, "writing cache file");
TIMER_DEF(report_gen, "generation of final report");
- TIMER_DEF(parse_files, "parsing ledger files");
TIMER_DEF(process_opts, "processing args and environment");
- TIMER_DEF(read_cache, "reading cache file");
}
#if !defined(DEBUG_LEVEL) || DEBUG_LEVEL <= RELEASE
@@ -72,73 +70,6 @@ namespace std {
#endif
-void parse_ledger_data(journal_t * journal,
- parser_t * text_parser,
- parser_t * cache_parser)
-{
- TIMER_START(parse_files);
-
- int entry_count = 0;
-
- if (! config.init_file.empty()) {
- if (parse_journal_file(config.init_file, journal))
- throw error("Entries not allowed in initialization file");
- journal->sources.pop_front(); // remove init file
- }
-
- if (config.use_cache && ! config.cache_file.empty() &&
- ! config.data_file.empty()) {
- config.cache_dirty = true;
- if (access(config.cache_file.c_str(), R_OK) != -1) {
- std::ifstream stream(config.cache_file.c_str());
- if (cache_parser->test(stream)) {
- entry_count += cache_parser->parse(stream, journal, NULL,
- &config.data_file);
- if (entry_count > 0)
- config.cache_dirty = false;
- }
- }
- }
-
- if (entry_count == 0 && ! config.data_file.empty()) {
- account_t * account = NULL;
- if (! config.account.empty())
- account = journal->find_account(config.account);
-
- if (config.data_file == "-") {
- config.use_cache = false;
- entry_count += parse_journal(std::cin, journal, account);
- } else {
- entry_count += parse_journal_file(config.data_file, journal, account);
- }
-
- if (! config.price_db.empty())
- if (parse_journal_file(config.price_db, journal))
- throw error("Entries not allowed in price history file");
- }
-
- for (strings_list::iterator i = config.price_settings.begin();
- i != config.price_settings.end();
- i++) {
- std::string conversion = "C ";
- conversion += *i;
- int i = conversion.find('=');
- if (i != -1) {
- conversion[i] = ' ';
- std::istringstream stream(conversion);
- text_parser->parse(stream, journal, journal->master);
- }
- }
-
- if (entry_count == 0)
- throw error("Please specify ledger file using -f,"
- " or LEDGER_FILE environment variable.");
-
- VALIDATE(journal->valid());
-
- TIMER_STOP(parse_files);
-}
-
item_handler<transaction_t> *
chain_formatters(const std::string& command,
item_handler<transaction_t> * base_formatter,
@@ -146,13 +77,11 @@ chain_formatters(const std::string& command,
{
item_handler<transaction_t> * formatter = NULL;
+ ptrs.push_back(formatter = base_formatter);
+
// format_transactions write each transaction received to the
// output stream.
- if (command == "b" || command == "E") {
- ptrs.push_back(formatter = base_formatter);
- } else {
- ptrs.push_back(formatter = base_formatter);
-
+ if (! (command == "b" || command == "E")) {
// filter_transactions will only pass through transactions
// matching the `display_predicate'.
if (! config.display_predicate.empty())
@@ -260,24 +189,6 @@ int parse_and_report(int argc, char * argv[], char * envp[])
TIMER_STOP(process_opts);
- // Parse initialization files, ledger data, price database, etc.
-
- std::auto_ptr<binary_parser_t> bin_parser(new binary_parser_t);
-#ifdef READ_GNUCASH
- std::auto_ptr<gnucash_parser_t> gnucash_parser(new gnucash_parser_t);
-#endif
- std::auto_ptr<qif_parser_t> qif_parser(new qif_parser_t);
- std::auto_ptr<textual_parser_t> text_parser(new textual_parser_t);
-
- register_parser(bin_parser.get());
-#ifdef READ_GNUCASH
- register_parser(gnucash_parser.get());
-#endif
- register_parser(qif_parser.get());
- register_parser(text_parser.get());
-
- parse_ledger_data(journal.get(), text_parser.get(), bin_parser.get());
-
// Read the command word, canonicalize it to its one letter form,
// then configure the system based on the kind of report to be
// generated
@@ -297,6 +208,26 @@ int parse_and_report(int argc, char * argv[], char * envp[])
else
throw error(std::string("Unrecognized command '") + command + "'");
+ // Parse initialization files, ledger data, price database, etc.
+
+ std::auto_ptr<binary_parser_t> bin_parser(new binary_parser_t);
+#ifdef READ_GNUCASH
+ std::auto_ptr<gnucash_parser_t> gnucash_parser(new gnucash_parser_t);
+#endif
+ std::auto_ptr<qif_parser_t> qif_parser(new qif_parser_t);
+ std::auto_ptr<textual_parser_t> text_parser(new textual_parser_t);
+
+ register_parser(bin_parser.get());
+#ifdef READ_GNUCASH
+ register_parser(gnucash_parser.get());
+#endif
+ register_parser(qif_parser.get());
+ register_parser(text_parser.get());
+
+ parse_ledger_data(journal.get(), text_parser.get(), bin_parser.get());
+
+ // Process the command word and its following arguments
+
config.process_options(command, arg, args.end());
std::auto_ptr<entry_t> new_entry;
diff --git a/main.py b/main.py
index 24fdc2b6..60c3e5ee 100644
--- a/main.py
+++ b/main.py
@@ -4,46 +4,114 @@ import time
from ledger import *
-def hello (str):
- print "Hello:", str
-def goodbye (str):
- print "Goodbye:", str
+journal = Journal ()
add_config_option_handlers ()
-add_option_handler ("hello", ":", hello)
-add_option_handler ("goodbye", ":", goodbye)
args = process_arguments (sys.argv[1:])
+config.use_cache = len (config.data_file) > 0
process_environment (os.environ, "LEDGER_")
-if len (args) > 0:
- config.process_options (args[0], args[1:])
+if os.environ.has_key ("LEDGER"):
+ process_option ("file", os.environ["LEDGER"])
+if os.environ.has_key ("PRICE_HIST"):
+ process_option ("price-db", os.environ["PRICE_HIST"])
+if os.environ.has_key ("PRICE_EXP"):
+ process_option ("price-exp", os.environ["PRICE_EXP"])
+
+if len (args) == 0:
+ option_help ()
+ sys.exit (0)
+
+command = args.pop (0);
+
+if command == "balance" or command == "bal" or command == "b":
+ command = "b"
+elif command == "register" or command == "reg" or command == "r":
+ command = "r"
+elif command == "print" or command == "p":
+ command = "p"
+elif command == "entry":
+ command = "e"
+elif command == "equity":
+ command = "E"
+else:
+ print "Unrecognized command:", command
+ sys.exit (1)
text_parser = TextualParser ()
+bin_parser = BinaryParser ()
+qif_parser = QifParser ()
+
register_parser (text_parser)
+register_parser (bin_parser)
+register_parser (qif_parser)
-journal = Journal ()
-print parse_journal_file (args[0], journal), "entries"
+parse_ledger_data (journal, text_parser, bin_parser)
+
+config.process_options(command, args);
+
+new_entry = None
+if command == "e":
+ new_entry = journal.derive_entry (args)
+ if new_entry is None:
+ sys.exit (1)
class FormatTransaction (TransactionHandler):
- def __init__ (self, fmt):
- self.formatter = Format (fmt)
+ last_entry = None
+
+ def __init__ (self, fmt = None):
+ if fmt is None:
+ self.formatter = config.format
+ self.nformatter = config.nformat
+ else:
+ self.formatter = Format (fmt)
+
+ self.last_entry = None
+
TransactionHandler.__init__ (self)
def __call__ (self, xact):
- print self.formatter.format(xact)
+ if xact.entry is self.last_entry:
+ print self.nformatter.format(xact),
+ else:
+ print self.formatter.format(xact),
+ self.last_entry = xact.entry
+
+handler = FormatTransaction()
+
+if not (command == "b" or command == "E"):
+ if config.display_predicate:
+ handler = FilterTransactions(handler, config.display_predicate)
+
+ handler = CalcTransactions(handler, config.show_inverted)
-expr = parse_value_expr ("a*2")
+ if config.sort_order:
+ handler = SortTransactions(handler, config.sort_order)
-def foo(x, val):
- return x.xact.amount + expr.compute (x) + val
+ if config.show_revalued:
+ handler = ChangedValueTransactions(handler, config.show_revalued_only)
-handler = FormatTransaction("%D %-20P %N %('foo'{$100})")
-handler = FilterTransactions (handler, "/Checking/")
+ if config.show_collapsed:
+ handler = CollapseTransactions(handler);
+
+ if config.show_subtotal:
+ handler = SubtotalTransactions(handler)
+ elif config.report_interval:
+ handler = IntervalTransactions(handler, config.report_interval)
+ elif config.days_of_the_week:
+ handler = DowTransactions(handler)
+
+if config.show_related:
+ handler = RelatedTransactions(handler, config.show_all_related)
+
+if config.predicate:
+ handler = FilterTransactions(handler, config.predicate)
for entry in journal:
for xact in entry:
handler (xact)
-for date in Interval ("weekly last month"):
- print time.strftime ("%c", time.localtime (date))
+handler.flush ()
+
+# jww (2004-09-14): still need to write out the cache
diff --git a/walk.cc b/walk.cc
index cfecf392..790369da 100644
--- a/walk.cc
+++ b/walk.cc
@@ -347,98 +347,97 @@ void py_walk_transactions(entry_t& entry, item_handler<transaction_t>& handler)
void export_walk()
{
- class_< item_handler<transaction_t>,
- item_handler_wrap<transaction_t> > ("TransactionHandler")
- .def(init<item_handler<transaction_t> *>())
+ typedef item_handler<transaction_t> xact_handler_t;
- .def("flush", &item_handler<transaction_t>::flush,
+ class_< xact_handler_t, item_handler_wrap<transaction_t> >
+ ("TransactionHandler")
+ .def(init<xact_handler_t *>())
+
+ .def("flush", &xact_handler_t::flush,
&item_handler_wrap<transaction_t>::default_flush)
- .def("__call__", &item_handler<transaction_t>::operator(),
+ .def("__call__", &xact_handler_t::operator(),
&item_handler_wrap<transaction_t>::default_call)
;
- class_< ignore_transactions > ("IgnoreTransactions")
- .def("flush", &item_handler<transaction_t>::flush)
+ class_< ignore_transactions, bases<xact_handler_t> >
+ ("IgnoreTransactions")
+ .def("flush", &xact_handler_t::flush)
.def("__call__", &ignore_transactions::operator());
;
- class_< clear_transaction_data > ("ClearTransactionData")
- .def("flush", &item_handler<transaction_t>::flush)
+ class_< clear_transaction_data, bases<xact_handler_t> >
+ ("ClearTransactionData")
+ .def("flush", &xact_handler_t::flush)
.def("__call__", &clear_transaction_data::operator());
;
- class_< set_account_value >
- ("SetAccountValue", init<item_handler<transaction_t> *>()
+ class_< set_account_value, bases<xact_handler_t> >
+ ("SetAccountValue", init<xact_handler_t *>()
[with_custodian_and_ward<1, 2>()])
- .def("flush", &item_handler<transaction_t>::flush)
+ .def("flush", &xact_handler_t::flush)
.def("__call__", &set_account_value::operator());
;
-#if 0
- class_< sort_transactions >
- ("SortTransactions", init<item_handler<transaction_t> *>()
+ class_< sort_transactions, bases<xact_handler_t> >
+ ("SortTransactions", init<xact_handler_t *, const value_expr_t *>()
[with_custodian_and_ward<1, 2>()])
.def("flush", &sort_transactions::flush)
.def("__call__", &sort_transactions::operator());
;
-#endif
- class_< filter_transactions >
- ("FilterTransactions", init<item_handler<transaction_t> *, std::string>()
+ class_< filter_transactions, bases<xact_handler_t> >
+ ("FilterTransactions", init<xact_handler_t *, std::string>()
[with_custodian_and_ward<1, 2>()])
- .def("flush", &item_handler<transaction_t>::flush)
+ .def("flush", &xact_handler_t::flush)
.def("__call__", &filter_transactions::operator());
;
- class_< calc_transactions >
- ("CalcTransactions", init<item_handler<transaction_t> *, optional<bool> >()
+ class_< calc_transactions, bases<xact_handler_t> >
+ ("CalcTransactions", init<xact_handler_t *, optional<bool> >()
[with_custodian_and_ward<1, 2>()])
- .def("flush", &item_handler<transaction_t>::flush)
+ .def("flush", &xact_handler_t::flush)
.def("__call__", &calc_transactions::operator());
;
- class_< collapse_transactions >
- ("CollapseTransactions", init<item_handler<transaction_t> *>()
+ class_< collapse_transactions, bases<xact_handler_t> >
+ ("CollapseTransactions", init<xact_handler_t *>()
[with_custodian_and_ward<1, 2>()])
.def("flush", &collapse_transactions::flush)
.def("__call__", &collapse_transactions::operator());
;
- class_< changed_value_transactions >
- ("ChangeValueTransactions", init<item_handler<transaction_t> *, bool>()
+ class_< changed_value_transactions, bases<xact_handler_t> >
+ ("ChangeValueTransactions", init<xact_handler_t *, bool>()
[with_custodian_and_ward<1, 2>()])
.def("flush", &changed_value_transactions::flush)
.def("__call__", &changed_value_transactions::operator());
;
- class_< subtotal_transactions >
- ("SubtotalTransactions", init<item_handler<transaction_t> *>()
+ class_< subtotal_transactions, bases<xact_handler_t> >
+ ("SubtotalTransactions", init<xact_handler_t *>()
[with_custodian_and_ward<1, 2>()])
.def("flush", subtotal_transactions_flush)
.def("__call__", &subtotal_transactions::operator());
;
-#if 0
- class_< interval_transactions >
- ("IntervalTransactions", init<item_handler<transaction_t> *>()
+ class_< interval_transactions, bases<xact_handler_t> >
+ ("IntervalTransactions", init<xact_handler_t *, interval_t>()
[with_custodian_and_ward<1, 2>()])
- .def("flush", &item_handler<transaction_t>::flush)
+ .def("flush", &xact_handler_t::flush)
.def("__call__", &interval_transactions::operator());
;
-#endif
- class_< dow_transactions >
- ("DowTransactions", init<item_handler<transaction_t> *>()
+ class_< dow_transactions, bases<xact_handler_t> >
+ ("DowTransactions", init<xact_handler_t *>()
[with_custodian_and_ward<1, 2>()])
.def("flush", &dow_transactions::flush)
.def("__call__", &dow_transactions::operator());
;
- class_< related_transactions >
- ("RelatedTransactions",
- init<item_handler<transaction_t> *, optional<bool> >()
+ class_< related_transactions, bases<xact_handler_t> >
+ ("RelatedTransactions", init<xact_handler_t *, optional<bool> >()
[with_custodian_and_ward<1, 2>()])
- .def("flush", &item_handler<transaction_t>::flush)
+ .def("flush", &xact_handler_t::flush)
.def("__call__", &related_transactions::operator());
;