Added support for "--pager PROGRAM". A likely way to define it in

your login file would be: "export LEDGER_PAGER=$PAGER".
This commit is contained in:
John Wiegley 2005-02-14 08:27:53 +00:00
parent 219492564c
commit 8fd5f4ee57
3 changed files with 75 additions and 4 deletions

View file

@ -725,6 +725,10 @@ OPT_BEGIN(tail, ":") {
config.tail_entries = std::atoi(optarg);
} OPT_END(tail);
OPT_BEGIN(pager, ":") {
config.pager = optarg;
} OPT_END(pager);
OPT_BEGIN(empty, "E") {
config.show_empty = true;
} OPT_END(empty);

View file

@ -49,6 +49,7 @@ struct config_t
std::string forecast_limit;
std::string reconcile_balance;
std::string reconcile_date;
std::string pager;
unsigned long budget_flags;
unsigned long pricing_leeway;
int head_entries;

74
main.cc
View file

@ -15,10 +15,18 @@ using namespace ledger;
#include <exception>
#include <iterator>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#ifdef HAVE_UNIX_PIPES
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include "fdstream.hpp"
#endif
#if !defined(DEBUG_LEVEL) || DEBUG_LEVEL <= RELEASE
#define auto_ptr bogus_auto_ptr
@ -306,9 +314,57 @@ int parse_and_report(int argc, char * argv[], char * envp[])
// Configure the output stream
#ifdef HAVE_UNIX_PIPES
int status, pfd[2]; // Pipe file descriptors
#endif
std::ostream * out = &std::cout;
if (! config.output_file.empty())
if (! config.output_file.empty()) {
out = new std::ofstream(config.output_file.c_str());
}
#ifdef HAVE_UNIX_PIPES
else if (! config.pager.empty()) {
status = pipe(pfd);
if (status == -1)
throw error("Failed to create pipe");
status = fork();
if (status < 0) {
throw error("Failed to fork child process");
}
else if (status == 0) { // child
const char *arg0;
// Duplicate pipe's reading end into stdin
status = dup2(pfd[0], STDIN_FILENO);
if (status==-1)
perror("dup2");
// Close unuseful file descriptors: the pipe's writing and
// reading ends (the latter is not needed anymore, after the
// duplication).
close(pfd[1]);
close(pfd[0]);
// Find command name: its the substring starting right of the
// rightmost '/' character in the pager pathname. See manpage
// for strrchr.
arg0 = std::strrchr(config.pager.c_str(), '/');
if (arg0 != NULL)
arg0++;
else
arg0 = config.pager.c_str(); // No slashes in pager.
execlp(config.pager.c_str(), arg0, (char *)0);
perror("execl");
exit(1);
}
else { // parent
close(pfd[0]);
out = new boost::fdostream(pfd[1]);
}
}
#endif
// Compile the format strings
@ -446,7 +502,6 @@ def vmax(d, val):\n\
}
#if DEBUG_LEVEL >= BETA
clear_all_xdata();
if (! config.output_file.empty())
@ -458,8 +513,7 @@ def vmax(d, val):\n\
i++)
delete *i;
formatter_ptrs.clear();
#endif // DEBUG_LEVEL >= BETA
#endif
// Write out the binary cache, if need be
@ -468,6 +522,18 @@ def vmax(d, val):\n\
write_binary_journal(stream, journal.get());
}
#ifdef HAVE_UNIX_PIPES
if (! config.pager.empty()) {
delete out;
close(pfd[1]);
// Wait for child to finish
wait(&status);
if (status & 0xffff != 0)
throw error("Something went wrong in the pager");
}
#endif
return 0;
}