summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--NEWS7
-rw-r--r--amount.cc12
-rw-r--r--amount.h56
-rw-r--r--binary.cc14
-rw-r--r--config.cc12
-rw-r--r--config.h2
-rw-r--r--configure.in4
-rw-r--r--format.cc61
-rw-r--r--format.h3
10 files changed, 126 insertions, 47 deletions
diff --git a/Makefile.am b/Makefile.am
index ba96fd9b..68dd5f48 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -47,7 +47,7 @@ endif
if DEBUG
libledger_la_CXXFLAGS += -DDEBUG_LEVEL=4
endif
-libledger_la_LDFLAGS = -release 2.6
+libledger_la_LDFLAGS = -release 3.0
pkginclude_HEADERS = \
acconf.h \
diff --git a/NEWS b/NEWS
index 22d686fa..5feedcd8 100644
--- a/NEWS
+++ b/NEWS
@@ -1,11 +1,16 @@
Ledger NEWS
-* 2.6
+* 3.0
- Error reporting has been greatly improving, now showing full
contextual information for most error messages.
+- Added new --ansi reporting option, which shows negative values as
+ red using ANSI terminal codes; --ansi-invert makes non-negative
+ values red (which makes more sense for income and budget reports,
+ for example).
+
- Added a new --only predicate, which occurs during transaction
processing between --limit and --display. Here is a summary of how
the three supported predicates are used:
diff --git a/amount.cc b/amount.cc
index 67a0ec8c..cad3e64d 100644
--- a/amount.cc
+++ b/amount.cc
@@ -1344,7 +1344,7 @@ void amount_t::annotate_commodity(const amount_t& price,
if (commodity().annotated) {
this_ann = &static_cast<annotated_commodity_t&>(commodity());
- this_base = this_ann->base;
+ this_base = this_ann->ptr;
} else {
this_base = &commodity();
}
@@ -1392,7 +1392,7 @@ amount_t amount_t::strip_annotations(const bool _keep_price,
(_keep_tag && ! ann_comm.tag.empty()))
{
new_comm = annotated_commodity_t::find_or_create
- (*ann_comm.base, _keep_price ? ann_comm.price : amount_t(),
+ (*ann_comm.ptr, _keep_price ? ann_comm.price : amount_t(),
_keep_date ? ann_comm.date : 0, _keep_tag ? ann_comm.tag : "");
} else {
new_comm = commodity_t::find_or_create(ann_comm.base_symbol());
@@ -1465,7 +1465,7 @@ commodity_t * commodity_t::create(const std::string& symbol)
{
std::auto_ptr<commodity_t> commodity(new commodity_t);
- commodity->ptr = commodity_base_t::create(symbol);
+ commodity->base = commodity_base_t::create(symbol);
if (needs_quotes(symbol)) {
commodity->qualified_symbol = "\"";
@@ -1607,10 +1607,10 @@ annotated_commodity_t::create(const commodity_t& comm,
commodity->date = date;
commodity->tag = tag;
- commodity->base = &comm;
- assert(commodity->base);
- commodity->ptr = comm.ptr;
+ commodity->ptr = &comm;
assert(commodity->ptr);
+ commodity->base = comm.base;
+ assert(commodity->base);
commodity->qualified_symbol = comm.symbol();
diff --git a/amount.h b/amount.h
index 5598043b..460047ae 100644
--- a/amount.h
+++ b/amount.h
@@ -444,25 +444,25 @@ class commodity_t
typedef unsigned long ident_t;
ident_t ident;
- commodity_base_t * ptr;
+ commodity_base_t * base;
std::string qualified_symbol;
bool annotated;
public:
- explicit commodity_t() : ptr(NULL), annotated(false) {}
+ explicit commodity_t() : base(NULL), annotated(false) {}
operator bool() const {
return this != null_commodity;
}
bool operator==(const commodity_t& comm) const {
- return ptr == comm.ptr;
+ return base == comm.base;
}
bool operator!=(const commodity_t& comm) const {
- return ptr != comm.ptr;
+ return base != comm.base;
}
std::string base_symbol() const {
- return ptr->symbol;
+ return base->symbol;
}
std::string symbol() const {
return qualified_symbol;
@@ -473,69 +473,69 @@ class commodity_t
}
std::string name() const {
- return ptr->name;
+ return base->name;
}
void set_name(const std::string& arg) {
- ptr->name = arg;
+ base->name = arg;
}
std::string note() const {
- return ptr->note;
+ return base->note;
}
void set_note(const std::string& arg) {
- ptr->note = arg;
+ base->note = arg;
}
unsigned char precision() const {
- return ptr->precision;
+ return base->precision;
}
void set_precision(unsigned char arg) {
- ptr->precision = arg;
+ base->precision = arg;
}
unsigned char flags() const {
- return ptr->flags;
+ return base->flags;
}
void set_flags(unsigned char arg) {
- ptr->flags = arg;
+ base->flags = arg;
}
void add_flags(unsigned char arg) {
- ptr->flags |= arg;
+ base->flags |= arg;
}
void drop_flags(unsigned char arg) {
- ptr->flags &= ~arg;
+ base->flags &= ~arg;
}
amount_t * smaller() const {
- return ptr->smaller;
+ return base->smaller;
}
void set_smaller(const amount_t& arg) {
- if (ptr->smaller)
- delete ptr->smaller;
- ptr->smaller = new amount_t(arg);
+ if (base->smaller)
+ delete base->smaller;
+ base->smaller = new amount_t(arg);
}
amount_t * larger() const {
- return ptr->larger;
+ return base->larger;
}
void set_larger(const amount_t& arg) {
- if (ptr->larger)
- delete ptr->larger;
- ptr->larger = new amount_t(arg);
+ if (base->larger)
+ delete base->larger;
+ base->larger = new amount_t(arg);
}
commodity_base_t::history_t * history() const {
- return ptr->history;
+ return base->history;
}
void add_price(const std::time_t date, const amount_t& price) {
- return ptr->add_price(date, price);
+ return base->add_price(date, price);
}
bool remove_price(const std::time_t date) {
- return ptr->remove_price(date);
+ return base->remove_price(date);
}
amount_t value(const std::time_t moment = std::time(NULL)) const {
- return ptr->value(moment);
+ return base->value(moment);
}
bool valid() const;
@@ -544,7 +544,7 @@ class commodity_t
class annotated_commodity_t : public commodity_t
{
public:
- const commodity_t * base;
+ const commodity_t * ptr;
amount_t price;
std::time_t date;
diff --git a/binary.cc b/binary.cc
index 9f34af95..005ed715 100644
--- a/binary.cc
+++ b/binary.cc
@@ -455,7 +455,7 @@ inline commodity_t * read_binary_commodity(char *& data)
commodity_t * commodity = new commodity_t;
*commodities_next++ = commodity;
- commodity->ptr =
+ commodity->base =
base_commodities[read_binary_long<commodity_base_t::ident_t>(data) - 1];
read_binary_string(data, commodity->qualified_symbol);
@@ -469,13 +469,13 @@ inline commodity_t * read_binary_commodity_annotated(char *& data)
annotated_commodity_t * commodity = new annotated_commodity_t;
*commodities_next++ = commodity;
- commodity->ptr =
+ commodity->base =
base_commodities[read_binary_long<commodity_base_t::ident_t>(data) - 1];
read_binary_string(data, commodity->qualified_symbol);
commodity->annotated = true;
- commodity->base =
+ commodity->ptr =
commodities[read_binary_long<commodity_t::ident_t>(data) - 1];
read_binary_amount(data, commodity->price);
read_binary_long(data, commodity->date);
@@ -658,7 +658,7 @@ unsigned int read_binary_journal(std::istream& in,
if (read_binary_number<char>(data) == 0) {
commodity = read_binary_commodity(data);
- mapping_key = commodity->ptr->symbol;
+ mapping_key = commodity->base->symbol;
} else {
read_binary_string(data, mapping_key);
commodity = read_binary_commodity_annotated(data);
@@ -677,7 +677,7 @@ unsigned int read_binary_journal(std::istream& in,
commodity));
if (! result.second && commodity->annotated)
throw new error(std::string("Failed to read commodity from cache: ") +
- commodity->ptr->symbol);
+ commodity->base->symbol);
}
commodity_t::ident_t ident;
@@ -1005,7 +1005,7 @@ void write_binary_commodity(std::ostream& out, commodity_t * commodity)
{
commodity->ident = ++commodity_index;
- write_binary_long(out, commodity->ptr->ident);
+ write_binary_long(out, commodity->base->ident);
write_binary_string(out, commodity->qualified_symbol);
}
@@ -1014,7 +1014,7 @@ void write_binary_commodity_annotated(std::ostream& out,
{
commodity->ident = ++commodity_index;
- write_binary_long(out, commodity->ptr->ident);
+ write_binary_long(out, commodity->base->ident);
write_binary_string(out, commodity->qualified_symbol);
annotated_commodity_t * ann_comm =
diff --git a/config.cc b/config.cc
index 907ab7c7..37198879 100644
--- a/config.cc
+++ b/config.cc
@@ -1115,6 +1115,16 @@ OPT_BEGIN(total_data, "J") {
config->format_string = config->plot_total_format;
} OPT_END(total_data);
+OPT_BEGIN(ansi, "") {
+ format_t::ansi_codes = true;
+ format_t::ansi_invert = false;
+} OPT_END(ansi);
+
+OPT_BEGIN(ansi_invert, "") {
+ format_t::ansi_codes =
+ format_t::ansi_invert = true;
+} OPT_END(ansi);
+
//////////////////////////////////////////////////////////////////////
//
// Commodity reporting
@@ -1192,6 +1202,8 @@ option_t config_options[CONFIG_OPTIONS_SIZE] = {
{ "add-budget", '\0', false, opt_add_budget, false },
{ "amount", 't', true, opt_amount, false },
{ "amount-data", 'j', false, opt_amount_data, false },
+ { "ansi", '\0', false, opt_ansi, false },
+ { "ansi-invert", '\0', false, opt_ansi_invert, false },
{ "average", 'A', false, opt_average, false },
{ "balance-format", '\0', true, opt_balance_format, false },
{ "basis", 'B', false, opt_basis, false },
diff --git a/config.h b/config.h
index dce8cca0..6a057979 100644
--- a/config.h
+++ b/config.h
@@ -107,7 +107,7 @@ class config_t
std::list<item_handler<transaction_t> *>& ptrs);
};
-#define CONFIG_OPTIONS_SIZE 86
+#define CONFIG_OPTIONS_SIZE 88
extern option_t config_options[CONFIG_OPTIONS_SIZE];
void option_help(std::ostream& out);
diff --git a/configure.in b/configure.in
index f595d3b7..444ba803 100644
--- a/configure.in
+++ b/configure.in
@@ -2,8 +2,8 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
-AC_INIT(ledger, 2.6, johnw@newartisans.com)
-AM_INIT_AUTOMAKE(ledger, 2.6)
+AC_INIT(ledger, 3.0, johnw@newartisans.com)
+AM_INIT_AUTOMAKE(ledger, 3.0)
AC_CONFIG_SRCDIR([main.cc])
AC_CONFIG_HEADER([acconf.h])
diff --git a/format.cc b/format.cc
index fea25dd3..75d52733 100644
--- a/format.cc
+++ b/format.cc
@@ -7,6 +7,9 @@
namespace ledger {
+bool format_t::ansi_codes = false;
+bool format_t::ansi_invert = false;
+
std::string truncated(const std::string& str, unsigned int width,
const int style)
{
@@ -264,6 +267,26 @@ static bool entry_state(const entry_t * entry, transaction_t::state_t * state)
return ! hetero;
}
+namespace {
+ void mark_red(std::ostream& out, const element_t * elem) {
+ out.setf(std::ios::left);
+ out.width(0);
+ out << "\e[31m";
+
+ if (elem->align_left)
+ out << std::left;
+ else
+ out << std::right;
+
+ if (elem->min_width > 0)
+ out.width(elem->min_width);
+ }
+
+ void mark_plain(std::ostream& out) {
+ out << "\e[0m";
+ }
+}
+
void format_t::format(std::ostream& out_str, const details_t& details) const
{
for (const element_t * elem = elements; elem; elem = elem->next) {
@@ -322,15 +345,37 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
case value_t::BOOLEAN:
out << (*((bool *) value.data) ? "true" : "false");
break;
+
case value_t::INTEGER:
+ if (ansi_codes) {
+ if (ansi_invert) {
+ if (*((long *) value.data) > 0)
+ mark_red(out, elem);
+ } else {
+ if (*((long *) value.data) < 0)
+ mark_red(out, elem);
+ }
+ }
out << *((long *) value.data);
break;
+
case value_t::DATETIME:
out << *((datetime_t *) value.data);
break;
+
case value_t::AMOUNT:
+ if (ansi_codes) {
+ if (ansi_invert) {
+ if (*((amount_t *) value.data) > 0)
+ mark_red(out, elem);
+ } else {
+ if (*((amount_t *) value.data) < 0)
+ mark_red(out, elem);
+ }
+ }
out << *((amount_t *) value.data);
break;
+
case value_t::BALANCE:
bal = (balance_t *) value.data;
// fall through...
@@ -339,14 +384,28 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
if (! bal)
bal = &((balance_pair_t *) value.data)->quantity;
+ if (ansi_codes) {
+ if (ansi_invert) {
+ if (*bal > 0)
+ mark_red(out, elem);
+ } else {
+ if (*bal < 0)
+ mark_red(out, elem);
+ }
+ }
bal->write(out, elem->min_width,
- (elem->max_width > 0 ? elem->max_width : elem->min_width));
+ (elem->max_width > 0 ?
+ elem->max_width : elem->min_width));
+
ignore_max_width = true;
break;
default:
assert(0);
break;
}
+
+ if (ansi_codes)
+ mark_plain(out);
break;
}
diff --git a/format.h b/format.h
index e245b9aa..09e1d746 100644
--- a/format.h
+++ b/format.h
@@ -72,6 +72,9 @@ struct format_t
std::string format_string;
element_t * elements;
+ static bool ansi_codes;
+ static bool ansi_invert;
+
format_t() : elements(NULL) {
DEBUG_PRINT("ledger.memory.ctors", "ctor format_t");
}