more options fixes
This commit is contained in:
parent
8a70bbed52
commit
6944e5950a
6 changed files with 93 additions and 89 deletions
52
ledger.cc
52
ledger.cc
|
|
@ -52,43 +52,41 @@ bool journal_t::remove_entry(entry_t * entry)
|
||||||
return true;
|
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 * added = new entry_t;
|
||||||
entry_t * matching = NULL;
|
entry_t * matching = NULL;
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
assert(index < argc);
|
if (! parse_date((*i).c_str(), &added->date)) {
|
||||||
|
std::cerr << "Error: Bad entry date: " << *i << std::endl;
|
||||||
if (! parse_date(argv[index++], &added->date)) {
|
|
||||||
std::cerr << "Error: Bad entry date: " << argv[index - 1]
|
|
||||||
<< std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
++i;
|
||||||
|
|
||||||
if (index == argc) {
|
if (i == end) {
|
||||||
std::cerr << "Error: Too few arguments to 'entry'." << std::endl;
|
std::cerr << "Error: Too few arguments to 'entry'." << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mask_t regexp(argv[index++]);
|
mask_t regexp(*i++);
|
||||||
|
|
||||||
for (entries_list::const_reverse_iterator i = entries.rbegin();
|
for (entries_list::const_reverse_iterator j = entries.rbegin();
|
||||||
i != entries.rend();
|
j != entries.rend();
|
||||||
i++)
|
j++)
|
||||||
if (regexp.match((*i)->payee)) {
|
if (regexp.match((*j)->payee)) {
|
||||||
matching = *i;
|
matching = *j;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
added->payee = matching ? matching->payee : regexp.pattern;
|
added->payee = matching ? matching->payee : regexp.pattern;
|
||||||
|
|
||||||
if (index == argc) {
|
if (i == end) {
|
||||||
std::cerr << "Error: Too few arguments to 'entry'." << std::endl;
|
std::cerr << "Error: Too few arguments to 'entry'." << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argv[index][0] == '-' || std::isdigit(argv[index][0])) {
|
if ((*i)[0] == '-' || std::isdigit((*i)[0])) {
|
||||||
if (! matching) {
|
if (! matching) {
|
||||||
std::cerr << "Error: Missing account name for non-matching entry."
|
std::cerr << "Error: Missing account name for non-matching entry."
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
@ -98,7 +96,7 @@ entry_t * journal_t::derive_entry(int argc, char **argv) const
|
||||||
transaction_t * m_xact, * xact, * first;
|
transaction_t * m_xact, * xact, * first;
|
||||||
m_xact = matching->transactions.front();
|
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);
|
first = xact = new transaction_t(added, m_xact->account, amt, amt);
|
||||||
|
|
||||||
if (xact->amount.commodity->symbol.empty()) {
|
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);
|
- first->amount, - first->amount);
|
||||||
added->add_transaction(xact);
|
added->add_transaction(xact);
|
||||||
|
|
||||||
if ((index + 1) < argc && std::string(argv[index]) == "-from")
|
if (std::string(*i++) == "-from" && i != end)
|
||||||
if (account_t * acct = find_account(argv[++index]))
|
if (account_t * acct = find_account(*i))
|
||||||
added->transactions.back()->account = acct;
|
added->transactions.back()->account = acct;
|
||||||
} else {
|
} else {
|
||||||
while (index < argc && std::string(argv[index]) != "-from") {
|
while (std::string(*i) != "-from") {
|
||||||
mask_t acct_regex(argv[index++]);
|
mask_t acct_regex(*i++);
|
||||||
|
|
||||||
account_t * acct = NULL;
|
account_t * acct = NULL;
|
||||||
commodity_t * cmdty = NULL;
|
commodity_t * cmdty = NULL;
|
||||||
|
|
@ -145,12 +143,12 @@ entry_t * journal_t::derive_entry(int argc, char **argv) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == argc) {
|
if (i == end) {
|
||||||
std::cerr << "Error: Too few arguments to 'entry'." << std::endl;
|
std::cerr << "Error: Too few arguments to 'entry'." << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
amount_t amt(argv[index]++);
|
amount_t amt(*i++);
|
||||||
transaction_t * xact = new transaction_t(added, acct, amt, amt);
|
transaction_t * xact = new transaction_t(added, acct, amt, amt);
|
||||||
|
|
||||||
if (! xact->amount.commodity)
|
if (! xact->amount.commodity)
|
||||||
|
|
@ -159,8 +157,8 @@ entry_t * journal_t::derive_entry(int argc, char **argv) const
|
||||||
added->add_transaction(xact);
|
added->add_transaction(xact);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((index + 1) < argc && std::string(argv[index]) == "-from") {
|
if (std::string(*i++) == "-from" && i != end) {
|
||||||
if (account_t * acct = find_account(argv[++index])) {
|
if (account_t * acct = find_account(*i++)) {
|
||||||
transaction_t * xact = new transaction_t(NULL, acct);
|
transaction_t * xact = new transaction_t(NULL, acct);
|
||||||
added->add_transaction(xact);
|
added->add_transaction(xact);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
6
ledger.h
6
ledger.h
|
|
@ -165,7 +165,8 @@ inline std::ostream& operator<<(std::ostream& out, const account_t& acct) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
typedef std::list<entry_t *> entries_list;
|
typedef std::list<entry_t *> entries_list;
|
||||||
|
typedef std::list<std::string> strings_list;
|
||||||
|
|
||||||
class journal_t
|
class journal_t
|
||||||
{
|
{
|
||||||
|
|
@ -208,7 +209,8 @@ class journal_t
|
||||||
bool add_entry(entry_t * entry);
|
bool add_entry(entry_t * entry);
|
||||||
bool remove_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);
|
int parse_journal_file(char * p, journal_t * journal);
|
||||||
|
|
|
||||||
68
main.cc
68
main.cc
|
|
@ -109,6 +109,7 @@ namespace {
|
||||||
bool use_cache = false;
|
bool use_cache = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// jww (2004-08-13): fix this
|
||||||
static std::string ledger_cache_file()
|
static std::string ledger_cache_file()
|
||||||
{
|
{
|
||||||
std::string cache_file;
|
std::string cache_file;
|
||||||
|
|
@ -175,12 +176,12 @@ static void show_help(std::ostream& out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEF_OPT_HANDLERS();
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Basic options
|
// Basic options
|
||||||
|
|
||||||
|
DEF_OPT_HANDLERS();
|
||||||
|
|
||||||
OPT_BEGIN(help, "h", false) {
|
OPT_BEGIN(help, "h", false) {
|
||||||
show_help(std::cout);
|
show_help(std::cout);
|
||||||
std::exit(0);
|
std::exit(0);
|
||||||
|
|
@ -191,10 +192,10 @@ OPT_BEGIN(version, "v", false) {
|
||||||
std::exit(0);
|
std::exit(0);
|
||||||
} OPT_END(version);
|
} OPT_END(version);
|
||||||
|
|
||||||
OPT_BEGIN(init_file, "i:", true) {
|
OPT_BEGIN(init, "i:", true) {
|
||||||
std::ifstream stream(optarg);
|
std::ifstream stream(optarg);
|
||||||
parse_textual_journal(stream, journal.get(), journal->master);
|
parse_textual_journal(stream, journal.get(), journal->master);
|
||||||
} OPT_END(init_file);
|
} OPT_END(init);
|
||||||
|
|
||||||
OPT_BEGIN(file, "f:", true) {
|
OPT_BEGIN(file, "f:", true) {
|
||||||
files.push_back(optarg);
|
files.push_back(optarg);
|
||||||
|
|
@ -428,22 +429,14 @@ int main(int argc, char * argv[], char * envp[])
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (char * p = std::getenv("DEBUG_FILE")) {
|
if (char * p = std::getenv("DEBUG_FILE")) {
|
||||||
debug_stream = new std::ofstream(p);
|
debug_stream = new std::ofstream(p);
|
||||||
free_debug_stream = true;
|
free_debug_stream = true;
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
// A ledger data file must be specified
|
||||||
|
|
||||||
|
// jww (2004-08-13): use LEDGER_FILE
|
||||||
use_cache = std::getenv("LEDGER") != NULL;
|
use_cache = std::getenv("LEDGER") != NULL;
|
||||||
|
|
||||||
if (use_cache) {
|
if (use_cache) {
|
||||||
|
|
@ -475,19 +468,23 @@ int main(int argc, char * argv[], char * envp[])
|
||||||
|
|
||||||
// Parse the command-line options
|
// Parse the command-line options
|
||||||
|
|
||||||
std::vector<char *> args;
|
std::list<std::string> args;
|
||||||
process_arguments(args, argc, argv);
|
process_arguments(argc, argv, false, args);
|
||||||
|
|
||||||
if (args.empty()) {
|
if (args.empty()) {
|
||||||
show_help(std::cerr);
|
show_help(std::cerr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
argc = args.size();
|
std::list<std::string>::iterator arg = args.begin();
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
// Process options from the environment
|
// 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
|
// 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
|
// 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")
|
if (command == "balance" || command == "bal" || command == "b")
|
||||||
command = "b";
|
command = "b";
|
||||||
|
|
@ -556,32 +553,25 @@ int main(int argc, char * argv[], char * envp[])
|
||||||
|
|
||||||
std::auto_ptr<entry_t> new_entry;
|
std::auto_ptr<entry_t> new_entry;
|
||||||
if (command == "e") {
|
if (command == "e") {
|
||||||
new_entry.reset(journal->derive_entry(argc - index, &args[index]));
|
new_entry.reset(journal->derive_entry(arg, args.end()));
|
||||||
} else {
|
} else {
|
||||||
// Treat the remaining command-line arguments as regular
|
// Treat the remaining command-line arguments as regular
|
||||||
// expressions, used for refining report results.
|
// expressions, used for refining report results.
|
||||||
|
|
||||||
int start = index;
|
std::list<std::string>::iterator i = args.begin();
|
||||||
for (; index < argc; index++)
|
for (; i != args.end(); i++)
|
||||||
if (std::strcmp(args[index], "--") == 0) {
|
if (*i == "--")
|
||||||
index++;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
if (start < index) {
|
std::string pred = regexps_to_predicate(arg, i);
|
||||||
std::list<std::string> regexps(&args[start], &args[index]);
|
if (! pred.empty()) {
|
||||||
std::string pred = regexps_to_predicate(regexps.begin(), regexps.end());
|
if (! predicate.empty())
|
||||||
if (! pred.empty()) {
|
predicate += "&";
|
||||||
if (! predicate.empty())
|
predicate += pred;
|
||||||
predicate += "&";
|
|
||||||
predicate += pred;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index < argc) {
|
if (i != args.end()) {
|
||||||
std::list<std::string> regexps(&args[index], &args[argc]);
|
std::string pred = regexps_to_predicate(i, args.end(), false);
|
||||||
std::string pred = regexps_to_predicate(regexps.begin(), regexps.end(),
|
|
||||||
false);
|
|
||||||
if (! pred.empty()) {
|
if (! pred.empty()) {
|
||||||
if (! predicate.empty())
|
if (! predicate.empty())
|
||||||
predicate += "&";
|
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()) {
|
if (! sort_string.empty()) {
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
47
option.cc
47
option.cc
|
|
@ -31,18 +31,6 @@ option_handler::option_handler(const std::string& label,
|
||||||
options.push_back(opt);
|
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,
|
static inline void process_option(const option_t& opt,
|
||||||
const char * arg = NULL) {
|
const char * arg = NULL) {
|
||||||
if (! opt.handler->handled || opt.handler->multiple) {
|
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;
|
int index = 1;
|
||||||
for (char ** i = argv + 1; index < argc; i++, index++) {
|
for (char ** i = argv + 1; index < argc; i++, index++) {
|
||||||
if ((*i)[0] != '-') {
|
if ((*i)[0] != '-') {
|
||||||
args.push_back(*i);
|
if (anywhere) {
|
||||||
continue;
|
args.push_back(*i);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
for (; index < argc; i++, index++)
|
||||||
|
args.push_back(*i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --long-option
|
// --long-option
|
||||||
again:
|
again:
|
||||||
if ((*i)[1] == '-') {
|
if ((*i)[1] == '-') {
|
||||||
|
if ((*i)[2] == '\0')
|
||||||
|
break;
|
||||||
|
|
||||||
for (std::vector<option_t>::iterator j
|
for (std::vector<option_t>::iterator j
|
||||||
= option_handler::options.begin();
|
= option_handler::options.begin();
|
||||||
j != option_handler::options.end();
|
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++)
|
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;
|
std::string opt;
|
||||||
char * q;
|
char * q;
|
||||||
for (q = *p + 7; *q && *q != '='; q++)
|
for (q = *p + 7; *q && *q != '='; q++)
|
||||||
|
|
|
||||||
6
option.h
6
option.h
|
|
@ -2,6 +2,7 @@
|
||||||
#define _OPTION_H
|
#define _OPTION_H
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <list>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
@ -34,8 +35,9 @@ struct option_handler {
|
||||||
};
|
};
|
||||||
|
|
||||||
bool process_option(const std::string& opt, const char * arg = NULL);
|
bool process_option(const std::string& opt, const char * arg = NULL);
|
||||||
void process_arguments(std::vector<char *>& args, int argc, char ** argv);
|
void process_arguments(int argc, char ** argv, const bool anywhere,
|
||||||
void process_environment(char ** envp);
|
std::list<std::string>& args);
|
||||||
|
void process_environment(char ** envp, const std::string& tag);
|
||||||
|
|
||||||
#define DEF_OPT_HANDLERS() \
|
#define DEF_OPT_HANDLERS() \
|
||||||
std::vector<option_t> option_handler::options; \
|
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 >> opt;
|
||||||
in.getline(line, MAX_LINE);
|
in.getline(line, MAX_LINE);
|
||||||
linenum++;
|
linenum++;
|
||||||
process_option(opt, line + 1);
|
char * p = skip_ws(line);
|
||||||
|
process_option(opt, *p == '\n' ? NULL : p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue