home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-11-02 | 43.2 KB | 1,404 lines |
- Newsgroups: comp.sources.misc
- From: pomeranz@aqm.com (Hal Pomeranz)
- Subject: v40i083: plod - keep track of the work you do, Part01/01
- Message-ID: <1993Nov2.234638.8003@sparky.sterling.com>
- Summary: Personal logging software
- X-Md4-Signature: d0f8a56c2dcd3d19998116a1a9edd94e
- Keywords: updated software
- Sender: kent@sparky.sterling.com (Kent Landfield)
- Organization: QMS Inc., Imagen Division
- Date: Tue, 2 Nov 1993 23:46:38 GMT
- Approved: kent@sparky.sterling.com
-
- Submitted-by: pomeranz@aqm.com (Hal Pomeranz)
- Posting-number: Volume 40, Issue 83
- Archive-name: plod/part01
- Environment: Perl
- Supersedes: plod: Volume 35, Issue 85
-
- PLOD is a Perl program designed to help folks keep a record of the
- work they do. Good journals help you solve recurring problems more
- quickly and impress the hell out of management around performance
- review time.
-
- The interface for PLOD looks a lot like Berkeley mail (tilde escapes
- and all). There's tons of customization switches, so check out
- the documentation.
-
- This version contains some enhancements based on feedback I received from
- the initial release, as well as a couple of Emacs modes for PLOD.
-
- Hal Pomeranz
- ------
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # Contents: README plod plod.el.v1 plod.el.v2 plod.man
- # Wrapped by kent@sparky on Tue Nov 2 17:39:16 1993
- PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 1 (of 1)."'
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(4069 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- XPLOD is a tool designed to help administrators (and others) keep track
- Xof their daily activities. Since your management will typically have
- Xno idea what you are doing to justify such an exorbitant salary (any
- Xamount of money they may be paying you being classified as
- X"exorbitant"), and since most people forget what they do themselves,
- Xit's good to keep a record. Trot your logs out around performance
- Xreview time, and show them to your management (after suitable
- Xsanitization) on a regular basis.
- X
- XThe interface is designed to make it quick to dash off a simple note
- Xto yourself. Since most folks who are going to use PLOD also use
- Xemail, I've based the interface on Berkeley mail-- tilde escapes and
- Xall (for a list of escapes, try ~h or ~?). By default, your logs will
- Xbe encrypted using the /bin/crypt command-- not secure in the least,
- Xbut marginally safe from casual browsing (I tend to vent into my logs
- Xsometimes rather than at those who might be offended and fire me).
- XYou can turn off the encryption if you find it more a hassle than a
- Xcomfort.
- X
- XWhich brings us to the subject of customization. Many escape
- Xsequences and variables have already been defined, but you can make
- Xyour own changes using your ~/.plodrc file. This file is interpreted
- Xusing eval(), so any valid Perl syntax is acceptable. Variables may
- Xbe customized by editing this script directly, setting an environment
- Xvariable with the same name as the PLOD variable, or by doing an
- Xassignment in your .plodrc (.plodrc value supersedes environment value
- Xwhich beats default value in script). New tilde escapes may be
- Xdefined by assigning a type glob, say *foo, to the global array
- X%funcs-- the index of the type glob in the array being the character
- X(single chars only!) of the escape sequence. &foo should be a
- Xfunction which performs the escape (any arguments after the escape are
- Xpassed in as a single string in @_), and $foo can be a descriptive
- Xhelp string (see &helpuser()). Your functions may reference any of
- Xthe PLOD customization variables as well as the list @lines, which
- Xcontains all information in the current log entry (including the
- Xdate/time stamp PLOD adds to the beginning of each entry). For
- Xexamples, consult the PLOD source code or the manual page.
- X
- XPLOD is a living, growing entity. If you have suggestions for
- Ximprovements or new features, or find any bugs, please send them to me
- Xvia email. Share and enjoy!
- X
- XHal Pomeranz, pomeranz@aqm.com
- X
- X===============================================================================
- X
- XHistory:
- X
- Xv1.0 (Original release to comp.lang.perl)
- X
- X
- Xv1.1 (Second release to comp.lang.perl)
- X** &pipetocmd() unlinks all temporary files it creates (Pomeranz)
- X
- X** Variable assignment idiom cleaned up (Rantapaa)
- X
- X** LOGDIR and HOME are only prepended to LOGFILE and DEADLOG after
- X .plodrc has been eval-ed and if LOGFILE and DEADLOG are relative
- X paths. This means that you can change LOGDIR in your .plodrc and
- X really affect where the log files go. (Rantapaa)
- X
- X** eval of .plodrc is done with "do" rather than "cat" (Rantapaa)
- X
- X** You can now do quick one-liner entries on the command line, e.g.
- X "plod Completed modifications to PLOD" (Rantapaa)
- X
- X** Time/date stamp only printed if user is entering info directly from
- X a tty (Rantapaa)
- X
- X** PLOD attempts to create logging directory if it does not exist (Ellis)
- X
- X
- Xv1.2 (not publicly released)
- X** Page/Edit/Visual log files from interactive mode or from the shell
- X (Tizard)
- X
- X
- Xv1.3 (comp.lang.perl again, and also comp.sources.misc)
- X** Multi-line Perl input function, ~M (Crabb)
- X
- X** Manual page generated (Pomeranz)
- X
- X
- Xv1.4 (not publicly released)
- X** Trap for empty log entries and don't add them to log file (Pomeranz)
- X
- X** -C flag to cat logfile to STDOUT (Prestemon)
- X
- X** /etc/plodrc (Lachowski)
- X
- X** $STAMP customization variable (Lachowski/Pomeranz)
- X
- X
- Xv1.5 (not publicly released)
- X** Trap for non-existant/zero size/non-executable CRYPTCMD
- X
- X
- Xv1.6 (current)
- X** Minor fix to above trap. Would have been part of v1.5 but I had already
- X distributed v1.5 to a few people.
- END_OF_FILE
- if test 4069 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test -f 'plod' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'plod'\"
- else
- echo shar: Extracting \"'plod'\" \(16947 characters\)
- sed "s/^X//" >'plod' <<'END_OF_FILE'
- X#!/usr/local/bin/perl
- X#
- X# PLOD-- Personal LOgging Device, v1.6
- X# Copyright (C), 1993, Hal Pomeranz (pomeranz@aqm.com)
- X# All rights reserved. No warranty expressed or implied.
- X# PLOD is freely distributable under the same terms as Perl.
- X# Inspired by Bill Mendyka (mendyka@dg-rtp.dg.com)
- X# Suggestions/Bugfixes:
- X# David W Crabb (crabb@phoenix.Princeton.EDU)
- X# John Ellis (ellis@rtsg.mot.com)
- X# Mike Lachowski (mlachow@erenj.com)
- X# Eric Prestemon (ecprest@pocorvares.er.usgs.GOV)
- X# Erik E. Rantapaa (rantapaa@math.umn.edu)
- X# James Tizard (james@ringo.ssn.flinders.edu.au)
- X#
- X######################### Begin Variable Declarations #########################
- X#
- X# All variables have default values which will be superceded by environment
- X# variables of the same name. The user's .plodrc is read after all other
- X# variable assignments, so any assignments there take precedence.
- X#
- X# Note that $LOGFILE and $DEADLOG are used as absolute pathnames. After
- X# the .plodrc has been evaluated, $LOGDIR or $HOME will be prepended to
- X# $LOGFILE and $DEADLOG respectively if either of these variables does not
- X# begin with a '/'.
- X#
- X# Set $CRYPTCMD to null if you don't want encryption to be performed.
- X#
- X# KEYVAL key value used by CRYPTCMD
- X# CRYPTCMD encryption command, set this to null for no encryption
- X# TMPFILE file name to use for temporary holding
- X# EDITOR editor called by ~e
- X# VISUAL editor called by ~v
- X# PAGER used by ~p and ~h when output longer than one page (see LINES)
- X# LINES number of lines on the screen
- X# LOGDIR directory containing log files
- X# LOGFILE absolute path of log file
- X# HOME user's home directory
- X# DEADLOG place to drop dead.log file on abort or ~q, also used by ~d
- X# STAMP time/date stamp printed at the top of each entry
- X
- X# Some variable values use date/time information
- X#
- X($ss, $mm, $hh, $DD, $MM, $YY) = localtime($^T); $MM++;
- X
- X$KEYVAL = sprintf("pl%d%dod", $YY, $MM);
- X$CRYPTCMD = "/bin/crypt";
- X$TMPFILE = "/tmp/plodtmp$$";
- X$HOME = (getpwuid($<))[7];
- X$EDITOR = "/usr/local/bin/emacs";
- X$VISUAL = "/usr/local/bin/emacs";
- X$PAGER = "/usr/local/bin/less";
- X$LINES = 24;
- X$LOGDIR = "$HOME/.logdir";
- X$LOGFILE = sprintf("%02d%02d", $YY, $MM);
- X$DEADLOG = "dead.log";
- X$STAMP = sprintf("%02d/%02d/%02d, %02d:%02d --", $MM, $DD, $YY, $hh, $mm);
- X
- X
- X########################## End Variable Declarations ##########################
- X######################### Begin Function Declarations #########################
- X
- X
- X# Printvar (~=): Output the value of one or more variables.
- X#
- Xsub printvar {
- X local($vars) = @_;
- X $, = ','; print eval "($vars)"; $, = '';
- X print "\n";
- X print "(continue composing note)\n";
- X}
- X$printvar = "\$var[, ...]\tOutput value of variables";
- X$funcs{'='} = *printvar;
- X
- X
- X# Bang (~!): Execute a command in the shell and then return to plod.
- X#
- Xsub bang {
- X local($cmdline) = @_;
- X system "$cmdline";
- X print "(continue composing note)\n";
- X}
- X$bang = "cmdline\tExecute system command and return";
- X$funcs{'!'} = *bang;
- X
- X
- X# Redirect (~>): Pipe the output of a command into the current buffer.
- X#
- Xsub redirect {
- X local($cmdline) = @_;
- X local($count);
- X if (!open(CMD, "$cmdline |")) {
- X warn "*** Unable to execute: $cmdline\n";
- X return;
- X }
- X &readit(CMD);
- X}
- X$redirect = "cmdline\tAdd output of given command to buffer";
- X$funcs{'>'} = *redirect;
- X
- X
- X# Pipetocmd (~|): Pipe the contents of the current buffer through a UNIX
- X# command line and replace the buffer with the result.
- X#
- Xsub pipetocmd {
- X local($cmdline) = @_;
- X local($header);
- X if (!open(PIPELN, "| $cmdline >$TMPFILE 2>&1")) { # output to tmp file
- X warn "*** Unable to execute: $cmdline\n";
- X return;
- X }
- X $header = shift @lines if ($STAMP); # don't include stamp
- X print PIPELN @lines;
- X close(PIPELN);
- X if (!open(INP, "<$TMPFILE")) {
- X warn "*** Unable to get command output\n";
- X unshift(@lines, $header);
- X unlink "$TMPFILE";
- X return;
- X }
- X undef @lines; # replace buffer with
- X @lines = <INP>; # contents of tmp file
- X close(INP);
- X unlink "$TMPFILE";
- X unshift(@lines, $header) if ($STAMP);
- X print "(continue composing note)\n";
- X}
- X$pipetocmd = "cmdline\tPipe contents of buffer through cmdline";
- X$funcs{'|'} = *pipetocmd;
- X
- X
- X# Perlit (~X): Execute Perl code.
- X#
- Xsub perlit {
- X local($code) = @_;
- X eval "$code";
- X warn $@ if $@;
- X print "(continue composing note)\n";
- X}
- X$perlit = "code\t\tExecute a line of Perl code";
- X$funcs{'X'} = *perlit;
- X
- X
- X# Longperl (~M): Edit then eval a multi-line Perl fragment
- X#
- Xsub longperl {
- X local($bogus) = @_;
- X return(&mistake) if ($bogus);
- X if (@code) {
- X if (!open(TMP, "> $TMPFILE")) {
- X warn "*** Unable to create temporary file\n";
- X return;
- X }
- X print TMP @code;
- X close(TMP);
- X }
- X system("$EDITOR $TMPFILE");
- X if (!open(TMP, "< $TMPFILE")) {
- X warn "*** Unable to read buffer\n";
- X return;
- X }
- X undef @code;
- X @code = <TMP>;
- X close(TMP);
- X system("/bin/rm -f $TMPFILE*");
- X eval "@code";
- X warn $@ if $@;
- X print "(continue composing note)\n";
- X}
- X$longperl = "\t\tInvoke \$EDITOR on command buffer, then execute as Perl code";
- X$funcs{'M'} = *longperl;
- X
- X
- X# Appendfl (~a): Append contents of buffer to a file and return to plod.
- X# To overwrite a file with the contents of the buffer, see &writefl().
- X#
- Xsub appendfl {
- X local($file) = @_;
- X if (!open(OUTP, ">> $file")) {
- X warn "*** Could not append to file $file\n";
- X return;
- X }
- X print OUTP @lines;
- X close(OUTP);
- X print "Wrote ", scalar(@lines), " lines to file $file\n";
- X print "(continue composing note)\n";
- X}
- X$appendfl = "file\t\tAppend contents of buffer to file";
- X$funcs{'a'} = *appendfl;
- X
- X
- X# Getdead (~d): Suck contents of DEADLOG file into buffer.
- X#
- Xsub getdead {
- X local($bogus) = @_;
- X return(&mistake) if ($bogus);
- X if (!open(DEAD, "<$DEADLOG")) {
- X warn "*** Unable to open $home/dead.log.\n";
- X return;
- X }
- X &readit(DEAD, "$DEADLOG");
- X}
- X$getdead = "\t\tIncorporate contents of \$DEADLOG into buffer";
- X$funcs{'d'} = *getdead;
- X
- X
- X# Editbuf (~e) and Visualbuf (~v): Call appropriate editor on buffer.
- X#
- Xsub editbuf {
- X local($bogus) = @_;
- X return(&mistake) if ($bogus);
- X &calledit($EDITOR);
- X}
- Xsub visualbuf {
- X local($bogus) = @_;
- X return(&mistake) if ($bogus);
- X &calledit($VISUAL);
- X}
- X$editbuf = "\t\tEdit buffer with \$EDITOR";
- X$visualbuf = "\t\tEdit buffer with \$VISUAL";
- X$funcs{'e'} = *editbuf;
- X$funcs{'v'} = *visualbuf;
- X
- X
- X# Editlog (~E) and Visuallog (~V): Call appropriate editor on LOGFILE.
- X#
- Xsub editlog {
- X local($args) = @_;
- X &logedit($EDITOR, $args);
- X print "(continue composing note)\n";
- X}
- Xsub visuallog {
- X local($args) = @_;
- X &logedit($VISUAL, $args);
- X print "(continue composing note)\n";
- X}
- X$editlog = "[file [key]]\tEdit LOGFILE [or older log] with \$EDITOR";
- X$visuallog = "[file [key]]\tEdit LOGFILE [or older log] with \$VISUAL";
- X$funcs{'E'} = *editlog;
- X$funcs{'l'} = *editlog;
- X$funcs{'V'} = *visuallog;
- X
- X
- X# Helpuser (~h or ~?): Output a list of tilde escapes with associated
- X# help messages (found in the scalar values of the type globs in %funcs).
- X# Use the defined PAGER if the output would be more than LINES long.
- X#
- Xsub helpuser {
- X $long = (scalar(keys %funcs) >= $LINES) && open(TMP, ">$TMPFILE");
- X for (sort keys %funcs) {
- X *info = $funcs{$_};
- X if ($long) {
- X print TMP "~$_ $info\n";
- X }
- X else { print "~$_ $info\n"; }
- X }
- X if ($long) {
- X close(TMP);
- X system("/bin/cat $TMPFILE | $PAGER");
- X unlink "$TMPFILE";
- X }
- X}
- X$helpuser = "\t\tPrint this message";
- X$funcs{'h'} = *helpuser;
- X$funcs{'?'} = *helpuser;
- X
- X
- X# Printout (~p): cat back the current buffer for review. Use PAGER if
- X# the buffer is longer than LINES.
- X#
- Xsub printout {
- X local($bogus) = @_;
- X return(&mistake) if ($bogus);
- X if (@lines < $LINES-1 || !open(TMP, ">$TMPFILE")) {
- X print "-----\n";
- X print @lines;
- X }
- X else {
- X print TMP @lines;
- X close(TMP);
- X system("/bin/cat $TMPFILE | $PAGER");
- X unlink "$TMPFILE";
- X }
- X print "(continue composing note)\n";
- X}
- X$printout = "\t\tView contents of buffer, one page at a time";
- X$funcs{'p'} = *printout;
- X
- X
- X# Pagelog (~P): Page contents of LOGFILE.
- X#
- Xsub pagelog {
- X local($args) = @_;
- X &pageit($args);
- X print "(continue composing note)\n";
- X}
- X$pagelog = "[file [key]]\tView contents of LOGFILE [or older log] with PAGER";
- X$funcs{'P'} = *pagelog;
- X$funcs{'L'} = *pagelog;
- X
- X
- X# Quitit (~q): Quit plod and attempt to save buffer in DEADLOG. Also
- X# called on SIGINT and SIGQUIT via &trapit().
- X#
- Xsub quitit {
- X local($bogus) = @_;
- X return(&mistake) if ($bogus);
- X open(DEAD, ">> $DEADLOG") || die "Can't open $DEADLOG\n";
- X print DEAD @lines;
- X close(DEAD);
- X exit;
- X}
- X$quitit = "\t\tQuit, attempts to save buffer in \$DEADLOG";
- X$funcs{'q'} = *quitit;
- X
- X
- X# Readfile (~r): Append contents of file into buffer.
- X#
- Xsub readfile {
- X local($file) = @_;
- X if (!open(INPT, "<$file")) {
- X warn "*** Unable to open $file.\n";
- X return;
- X }
- X &readit(INPT, $file);
- X}
- X$readfile = "file\t\tRead contents of file into buffer";
- X$funcs{'r'} = *readfile;
- X
- X
- X# Writefl (~w): Overwrite file with contents of buffer. To append to a
- X# given file, see &appendfl().
- X#
- Xsub writefl {
- X local($file) = @_;
- X if (!open(OUTP, "> $file")) {
- X warn "*** Could not write to file $file\n";
- X return;
- X }
- X print OUTP @lines;
- X close(OUTP);
- X print "Wrote ", scalar(@lines), " lines to file $file\n";
- X print "(continue composing note)\n";
- X}
- X$writefl = "file\t\tOverwrite file with contents of buffer";
- X$funcs{'w'} = *writefl;
- X
- X
- X# Exitnow (~x): Exit plod without writing to DEADLOG or LOGFILE.
- X#
- Xsub exitnow {
- X local($bogus) = @_;
- X return(&mistake) if ($bogus);
- X exit;
- X}
- X$exitnow = "\t\tExit without saving buffer";
- X$funcs{'x'} = *exitnow;
- X
- X
- X########################## End Function Declarations ##########################
- X############################# Begin Main Program ##############################
- X
- X
- X# Check for /etc/plodrc and ~/.plodrc and eval() contents. Exit with an
- X# error message if eval() complains for any reason. Environment supercedes
- X# /etc/plodrc but is overridden by ~/.plodrc.
- X#
- Xif (-e "/etc/plodrc") {
- X eval { do "/etc/plodrc"; };
- X die "*** Error in /etc/plodrc:\n$@" if $@;
- X}
- X
- X$CRYPTCMD = $ENV{'CRYPTCMD'} if (defined($ENV{'CRYPTCMD'}));
- X$DEADLOG = $ENV{'DEADLOG'} if ($ENV{'DEADLOG'});
- X$EDITOR = $ENV{'EDITOR'} if ($ENV{'EDITOR'});
- X$HOME = $ENV{'HOME'} if ($ENV{'HOME'});
- X$KEYVAL = $ENV{'KEYVAL'} if ($ENV{'KEYVAL'});
- X$LINES = $ENV{'LINES'} if ($ENV{'LINES'});
- X$LOGDIR = $ENV{'LOGDIR'} if ($ENV{'LOGDIR'});
- X$LOGFILE = $ENV{'LOGFILE'} if ($ENV{'LOGFILE'});
- X$PAGER = $ENV{'PAGER'} if ($ENV{'PAGER'});
- X$STAMP = $ENV{'STAMP'} if (defined($ENV{'STAMP'}));
- X$TMPFILE = $ENV{'TMPFILE'}if ($ENV{'TMPFILE'});
- X$VISUAL = $ENV{'VISUAL'} if ($ENV{'VISUAL'});
- X
- Xif (-e "$HOME/.plodrc") {
- X eval { do "$HOME/.plodrc"; };
- X die "*** Error in $HOME/.plodrc:\n$@" if $@;
- X}
- X
- X# You can lose your log file if CRYPTCMD is set, but the executable
- X# doesn't actually exist.
- X#
- Xdie "There's something wrong with $CRYPTCMD-- I can't deal!\n"
- X if ($CRYPTCMD && !(-e "$CRYPTCMD" && -x _ && -f _ && -s _));
- X
- X# Prepend parent directories unless we have explicit pathnames
- X#
- X$LOGFILE = "$LOGDIR/$LOGFILE" unless ($LOGFILE =~ /^\//);
- X$DEADLOG = "$HOME/$DEADLOG" unless ($DEADLOG =~ /^\//);
- X
- X# Extract dirname from $LOGFILE and make sure it exists
- X#
- X($dirname = $LOGFILE) =~ s,/[^/]*$,,;
- Xif (!(-d $dirname)) {
- X warn "Attempting to create logging directory, $dirname\n";
- X die "Attempt failed!\n" unless (mkdir($dirname, 0700));
- X}
- X
- X# Jam time/date stamp into buffer...
- X#
- Xpush(@lines, "$STAMP\n") if ($STAMP);
- X
- X# Log entry can appear on the command line, otherwise loop until end of
- X# STDIN or '.' recognized on a line by itself.
- X#
- Xif ($ARGV[0] eq "-P") { shift @ARGV; &pageit("@ARGV"); exit; }
- Xelsif ($ARGV[0] eq "-E") { shift @ARGV; &logedit($EDITOR, "@ARGV"); exit; }
- Xelsif ($ARGV[0] eq "-V") { shift @ARGV; &logedit($VISUAL, "@ARGV"); exit; }
- Xelsif ($ARGV[0] eq "-C") {
- X shift @ARGV;
- X $file = (shift @ARGV) || $LOGFILE;
- X $file = "$LOGDIR/$file" unless ($file =~ /^\//);
- X $key = (shift @ARGV) || $KEYVAL;
- X $cmd = $CRYPTCMD ? "$CRYPTCMD $key < $file" : "/bin/cat $file";
- X system("$cmd");
- X exit;
- X}
- Xelsif (@ARGV) { push(@lines, "@ARGV\n"); }
- Xelse {
- X if (-t STDIN) {
- X print "$STAMP\n" if ($STAMP);
- X $SIG{'QUIT'} = trapit;
- X $SIG{'INT'} = trapit;
- X }
- X while (<STDIN>) {
- X if (/^~/) { # escape sequence:
- X ($esc, $args) = /^~(\S)\s*(.*)$/; # 1) parse line
- X *glob = $funcs{$esc}; # 2) unpack type glob
- X if (!defined(&glob)) { # 3) check defined()
- X warn "Unrecognized escape sequence: ~$esc\n";
- X next;
- X }
- X &glob($args); # 4) call func w/ args
- X }
- X elsif (/^\.\s*$/) { # lone dot means end
- X print "(eot)\n"; # of log entry
- X last;
- X }
- X else { # else append line to
- X push(@lines, $_); # log buffer
- X }
- X }
- X}
- X
- X# Drop out if buffer is empty. Append a final newline if one isn't there.
- X#
- Xif (!@lines || (@lines == 1 && $STAMP)) {
- X warn "*** Empty log entry not added to log file\n";
- X exit;
- X}
- X$lines[$#lines] = "$lines[$#lines]\n" unless ($lines[$#lines] =~ /\n$/);
- X
- X# Completed log entry now in @lines. If using encryption, call encryption
- X# command to decrypt previous log entries (if present). If not encrypting,
- X# simply open log file to append.
- X#
- Xif ($CRYPTCMD) { # encrypting
- X if (-e "$LOGFILE") {
- X system "$CRYPTCMD $KEYVAL <$LOGFILE >$TMPFILE";
- X }
- X if (!open(LOGFILE, ">> $TMPFILE")) {
- X unlink "$TMPFILE";
- X warn "*** Unable to append new log entry\n";
- X &quitit();
- X }
- X}
- Xelse { # not encyrpting
- X if (!open(LOGFILE, ">> $LOGFILE")) {
- X warn "*** Unable to append new log entry\n";
- X &quitit();
- X }
- X}
- X
- X# Dump contents of buffer into plain text file.
- X#
- Xprint LOGFILE "-----\n";
- Xprint LOGFILE @lines;
- Xclose(LOGFILE);
- X
- X# If encrypting, replace old log file with new version. Unlink plain
- X# text temporary file when done.
- X#
- Xif ($CRYPTCMD) {
- X unlink "$LOGFILE";
- X system "$CRYPTCMD $KEYVAL <$TMPFILE >$LOGFILE";
- X chmod 0600, "$LOGFILE";
- X unlink "$TMPFILE";
- X}
- X
- X
- X############################## End Main Program ###############################
- X########################### Miscellaneous Functions ###########################
- X
- X
- X# Append contents of file $fname (associated with file handle $fh) to buffer.
- X# Assume $fh is a pipe if $fname is null. This function called by many tilde
- X# escapes.
- X#
- Xsub readit {
- X local($fh, $fname) = @_;
- X push(@lines, <$fh>);
- X print STDOUT ($fname) ? "$fname: " : "Added ";
- X print STDOUT "$. lines";
- X print STDOUT ($fname) ? "\n" : " to buffer.\n";
- X print STDOUT "(continue composing note)\n";
- X close($fh);
- X}
- X
- X
- X# Call the editor $_[0] on the contents of the buffer. Used by &editbuf()
- X# and &visualbuf().
- X#
- Xsub calledit {
- X local($edit) = @_;
- X if (!open(EDIT, ">$TMPFILE")) {
- X warn "*** Unable to create file for editing\n";
- X return;
- X }
- X print EDIT @lines;
- X close(EDIT);
- X chmod 0600, "$TMPFILE";
- X system "$edit $TMPFILE";
- X if (!open(EDIT, "<$TMPFILE")) {
- X warn "*** Unable to read changes, returning to previous state.\n";
- X system "/bin/rm -f $TMPFILE*";
- X return;
- X }
- X undef @lines;
- X @lines = <EDIT>;
- X close(EDIT);
- X system "/bin/rm -f $TMPFILE*";
- X print "(continue composing note)\n";
- X}
- X
- X
- X# Call the appropriate editor on a log file. Used by &editlog and &visualedit.
- X#
- Xsub logedit {
- X local($edit, $args) = @_;
- X local($file, $key) = split(/\s+/, $args);
- X $key = $key || $KEYVAL;
- X $file = $file || $LOGFILE;
- X $file = "$LOGDIR/$file" unless ($file =~ /^\//);
- X if ($CRYPTCMD) {
- X if (!(-e "$file")) {
- X warn "*** $file does not exist\n";
- X return;
- X }
- X system("$CRYPTCMD $key <$file >$TMPFILE");
- X chmod 0600, "$TMPFILE";
- X system("$edit $TMPFILE");
- X if (!(-e "$TMPFILE") || -z _) {
- X warn "*** Modified file is empty-- restoring old version\n";
- X unlink "$TMPFILE";
- X return;
- X }
- X unlink "$file";
- X system "$CRYPTCMD $key <$TMPFILE >$file";
- X chmod 0600, "$file";
- X unlink "$TMPFILE";
- X }
- X else { system("$edit $file"); }
- X}
- X
- X
- X# Page a log file.
- X#
- Xsub pageit {
- X local($args) = @_;
- X local($file, $key) = split(/\s+/, $args);
- X local($cmd);
- X $key = $key || $KEYVAL;
- X $file = $file || $LOGFILE;
- X $file = "$LOGDIR/$file" unless ($file =~ /^\//);
- X $cmd = $CRYPTCMD ? "$CRYPTCMD $key < $file" : "/bin/cat $file";
- X system("$cmd | $PAGER");
- X}
- X
- X
- X# Generic warning message called by all escapes that do not expect arguments
- X# when @_ is not empty.
- X#
- Xsub mistake {
- X warn "*** Arguments are not expected for this escape.\n";
- X}
- X
- X
- X# Wrapper for &quitit()-- called on SIGINT and SIGQUIT. Wrapper required
- X# because signal handlers get the signal as an argument and &quitit() does
- X# not appreciate arguments.
- X#
- Xsub trapit {
- X &quitit();
- X}
- END_OF_FILE
- if test 16947 -ne `wc -c <'plod'`; then
- echo shar: \"'plod'\" unpacked with wrong size!
- fi
- chmod +x 'plod'
- # end of 'plod'
- fi
- if test -f 'plod.el.v1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'plod.el.v1'\"
- else
- echo shar: Extracting \"'plod.el.v1'\" \(3523 characters\)
- sed "s/^X//" >'plod.el.v1' <<'END_OF_FILE'
- XNewsgroups: comp.lang.perl
- XFrom: paul@ascent.com (Paul Foley)
- XSubject: Emacs interface to PLOD
- XMessage-ID: <PAUL.93Jan21125701@MountRushmore.ascent.com>
- XDate: 21 Jan 93 12:57:01
- XOrganization: Ascent Technology, Inc., Cambridge Massachusetts
- XLines: 119
- X
- XHere is an emacs-lisp interface to PLOD --- the Personal LOgging
- XDevice posted to comp.lang.perl a few days ago.
- X
- XSimplest way to use is M-x plod.
- X
- XThere is also an "alarm" interface that will switch you to a PLOD
- Xbuffer every so often, in case you forget to invoke it yourself.
- X
- XEnjoy.
- X
- X------------------------------------------------------------------
- X
- X;;;;
- X;;;; plod.el
- X;;;;
- X;;;; Emacs interface to PLOD --- A (Perl) tool to keep track of the work you do
- X;;;; PLOD was written by pomeranz@aqm.com (Hal R. Pomeranz).
- X;;;;
- X;;;; This software is FREE to all and may be used for any purpose as long as this
- X;;;; notice remains intact. The author does not assume responsibility for anything.
- X;;;;
- X;;;; Suggested addition to .emacs:
- X;;;; (load-library "plod")
- X;;;; (plod-alarm-on 60) ; once an hour
- X;;;;
- X;;;; When you are tired of PLODding use "M-x plod-alarm-off"
- X;;;;
- X;;;; Alternately, use "M-x plod" whenever you want to log something.
- X;;;;
- X;;;; paul@ascent.com (Paul Foley) Wednesday January 20, 1993
- X
- X(require 'shell)
- X
- X;;;
- X;;; Variables
- X;;;
- X
- X;; Name of executable --- should be in your $PATH
- X(defvar plod-program-name "plod")
- X(defvar plod-buffer-name "*PLOD*")
- X
- X;;;
- X;;; Manual Interface
- X;;;
- X
- X(defvar plod-buffer-process nil)
- X
- X;; Interactive command to invoke PLOD in a shell-mode buffer.
- X;;
- X
- X(defun plod ()
- X "Invoke PLOD."
- X (interactive)
- X ; restart PLOD if necessary
- X (if (not (get-buffer-process plod-buffer-name))
- X (setq plod-buffer-process (start-process "plod-process" plod-buffer-name plod-program-name)))
- X (switch-to-buffer plod-buffer-name t)
- X (if (not (eq major-mode 'shell-mode)) (shell-mode)))
- X
- X
- X;;;
- X;;; Alarm interface
- X;;;
- X
- X(defvar plod-alarm-on-p nil) ; t if alarm is on
- X(defvar plod-alarm-process nil)
- X
- X;; run when plod-alarm-process is killed
- X(defun plod-alarm-sentinel (proc reason)
- X (or (eq (process-status proc) 'run)
- X (setq plod-alarm-on-p nil)
- X (ding)
- X (message "PLOD alarm off")))
- X
- X;; run every interval & at initial call to plod-alarm-on
- X(defun plod-alarm-filter (proc string)
- X (if plod-alarm-on-p
- X (plod)
- X (setq plod-alarm-on-p t)))
- X
- X;; Set alarm to call PLOD every so often
- X;;
- X(defun plod-alarm-on (interval)
- X "Turn the Emacs PLOD alarm on. The alarm goes off every INTERVAL minutes
- Xand you will be switched to the PLOD buffer automatically.
- XUse plod-alarm-off to stop this behaviour."
- X (interactive "nEnter PLOD alarm interval (in minutes): ")
- X (let ((live (and plod-alarm-process
- X (eq (process-status plod-alarm-process) 'run))))
- X (if (not live)
- X (progn
- X (setq plod-alarm-on-p nil)
- X (if plod-alarm-process
- X (delete-process plod-alarm-process))
- X (let ((process-connection-type nil))
- X (setq plod-alarm-process
- X (start-process "plod-alarm" nil
- X (concat exec-directory "wakeup")
- X ; convert minutes -> seconds for wakeup
- X (int-to-string (* 60 interval)))))
- X (process-kill-without-query plod-alarm-process)
- X (set-process-sentinel plod-alarm-process 'plod-alarm-sentinel)
- X (set-process-filter plod-alarm-process 'plod-alarm-filter)))))
- X
- X;; Turn PLOD alarm off
- X;;
- X(defun plod-alarm-off ()
- X "Turn the Emacs PLOD alarm off."
- X (interactive)
- X (if plod-alarm-on-p (kill-process plod-alarm-process)))
- X
- X;;; End
- X--
- Xpaul@ascent.com
- X...!uunet!ascent!paul
- X
- X
- X
- X
- X
- X
- END_OF_FILE
- if test 3523 -ne `wc -c <'plod.el.v1'`; then
- echo shar: \"'plod.el.v1'\" unpacked with wrong size!
- fi
- # end of 'plod.el.v1'
- fi
- if test -f 'plod.el.v2' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'plod.el.v2'\"
- else
- echo shar: Extracting \"'plod.el.v2'\" \(5558 characters\)
- sed "s/^X//" >'plod.el.v2' <<'END_OF_FILE'
- X;; Plod sending commands for Emacs.
- X
- X;; This file is not part of GNU Emacs.
- X
- X;; GNU Emacs is free software; you can redistribute it and/or modify
- X;; it under the terms of the GNU General Public License as published by
- X;; the Free Software Foundation; either version 1, or (at your option)
- X;; any later version.
- X
- X;; GNU Emacs is distributed in the hope that it will be useful,
- X;; but WITHOUT ANY WARRANTY; without even the implied warranty of
- X;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X;; GNU General Public License for more details.
- X
- X;; You should have received a copy of the GNU General Public License
- X;; along with GNU Emacs; see the file COPYING. If not, write to
- X;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- X
- X;; Suggested addition to .emacs:
- X;; (load-library "plod-mode")
- X;; (plod-alarm-on 60) ; once an hour
- X;;
- X;; When you are tired of PLODding use "M-x plod-alarm-off"
- X;;
- X;; Alternately, use "M-x plod" whenever you want to log something.
- X;;
- X;; paul@ascent.com (Paul Foley) Wednesday January 20, 1993
- X;; paulh@harlequin.com (Paul Hudson) Later in 1993 (I forget when :-)
- X
- X
- X(provide 'plod)
- X
- X(defvar send-plod-function 'plod-send-it
- X "Function to call to send the current buffer as plod.")
- X
- X(defvar plod-mode-map nil)
- X
- X(defun plod-mode ()
- X "Major mode for editing text to be sent to plod.
- XLike Text Mode but with these additional commands:
- XC-c C-s plod-send (send the message) C-c C-c plod-send-and-exit"
- X (interactive)
- X (kill-all-local-variables)
- X (make-local-variable 'plod-reply-buffer)
- X (setq plod-reply-buffer nil)
- X (set-syntax-table text-mode-syntax-table)
- X (use-local-map plod-mode-map)
- X (setq local-abbrev-table text-mode-abbrev-table)
- X (setq major-mode 'plod-mode)
- X (setq mode-name "Plod")
- X (setq buffer-offer-save t)
- X (run-hooks 'text-mode-hook 'plod-mode-hook))
- X
- X(if plod-mode-map
- X nil
- X (setq plod-mode-map (make-sparse-keymap))
- X (define-key plod-mode-map "\C-c?" 'describe-mode)
- X (define-key plod-mode-map "\C-c\C-c" 'plod-send-and-exit)
- X (define-key plod-mode-map "\C-c\C-s" 'plod-send))
- X
- X(defun plod-send-and-exit (arg)
- X "Send message like plod-send, then, if no errors, exit from plod buffer.
- XPrefix arg means don't delete this window."
- X (interactive "P")
- X (plod-send)
- X (bury-buffer (current-buffer))
- X (if (and (not arg)
- X (not (one-window-p)))
- X (delete-window)
- X (switch-to-buffer (other-buffer (current-buffer)))))
- X
- X(defun plod-send ()
- X "Send the message in the current buffer to plod."
- X (interactive)
- X (message "Sending...")
- X (funcall send-plod-function)
- X (set-buffer-modified-p nil)
- X (delete-auto-save-file-if-necessary)
- X (message "Sending...done"))
- X
- X(defun plod-send-it ()
- X (let ((tembuf (generate-new-buffer " plod temp"))
- X (plodbuf (current-buffer)))
- X (unwind-protect
- X (call-process-region (point-min) (point-max)
- X (if (boundp 'plod-program)
- X plod-program
- X "/usr/local/bin/plod")
- X nil tembuf nil)
- X (kill-buffer tembuf))))
- X
- X
- X(defun plod (&optional noerase)
- X "Edit a message to be sent. Argument means resume editing (don't erase).
- XReturns with message buffer selected; value t if message freshly initialized.
- XWhile editing message, type C-c C-c to send the message and exit.
- X
- X\\{plod-mode-map}
- X
- XIf plod-setup-hook is bound, its value is called with no arguments
- Xafter the message is initialized. "
- X (interactive "P")
- X (switch-to-buffer "*plod*")
- X (setq default-directory (expand-file-name "~/"))
- X (auto-save-mode auto-save-default)
- X (plod-mode)
- X (and (not noerase)
- X (or (not (buffer-modified-p))
- X (y-or-n-p "Unsent message being composed; erase it? "))
- X (progn (erase-buffer)
- X (set-buffer-modified-p nil)
- X (run-hooks 'plod-setup-hook)
- X t)))
- X
- X(defun plod-other-window (&optional noerase)
- X "Like `plod' command, but display plod buffer in another window."
- X (interactive "P")
- X (let ((pop-up-windows t))
- X (pop-to-buffer "*plod*"))
- X (plod noerase))
- X
- X
- X;;;
- X;;; Alarm interface
- X;;;
- X
- X(defvar plod-alarm-on-p nil) ; t if alarm is on
- X(defvar plod-alarm-process nil)
- X
- X;; run when plod-alarm-process is killed
- X(defun plod-alarm-sentinel (proc reason)
- X (or (eq (process-status proc) 'run)
- X (setq plod-alarm-on-p nil)
- X (ding)
- X (message "PLOD alarm off")))
- X
- X;; run every interval & at initial call to plod-alarm-on
- X(defun plod-alarm-filter (proc string)
- X (if plod-alarm-on-p
- X (plod)
- X (setq plod-alarm-on-p t)))
- X
- X;; Set alarm to call PLOD every so often
- X;;
- X(defun plod-alarm-on (interval)
- X "Turn the Emacs PLOD alarm on. The alarm goes off every INTERVAL minutes
- Xand you will be switched to the PLOD buffer automatically.
- XUse plod-alarm-off to stop this behaviour."
- X (interactive "nEnter PLOD alarm interval (in minutes): ")
- X (let ((live (and plod-alarm-process
- X (eq (process-status plod-alarm-process) 'run))))
- X (if (not live)
- X (progn
- X (setq plod-alarm-on-p nil)
- X (if plod-alarm-process
- X (delete-process plod-alarm-process))
- X (let ((process-connection-type nil))
- X (setq plod-alarm-process
- X (start-process "plod-alarm" nil
- X (concat exec-directory "wakeup")
- X ; convert minutes -> seconds for wakeup
- X (int-to-string (* 60 interval)))))
- X (process-kill-without-query plod-alarm-process)
- X (set-process-sentinel plod-alarm-process 'plod-alarm-sentinel)
- X (set-process-filter plod-alarm-process 'plod-alarm-filter)))))
- X
- X;; Turn PLOD alarm off
- X;;
- X(defun plod-alarm-off ()
- X "Turn the Emacs PLOD alarm off."
- X (interactive)
- X (if plod-alarm-on-p (kill-process plod-alarm-process)))
- X
- X;;; End
- X
- X
- END_OF_FILE
- if test 5558 -ne `wc -c <'plod.el.v2'`; then
- echo shar: \"'plod.el.v2'\" unpacked with wrong size!
- fi
- # end of 'plod.el.v2'
- fi
- if test -f 'plod.man' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'plod.man'\"
- else
- echo shar: Extracting \"'plod.man'\" \(9043 characters\)
- sed "s/^X//" >'plod.man' <<'END_OF_FILE'
- X.nh
- X.de Sp
- X.if t .sp .5v
- X.if n .sp
- X..
- X.de Ip
- X.br
- X.ie \\n.$>=3 .ne \\$3
- X.el .ne 3
- X.IP "\\$1" \\$2
- X..
- X.TH PLOD 1 "2 February 1993" "PLOD"
- X.SH NAME
- XPLOD \- keep a log of your work
- X.SH SYNOPSIS
- X.B plod
- X\ [\ \fIone line message\fR\ ]
- X.br
- X.B plod
- X\ \fB-E\fR|\fB-P\fR|\fB-V\fR\ [\ \fIlogfile\fR\ [\ \fIkey\fR\ ]]
- X.SH DESCRIPTION
- X\fBPLOD\fR
- Xis a tool developed to help System/Network Administrators (and others)
- Xkeep track of the work that they do. Good logs are useful both as a
- Xpersonal reference and to show to your management on a regular basis
- Xor around performance review time. By default, logs will be stored in
- Xan encrypted format in the directory \fI$HOME/.logdir\fR, but this
- Xbehavior is completely customizable (see \fBENVIRONMENT\fR and
- X\fBCUSTOMIZATION\fR below).
- X
- XThe first form of the command will enter a short message on the command
- Xline into your log file. If no message is present on the command line,
- Xa date/time stamp will be printed and \fBPLOD\fR
- Xwill go into an interactive mode reminiscent of BSD mail. Many tilde
- Xescape sequences are supported (see \fBCOMMANDS\fR below or type
- X\fI~h\fR or \fI~?\fR within interactive mode). Enter a period on a
- Xline by itself to end your log entry.
- X
- XThe second mode allows you to review or edit your old log files. The
- X\fB-P\fR option invokes the default \fBPAGER\fR defined in the \fBPLOD\fR
- Xsource, or as defined in your environment, on the current log file. The
- X\fB-E\fR and \fB-V\fR flags invoke \fBEDITOR\fR and \fBVISUAL\fR respectively.
- XOlder log files may be accessed by specifying a file name and optional
- Xencryption key on the command line.
- X
- X.SH ENVIRONMENT
- X\fBPLOD\fR supports a number of variables which can be modified to customize
- Xits behavior. The values of these variables may be changed by editing
- X\fBPLOD\fR directly, by assignment in a system-wide startup file,
- Xby creating an environment variable, or by assignment
- Xin the user's startup file (see \fBCUSTOMIZATION\fR below). \fBPLOD\fR
- Xrecognizes the following environment variables:
- X.Ip "\fBSTAMP\fR" 4
- XThe time/date stamp entered into every log entry. Set this to null if you
- Xdo not wish to datestamp your logs. Default is \fIMM/DD/YY, HH:MM --\fR.
- X.Sp
- X.Ip "\fBEDITOR\fR" 4
- XThe user's preferred editor (used by the \fB-E\fR command line flag and the
- X\fB~e\fR, \fB~E\fR, and \fB~M\fR escape sequences). Default is
- X\fI/usr/local/bin/emacs\fR.
- X.Sp
- X.Ip "\fBVISUAL\fR" 4
- XThe user's preferred visual editor (used by \fB-V\fR, \fB~v\fR, and \fB~V\fR).
- XDefault is \fI/usr/local/bin/emacs\fR.
- X.Sp
- X.Ip "\fBPAGER\fR" 4
- XThe user's preferred pager (used by \fB-P\fR, \fB~p\fR, and \fB~P\fR).
- XDefault is \fI/usr/local/bin/less\fR.
- X.Sp
- X.Ip "\fBLINES\fR" 4
- XThe number of lines on the current display. Used to determine when the
- X\fBPAGER\fR needs to be invoked. Default is \fI24\fR.
- X.Sp
- X.Ip "\fBCRYPTCMD\fR" 4
- XThe encryption command to be used. If you do not wish to encrypt your
- Xlog files, set this to null. The standard UNIX \fBcrypt\fR command is
- Xnot in the least secure, but does provide protection from casual browsing.
- XDefault is \fI/bin/crypt\fR.
- X.Sp
- X.Ip "\fBKEYVAL\fR" 4
- XThe key to be used with \fBCRYPTCMD\fR. Default is \fIpl<yr><mn>od\fR.
- X.Sp
- X.Ip "\fBLOGDIR\fR" 4
- XWhere log files are placed. Default is \fI$HOME/.logdir\fR.
- X.Sp
- X.Ip "\fBLOGFILE\fR" 4
- XThe name of the current log file. \fBLOGDIR\fR will be prepended to this
- Xvalue if \fBLOGFILE\fR does not begin with a \fI/\fR. Default is
- X\fI<yr><mn>\fR.
- X.Sp
- X.Ip "\fBHOME\fR" 4
- XThe user's home directory. Default taken from user's password entry.
- X.Sp
- X.Ip "\fBDEADLOG\fR" 4
- XWhere interrupted log entries are placed. \fBHOME\fR will be prepended
- Xto this value if \fBDEADLOG\fR does not begin with a \fI/\fR. Default
- Xis \fIdead.log\fR.
- X.Sp
- X.Ip "\fBTMPFILE\fR" 4
- XScratch file used throughout execution of program. Default is
- X\fI/tmp/plodtmp<pid>\fR.
- X.Sp
- X
- X.SH COMMANDS
- XMany tilde escape sequences are supported under \fBPLOD\fR's interactive
- Xmode. Users may also define their own escape sequences in \fBPLOD\fR's
- Xinitialization file (see \fBCUSTOMIZATION\fR below). Currently defined
- Xsequences are:
- X.Ip "~h, ~?" 8
- XShow a list of all escape sequences with a short usage message.
- X.Sp
- X.Ip "~= var[, ...]" 8
- XDisplay the current value of one or more variables.
- X.Ip ~e 8
- XEdit the current buffer with \fB$EDITOR\fR.
- X.Sp
- X.Ip ~v 8
- XEdit the current buffer with \fB$VISUAL\fR.
- X.Sp
- X.Ip ~p 8
- XDisplay the contents of the current buffer (using \fB$PAGER\fR if necessary).
- X.Sp
- X.Ip "~V [\ logfile\ [\ key\ ]]" 8
- XCall \fB$VISUAL\fR on the current log file, or on some other log file as
- Xspecified. An additional encryption key may also be supplied.
- X.Sp
- X.Ip "~E, ~l [\ logfile\ [\ key\ ]]" 8
- XSimilar to ~E except that \fB$EDITOR\fR is used.
- X.Sp
- X.Ip "~P, ~L [\ logfile\ [\ key\ ]]" 8
- XSame as ~E and ~V except that \fB$PAGER\fR is invoked.
- X.Sp
- X.Ip ~q 8
- XQuit \fBPLOD\fR, saving contents of buffer into \fB$DEADLOG\fR.
- X.Sp
- X.Ip ~x 8
- XQuit without attempting to save buffer.
- X.Sp
- X.Ip ~d 8
- XAppend contents of \fB$DEADLOG\fR to current buffer.
- X.Sp
- X.Ip "~r somefile" 8
- XAppend contents of file to current buffer.
- X.Sp
- X.Ip "~a somefile" 8
- XAppend contents of current buffer to file.
- X.Sp
- X.Ip "~w somefile" 8
- XOverwrite file with contents of current buffer.
- X.Sp
- X.Ip "~X Perl-code" 8
- XExecute a line of Perl code.
- X.Sp
- X.Ip ~M 8
- XInvoke \fB$EDITOR\fR and execute resulting file as Perl code. Each successive
- Xinvocation of this escape will edit the previously executed Perl code so as
- Xto make it easier to go back and correct small errors.
- X.Sp
- X.Ip "~! command" 8
- XExecute a command in the shell and return.
- X.Sp
- X.Ip "~> command" 8
- XAppend the output of a command to the current buffer.
- X.Sp
- X.Ip "~| command" 8
- XPipe the current buffer through a command and replace the buffer with the
- Xresulting output.
- X.Sp
- X
- X.SH CUSTOMIZATION
- XLike most UNIX utilities, \fBPLOD\fR has an initialization file,
- Xthe \fI\.plodrc\fR,
- Xwhich is read at startup. Unlike most UNIX utilities,
- Xthis file is interpreted as Perl code. Thus, if you wished to assign
- Xa new value to a customization variable you would use the syntax
- X.RS
- X.PP
- X$LOGDIR = "$HOME/mylogs";
- X.RE
- X.PP
- X\fBPLOD\fR also looks for a system-wide customization file, \fI/etc/plodrc\fR.
- XThe order of evaluation is: hard coded defaults in \fBPLOD\fR, then
- Xthe \fI/etc/plodrc\fR file, then the user's environment, and finally the
- Xuser's \fI\.plodrc\fR file.
- X
- XIt is also possible for the user to create their own tilde escapes. First,
- Xcreate a subroutine which performs the desired function. Then assign the
- Xtype glob which references that function to global array \fI%funcs\fR indexed
- Xby the character of the escape sequence. Any arguments that the user enters
- Xafter the tilde escape will be passed into the function as a single string
- Xin \fI@_\fR. The list \fI@lines\fR contains the current buffer.
- X
- XAs an example, here is the append to file function (~a) from the \fBPLOD\fR
- Xsource:
- X.RS
- X.PP
- X.nf
- Xsub appendfl {
- X local($file) = @_;
- X if (!open(OUTP, ">> $file")) {
- X warn "*** Could not append to file $file\\n";
- X return;
- X }
- X print OUTP @lines;
- X close(OUTP);
- X print "Wrote ", scalar(@lines), " lines to file $file\\n";
- X print "(continue composing note)\\n";
- X}
- X$appendfl = "file\\t\\tAppend contents of buffer to file";
- X$funcs{'a'} = *appendfl;
- X.fi
- X.RE
- X.PP
- XThe scalar variable \fI$appendfl\fR is used by \fBPLOD\fR's help function
- X(~h or ~?) to provide a descriptive message about the escape sequence.
- XAs a further example, here is \fBPLOD\fR's help function
- X.RS
- X.PP
- X.nf
- Xsub helpuser {
- X $long = (scalar(keys %funcs) >= $LINES)
- X && open(TMP, ">$TMPFILE");
- X for (sort keys %funcs) {
- X *info = $funcs{$_};
- X if ($long) {
- X print TMP "~$_ $info\\n";
- X }
- X else { print "~$_ $info\\n"; }
- X }
- X if ($long) {
- X close(TMP);
- X system("/bin/cat $TMPFILE | $PAGER");
- X unlink "$TMPFILE";
- X }
- X}
- X$helpuser = "\\t\\tPrint this message";
- X$funcs{'h'} = *helpuser;
- X$funcs{'?'} = *helpuser;
- X.fi
- X.RE
- X.PP
- XNote the use of various customization variables as well as the assignment
- Xof the type glob to two different indices of the \fI%funcs\fR array.
- X
- X.SH FILES
- X.PP
- X.Ip $HOME/.plodrc 24
- XUsers' personal initialization files
- X.Sp
- X.Ip /etc/plodrc 24
- XSystem-wide initialization file
- X.Sp
- X.PP
- XVarious other customizable file locations.
- X
- X.SH SEE ALSO
- X.BR perl (1)
- X
- X.SH AUTHORS
- XThe original idea for \fBPLOD\fR comes from Bill Mendyka
- X(\fBmendyka@dg-rtp.dg.com\fR).
- X
- XThe current Perl implementation was developed by Hal Pomeranz
- X(\fBpomeranz@aqm.com\fR).
- X
- XAn Emacs mode for \fBPLOD\fR was developed by Paul Foley
- X(\fBpaul@ascent.com\fR).
- X
- XAdditional improvements have been suggested/developed by:
- XDavid W Crabb (\fBcrabb@phoenix.Princeton.EDU\fR),
- XJohn Ellis (\fBellis@rtsg.mot.com\fR),
- XMike Lachowski (\fBmlachow@erenj.com\fR),
- XEric Prestemon (\fBecprest@pocorvares.er.usgs.GOV\fR),
- XErik E. Rantapaa (\fBrantapaa@math.umn.edu\fR), and
- XJames Tizard (\fBjames@ringo.ssn.flinders.edu.au\fR).
- X
- X.SH BUGS
- XAny bug reports or suggestions for improvement should be submitted to
- XHal Pomeranz via email at \fBpomeranz@aqm.com\fR.
- END_OF_FILE
- if test 9043 -ne `wc -c <'plod.man'`; then
- echo shar: \"'plod.man'\" unpacked with wrong size!
- fi
- # end of 'plod.man'
- fi
- echo shar: End of archive 1 \(of 1\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have the archive.
- rm -f ark[1-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-