main.py now implements nearly all the functionality of main.cc
This commit is contained in:
parent
f2162bf7ee
commit
0c890de44b
5 changed files with 229 additions and 152 deletions
73
config.cc
73
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
6
config.h
6
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) {
|
||||
|
|
|
|||
115
main.cc
115
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;
|
||||
|
|
|
|||
110
main.py
110
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 ()
|
||||
register_parser (text_parser)
|
||||
bin_parser = BinaryParser ()
|
||||
qif_parser = QifParser ()
|
||||
|
||||
journal = Journal ()
|
||||
print parse_journal_file (args[0], journal), "entries"
|
||||
register_parser (text_parser)
|
||||
register_parser (bin_parser)
|
||||
register_parser (qif_parser)
|
||||
|
||||
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
|
||||
|
||||
expr = parse_value_expr ("a*2")
|
||||
handler = FormatTransaction()
|
||||
|
||||
def foo(x, val):
|
||||
return x.xact.amount + expr.compute (x) + val
|
||||
if not (command == "b" or command == "E"):
|
||||
if config.display_predicate:
|
||||
handler = FilterTransactions(handler, config.display_predicate)
|
||||
|
||||
handler = FormatTransaction("%D %-20P %N %('foo'{$100})")
|
||||
handler = FilterTransactions (handler, "/Checking/")
|
||||
handler = CalcTransactions(handler, config.show_inverted)
|
||||
|
||||
if config.sort_order:
|
||||
handler = SortTransactions(handler, config.sort_order)
|
||||
|
||||
if config.show_revalued:
|
||||
handler = ChangedValueTransactions(handler, config.show_revalued_only)
|
||||
|
||||
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
|
||||
|
|
|
|||
77
walk.cc
77
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());
|
||||
;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue