more options fixes
This commit is contained in:
parent
8a70bbed52
commit
6944e5950a
6 changed files with 93 additions and 89 deletions
48
ledger.cc
48
ledger.cc
|
|
@ -52,43 +52,41 @@ bool journal_t::remove_entry(entry_t * entry)
|
|||
return true;
|
||||
}
|
||||
|
||||
entry_t * journal_t::derive_entry(int argc, char **argv) const
|
||||
entry_t * journal_t::derive_entry(strings_list::iterator i,
|
||||
strings_list::iterator end) const
|
||||
{
|
||||
entry_t * added = new entry_t;
|
||||
entry_t * matching = NULL;
|
||||
int index = 0;
|
||||
|
||||
assert(index < argc);
|
||||
|
||||
if (! parse_date(argv[index++], &added->date)) {
|
||||
std::cerr << "Error: Bad entry date: " << argv[index - 1]
|
||||
<< std::endl;
|
||||
if (! parse_date((*i).c_str(), &added->date)) {
|
||||
std::cerr << "Error: Bad entry date: " << *i << std::endl;
|
||||
return false;
|
||||
}
|
||||
++i;
|
||||
|
||||
if (index == argc) {
|
||||
if (i == end) {
|
||||
std::cerr << "Error: Too few arguments to 'entry'." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
mask_t regexp(argv[index++]);
|
||||
mask_t regexp(*i++);
|
||||
|
||||
for (entries_list::const_reverse_iterator i = entries.rbegin();
|
||||
i != entries.rend();
|
||||
i++)
|
||||
if (regexp.match((*i)->payee)) {
|
||||
matching = *i;
|
||||
for (entries_list::const_reverse_iterator j = entries.rbegin();
|
||||
j != entries.rend();
|
||||
j++)
|
||||
if (regexp.match((*j)->payee)) {
|
||||
matching = *j;
|
||||
break;
|
||||
}
|
||||
|
||||
added->payee = matching ? matching->payee : regexp.pattern;
|
||||
|
||||
if (index == argc) {
|
||||
if (i == end) {
|
||||
std::cerr << "Error: Too few arguments to 'entry'." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (argv[index][0] == '-' || std::isdigit(argv[index][0])) {
|
||||
if ((*i)[0] == '-' || std::isdigit((*i)[0])) {
|
||||
if (! matching) {
|
||||
std::cerr << "Error: Missing account name for non-matching entry."
|
||||
<< std::endl;
|
||||
|
|
@ -98,7 +96,7 @@ entry_t * journal_t::derive_entry(int argc, char **argv) const
|
|||
transaction_t * m_xact, * xact, * first;
|
||||
m_xact = matching->transactions.front();
|
||||
|
||||
amount_t amt(argv[index++]);
|
||||
amount_t amt(*i++);
|
||||
first = xact = new transaction_t(added, m_xact->account, amt, amt);
|
||||
|
||||
if (xact->amount.commodity->symbol.empty()) {
|
||||
|
|
@ -113,12 +111,12 @@ entry_t * journal_t::derive_entry(int argc, char **argv) const
|
|||
- first->amount, - first->amount);
|
||||
added->add_transaction(xact);
|
||||
|
||||
if ((index + 1) < argc && std::string(argv[index]) == "-from")
|
||||
if (account_t * acct = find_account(argv[++index]))
|
||||
if (std::string(*i++) == "-from" && i != end)
|
||||
if (account_t * acct = find_account(*i))
|
||||
added->transactions.back()->account = acct;
|
||||
} else {
|
||||
while (index < argc && std::string(argv[index]) != "-from") {
|
||||
mask_t acct_regex(argv[index++]);
|
||||
while (std::string(*i) != "-from") {
|
||||
mask_t acct_regex(*i++);
|
||||
|
||||
account_t * acct = NULL;
|
||||
commodity_t * cmdty = NULL;
|
||||
|
|
@ -145,12 +143,12 @@ entry_t * journal_t::derive_entry(int argc, char **argv) const
|
|||
return false;
|
||||
}
|
||||
|
||||
if (index == argc) {
|
||||
if (i == end) {
|
||||
std::cerr << "Error: Too few arguments to 'entry'." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
amount_t amt(argv[index]++);
|
||||
amount_t amt(*i++);
|
||||
transaction_t * xact = new transaction_t(added, acct, amt, amt);
|
||||
|
||||
if (! xact->amount.commodity)
|
||||
|
|
@ -159,8 +157,8 @@ entry_t * journal_t::derive_entry(int argc, char **argv) const
|
|||
added->add_transaction(xact);
|
||||
}
|
||||
|
||||
if ((index + 1) < argc && std::string(argv[index]) == "-from") {
|
||||
if (account_t * acct = find_account(argv[++index])) {
|
||||
if (std::string(*i++) == "-from" && i != end) {
|
||||
if (account_t * acct = find_account(*i++)) {
|
||||
transaction_t * xact = new transaction_t(NULL, acct);
|
||||
added->add_transaction(xact);
|
||||
}
|
||||
|
|
|
|||
4
ledger.h
4
ledger.h
|
|
@ -166,6 +166,7 @@ inline std::ostream& operator<<(std::ostream& out, const account_t& acct) {
|
|||
|
||||
|
||||
typedef std::list<entry_t *> entries_list;
|
||||
typedef std::list<std::string> strings_list;
|
||||
|
||||
class journal_t
|
||||
{
|
||||
|
|
@ -208,7 +209,8 @@ class journal_t
|
|||
bool add_entry(entry_t * entry);
|
||||
bool remove_entry(entry_t * entry);
|
||||
|
||||
entry_t * derive_entry(int argc, char **argv) const;
|
||||
entry_t * derive_entry(strings_list::iterator begin,
|
||||
strings_list::iterator end) const;
|
||||
};
|
||||
|
||||
int parse_journal_file(char * p, journal_t * journal);
|
||||
|
|
|
|||
58
main.cc
58
main.cc
|
|
@ -109,6 +109,7 @@ namespace {
|
|||
bool use_cache = false;
|
||||
}
|
||||
|
||||
// jww (2004-08-13): fix this
|
||||
static std::string ledger_cache_file()
|
||||
{
|
||||
std::string cache_file;
|
||||
|
|
@ -175,12 +176,12 @@ static void show_help(std::ostream& out)
|
|||
}
|
||||
|
||||
|
||||
DEF_OPT_HANDLERS();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Basic options
|
||||
|
||||
DEF_OPT_HANDLERS();
|
||||
|
||||
OPT_BEGIN(help, "h", false) {
|
||||
show_help(std::cout);
|
||||
std::exit(0);
|
||||
|
|
@ -191,10 +192,10 @@ OPT_BEGIN(version, "v", false) {
|
|||
std::exit(0);
|
||||
} OPT_END(version);
|
||||
|
||||
OPT_BEGIN(init_file, "i:", true) {
|
||||
OPT_BEGIN(init, "i:", true) {
|
||||
std::ifstream stream(optarg);
|
||||
parse_textual_journal(stream, journal.get(), journal->master);
|
||||
} OPT_END(init_file);
|
||||
} OPT_END(init);
|
||||
|
||||
OPT_BEGIN(file, "f:", true) {
|
||||
files.push_back(optarg);
|
||||
|
|
@ -433,17 +434,9 @@ int main(int argc, char * argv[], char * envp[])
|
|||
}
|
||||
#endif
|
||||
|
||||
// Initialize some variables based on environment variable settings
|
||||
|
||||
// jww (2004-08-13): fix these
|
||||
if (char * p = std::getenv("PRICE_HIST"))
|
||||
price_db = p;
|
||||
|
||||
if (char * p = std::getenv("PRICE_EXP"))
|
||||
pricing_leeway = std::atol(p) * 60;
|
||||
|
||||
// A ledger data file must be specified
|
||||
|
||||
// jww (2004-08-13): use LEDGER_FILE
|
||||
use_cache = std::getenv("LEDGER") != NULL;
|
||||
|
||||
if (use_cache) {
|
||||
|
|
@ -475,19 +468,23 @@ int main(int argc, char * argv[], char * envp[])
|
|||
|
||||
// Parse the command-line options
|
||||
|
||||
std::vector<char *> args;
|
||||
process_arguments(args, argc, argv);
|
||||
std::list<std::string> args;
|
||||
process_arguments(argc, argv, false, args);
|
||||
|
||||
if (args.empty()) {
|
||||
show_help(std::cerr);
|
||||
return 1;
|
||||
}
|
||||
argc = args.size();
|
||||
int index = 0;
|
||||
std::list<std::string>::iterator arg = args.begin();
|
||||
|
||||
// Process options from the environment
|
||||
|
||||
process_environment(envp);
|
||||
process_environment(envp, "LEDGER_");
|
||||
|
||||
if (char * p = std::getenv("PRICE_HIST"))
|
||||
process_option("price-db", p);
|
||||
if (char * p = std::getenv("PRICE_EXP"))
|
||||
process_option("price-exp", p);
|
||||
|
||||
// Read the ledger file, unless we already read it from the cache
|
||||
|
||||
|
|
@ -534,7 +531,7 @@ int main(int argc, char * argv[], char * envp[])
|
|||
|
||||
// Read the command word, and then check and simplify it
|
||||
|
||||
std::string command = args[index++];
|
||||
std::string command = *arg++;
|
||||
|
||||
if (command == "balance" || command == "bal" || command == "b")
|
||||
command = "b";
|
||||
|
|
@ -556,32 +553,25 @@ int main(int argc, char * argv[], char * envp[])
|
|||
|
||||
std::auto_ptr<entry_t> new_entry;
|
||||
if (command == "e") {
|
||||
new_entry.reset(journal->derive_entry(argc - index, &args[index]));
|
||||
new_entry.reset(journal->derive_entry(arg, args.end()));
|
||||
} else {
|
||||
// Treat the remaining command-line arguments as regular
|
||||
// expressions, used for refining report results.
|
||||
|
||||
int start = index;
|
||||
for (; index < argc; index++)
|
||||
if (std::strcmp(args[index], "--") == 0) {
|
||||
index++;
|
||||
std::list<std::string>::iterator i = args.begin();
|
||||
for (; i != args.end(); i++)
|
||||
if (*i == "--")
|
||||
break;
|
||||
}
|
||||
|
||||
if (start < index) {
|
||||
std::list<std::string> regexps(&args[start], &args[index]);
|
||||
std::string pred = regexps_to_predicate(regexps.begin(), regexps.end());
|
||||
std::string pred = regexps_to_predicate(arg, i);
|
||||
if (! pred.empty()) {
|
||||
if (! predicate.empty())
|
||||
predicate += "&";
|
||||
predicate += pred;
|
||||
}
|
||||
}
|
||||
|
||||
if (index < argc) {
|
||||
std::list<std::string> regexps(&args[index], &args[argc]);
|
||||
std::string pred = regexps_to_predicate(regexps.begin(), regexps.end(),
|
||||
false);
|
||||
if (i != args.end()) {
|
||||
std::string pred = regexps_to_predicate(i, args.end(), false);
|
||||
if (! pred.empty()) {
|
||||
if (! predicate.empty())
|
||||
predicate += "&";
|
||||
|
|
@ -608,7 +598,7 @@ int main(int argc, char * argv[], char * envp[])
|
|||
}
|
||||
}
|
||||
|
||||
// Compile the sort criteria
|
||||
// Compile the sorting criteria
|
||||
|
||||
if (! sort_string.empty()) {
|
||||
try {
|
||||
|
|
|
|||
41
option.cc
41
option.cc
|
|
@ -31,18 +31,6 @@ option_handler::option_handler(const std::string& label,
|
|||
options.push_back(opt);
|
||||
}
|
||||
|
||||
bool process_option(const std::string& opt, const char * arg)
|
||||
{
|
||||
option_handler_map::iterator handler = option_handler::handlers.find(opt);
|
||||
if (handler != option_handler::handlers.end() &&
|
||||
(! (*handler).second->handled || (*handler).second->multiple)) {
|
||||
(*handler).second->handle_option(arg);
|
||||
(*handler).second->handled = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void process_option(const option_t& opt,
|
||||
const char * arg = NULL) {
|
||||
if (! opt.handler->handled || opt.handler->multiple) {
|
||||
|
|
@ -51,18 +39,41 @@ static inline void process_option(const option_t& opt,
|
|||
}
|
||||
}
|
||||
|
||||
void process_arguments(std::vector<char *>& args, int argc, char ** argv)
|
||||
bool process_option(const std::string& opt, const char * arg)
|
||||
{
|
||||
option_handler_map::iterator handler = option_handler::handlers.find(opt);
|
||||
if (handler != option_handler::handlers.end()) {
|
||||
if (! (*handler).second->handled || (*handler).second->multiple) {
|
||||
(*handler).second->handle_option(arg);
|
||||
(*handler).second->handled = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void process_arguments(int argc, char ** argv, const bool anywhere,
|
||||
std::list<std::string>& args)
|
||||
{
|
||||
int index = 1;
|
||||
for (char ** i = argv + 1; index < argc; i++, index++) {
|
||||
if ((*i)[0] != '-') {
|
||||
if (anywhere) {
|
||||
args.push_back(*i);
|
||||
continue;
|
||||
} else {
|
||||
for (; index < argc; i++, index++)
|
||||
args.push_back(*i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// --long-option
|
||||
again:
|
||||
if ((*i)[1] == '-') {
|
||||
if ((*i)[2] == '\0')
|
||||
break;
|
||||
|
||||
for (std::vector<option_t>::iterator j
|
||||
= option_handler::options.begin();
|
||||
j != option_handler::options.end();
|
||||
|
|
@ -114,10 +125,10 @@ void process_arguments(std::vector<char *>& args, int argc, char ** argv)
|
|||
}
|
||||
}
|
||||
|
||||
void process_environment(char ** envp)
|
||||
void process_environment(char ** envp, const std::string& tag)
|
||||
{
|
||||
for (char ** p = envp; *p; p++)
|
||||
if (std::strncmp(*p, "LEDGER_", 7) == 0) {
|
||||
if (std::strncmp(*p, tag.c_str(), 7) == 0) {
|
||||
std::string opt;
|
||||
char * q;
|
||||
for (q = *p + 7; *q && *q != '='; q++)
|
||||
|
|
|
|||
6
option.h
6
option.h
|
|
@ -2,6 +2,7 @@
|
|||
#define _OPTION_H
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
|
|
@ -34,8 +35,9 @@ struct option_handler {
|
|||
};
|
||||
|
||||
bool process_option(const std::string& opt, const char * arg = NULL);
|
||||
void process_arguments(std::vector<char *>& args, int argc, char ** argv);
|
||||
void process_environment(char ** envp);
|
||||
void process_arguments(int argc, char ** argv, const bool anywhere,
|
||||
std::list<std::string>& args);
|
||||
void process_environment(char ** envp, const std::string& tag);
|
||||
|
||||
#define DEF_OPT_HANDLERS() \
|
||||
std::vector<option_t> option_handler::options; \
|
||||
|
|
|
|||
|
|
@ -477,7 +477,8 @@ unsigned int parse_textual_journal(std::istream& in, journal_t * journal,
|
|||
in >> opt;
|
||||
in.getline(line, MAX_LINE);
|
||||
linenum++;
|
||||
process_option(opt, line + 1);
|
||||
char * p = skip_ws(line);
|
||||
process_option(opt, *p == '\n' ? NULL : p);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue