Create a new interactive_t helper class
The purpose of this class is much like Emacs' (interactive) form: it
allows a value expression function to declare exactly how many
arguments, and of what type, it intends to receive. It then offers
type-safe access to theese arguments in a consistent manner.
An example value expression function definition in C++:
value_t fn_foo(call_scope_t& scope) {
// We expect a string, an integer, and an optional date
interactive_t args(scope, "sl&d");
std::cout << "String = " << args.get<string>(0)
<< "Integer = " << args.get<long>(1) << std::endl;
if (args.has(2)) // was a date provided?
std::cout << "Date = " << args.get<date_t>(2) << std::endl;
return NULL_VALUE;
}
There is also an in_context_t<T> template, which finds the context type
T in the current scope hierarchy. The in_context_t then also acts as a
smart pointer to reference this context object, in addition to serving
the same duty as interactive_t. This combination of intent is solely
for the sake of brevity.
value_t fn_bar(call_scope_t& scope) {
in_context_t<account_t> env(scope, "sl&d");
std::cout << "Account name = " << env->fullname()
<< "String arg = " << env.get<string>(0)
<< std::endl;
return NULL_VALUE;
}
As you can see here, 'env' acts as a smart pointer to the required
context, and an object to extract the typed arguments.
This commit is contained in:
parent
45e41b023a
commit
1f39d4148e
11 changed files with 367 additions and 152 deletions
|
|
@ -37,6 +37,7 @@ libledger_expr_la_SOURCES = \
|
|||
src/format.cc \
|
||||
src/predicate.cc \
|
||||
src/scope.cc \
|
||||
src/interactive.cc \
|
||||
src/expr.cc \
|
||||
src/op.cc \
|
||||
src/parser.cc \
|
||||
|
|
@ -96,6 +97,7 @@ pkginclude_HEADERS = \
|
|||
src/op.h \
|
||||
src/expr.h \
|
||||
src/scope.h \
|
||||
src/interactive.h \
|
||||
src/predicate.h \
|
||||
src/format.h \
|
||||
src/option.h \
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
*/
|
||||
|
||||
#include "account.h"
|
||||
#include "interactive.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
|
|
@ -152,11 +153,9 @@ std::ostream& operator<<(std::ostream& out, const account_t& account)
|
|||
namespace {
|
||||
value_t get_partial_name(call_scope_t& scope)
|
||||
{
|
||||
account_t& account(find_scope<account_t>(scope));
|
||||
|
||||
var_t<bool> flatten(scope, 0);
|
||||
|
||||
return string_value(account.partial_name(flatten ? *flatten : false));
|
||||
in_context_t<account_t> env(scope, "&b");
|
||||
return string_value(env->partial_name(env.has(0) ?
|
||||
env.get<bool>(0) : false));
|
||||
}
|
||||
|
||||
value_t get_account(account_t& account) { // this gets the name
|
||||
|
|
|
|||
184
src/interactive.cc
Normal file
184
src/interactive.cc
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2009, John Wiegley. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of New Artisans LLC nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "interactive.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
void interactive_t::verify_arguments() const
|
||||
{
|
||||
value_t::sequence_t::const_iterator i;
|
||||
|
||||
const char * p = spec.c_str();
|
||||
const char * label = "unknown";
|
||||
bool wrong_arg = false;
|
||||
bool dont_skip = false;
|
||||
bool optional = *p == '&';
|
||||
bool exit_loop = *p == '*';
|
||||
std::size_t offset = 1;
|
||||
bool is_seq = args.value().is_sequence();
|
||||
const value_t * next_arg = NULL;
|
||||
string vlabel;
|
||||
|
||||
if (is_seq) {
|
||||
i = args.begin();
|
||||
if (i != args.end())
|
||||
next_arg = &(*i);
|
||||
}
|
||||
else if (! args.value().is_null()) {
|
||||
next_arg = &args.value();
|
||||
}
|
||||
|
||||
for (; ! wrong_arg && ! exit_loop && *p && next_arg; p++) {
|
||||
switch (*p) {
|
||||
case 'a':
|
||||
label = "an amount";
|
||||
wrong_arg = (! next_arg->is_long() &&
|
||||
! next_arg->is_amount() &&
|
||||
! next_arg->is_balance());
|
||||
break;
|
||||
case 'b':
|
||||
label = "a boolean";
|
||||
wrong_arg = false; // booleans are converted
|
||||
break;
|
||||
case 'd':
|
||||
label = "a date";
|
||||
wrong_arg = ! next_arg->is_date();
|
||||
break;
|
||||
case 'i':
|
||||
case 'l':
|
||||
label = "an integer";
|
||||
if (next_arg->is_long() ||
|
||||
(next_arg->is_amount() &&
|
||||
! next_arg->as_amount().has_commodity())) {
|
||||
wrong_arg = false;
|
||||
}
|
||||
else if (next_arg->is_string()) {
|
||||
wrong_arg = false;
|
||||
for (const char * q = next_arg->as_string().c_str(); *q; q++) {
|
||||
if (! std::isdigit(*q) && *q != '-') {
|
||||
wrong_arg = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
wrong_arg = true;
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
label = "a regex";
|
||||
wrong_arg = ! next_arg->is_mask();
|
||||
break;
|
||||
case 's':
|
||||
label = "a string";
|
||||
wrong_arg = ! next_arg->is_string();
|
||||
break;
|
||||
case 't':
|
||||
label = "a date or time";
|
||||
wrong_arg = (! next_arg->is_date() &&
|
||||
! next_arg->is_datetime());
|
||||
break;
|
||||
case 'v':
|
||||
label = "any value";
|
||||
wrong_arg = false;
|
||||
break;
|
||||
case 'P':
|
||||
label = "a pointer";
|
||||
wrong_arg = ! next_arg->is_pointer();
|
||||
break;
|
||||
case 'S':
|
||||
label = "a sequence";
|
||||
wrong_arg = ! next_arg->is_sequence();
|
||||
break;
|
||||
case '&':
|
||||
optional = true;
|
||||
dont_skip = true;
|
||||
break;
|
||||
case '*':
|
||||
optional = true;
|
||||
exit_loop = true;
|
||||
dont_skip = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (wrong_arg)
|
||||
vlabel = next_arg->label();
|
||||
|
||||
if (! dont_skip) {
|
||||
if (is_seq) {
|
||||
if (++i != args.end()) {
|
||||
next_arg = &(*i);
|
||||
offset++;
|
||||
} else {
|
||||
next_arg = NULL;
|
||||
}
|
||||
} else {
|
||||
next_arg = NULL;
|
||||
}
|
||||
}
|
||||
dont_skip = false;
|
||||
}
|
||||
|
||||
if (*p == '&' || *p == '*')
|
||||
optional = true;
|
||||
|
||||
if (wrong_arg) {
|
||||
throw_(std::logic_error,
|
||||
"Expected " << label << " for argument " << offset
|
||||
<< ", but received " << vlabel);
|
||||
}
|
||||
else if (! optional && ! next_arg) {
|
||||
throw_(std::logic_error, "Too few arguments to function");
|
||||
}
|
||||
else if (! *p && next_arg) {
|
||||
throw_(std::logic_error, "Too many arguments to function");
|
||||
}
|
||||
}
|
||||
|
||||
string join_args(call_scope_t& args)
|
||||
{
|
||||
std::ostringstream buf;
|
||||
bool first = true;
|
||||
|
||||
for (std::size_t i = 0; i < args.size(); i++) {
|
||||
if (first) {
|
||||
buf << args[i];
|
||||
first = false;
|
||||
} else {
|
||||
buf << ' ' << args[i];
|
||||
}
|
||||
}
|
||||
|
||||
return buf.str();
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
142
src/interactive.h
Normal file
142
src/interactive.h
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2009, John Wiegley. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of New Artisans LLC nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup expr
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file interactive.h
|
||||
* @author John Wiegley
|
||||
*
|
||||
* @ingroup expr
|
||||
*
|
||||
* @brief Brief
|
||||
*
|
||||
* Long.
|
||||
*/
|
||||
#ifndef _INTERACTIVE_H
|
||||
#define _INTERACTIVE_H
|
||||
|
||||
#include "scope.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
/**
|
||||
* @brief Brief
|
||||
*
|
||||
* Long.
|
||||
*/
|
||||
class interactive_t : public noncopyable
|
||||
{
|
||||
call_scope_t& args;
|
||||
string spec;
|
||||
|
||||
public:
|
||||
explicit interactive_t(call_scope_t& _args, const string& _spec = "")
|
||||
: args(_args), spec(_spec) {
|
||||
TRACE_CTOR(interactive_t, "call_scope_t&, const string&");
|
||||
verify_arguments();
|
||||
}
|
||||
virtual ~interactive_t() {
|
||||
TRACE_DTOR(interactive_t);
|
||||
}
|
||||
|
||||
void verify_arguments() const;
|
||||
|
||||
bool has(std::size_t index) const {
|
||||
if (index < args.size())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
const value_t& value_at(std::size_t index) const {
|
||||
assert(has(index));
|
||||
return args[index];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T get(std::size_t index) const;
|
||||
};
|
||||
|
||||
template <>
|
||||
inline bool interactive_t::get<bool>(std::size_t index) const {
|
||||
return value_at(index).to_boolean();
|
||||
}
|
||||
template <>
|
||||
inline long interactive_t::get<long>(std::size_t index) const {
|
||||
return value_at(index).to_long();
|
||||
}
|
||||
template <>
|
||||
inline string interactive_t::get<string>(std::size_t index) const {
|
||||
return value_at(index).to_string();
|
||||
}
|
||||
template <>
|
||||
inline mask_t interactive_t::get<mask_t>(std::size_t index) const {
|
||||
return value_at(index).to_mask();
|
||||
}
|
||||
template <>
|
||||
inline date_t interactive_t::get<date_t>(std::size_t index) const {
|
||||
return value_at(index).to_date();
|
||||
}
|
||||
template <>
|
||||
inline datetime_t interactive_t::get<datetime_t>(std::size_t index) const {
|
||||
return value_at(index).to_datetime();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class in_context_t : public interactive_t
|
||||
{
|
||||
T& context;
|
||||
|
||||
public:
|
||||
explicit in_context_t(call_scope_t& args, const string& spec)
|
||||
: interactive_t(args, spec), context(find_scope<T>(args)) {
|
||||
TRACE_CTOR(in_context_t, "call_scope_t&, const string&");
|
||||
}
|
||||
virtual ~in_context_t() {
|
||||
TRACE_DTOR(in_context_t);
|
||||
}
|
||||
|
||||
T& operator *() {
|
||||
return context;
|
||||
}
|
||||
T * operator->() {
|
||||
return &context;
|
||||
}
|
||||
};
|
||||
|
||||
string join_args(call_scope_t& args);
|
||||
|
||||
} // namespace ledger
|
||||
|
||||
#endif // _INTERACTIVE_H
|
||||
|
||||
|
|
@ -30,6 +30,7 @@
|
|||
*/
|
||||
|
||||
#include "precmd.h"
|
||||
#include "interactive.h"
|
||||
#include "report.h"
|
||||
|
||||
namespace ledger {
|
||||
|
|
|
|||
|
|
@ -46,10 +46,12 @@
|
|||
#ifndef _PRECMD_H
|
||||
#define _PRECMD_H
|
||||
|
||||
#include "scope.h"
|
||||
#include "value.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
class call_scope_t;
|
||||
|
||||
value_t parse_command(call_scope_t& args);
|
||||
value_t eval_command(call_scope_t& args);
|
||||
value_t format_command(call_scope_t& args);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
*/
|
||||
|
||||
#include "report.h"
|
||||
#include "interactive.h"
|
||||
#include "iterators.h"
|
||||
#include "filters.h"
|
||||
#include "chain.h"
|
||||
|
|
@ -121,19 +122,20 @@ value_t report_t::fn_display_total(call_scope_t& scope)
|
|||
|
||||
value_t report_t::fn_market_value(call_scope_t& args)
|
||||
{
|
||||
var_t<datetime_t> date(args, 1);
|
||||
var_t<string> in_terms_of(args, 2);
|
||||
interactive_t env(args, "a&ts");
|
||||
|
||||
commodity_t * commodity = NULL;
|
||||
if (in_terms_of)
|
||||
commodity = amount_t::current_pool->find_or_create(*in_terms_of);
|
||||
if (env.has(2))
|
||||
commodity = amount_t::current_pool->find_or_create(env.get<string>(2));
|
||||
|
||||
DEBUG("report.market", "getting market value of: " << args[0]);
|
||||
DEBUG("report.market", "getting market value of: " << env.value_at(0));
|
||||
|
||||
value_t result =
|
||||
args[0].value(date ? optional<datetime_t>(*date) : optional<datetime_t>(),
|
||||
commodity ? optional<commodity_t&>(*commodity) :
|
||||
optional<commodity_t&>());
|
||||
env.value_at(0).value(env.has(1) ?
|
||||
env.get<datetime_t>(1) : optional<datetime_t>(),
|
||||
commodity ?
|
||||
optional<commodity_t&>(*commodity) :
|
||||
optional<commodity_t&>());
|
||||
|
||||
DEBUG("report.market", "result is: " << result);
|
||||
return result;
|
||||
|
|
@ -160,28 +162,24 @@ value_t report_t::fn_quantity(call_scope_t& args)
|
|||
|
||||
value_t report_t::fn_truncate(call_scope_t& args)
|
||||
{
|
||||
var_t<long> width(args, 1);
|
||||
var_t<long> account_abbrev(args, 2);
|
||||
|
||||
return string_value(format_t::truncate(args[0].as_string(),
|
||||
width && *width > 0 ? *width : 0,
|
||||
account_abbrev ? *account_abbrev : -1));
|
||||
interactive_t env(args, "v&ll");
|
||||
return string_value(format_t::truncate
|
||||
(env.get<string>(0),
|
||||
env.has(1) && env.get<long>(1) > 0 ? env.get<long>(1) : 0,
|
||||
env.has(2) ? env.get<long>(2) : -1));
|
||||
}
|
||||
|
||||
value_t report_t::fn_print(call_scope_t& args)
|
||||
{
|
||||
var_t<long> first_width(args, 1);
|
||||
var_t<long> latter_width(args, 2);
|
||||
var_t<string> date_format(args, 3);
|
||||
|
||||
interactive_t env(args, "vl&ls");
|
||||
std::ostringstream out;
|
||||
|
||||
args[0].strip_annotations(what_to_keep())
|
||||
.print(out, *first_width, latter_width ? *latter_width : -1,
|
||||
date_format ? *date_format :
|
||||
env.value_at(0)
|
||||
.strip_annotations(what_to_keep())
|
||||
.print(out, env.get<long>(1),
|
||||
env.has(2) ? env.get<long>(2) : -1,
|
||||
env.has(3) ? env.get<string>(3) :
|
||||
(HANDLED(date_format_) ?
|
||||
HANDLER(date_format_).str() : optional<string>()));
|
||||
|
||||
return string_value(out.str());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -502,13 +502,13 @@ public:
|
|||
"3 + date_width + payee_width + account_width + amount_width))"
|
||||
" %(print(strip(display_total), total_width, "
|
||||
"4 + date_width + payee_width + account_width + amount_width "
|
||||
"+ total_width, true))\n%/"
|
||||
"+ total_width))\n%/"
|
||||
"%(print(\" \", 2 + date_width + payee_width))"
|
||||
"%(print(truncate(account, account_width, abbrev_len), account_width))"
|
||||
" %(print(strip(display_amount), amount_width, 3 + date_width "
|
||||
"+ payee_width + account_width + amount_width))"
|
||||
" %(print(strip(display_total), total_width, 4 + date_width "
|
||||
"+ payee_width + account_width + amount_width + total_width, true))\n");
|
||||
"+ payee_width + account_width + amount_width + total_width))\n");
|
||||
});
|
||||
|
||||
OPTION(report_t, related); // -r
|
||||
|
|
|
|||
17
src/scope.cc
17
src/scope.cc
|
|
@ -60,21 +60,4 @@ expr_t::ptr_op_t symbol_scope_t::lookup(const string& name)
|
|||
return child_scope_t::lookup(name);
|
||||
}
|
||||
|
||||
string join_args(call_scope_t& args)
|
||||
{
|
||||
std::ostringstream buf;
|
||||
bool first = true;
|
||||
|
||||
for (std::size_t i = 0; i < args.size(); i++) {
|
||||
if (first) {
|
||||
buf << args[i];
|
||||
first = false;
|
||||
} else {
|
||||
buf << ' ' << args[i];
|
||||
}
|
||||
}
|
||||
|
||||
return buf.str();
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
|
|
|
|||
97
src/scope.h
97
src/scope.h
|
|
@ -158,13 +158,9 @@ public:
|
|||
}
|
||||
|
||||
void set_args(const value_t& _args) {
|
||||
if (_args.is_sequence())
|
||||
args = _args;
|
||||
else
|
||||
args = _args.to_sequence();
|
||||
args = _args;
|
||||
}
|
||||
value_t& value() {
|
||||
assert(args.is_null() || args.is_sequence());
|
||||
return args;
|
||||
}
|
||||
|
||||
|
|
@ -291,97 +287,6 @@ public:
|
|||
T * operator->() { return value; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Brief
|
||||
*
|
||||
* Long.
|
||||
*/
|
||||
template <typename T>
|
||||
class var_t : public noncopyable
|
||||
{
|
||||
optional<value_t> value;
|
||||
|
||||
var_t();
|
||||
|
||||
public:
|
||||
var_t(scope_t& scope, const string& name)
|
||||
{
|
||||
TRACE_CTOR(var_t, "scope_t&, const string&");
|
||||
|
||||
try {
|
||||
value = scope.resolve(name);
|
||||
}
|
||||
catch (...) {
|
||||
DEBUG("scope.var_t", "Failed lookup var_t(\"" << name << "\")");
|
||||
value = none;
|
||||
}
|
||||
}
|
||||
|
||||
var_t(call_scope_t& scope, const std::size_t idx)
|
||||
{
|
||||
TRACE_CTOR(var_t, "call_scope_t&, const std::size_t");
|
||||
|
||||
if (idx < scope.size())
|
||||
value = scope[idx];
|
||||
else
|
||||
value = none;
|
||||
}
|
||||
|
||||
~var_t() throw() {
|
||||
TRACE_DTOR(var_t);
|
||||
}
|
||||
|
||||
operator bool() { return value; }
|
||||
|
||||
T operator *();
|
||||
T operator *() const;
|
||||
|
||||
T * operator->() {
|
||||
return &**this;
|
||||
}
|
||||
const T * operator->() const {
|
||||
return &**this;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
inline bool var_t<bool>::operator *() {
|
||||
return value->to_boolean();
|
||||
}
|
||||
template <>
|
||||
inline bool var_t<bool>::operator *() const {
|
||||
return value->to_boolean();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline long var_t<long>::operator *() {
|
||||
return value->to_long();
|
||||
}
|
||||
template <>
|
||||
inline long var_t<long>::operator *() const {
|
||||
return value->to_long();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline string var_t<string>::operator *() {
|
||||
return value->to_string();
|
||||
}
|
||||
template <>
|
||||
inline string var_t<string>::operator *() const {
|
||||
return value->to_string();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline datetime_t var_t<datetime_t>::operator *() {
|
||||
return value->to_datetime();
|
||||
}
|
||||
template <>
|
||||
inline datetime_t var_t<datetime_t>::operator *() const {
|
||||
return value->to_datetime();
|
||||
}
|
||||
|
||||
string join_args(call_scope_t& args);
|
||||
|
||||
} // namespace ledger
|
||||
|
||||
#endif // _SCOPE_H
|
||||
|
|
|
|||
15
src/xact.cc
15
src/xact.cc
|
|
@ -32,6 +32,7 @@
|
|||
#include "xact.h"
|
||||
#include "journal.h"
|
||||
#include "account.h"
|
||||
#include "interactive.h"
|
||||
#include "format.h"
|
||||
|
||||
namespace ledger {
|
||||
|
|
@ -186,17 +187,15 @@ namespace {
|
|||
|
||||
value_t get_account(call_scope_t& scope)
|
||||
{
|
||||
xact_t& xact(find_scope<xact_t>(scope));
|
||||
in_context_t<xact_t> env(scope, "&l");
|
||||
|
||||
var_t<long> max_width(scope, 0);
|
||||
string name = env->reported_account()->fullname();
|
||||
|
||||
string name = xact.reported_account()->fullname();
|
||||
if (env.has(0) && env.get<long>(0) > 2)
|
||||
name = format_t::truncate(name, env.get<long>(0) - 2, true);
|
||||
|
||||
if (max_width && *max_width > 2)
|
||||
name = format_t::truncate(name, *max_width - 2, true);
|
||||
|
||||
if (xact.has_flags(XACT_VIRTUAL)) {
|
||||
if (xact.must_balance())
|
||||
if (env->has_flags(XACT_VIRTUAL)) {
|
||||
if (env->must_balance())
|
||||
name = string("[") + name + "]";
|
||||
else
|
||||
name = string("(") + name + ")";
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue