summaryrefslogtreecommitdiff
path: root/src/report.cc
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2009-01-22 16:27:24 -0400
committerJohn Wiegley <johnw@newartisans.com>2009-01-22 16:27:24 -0400
commit0b9f22b4d24e8fa545af2d7d448ddfe9fb3736ba (patch)
tree61bb92dac4a3adc07e6b61a4b7516252fc6abbe1 /src/report.cc
parentccedf7d57f6cc42553f1d80189bf1491df6680e2 (diff)
downloadledger-0b9f22b4d24e8fa545af2d7d448ddfe9fb3736ba.tar.gz
ledger-0b9f22b4d24e8fa545af2d7d448ddfe9fb3736ba.tar.bz2
ledger-0b9f22b4d24e8fa545af2d7d448ddfe9fb3736ba.zip
Redid the way command-line arguments are processed. Before, Ledger used - and
-- to mean special things after the command verb was seen. But now, what used to be specified as this: ledger -n reg cash -payable -- shell Is now specified as this: ledger reg -n cash not payable @shell It could also be specified as: ledger -n reg \(cash and not payable\) and @shell
Diffstat (limited to 'src/report.cc')
-rw-r--r--src/report.cc169
1 files changed, 92 insertions, 77 deletions
diff --git a/src/report.cc b/src/report.cc
index 49deeb44..50a199f4 100644
--- a/src/report.cc
+++ b/src/report.cc
@@ -321,99 +321,114 @@ namespace {
string args_to_predicate(value_t::sequence_t::const_iterator begin,
value_t::sequence_t::const_iterator end)
{
- string acct_value_expr;
- string payee_value_expr;
- string note_value_expr;
+ std::ostringstream expr;
+ bool append_and = false;
- string * value_expr;
-
- enum regexp_kind_t {
- ACCOUNT_REGEXP,
- PAYEE_REGEXP,
- NOTE_REGEXP
- }
- kind = ACCOUNT_REGEXP;
-
- value_expr = &acct_value_expr;
-
- for ( ; begin != end; begin++) {
+ while (begin != end) {
const string& arg((*begin).as_string());
- if (arg == "--") {
- kind = PAYEE_REGEXP;
- value_expr = &payee_value_expr;
+ bool parse_argument = true;
+
+ if (arg == "not") {
+ expr << " ! ";
+ parse_argument = false;
+ append_and = false;
}
- else if (arg == "/") {
- kind = NOTE_REGEXP;
- value_expr = &note_value_expr;
+ else if (arg == "and") {
+ expr << " & ";
+ parse_argument = false;
+ append_and = false;
+ }
+ else if (arg == "or") {
+ expr << " | ";
+ parse_argument = false;
+ append_and = false;
+ }
+ else if (append_and) {
+ expr << " & ";
}
else {
- if (! value_expr->empty())
- *value_expr += "|";
-
- switch (kind) {
- case ACCOUNT_REGEXP:
- *value_expr += "account =~ ";
- break;
- case PAYEE_REGEXP:
- *value_expr += "payee =~ ";
- break;
- case NOTE_REGEXP:
- *value_expr += "note =~ ";
- break;
- }
+ append_and = true;
+ }
+ if (parse_argument) {
const char * p = arg.c_str();
- if (*p == '-') {
- *value_expr += "!";
- p++;
+
+ bool in_prefix = true;
+ bool in_suffix = false;
+ bool found_specifier = false;
+ bool saw_tag_char = false;
+
+ for (const char * c = p; *c != '\0'; c++) {
+ bool consumed = false;
+ if (in_prefix) {
+ switch (*c) {
+ case '(':
+ break;
+ case '@':
+ expr << "(payee =~ /";
+ found_specifier = true;
+ consumed = true;
+ break;
+ case '=':
+ expr << "(note =~ /";
+ found_specifier = true;
+ consumed = true;
+ break;
+ case '%':
+ expr << "(note =~ /:";
+ found_specifier = true;
+ saw_tag_char = true;
+ consumed = true;
+ break;
+ case '/':
+ case '_':
+ default:
+ if (! found_specifier) {
+ expr << "(account =~ /";
+ found_specifier = true;
+ }
+ in_prefix = false;
+ break;
+ }
+ } else {
+ switch (*c) {
+ case ')':
+ if (! in_suffix) {
+ if (found_specifier) {
+ if (saw_tag_char)
+ expr << ':';
+ expr << "/)";
+ }
+ in_suffix = true;
+ }
+ break;
+ default:
+ if (in_suffix)
+ throw_(parse_error, "Invalid text in specification argument");
+ break;
+ }
+ }
+
+ if (! consumed)
+ expr << *c;
}
- *value_expr += "/";
- if (kind == NOTE_REGEXP) *value_expr += ":";
- while (*p) {
- if (*p == '/')
- *value_expr += "\\";
- *value_expr += *p;
- p++;
+ if (! in_suffix) {
+ if (found_specifier) {
+ if (saw_tag_char)
+ expr << ':';
+ expr << "/)";
+ }
}
- if (kind == NOTE_REGEXP) *value_expr += ":";
- *value_expr += "/";
}
- }
-
- string final_value_expr;
- if (! acct_value_expr.empty()) {
- if (! payee_value_expr.empty() ||
- ! note_value_expr.empty())
- final_value_expr = string("(") + acct_value_expr + ")";
- else
- final_value_expr = acct_value_expr;
+ begin++;
}
- if (! payee_value_expr.empty()) {
- if (! acct_value_expr.empty())
- final_value_expr += string("&(") + payee_value_expr + ")";
- else if (! note_value_expr.empty())
- final_value_expr = string("(") + payee_value_expr + ")";
- else
- final_value_expr = payee_value_expr;
- }
-
- if (! note_value_expr.empty()) {
- if (! acct_value_expr.empty() ||
- ! payee_value_expr.empty())
- final_value_expr += string("&(") + note_value_expr + ")";
- else if (acct_value_expr.empty() &&
- payee_value_expr.empty())
- final_value_expr = note_value_expr;
- }
-
- DEBUG("report.predicate",
- "Regexp predicate expression = " << final_value_expr);
+ DEBUG("report.predicate", "Regexp predicate expression = " << expr.str());
- return final_value_expr;
+ return expr.str();
}
template <class Type = xact_t,