This commit is contained in:
John Wiegley 2004-08-17 16:41:07 -04:00
parent 019a42f199
commit bbcb49fed2
5 changed files with 123 additions and 59 deletions

107
README
View file

@ -914,12 +914,13 @@ If you are an accountant, or you are familiar with accounting
terminology, then you might be tearing your hair out after reading the terminology, then you might be tearing your hair out after reading the
above. Please don't! above. Please don't!
Ledger is a lightweight tool that gets people comfortable with their Ledger is intended to make people comfortable with their finances; to
finances. Contemporary accounting practices will often seem help them better control the flow of their money. Contemporary
counter-intuitive and confusing to the layman. To make Ledger more accounting practices, on the other hand, often seem counter-intuitive
accessible, it deviates from the accounting conventions and and confusing to the layman. To make Ledger more accessible, it
terminology. However, Ledger is flexible enough that you can avoids the use of standard accounting conventions and terminology.
interpret your transactions however you wish. However, Ledger is flexible enough that you may interpret what is
happening however you wish.
Most probably, the following section will confuse you, and you should Most probably, the following section will confuse you, and you should
skip it if you've managed to understand everything so far. However, skip it if you've managed to understand everything so far. However,
@ -1101,13 +1102,12 @@ ledger, with the attached prefix "Billable":
* Running Ledger * Running Ledger
Now that you have an orderly and well-organized general ledger, it's Once you have an orderly and well-organized general ledger, the next
time to start generating some orderly and well-organized reports. step is to generate orderly and well-organized reports. This is where
This is where the Ledger tool comes in. With it, you can balance your the Ledger command-line tool comes in. With it, you can balance your
checkbook, see where your money is going, tell whether you've made a checkbook, see where your money is going, tell whether you've made a
profit this year, and even compute the present day value of your profit this year, and compute the present value of your retirement
retirement accounts. And all with the simplest of interfaces: the accounts. And all with the simplest of interfaces, the command-line.
command-line.
The most often used command will be the "balance" command: The most often used command will be the "balance" command:
@ -1344,26 +1344,66 @@ There is a shell script in the distribution called "entry", which
simplifies the task of adding a new entry to your ledger, and then simplifies the task of adding a new entry to your ledger, and then
launches =vi= to let you confirm that the entry looks appropriate. launches =vi= to let you confirm that the entry looks appropriate.
** Option summary ** Using command options
With all of the commands, various command-line options are allowed
that will modify the behavior of the command in some way. And while
the basic commands themselves are useful, you will often find
yourselves adding option flags to the command-line to modify those
commands.
The command-line options always occur before the command word. This
is done to distinguish them from the matching expressions that always
occur after the command word. The basic form of any command is:
<example>
ledger [OPTIONS] COMMAND [MATCH]
</example>
Both the OPTIONS and MATCH expressions are optional. You could, for
example, just use "ledger balance" without any modification. This
would print the summarized total of all account types. But to get
more specific reporting, or to change the way the output looks, you
must use the options.
*** Basic options *** Basic options
**-v** :: The =--help= (=-h=) option causes ledger to print a summary of all the
Display the version of ledger being used. options, and what they are used for. This can be a handy way to
remember which options do what. This help screen is also printed if
ledger is run without a command.
**-h** :: =--version= (=-v=) prints the current version of ledger and exits.
Print out quick help on the various options and commands. This is useful for sending bug reports (to johnw@newartisans.com), to
let the author know which version of ledger you are using.
**-f FILE[<verbatim>=</verbatim>ACCOUNT]** :: =--init FILE= (=-i FILE=) causes FILE to be read by ledger before any
Read ledger entries from FILE. This takes precedence over the other ledger file. This file may not contain any transactions, but it
environment variable LEDGER. If "<verbatim>=</verbatim>ACCOUNT" is may contain option settings. To specify options in the init file, use
appended to the filename, then all of the entries are seen as if the the same syntax as the command-line. Here's an example init file:
transactions accounts were prefixed by "ACCOUNT:". There may be
multiple occurrences of the =-f= option.
**-i FILE** :: <example>
Read in the list of patterns to include/exclude from FILE. --price-db ~/finance/.pricedb
Ordinarily, these are specified as arguments after the command. </example>
Option settings on the command-line or in the environment always take
precedence over settings in the init file.
=--file FILE= (=-f FILE=) reads FILE as a ledger file. This command
may be used multiple times. FILE may also be a list of file names
separated by colons. Typically, the environment variable
=LEDGER_FILE= is set, rather than using this command-line option.
=--cache FILE= identifies FILE as the default binary cache file. That
is, if the ledger files to be read are specified using the environment
variable =LEDGER_FILE=, then whenever a command is finished a binary
copy will be written to the specified cache, to speed up the loading
time of subsequent queries. This filename can also be given using the
environment variable =LEDGER_CACHE=, or by putting the option into
your init file.
=--output FILE= (=-o FILE=) redirects output from any command to
=FILE=. By default, all output goes to standard output.
*** Filtering options *** Filtering options
@ -1505,21 +1545,6 @@ launches =vi= to let you confirm that the entry looks appropriate.
use: -p "$=0.00280112 AU" (or whatever the current exchange rate use: -p "$=0.00280112 AU" (or whatever the current exchange rate
is). is).
** Environment variables
=LEDGER= ::
A colon-separated list of files to be parsed whenever ledger is run.
Easier than typing =-f= all the time.
=PRICE_HIST= ::
The ledger file used to hold pricing data. =~/.pricedb= would be a
good choice.
=PRICE_EXP= ::
The number of minutes before pricing data becomes out-of-date. The
default is one day. Use =-L= to temporarily decrease or increase
the value.
Footnotes: Footnotes:
[1] In some special cases, it will automatically balance the entry [1] In some special cases, it will automatically balance the entry
for you. for you.

View file

@ -13,8 +13,8 @@
namespace ledger { namespace ledger {
unsigned long binary_magic_number = 0xFFEED765; const unsigned long binary_magic_number = 0xFFEED765;
static unsigned long format_version = 0x0002000a; static const unsigned long format_version = 0x0002000b;
static std::vector<account_t *> accounts; static std::vector<account_t *> accounts;
static account_t::ident_t ident; static account_t::ident_t ident;
@ -82,7 +82,7 @@ void read_binary_amount(std::istream& in, amount_t& amt)
{ {
commodity_t::ident_t id; commodity_t::ident_t id;
read_binary_number(in, id); read_binary_number(in, id);
if (id == 0xffff) if (id == 0xffffffff)
amt.commodity = NULL; amt.commodity = NULL;
else else
amt.commodity = commodities[id]; amt.commodity = commodities[id];
@ -94,9 +94,7 @@ transaction_t * read_binary_transaction(std::istream& in, entry_t * entry)
{ {
transaction_t * xact = new transaction_t(entry, NULL); transaction_t * xact = new transaction_t(entry, NULL);
account_t::ident_t id; xact->account = accounts[read_binary_number<account_t::ident_t>(in)];
read_binary_number(in, id);
xact->account = accounts[id];
xact->account->add_transaction(xact); xact->account->add_transaction(xact);
read_binary_amount(in, xact->amount); read_binary_amount(in, xact->amount);
@ -131,10 +129,8 @@ commodity_t * read_binary_commodity(std::istream& in)
commodity_t * commodity = new commodity_t; commodity_t * commodity = new commodity_t;
commodities.push_back(commodity); commodities.push_back(commodity);
commodity_t::ident_t id; commodity->ident = read_binary_number<commodity_t::ident_t>(in);
read_binary_number(in, id); assert(commodity->ident == commodities.size() - 1);
commodity->ident = id;
assert(id == commodities.size() - 1);
read_binary_string(in, commodity->symbol); read_binary_string(in, commodity->symbol);
read_binary_string(in, commodity->name); read_binary_string(in, commodity->name);
@ -162,13 +158,12 @@ account_t * read_binary_account(std::istream& in, account_t * master = NULL)
account_t * acct = new account_t(NULL); account_t * acct = new account_t(NULL);
accounts.push_back(acct); accounts.push_back(acct);
account_t::ident_t id; acct->ident = read_binary_number<account_t::ident_t>(in);
read_binary_number(in, id); assert(acct->ident == accounts.size() - 1);
acct->ident = id;
assert(id == accounts.size() - 1);
account_t::ident_t id;
read_binary_number(in, id); // parent id read_binary_number(in, id); // parent id
if (id == 0xffff) if (id == 0xffffffff)
acct->parent = NULL; acct->parent = NULL;
else else
acct->parent = accounts[id]; acct->parent = accounts[id];
@ -289,7 +284,7 @@ void write_binary_amount(std::ostream& out, const amount_t& amt)
if (amt.commodity) if (amt.commodity)
write_binary_number(out, amt.commodity->ident); write_binary_number(out, amt.commodity->ident);
else else
write_binary_number<commodity_t::ident_t>(out, 0xffff); write_binary_number<commodity_t::ident_t>(out, 0xffffffff);
amt.write_quantity(out); amt.write_quantity(out);
} }
@ -349,7 +344,7 @@ void write_binary_account(std::ostream& out, account_t * account)
if (account->parent) if (account->parent)
write_binary_number(out, account->parent->ident); write_binary_number(out, account->parent->ident);
else else
write_binary_number<account_t::ident_t>(out, 0xffff); write_binary_number<account_t::ident_t>(out, 0xffffffff);
write_binary_string(out, account->name); write_binary_string(out, account->name);
write_binary_string(out, account->note); write_binary_string(out, account->note);

View file

@ -229,7 +229,7 @@ unsigned int parse_textual_journal(std::istream& in,
journal_t * ledger, journal_t * ledger,
account_t * master = NULL); account_t * master = NULL);
extern unsigned long binary_magic_number; extern const unsigned long binary_magic_number;
unsigned int read_binary_journal(std::istream& in, unsigned int read_binary_journal(std::istream& in,
journal_t * journal, journal_t * journal,

View file

@ -97,12 +97,16 @@ int main(int argc, char * argv[], char * envp[])
process_environment(envp, "LEDGER_"); process_environment(envp, "LEDGER_");
#if 1
// These are here until 3.x, for backwards compatability.
if (const char * p = std::getenv("LEDGER")) if (const char * p = std::getenv("LEDGER"))
process_option("file", p); process_option("file", p);
if (const char * p = std::getenv("PRICE_HIST")) if (const char * p = std::getenv("PRICE_HIST"))
process_option("price-db", p); process_option("price-db", p);
if (const char * p = std::getenv("PRICE_EXP")) if (const char * p = std::getenv("PRICE_EXP"))
process_option("price-exp", p); process_option("price-exp", p);
#endif
TIMER_STOP(process_env); TIMER_STOP(process_env);
@ -123,9 +127,11 @@ int main(int argc, char * argv[], char * envp[])
journal->sources.pop_front(); // remove cache_file journal->sources.pop_front(); // remove cache_file
strings_list exceptions; strings_list exceptions;
#if 0
std::set_difference(journal->sources.begin(), journal->sources.end(), std::set_difference(journal->sources.begin(), journal->sources.end(),
config->files.begin(), config->files.end(), config->files.begin(), config->files.end(),
exceptions.begin()); exceptions.begin());
#endif
if (entry_count == 0 || exceptions.size() > 0) { if (entry_count == 0 || exceptions.size() > 0) {
journal.reset(new journal_t); journal.reset(new journal_t);

38
util.h Normal file
View file

@ -0,0 +1,38 @@
#ifndef _UTIL_H
#define _UTIL_H
inline char * skip_ws(char * ptr) {
while (*ptr == ' ' || *ptr == '\t' || *ptr == '\n')
ptr++;
return ptr;
}
inline char peek_next_nonws(std::istream& in) {
char c = in.peek();
while (! in.eof() && std::isspace(c)) {
in.get(c);
c = in.peek();
}
return c;
}
#define READ_INTO(str, targ, size, var, cond) { \
char * _p = targ; \
var = str.peek(); \
while (! str.eof() && (cond)) { \
str.get(var); \
if (str.eof()) \
break; \
if (var == '\\') { \
str.get(var); \
if (in.eof()) \
break; \
} \
*_p++ = var; \
var = str.peek(); \
} \
assert(_p < targ + ((size) - 1)); \
*_p = '\0'; \
}
#endif // _UTIL_H