Anonymous avatar Anonymous committed 365de1c

Import author version 2.4.1

Comments (0)

Files changed (39)

+2000-12-20  Yoshiki Hayashi  <yoshiki@xemacs.org>
+
+	* Upstream version 2.4.1
+Here are some of the fun things that Eshell can do, for those too
+impatient for manuals!
+
+- First off, Eshell should work anywhere that Emacs does.  Eshell uses
+  no external processes -- only Emacs Lisp functions.  So if
+  `directory-files' returns a list of filenames on your VAX, then
+  Eshell's implementation of ls should too.
+
+- Lisp functions can be called using either Lisp or Eshell syntax.
+  Take the `+' function, for example:
+
+    /tmp $ (+ 1 2)
+    3
+    /tmp $ + 1 2
+    3
+
+  In the first case, the Lisp expression is simply handed to the Lisp
+  interpretor.  In the second case, the arguments are parsed by
+  Eshell, and converted to numbers because they look like numbers.
+  The argument list is then passed to `+'.
+
+- Several things return lists as their result.  Globbing and command
+  interpolation are good examples.  This means you can pass these
+  lists to Lisp functions that can deal with lists.
+
+  For example, the `length' function, if passed a list, will return
+  the number of items in the list.  And since a globbing pattern
+  always returns a list, here is a way to tell how many files match a
+  glob:
+
+    /tmp $ length *.el
+
+  Finding out the same information on UNIX requires two process
+  invocations:
+
+    /tmp $ ls -1 *.el | wc -l
+
+  This version can also be used with Eshell, but it's more complex,
+  and more expensive.
+
+- Command interpolations result in lists as well.  Each element of the
+  list represents one line of the command's output.
+
+    /tmp $ length ${egrep johnw /etc/passwd}
+
+- To review all occurances of a regexp anywhere in the command outputs
+  of the current Eshell session, enter:
+
+    /tmp $ occur REGEXP
+
+- Instead of "find . -print | xargs grep REGEXP", you can use Eshell's
+  recursive globbing syntax, which is taken from zsh:
+
+    /tmp $ grep REGEXP **/*(.)    # grep all normal files
+
+  This command will also display the grep hits in a "*grep*" buffer,
+  allowing you to type C-x ` to visit the locations of the hits.  The
+  "(.)" at the end of the glob pattern is an argument predicate, which
+  constrains the resulting list to only those entries for which
+  `file-regular-p' returns true.
+
+- bash-style history references (!, C-r, C-p, etc).
+
+- Supports 4nt's history reference style of typing the beginning of a
+  command, and then hitting up arrow to see all the commands beginning
+  with that text.
+
+- There are a lot of other things, but I'm always so tired when I get
+  to this point.
+Installing Eshell
+=================
+
+THE SHORT FORM
+--------------
+
+Here's exactly what to do, with no explanation why.
+
+  1. M-x load-file RET eshell-auto.el RET
+  2. ESC : (add-to-list 'load-path "<path where Eshell resides>") RET
+  3. ESC : (add-to-list 'load-path "<path where Pcomplete resides>") RET
+  4. M-x eshell RET             ; should see a version banner displayed
+  5. ls RET                     ; confirm that you see a file listing
+  6. eshell-test RET            ; confirm that everything runs correctly
+                                ; use `M-x eshell-report-bug' if not
+  7. cd ${dirname (locate-library "eshell-auto")} RET
+  8. find-file Makefile RET
+  9. [edit the Makefile to reflect your site]
+ 10. M-x eshell RET
+ 11. make install RET
+ 12. find-file $user-init-file RET
+ 13. [add the following lines to your .emacs file]
+       (add-to-list 'load-path "<directory where you install Eshell>")
+       (load "eshell-auto")
+ 14. M-x eshell RET
+ 15. customize-option #'eshell-modules-list RET
+ 16. [select the extension modules you prefer]
+ 17. [restart Emacs!]
+ 18. M-x info RET m Eshell RET  ; read the manual and enjoy!
+
+THE LONG FORM
+-------------
+
+ 1. Before building and installing Eshell, it is important to test
+    that it will work properly on your system.  To do this, first load
+    `eshell-auto', which will define certain autoloads required to run
+    Eshell.  This can be done using the command `M-x load-file', and
+    then selecting the file "eshell-auto.el".
+
+ 2. In order for Emacs to find Eshell's files, the Eshell directory
+    must be added to the `load-path' variable.  This can be done
+    within Emacs by typing:
+
+    ESC : (add-to-list 'load-path "<path where Eshell resides>") RET
+    ESC : (add-to-list 'load-path "<path where Pcomplete resides>") RET
+ 
+ 2. Start Eshell from the distributed sources, using default settings,
+    by typing `M-x eshell'.
+
+ 3. Verify that Eshell is functional by typing "ls" followed by RET.
+    You should have already seen a version banner announcing the
+    version number of this release, followed by a prompt.
+
+ 4. Run the test suite by typing "eshell-test" followed by RET in the
+    Eshell buffer.  It is important that Emacs be left alone while the
+    tests are running, since extraneous command input may cause some
+    of the tests to fail (they were never intended to run in the
+    background).  If all of the tests pass, Eshell should work just
+    fine on your system.  If any of the tests fail, please send e-mail
+    to the Eshell maintainer using the command `M-x eshell-report-bug'.
+
+ 5. Edit the file `Makefile' in the directory containing the Eshell
+    sources to reflect the location of certain Emacs dircetories at
+    your site.  The only things you really have to change are the
+    definitions of `lispdir' and `infodir'.  The elisp files will be
+    copied to `lispdir', and the info file to `infodir'.
+
+ 6. Type `make install' in the directory containing the Eshell
+    sources.  This will byte-compile all of the `.el' files and copy
+    both the source and compiled versions to the directories specified
+    in the previous step.  It will also copy the info file, and add a
+    corresponding entry to your "dir" file -- if install-info can be
+    found.
+
+    If you only want to create the compiled elisp files, but don't
+    want to install them, you can type just `make' instead.
+
+ 7. Add the directory into which Eshell was installed to your
+    `load-path' variable.  This can be done by adding the following
+    line to your .emacs file:
+
+    (add-to-list 'load-path "/usr/local/share/emacs/site-lisp/eshell")
+
+    The actual directory on your system may differ.
+
+ 8. To install Eshell privately, edit your .emacs file; to install
+    Eshell site-wide, edit the file `site-start.el' in your site-lisp
+    directory (usually `/usr/local/share/emacs/site-lisp' or something
+    similar).  In either case enter the following line into the
+    appropriate file:
+
+    (load "eshell-auto")
+
+ 9. Restart Emacs.  After restarting, customize the variable
+    `eshell-modules-list'.  This variable selects which Eshell
+    extension modules you want to use.  You will find documentation on
+    each of those modules in the Info manual.
+
+10. Read the Info manual.  Although Eshell behaves like most ordinary
+    shells, it has other advanced features and Lisp integration
+    facilities that require a more thorough presentation than these
+    meager notes.
+
+How to make typeset documentation from eshell.doci
+======================================================
+
+   If you have TeX installed at your site, you can make a typeset
+manual from `eshell.doci' by typing "make eshell.dvi".  If you prefer
+a postscript version of this file, use "make eshell.ps" instead.
+# Makefile for eshell
+
+# This file is part of XEmacs.
+
+# XEmacs is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2, or (at your option) any
+# later version.
+
+# XEmacs is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with XEmacs; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+VERSION = 1.01
+AUTHOR_VERSION = 2.4.1
+MAINTAINER = John Wiegley <johnw@gnu.org>
+PACKAGE = eshell
+PKG_TYPE = regular
+REQUIRES = xemacs-base eterm
+CATEGORY = os
+
+ELCS = em-alias.elc em-banner.elc em-basic.elc em-cmpl.elc em-dirs.elc \
+	em-glob.elc em-hist.elc em-ls.elc em-pred.elc em-prompt.elc \
+	em-rebind.elc em-script.elc em-smart.elc em-term.elc em-unix.elc \
+	em-xtra.elc esh-arg.elc esh-cmd.elc esh-ext.elc \
+	esh-io.elc esh-maint.elc esh-mode.elc esh-module.elc esh-opt.elc \
+	esh-proc.elc esh-test.elc esh-toggle.elc esh-util.elc esh-var.elc \
+	eshell.elc
+
+DATA_FILES =
+DATA_DEST =
+EXTRA_SOURCES = esh-groups.el
+
+TEXI_FILES = eshell.texi
+INFO_FILES = eshell.info*
+MANUAL = eshell
+
+include ../../XEmacs.rules
+
+GENERATED += custom-load.elc
+
+all:: $(ELCS) auto-autoloads.elc custom-load.elc eshell.info
+
+srckit: srckit-std
+
+binkit: binkit-common

Makefile.upstream

+# Makefile for Eshell lisp code
+
+# Copyright (C) 1998-1999  John Wiegley <johnw@gnu.org>
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2, or (at your option) any
+# later version.
+
+# This file is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GNU Emacs; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+prefix  = /usr/local
+datadir = $(prefix)/share
+
+# the directory where you install third-party emacs packges
+lispdir = $(datadir)/emacs/site-lisp
+
+# the directory where you install the info doc
+infodir = $(prefix)/info
+docdir	= $(prefix)/doc
+
+EMACS	 = emacs
+MAKEINFO = makeinfo
+TEXI2DVI = texi2dvi
+SHELL	 = /bin/sh
+DVIPS	 = dvips
+CP	 = cp
+MKDIR	 = mkdir -p
+ETAGS	 = etags
+
+######################################################################
+###        No changes below this line should be necessary          ###
+######################################################################
+
+PACKAGE = eshell
+
+# the directory where the .elc files will be installed
+elcdir  = $(lispdir)/$(PACKAGE)
+eldir   = $(elcdir)
+
+MARGS   = --no-init-file --no-site-file -l ./esh-maint.el -batch
+BEMACS  = $(EMACS) $(MARGS)
+ELC	= $(BEMACS) -f batch-byte-compile
+
+ELFILES =		\
+	eshell.el	\
+	esh-arg.el	\
+	esh-cmd.el	\
+	esh-ext.el	\
+	esh-io.el	\
+	esh-mode.el	\
+	esh-module.el	\
+	esh-opt.el	\
+	esh-proc.el	\
+	esh-test.el	\
+	esh-toggle.el	\
+	esh-util.el	\
+	esh-var.el	\
+	em-alias.el	\
+	em-banner.el	\
+	em-basic.el	\
+	em-cmpl.el	\
+	em-dirs.el	\
+	em-glob.el	\
+	em-hist.el	\
+	em-ls.el	\
+	em-pred.el	\
+	em-prompt.el	\
+	em-rebind.el	\
+	em-script.el	\
+	em-smart.el	\
+	em-term.el	\
+	em-unix.el	\
+	em-xtra.el
+
+ELCFILES = $(ELFILES:.el=.elc)
+
+TEXEXTS =  *.cps *.fns *.kys *.vr *.tp *.pg *.log *.aux *.toc *.cp *.ky *.fn *.vrs
+
+.SUFFIXES: .elc .el .info .ps .dvi .texi
+.PHONY: elcfiles info clean distclean default
+.PHONY: install_elc install install_el install_info
+
+.el.elc:
+	$(ELC) $<
+
+.texi.info:
+	$(MAKEINFO) $<
+
+.texi.dvi:
+	$(TEXI2DVI) $<
+
+.dvi.ps:
+	$(DVIPS) -f $< >$@
+
+######################################################################
+
+default: eshell-auto.el elcfiles
+
+dist: eshell-auto.el
+
+eshell-auto.el: $(ELFILES)
+	echo ";;; DO NOT MODIFY THIS FILE" > eshell-auto.el
+	echo "(if (featurep 'eshell-auto) (error \"Already loaded\"))" \
+		>> eshell-auto.el
+	$(BEMACS) -f eshell-generate-autoloads ./eshell-auto.el .
+	echo "(provide 'eshell-auto)" >> eshell-auto.el
+	ln -f eshell-auto.el auto-autoloads.el
+
+elcfiles: Makefile $(ELFILES)
+	$(ELC) $(ELFILES)
+
+info: $(PACKAGE).info
+
+install_elc: $(ELCFILES) eshell-auto.el _pkg.el
+	$(MKDIR) $(elcdir)
+	$(CP) $(ELCFILES) auto-autoloads.el \
+		eshell-auto.el _pkg.el $(elcdir)/
+
+install_el: $(ELFILES)
+	$(MKDIR) $(eldir)
+	$(CP) $(ELFILES) $(eldir)/
+
+install_info: $(PACKAGE).info
+	$(MKDIR) $(infodir)
+	$(CP) *.info* $(infodir)/
+	-[ ! -w $(infodir)/dir ] || install-info $(PACKAGE).info $(infodir)/dir
+
+install: install_elc install_info install_el
+
+TAGS tags:
+	$(ETAGS) $(ELFILES)
+
+clean:
+	$(RM) *~ core .\#* $(TEXEXTS)
+
+distclean: clean
+	$(RM) *.elc *.dvi *.info* *.texi *.ps README TAGS
+	$(RM) eshell-auto.el* esh-groups.el* auto-autoloads.el*
+-*- mode: text; outline-layout: (1 :) -*-
+
+This is the NEWS file for Eshell, a command shell written in Emacs
+Lisp.
+
+Please note that proper documentation is still on its way.  I expect
+that 2.4.1 will include the final Info document.
+
+* Changes in 2.4:
+
+** Primarily a performance release, in addition to a few slight
+   changes in avaliable configuration variables:
+
+** There is a distinction made between "simple" and "complex"
+   functions.  Complex functions are likely to cause modifications to
+   the running Eshell command form, and thus require a form of
+   evaluation that simulates Scheme continuations.  This uses three
+   times as much memory as using plain `eval', which is entirely
+   sufficient for "simple" commands such as ls, cp, mv, etc.
+
+   NOTE: If you write a command named eshell/NAME, which must throw
+   either `eshell-defer' or `eshell-replace-command', you must add
+   NAME to `eshell-complex-commands'.
+
+** `ls' now uses `eshell-ls-exclude-hidden' to indicate that files
+   beginning with a dot should be excluded.
+
+** `eshell-glob-show-progress' is now nil by default, since it slows
+   down recursive glob processing so much.
+
+** ange-ftp is no longer required to compile Eshell, which broke
+   XEmacs users in 2.3.2.
+
+** `eshell-ls-initial-args' is new, and should be used instead of
+   command aliases to introduce a common argument (such as -h).
+
+** Command aliases and smart scrolling are both very slow and memory
+   consumptive, although not much can be done about this.  For
+   complicated commands that themselves run slowly, the percentile
+   impact is little.  But for quick, simple commands such as cd, ls,
+   etc., command aliases should definitely be avoided.  And while
+   smart scrolling (eshell-smart) is quite useful, it should be run on
+   fast machines to be fully appreciated.
+
+** The new option `eshell-stringify-t' determines whether Lisp `t'
+   should be rendered as `t', or not at all.  The truth of an
+   expression can still be determined using:
+
+     file-exists-p FILE && echo true
+
+** Added a new option `eshell-default-target-is-dot', which if non-nil
+   states that the default target of cp/mv/ln is the current
+   directory, which mirrors the behavior of most DOS shells.
+
+* Changes in 2.3.2:
+
+** More bug fixes.  Greatly improved remote directory support, since
+   now nearly all file attributes can be viewed.
+
+* Changes in 2.3.1:
+
+** This a bug fix release, in preparation for inclusion as part of
+   Emacs 21.
+
+** One little feature, however, did sneak in: C-c C-y in the Eshell
+   buffer will repeat the last argument entered.  With a numeric
+   prefix, it will repeat that many arguments.
+
+* Changes in 2.3:
+
+** The control flow commands: if, unless, while, until: now test the
+   exit code of external processes against 0 for truth, and the value
+   of Lisp forms against t.  Before, they would only check to see if
+   the test expression generated output.
+
+** Because the Elisp manual declares that C-c LETTER bindings be left
+   to the user, several of Eshell's command mode bindings had to be
+   changed.  The equivalences are:
+
+      2.2     2.3
+     -----   -------
+     C-c e   C-c M-v
+     C-c p   C-c M-i
+     C-c h   C-c M-o
+     C-c b   C-c M-b
+     C-c l   C-c M-l
+     C-c ?   C-c M-q,
+     C-c m   C-c M-m
+     C-c i   C-c M-h
+     
+** Added support for a ksh feature: "cd OLD NEW".  This will replace
+   OLD with NEW in the current directory name (the name returned by
+   `pwd' specifically), and then attempt to change to that directory.
+
+** Added a syntax convenience for short-circuited commands:
+
+     file-exists-p file.cpp && echo file exists
+     file-exists-p file.cpp || echo file does not exist
+
+   These operators test either the return code of the Lisp function on
+   the left-hand side (to determine if it's non-nil), or the exit code
+   of an external function (testing for 0), whichever is appropriate.
+
+   The precedence for these operators is lower than sequencing (;) and
+   backgrounding (&), but higher than redirection (>) and piping (|).
+   Within themselves, they are strictly left to right.  In this sense,
+   it acts on a chain of success and failure, continuing to the next
+   part of the chain only if the operator would allow it.
+
+** Added three new configuration variables:
+
+     eshell-mv-overwrite-files
+     eshell-cp-overwrite-files
+     eshell-ln-overwrite-files
+
+   The default for all three is t.  If nil, a --force argument (-f) is
+   required before any of the three commands will overwrite anything.
+   This is different from --interactive (-i), which queries before
+   destruction.
+
+* Changes in 2.2:
+
+** Added a "FEATURES" file to the distribution, which gives a brief
+   overview of the features offered by Eshell.
+
+** When `eshell-command' is invoked, the minibuffer is put into
+   eshell-mode, making all of your preferred Eshell keybindings
+   available (such as completion).
+
+   To bind M-! to use eshell-command, customize the variable
+   `eshell-prefer-to-shell'.
+
+** If both the `eshell-history' and `eshell-rebind' are in use, C-r
+   and C-s now behave similarly to bash.  In 2.1, it was necessary to
+   enter a full regexp in the minibuffer before searching would
+   begin.  Now it's incremental, using isearch.
+
+** All of the optional Eshell extension modules are now named
+   "em-NAME.el".  Required modules are named "esh-NAME.el".  This
+   prevents name collisions from occuring on filesystems with 8.3 name
+   limits.
+
+** New conditional constructs: if, unless, while and until.  They can
+   be used in any of the following fashions:
+
+     if (string-match "gumby" (system-name)) {
+  	echo true
+     } else {
+  	echo false
+     }
+
+     while {/sbin/ifconfig | egrep ppp0} {
+        echo connected via ppp
+     }
+
+** New ls option implemented: -I GLOB.  Used to exclude files matching
+   GLOB from the listing.
+
+** New list argument modifiers: (:i/REGEXP/) strips all elements not
+   matching REGEXP.  (:x/REGEXP/) strips all elements that do match
+   the REGEXP.  Other delimiters can also be used: (:i,REGEXP,).
+
+** Extended the file-time predicate, so that a file can be used as a
+   comparison basis.  Example: "ls *(a+'file.c')" displays files
+   accessed before "file.c" was last accessed.
+
+** The eshell-xtra extension module now offers some cl (Emacs Common
+   Lisp) convenience functions.  They make it much easier to perform
+   complex manipulations on list arguments.  Since glob patterns and
+   command substitutions both yield list values, they can be very
+   useful.  To enable eshell-xtra, customize the variable
+   `eshell-options-list'.
+
+     # Return results of glob, minus happy.el.  The same as:
+     #   *.el~happy.el
+
+     remove happy.el *.el
+
+     # Remove all duplicate lines from command results.  The same as:
+     #   egrep johnw /etc/passwd | uniq
+
+     remove-duplicates ${egrep johnw /etc/passwd}
+
+     # Replace a given list element with another.  The same as:
+     #   *.el(:s/em-ls\.el/happy.el/)
+
+     substitute happy.el em-ls.el *.el
+
+     # Return element value if member of a list.  This is roughly
+     # equivalent to:
+     #   echo *.el | egrep "^happy.el$" | uniq
+
+     find happy.el *.el
+
+     # Count the number of times a string appears in a list.
+     # Equivalent to:
+     #   echo *.el | egrep "^happy.el$" | wc -l
+
+     count happy.el *.el
+
+     # Combine two lists, eliminating duplicates.  Roughly equivalent
+     # to (difference is that the result is always sorted):
+     #   echo *.el e* | sort | uniq
+
+     union *.el e*
+
+     # Return overlapping members of two lists.  Roughly equivalent
+     # to:
+     #   comm -12 $<printnl *.el(:o:u)> $<printnl e*(:o:u)>
+
+     intersection *.el e*
+
+     # Return members unique to the first list.  Roughly equivalent
+     # to:
+     #   comm -23 $<printnl *.el(:o:u)> $<printnl e*(:o:u)>
+
+     set-difference *.el e*
+
+     # Return all members that don't overlap.  Roughly equivalent to:
+     #  append ${comm -23 $<printnl *.el(:o:u)> $<printnl e*(:o:u)>}
+     #         ${comm -13 $<printnl *.el(:o:u)> $<printnl e*(:o:u)>}
+     
+     set-exclusive-or *.el e*
+
+** cp and mv now support moving and copying of directories.  With mv,
+   this happens whenever a directory name is given as a source.  With
+   cp, it requires using either the -R or -a switch.
+
+   Please be careful when using these options.  A good backup policy
+   is always worth the trouble, and until Eshell has been in active
+   use for a few years, I wouldn't want to start moving directories
+   around without a backup.
+
+** Copying and moving directly TO a tar archive is allowed.  It
+   creates the archive if it doesn't exist, and updates it if it does
+   (removing the filesystem entries in the case of mv).  Note that
+   this happens only with multiple sources, or a single directory
+   source.
+
+   If the archive name ends in ".tgz", ".tz2", ".taz", ".taZ",
+   ".tar.gz", ".tar.bz2", or ".tar.Z", it will be
+   compressed/decompressed appropriately.  Using "-v" after the
+   command name also works, for displaying the filenames as they are
+   copied/moved:
+
+     cp -v some_dir some_dir.tar.bz2
+
+** Implemented `du' in Lisp.  If an external version of `du' is
+   present, it is always used instead, since the Lisp version is much
+   slower, and blocks Emacs while it's running.
+
+** Implemented `time' in Lisp.  It only displays elapsed wall-clock
+   time, since Emacs doesn't provide facilities for determining the
+   user/kernel time consumed by a subprocess.  Its usefulness lies in
+   the fact that it can show the elapsed time of Lisp function calls,
+   and it's available on all operating systems.
+
+** If a `grep' command is neither redirected, nor part of a command
+   pipeline, it's output will occur in a `*grep*' buffer, allowing the
+   user to use C-x ` to move to the source of each hit.  The applies
+   to the whole grep family: egrep, fgrep, agrep, and glimpse.
+
+   Disable by customizing `eshell-plain-grep-behavior'.
+
+** If a `diff' command is neither redirected, nor part of a command
+   pipeline -- and if diff-mode.el is loaded -- the command's output
+   will occur in a separate buffer in diff-mode, allowing the user to
+   use C-x ` to move to each source difference.
+
+   Disable by customizing `eshell-plain-diff-behavior'.
+
+** If a `locate' command is neither redirected, nor part of a command
+   pipeline -- and if diff-mode.el is loaded -- the command's output
+   will occur in a separate buffer in locate-mode.
+
+   Disable by customizing `eshell-plain-locate-behavior'.
+
+** If a `make' command is sent to the background and not redirected,
+   it's output will appear in a `*compilation*', allowing the user to
+   enter C-x ` to view the source of each error.
+
+** New list argument modifier ':u'.  This removes any contiguous
+   duplicate strings in the list.  Used after ':o', it's the same as
+   "sort | uniq".  Example:
+
+     echo **/*.c(:o:u)   # returns uniq'd list of all .c files
+
+** Arguments to `which' that are preceded by an asterix `*', will
+   bypass alias lookup.  This makes it possible to find out what the
+   alias will invoke.
+
+** Three new globbing constructs: #?, #* and #+, which correspond to
+   the ?, * and + regular expressions.  To show the correlation:
+
+     glob   regexp
+     ----   ------
+      *       .*
+      ?       .
+      #*      *
+      #+      +
+      #?      ?
+      ##      +      # zsh compatible
+      #       *      # zsh compatible
+
+** Changed the syntax of variable name quoting.  The new syntax is:
+
+     $VAR-NAME       # interpolate the value of `VAR-NAME'
+     $'VAR'-NAME     # interpolate `VAR', followed by "-NAME"
+     $"VAR"-NAME     # (same)
+     $"VA$VAR"-NAME  # interpolate `VAR' into "VA?", then interpolate
+  		       into "?-NAME".  This syntax can be nested.
+
+   Previously the argument "$<LOGNAME>-name" would have interpolated
+   the value of $LOGNAME into the argument, yielding something like
+   "johnw-name".
+
+** New syntax for temporary data interpolation.  Example:
+
+     xdu -n $<du -k>
+
+   This invokes the command "du -k", copies the result to a temp file,
+   then passes the name of that temp file as an argument to `xdu'.
+   Once `xdu' completes, the temp file is deleted.
+
+   This syntax is quite similar to "<{command}" in bash, except that
+   Emacs doesn't permit writing to named pipes.
+
+   This is also useful with commands that need multiple generated
+   inputs:
+
+     comm -23 $<cd ~/src; printnl **/*.c(:o:u)>   \
+              $<cd /usr/src; printl **/*.c(:o:u)>
+
+   This command will display all the .c files in "~/src" that are not
+   in "/usr/src", with `comm' the only external process invoked.
+
+** New commands: C-c ? and C-c m.  These two popup quick help buffers
+   showing the various glob predicate and argument modifier
+   characters.  All those characters were too easy to forget.
+
+** Using the '@' predicate with globs containing directories now
+   works.  Example: "ls -d *(^@)" (anywhere containing directories).
+
+** Corrected the behavior of "ls -L".
+
+** rm, cp, mv and ln now support "-i" (--interactive), which queries
+   before overwriting/deleting any files.  This is the default when
+   the user id is 0.
+
+** Line splitting in command result interpolation now works.  This
+   makes the following possible:
+
+     length {listify {egrep blah FILE}}
+
+   This invokes "egrep blah FILE", interpolating the result as a Lisp
+   list, with each element a line of the output.  The above command
+   will report how many hits were found.  Note that the `listify' is
+   required here, since if egrep finds only one match, it will return
+   it as a string, not a list.
+
+** New configuration variable `eshell-virtual-targets'.  Allows the
+   user to specify new virtual targets, such as "/dev/kill" and
+   "/dev/null".
+
+** New virtual target "/dev/eshell".  Anything output to this
+   pseudo-device will be displayed in the Eshell window as normal
+   output from the command.  Useful on operating systems without
+   "tee", since it lets you both view the command output, and redirect
+   it somewhere else:
+
+     ls > blah > /dev/eshell   ; output goes to both "blah" and display
+
+** New configuration variable `eshell-kill-processes-on-exit'.  It can
+   be set to one of: t, ask, every, nil.  These settings mean:
+
+   t     - kill all processes spawned by an Eshell buffer when it is
+           killed/exited.
+
+   ask   - same operation as t, but ask the user before doing so.
+
+   every - some operation as ask, but query for every single process.
+
+   nil   - don't kill processes on exit.  They will be killed only if
+           Emacs itself is killed, or if the user kills/exits them.
+           This is the default, and matches the behavior of 2.1.
+   
+** New configuration hook `eshell-first-time-mode-hook', which is
+   called at the same time as `eshell-mode-hook' (just before it), but
+   only once per Emacs session.
+
+** Added '#*' '.#*' files to the `eshell-ls-backup-regexp'.
+
+** Added '.bz2' files to the `eshell-ls-archive-regexp'.
+
+** The "echo" command now takes a "-n" flag, which causes it to
+   generate a newline after the printed text.
+
+** New module `esh-toggle', which provides the global commands
+   `eshell-toggle' and `eshell-toggle-cd'.
+
+To use these functions, simply type `M-x eshell-toggle'.  With a
+prefix argument, it is the same as calling `eshell-toggle-cd', which
+emits a "cd $default-directory" immediately after switching.
+
+If `eshell-toggle' is called once, it will bring up Eshell in another
+window.  If called twice in succession, it will take up the whole
+frame.  After doing anything in the Eshell buffer, calling
+`eshell-toggle' yet again will restore the window configuration that
+was extent before the first call.
+
+** Improved support for XEmacs 21.1 and 21.2.
+
+* Changes in 2.1:
+
+** Eshell has been split into several functional "modules".
+   There are base modules, which define the core of Eshell, and
+   extension modules, whose use is entirely optional.  See the
+   variable `eshell-modules-list'.
+
+** comint.el is no longer used.  The functionality that Eshell had been
+   using is now divided between eshell-mode.el, eshell-hist.el,
+   eshell-cmpl.el and eshell-io.el.  Most of that code is now
+   radically altered from its original form.
+
+** there is complete documentation available, using a prototype
+   embedded documentation system called "texidoc".  texidoc.el is
+   included with the distribution of Eshell, but is not yet ready for
+   general consumption.
+
+** pushd, popd and dirs are provided in the extension module
+   `eshell-dirs'.
+
+** `cd', as defined in the extension module `eshell-dirs', can accept
+   parent directory references of the form "...", where each
+   additional "." refers to the next highest directory.
+
+** recursive globbing, similar to zsh, is provided in the extension
+   module `eshell-glob'.  The syntax is "**/*.c", which means matches
+   all of the C files in the current directory and below.  Symbolic
+   links are not traversed.  To traverse them, use three asterices:
+   "***/*.c".
+
+** argument predicates and modifiers are provided in the extension
+   module `eshell-pred'.  The syntax is to suffix the argument with
+   "(PREDS)" or "(:MOD:MOD)", or any combination.  The allowable
+   predicates follow zsh syntax, whereas the allowable modifiers
+   follow bash's history argument modifier syntax.  Thus, the command
+   "echo alpha(:s/al/be/)" would yield the string "bepha".
+
+   The history code and globbing rely upon this extension module to
+   provide globbing predicates and history argument modifiers.  If it
+   is not used, those facilities won't be available.  See the Info
+   manual for a fuller description of predicates and modifiers, and
+   how to use them.  They are comprehensive enough to replace the use
+   of "find ... | xargs <cmd>" in most cases.
+
+** the version info banner displayed at login is part of a
+   sample extension module named `eshell-banner'.  It can be
+   de-selected by disabling the use of that module.  If authors choose
+   to write their on Eshell extension modules, they should copy this
+   file ("eshell-banner.el") as a starting point.
+
+** command aliases are provided in the extension module
+   `eshell-alias'.  These aliases are intended for simplicity, and
+   persist immediately (i.e., no customization of Lisp variable is
+   necesary in order to use them).  The only caveat, and difference
+   from other shells, is that argument expansion must always be
+   provided by specifying '$*' somewhere in the alias string.  A
+   typical use might be: "alias ll 'ls -l $*'"
+
+** argument parsing has complete changed in structure.  It is now much
+   easier for extension modules to extend the capability of the parser
+   for their own needs.  See `eshell-dirs' for an example, which
+   extends the parser to properly handle filenames beginning with a
+   tilde character, such as "cat ~johnw/.emacs".
+
+** several more UNIX commands are now implemented in Lisp, in the
+   extension module `eshell-unix': basename, cat, cp, date, dirname,
+   ln, man, mkdir, mv and rmdir.
+
+** the extension module `eshell-basic' defines some of the more basic
+   shell commands, which are typically builtins in most shells: echo,
+   umask, version, etc.
+
+** programmable, context-aware completion is available using the
+   extension module `eshell-cmpl'.  This is accomplished by taking
+   advantage of the functionality in the `pcomplete' module, which is
+   included with the standard Eshell distribution.
+
+** history code, which is almost entirely bash compatible, is provided
+   in the extension module `eshell-hist'.
+
+** rebinding of command keys while editing command input is provided
+   in the extension module `eshell-rebind'.  For example, this causes
+   C-u to delete the current input text, rather than act as the
+   universal argument prefix -- but only while editing command input.
+   This is done to make Eshell feel more like a standard system
+   shell.  Once the point moves away from the command input text (C-c
+   C-p is the typical way to do this), C-u takes on its normal
+   meaning.
+
+   The keys which get rebound, and their definition, are fully
+   customizable.
+
+** execution of Eshell scripts is provided in the extension module
+   `eshell-script'.  The interpretor should be named
+   "/usr/local/bin/eshell", which is not offered with this
+   release. Eshell itself can execute such scripts, however, since it
+   evaluates them within the currently running Emacs.
+
+** a new form of smart output display is provided in the extension
+   module `eshell-smart'.  See the Info manual for more details, since
+   an accurate description of what "smart" means in this case is
+   somewhat difficult to describe.
+
+** a test suite is now included with Eshell, which is runnable by
+   typing `M-x eshell-test'.  However, this test can only be run
+   against non-byte-compiled sources.  For efficiency sake, all of the
+   testing code is removed during byte-compilation.
+
+** a few other niceties, such as implementing `expr' in terms of the
+   calc package, or defining `make' to use compilation-mode whenever
+   the user invokes it asynchronously, are provided in the extension
+   module `eshell-xtra'.
+
+** cd now maintains its own "directory ring", which remembers the last
+   `eshell-last-dir-ring-size' places that Eshell has been to.  The
+   syntax is:
+
+     cd -       ; go to last location (swap top of ring and current)
+     cd -4      ; go to 4th from last location
+     cd =bcc    ; go to last location containing regexp "bcc"
+     cd =       ; show list of locations
+    
+   If `eshell-last-dir-unique' is non-nil, this ring will never contain
+   duplicate items.
+
+** if an alias command like "ls" doesn't recognize a specified option,
+   it will defer to the external version (searched for on the PATH).
+
+** improved the "history" alias to be more like bash; specifically,
+   there is support for the -r, -w and -a options.
+ 
+** removed all dependencies on font-lock.  eshell now does its own
+   buffer highlighting.
+
+** added full support for colorized ls output.  To disable this
+   feature, set `eshell-ls-use-colors' to nil.
+
+** fixed a bug which was causing filter overruns when using pipes
+   and processes that generate a lot of output (like "find" with
+   "xargs").
+
+** removed `eshell-ls-default-args'.  The proper way to pass default
+   arguments to ls is by using a command alias.
+
+** fixed a bug which prevented Eshell's ls from displaying very large
+   file sizes.
+
+* Changes in 1.5:
+
+** eshell now uses comint directly, rather than duplicating that
+   code.
+
+For this to work, you will need an updated copy of comint, which can
+be found at
+
+  http://www.emacs.org/~johnw/comint.el
+
+Or ask the author to send you a copy!
+
+** optimized handling of output from a subprocess.  In cases where
+   both standard output and standard error are both headed for the
+   "*eshell*" buffer (which is most of the time), the comint filter is
+   used directly, bypassing eshell's redirection code.
+
+** there is a new user variable, `eshell-visual-commands'.  If any
+   command name matches a member of this list, it will be executed
+   using "term", and started in a new buffer.  When that process exits
+   -- and if you were viewing that buffer at the time -- it will
+   return you to eshell.
+
+** fixed "/dev/null".  It now dumps output once again (before, it
+   would give an error about trying to change the value of the
+   constant symbol "nil").
+
+** fixed a problem with subcommands that was causing "echo
+   ${whoami}" not to work.
+
+** implemented a simple version of "history" that mimics the
+   behavior of bash's same command.  None of the command switches are
+   supported, however, nor can an alternate history file be specified.
+   Yet.
+
+** if `eshell-input-ring-file-name' is non-nil (and it now defaults
+   to "~/.history"), eshell will write out the current command history
+   whenever the eshell buffer is killed.
+
+** the "exit" alias will bury the eshell buffer; but it does not
+   kill it (for the time being, there are some problems with trying to
+   do that, while at the same time keep everything sane).
+
+** after a call to `eshell-print', the display is now refreshed --
+   with consquent result that some of the lisp functions are now
+   visibly slower, although you can at least now see that they're
+   doing something.  Setting `eshell-refresh-interval' to a higher
+   value will make the functions run faster, but it will also make
+   them seem a little choppier (no frequent updates).  Setting this to
+   a really high number will match the functionality of 1.4.
+
+** if a "foreground" process is active, pressing RETURN will send
+   the current string to that process; if there are multiple
+   foreground processes active, the user will be prompted for which
+   one.  Note that eshell echos locally, so the app you're using (such
+   as telnet) may have to turn echoing off.
+
+** executables are searched for along the PATH, not the `exec-path'.
+   Also, specifying a relative executable name now works (before,
+   saying "src/ls", even if it was there, would not work).
+
+** added an alias for "export" which behaves just as in bourne
+   shell.  That is, you can now add to the path by saying:
+
+     export PATH=$PATH:/usr/local/bin"
+
+** fixed a bug which made it impossible to say "echo $exec-path",
+   and was causing $_ to be inaccessible.
+
+** "ls -l" (the alias version, written in Lisp) now shows symbolic
+   link targets.  "ls -r" correctly reverses the file list.  "ls -t"
+   sorts by mod time.  Ganging up options ("ls -ltr") now also works.
+
+** before calling start-process, use `expand-file-name' on the
+   program name, so that relative paths are seen as absolute
+
+** looking up the command interpretor got broken again in 1.4
+
+** fixed problem where you couldn't cd to a directory with a numeric
+   name
+
+** `eshell-kill-alias' was reversing its arguments, so that "kill -9
+   PROC" wasn't working.
+
+** fixed a problem in `eshell-argument-syntax-list', that was
+   causing process references (e.g., #<process ispell>) to cause a
+   syntax error.
+
+** if output continues to generate from a subprocess, and you move
+   point to another window or frame, eshell will now scroll to the end
+   of the buffer.  In 1.4, it would freeze the point of display at the
+   location you were last at when leaving the window.
+
+** protected a reference to `transient-mark-mode' with a call to
+   `boundp', in case it's not bound yet.
+
+** "date" now calls (current-time-string).  If you want the other
+   functions of the date command, call it with an explicit path, such
+   as /bin/date.  In the future, I'll make "date" an alias, and just
+   call the real "date" if the alias doesn't recognize any of the
+   command line switches.
+
+** beyond these features and bugs, there were several other, smaller
+   bugs fixed.  Thanks to everyone who submitted feedback, and
+   provided test cases.  Most everything else on my TODO list is
+   either a major bug, requiring redesign, or a new feature.
+
+* Changes in 1.4
+
+** `eshell-funcalln' was incorrectly calling `eshell-apply' rather
+   than `eshell-applyn'.
+
+** Pipes and subcommands were totally broken by the rewrite of the
+   output handling code.  And subcommands were even changing the main
+   eshell buffer!  So that's all working again.
+
+** Always go the end of the current line when RETURN is pressed.
+
+** Fixed a serious problem with globbing patterns and disk commands.
+
+** Process interaction, when there is only one non-background
+   process active, now works as expected again.
+
+* Changes in 1.3
+
+** The variable `eshell-cd-shows-directory' now control whether
+   "cd" will report the directory name it changes to.
+
+** The "alias" command didn't even really work, but now it's
+   fixed.
+
+** Removed dependency on `dired-replace-in-string' and
+   `dired-glob-regexp'.
+
+** If a variable is not found, it's value evaluates to "".  If a
+   command cannot be found, it prints "name not found", as rc does
+   (rc: the Other Shell [read like 'the Other Woman'] :).
+
+** "ls" has been implemented in Lisp.  Remove it from the list of
+   aliases if you still want to use the disk-based version.  If there
+   are flags which my implementation does not recognize, it will
+   revert to the disk based version.
+
+** "rm" has been implemented to call the Lisp function
+   `delete-file'.  If the argument is a buffer or process, it will
+    kill it.  If it is a symbol, it will delete it.
+
+** If `cd' is given an ange-ftp file name, and then a disk
+   command is run from that directory, eshell will call
+   `shell-command' so that the command is run via "rsh" on the remote
+   machine.
+
+** Command aliases take a new second argument which allows you
+   specify what kind of alias you're defining.  So it's now possible
+   to define an alias as '("ll" command "ls -l").
+
+** The history and input handling code was copied directly over from
+   comint, rather than being reimplemented.  The only changes I had to
+   make were due to the fact that comint assumes that the current
+   buffer always has exactly one underlying process associated with
+   it.  So although it's ugly to block move that much code, rather
+   than just reuse it in place, at least for this version eshell
+   supports comint's code for history and input navigation:
+
+*** !! accesses last command
+
+*** !command searches for last command, with option of command
+    being a ;; regexp
+
+*** !?<TAB> causes the current line to be replaced with that
+    history ;; element
+
+*** M-p M-n walk through the history list
+
+*** If RETURN is pressed at a previous location in the eshell
+    buffer (i.e., before `eshell-output-mark'), repeat the command
+    text at the bottom before executing it.
+
+*** Note: numerical references to history sub-elements are
+    currently ignored.
+
+* Changes in 1.2
+
+** Fixed some bugs with list flattening, `eshell-echo' and
+   `eshell-dos-to-unix'.
+
+** Removed "grep" alias.  Too troublesome and confusing.
+
+** Giving a prefix argument to C-RET (send string to process),
+   will cause Emacs to read the input as a password.  Also, a newline
+   is now automatically appended to the string sent.
+
+** Fixed many bugs dealing with aliases and foreign command
+   interpretors.  How did all those bugs creep in?  :)
+
+** The "dos2unix" alias no longer untabifies your files.
+
+** Added aliases for "setq" and "if".  More to come...
+
+** Added some bindings to provide some compatibility with what
+   comint users expect.
+
+** Accessing history is now possible with "!command".  The last
+   command is available using "!!".  If `eshell-history-by-regexp' is
+   non-nil, you can use "!regexp", which will match anywhere with the
+   line, requiring "!^regexp" to emulate the default behavior.
+
+** "cd -" will return to the last directory visited.
+
+** Variable referencing is now supported.  It takes many forms:
+
+*** $VARIABLE      name of an environment or Lisp variable
+
+*** $ALSO-VAR      "-" is considered part of a name
+
+*** $<MYVAR>-TOO   only "MYVAR" is part of the variable name
+
+*** $#VARIABLE     length of the value of VARIABLE
+
+*** $(lisp)
+
+Returns result of lisp evaluation.  Note: Used alone like this, it is
+identical to just saying (lisp); but with the variable expansion form,
+the result may be interpolated a larger string, like "$(lisp)/other".
+
+*** ${command}
+
+Returns the value of an eshell subcommand.  See the note above
+regarding lisp evaluations.  The same applies here.
+
+*** $ANYVAR[10]
+
+Attempts to return the 10th element of ANYVAR.  If ANYVAR's value is a
+string, it will be split in order to make it a list.  The splitting
+will occur at whitespace.
+
+*** $ANYVAR[: 10]
+
+Just like above, except that splitting occurs at the colon now.
+
+*** $ANYVAR[: 10 20 ]
+
+Like above, but instead of returning just a string, it now returns a
+list of two elements.  If the result is being interpolated into a
+larger string, this list will be flattened into one big string, with
+each element separated by a space.
+
+*** $ANYVAR["\\\\" 10]
+
+Separate on backslash characters.  Actually, the first argument -- if
+it doesn't have the form of a number, or plain variable name -- is
+just a regular expression.  So if you did want to split on numbers,
+you could say:
+
+  $ANYVAR["[0-9]+" 10 20].
+
+*** $ANYVAR[hello]
+
+Does an assoc with ANYVAR, expecting it to be an alist.
+
+*** $#ANYVAR[hello]
+
+Returns the length of the element of the alist ANYVAR who car is equal
+to "hello"
+
+*** Thus, you can now do crazy things like:
+
+  1+ ${egrep johnw /etc/passwd}[: $pu-index] > 'uid-after-me
+
+And return the value of the `pu-index'th element of your passwd entry
+(let's assuming it's set to 2, the user id), increment it by one, and
+then store this integer in the Lisp variable `uid-after-me'.
+
+** $_ is defined (via an alias) as the arguments for the last
+   command.  If referenced plainly, it refers to the last argument of
+   the last argument.  If referenced as an array, it will return the
+   Nth argument of the last command.
+
+* Changes in 1.1
+
+** Fixed a bug which made some of the defcustom forms unusable.
+
+** `esh' is an alias for `eshell-subcommand', making it easier to
+   run eshell commands synchronously from lisp forms.
+
+** Fixed some erroneous ways that files were being separated and
+   globbed.  Failed globs get passed as the glob string.
+
+** Special characters in filenames are now quoted when doing name
+   completion.
+
+** Eshell outputs a short banner message on startup, announcing the
+   version.  Set `eshell-display-banner-p' to nil to turn this off.
+
+** Removed the troublesome global variables that were being used
+   for capturing the output from the subcommands.
+
+** Outputting to 'nil, or the pseudo-name "/dev/null", will drop
+   output.
+
+** Using ";;" means three empty commands now, instead of the
+   unknown token ";;".
+
+** The process interaction functions, such as C-c C-c, now always
+   use the currently running sub-process if eshell has invoked only
+   one.  Otherwise, it prompts from among all running processes in
+   Emacs.
+
+** Changed C-c RET to just C-RET.
+
+** Emacs-lisp-mode is run before switching the major mode to
+   eshell, so that any hooks (like starting eldoc mode) work as you
+   would expect for a lisp mode.
+
+* Changes in 1.0 (from the first pre-release version 0.2)
+
+** Simplified the code a great deal, and broke it down into several
+   more functions.
+
+** Now uses `dired-glob-regexp', instead of duplicating that code.
+
+** Redirection is possible to multiple targets.  They will all
+   receive the same output.
+
+** Redirection of files, buffers or processes, using the Emacs
+   syntax #<buffer NAME> or #<process NAME>.  If
+   `eshell-buffer-shorthand' is nil, you can even redirect into a lisp
+   variable using the syntax: 'name.
+
+** If you redirect within a pipe, the output will still go to the
+   pipe, eliminating the need for "tee".  To prevent this behavior,
+   set `eshell-always-to-pipe' to nil.
+
+** When redirecting to a buffer, the operator ">>>" will cause the
+   redirection to insert at the current location of point in that
+   buffer.  Beware of the asynchronous nature of the subprocess,
+   though, since it will continue inserting at point, even if point
+   moves around.
+
+** ~, ~user, and /:/path (to prevent environment variable
+   substitution) are now supported.
+
+** You can turn off the bogus nature of "&" by setting
+   `eshell-support-ampersand' to nil.
+
+** There is now extensive support for aliases, and redefinition of
+   commands.
+
+You can either replace the definition of a command, or alter it.  You
+can also modify the output which comes from the command, and still
+have it show up in all the places the user specified redirections to.
+
+** Synchronous subcommands are supported, and can be used either to
+   generate output, or to substitute for an argument.
+
+The syntax used is similar to rc, except that no whitespace is allowed
+after the initial brace.  This is so that users can avoid the tedium
+of quoting all the time.
+
+  echo {cd; ls}      ; echos contents of home directory
+  echo {+ 1 3}       ; print `t', since sub-expr yields non-nil
+  {+ 1 3}            ; evalute in a subcommand, and print result
+
+** Synchronous chaining of commands is supported, using ";":
+
+  ls; ls -l; ls; ls -l     ; appears in the order you expect
+
+** There is a series of functions behind C-c now, for the purposes
+   of interrupting processes.
+
+** You can use C-c p and C-c b to insert named references to
+   process and buffers.
+
+** When a subprocess asks a question, you cannot answer it just by
+   typing into the eshell buffer, since there's no way to know for
+   certain which asynchronous subprocess you intend for the string to
+   go to.  Instead, use C-c RET, select the name of the process, and
+   then enter your string in the minibuffer.
+The Emacs Shell: Eshell
+***********************
+
+   Eshell is a command shell implemented entirely in Emacs Lisp.  It
+invokes no external processes beyond those requested by the user.  It
+is intended to be a functional replacement for command shells such as
+bash, zsh, rc, 4dos; since Emacs itself is capable of handling most of
+the tasks accomplished by such tools.
+
+What does Eshell offer you?
+===========================
+
+   Despite the sheer fact that running an Emacs shell can be fun, here
+are a few of the unique features offered by Eshell:
+
+   * Integration with the Emacs Lisp programming environment
+
+   * A high degree of configurability
+
+   * The ability to have the same shell on every system Emacs has been
+     ported to. Since Eshell imposes no external requirements, and
+     relies upon only the Lisp functions exposed by Emacs, it is quite
+     operating system independent. Several of the common UNIX commands,
+     such as ls, mv, rm, ln, etc., have been implemented in Lisp in
+     order to provide a more consistent work environment.
+
+   For those who might be using an older version of Eshell, version 2.1
+represents an entirely new, module-based architecture. It supports most
+of the features offered by modern shells. Here is a brief list of some
+of its more visible features:
+
+   * Command argument completion (tcsh, zsh)
+
+   * Input history management (bash)
+
+   * Intelligent output scrolling
+
+   * Psuedo-devices (such as "/dev/clip" for copying to the clipboard)
+
+   * Extended globbing (zsh)
+
+   * Argument and globbing predication (zsh)
+
+   * I/O redirection to buffers, files, symbols, processes, etc.
+
+   * Many niceties otherwise seen only in 4DOS
+
+   * Alias functions, both Lisp and Eshell-syntax
+
+   * Piping, sequenced commands, background jobs, etc...
+
+Eshell is free software
+=======================
+
+   Eshell is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+   This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+along with Eshell; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+
+How to begin
+============
+
+   To start using Eshell, add the following to your .emacs file:
+
+     (load "eshell-auto")
+
+   This will define all of the necessary autoloads.
+
+   Now type `M-x eshell'.  See the INSTALL file for full installation
+instructions.
+
+Philosophy
+==========
+
+   A shell is a layer which metaphorically surrounds the kernel, or
+heart of an operating system.  This kernel can be seen as an engine of
+pure functionality, waiting to serve, while the user programs take
+advantage of that functionality to accomplish their purpose.
+
+   The shell's role is to make that functionality accessible to the
+user in an unformed state.  Very roughly, it associates kernel
+functionality with textual commands, allowing the user to interact with
+the operating system via linguistic constructs.  Process invocation is
+perhaps the most significant form this takes, using the kernel's `fork'
+and `exec' functions.
+
+   Other programs also interact with the functionality of the kernel,
+but these user applications typically offer a specific range of
+functionality, and thus are not classed as "shells" proper.  (What they
+lose in quiddity, they gain in rigidity).
+
+   Emacs is also a user application, but it does make the functionality
+of the kernel accessible through an interpreted language--namely, Lisp.
+For that reason, there is little preventing Emacs from serving the
+same role as a modern shell.  It too can manipulate the kernel in an
+unpredetermined way to cause system changes.  All it's missing is the
+shell-ish linguistic model.
+
+   Enter Eshell.  Eshell translates "shell-like" syntax into Lisp in
+order to exercise the kernel in the same manner as typical system
+shells.  There is a fundamental difference here, however, although it
+may seem subtle at first....
+
+   Shells like csh and Bourne shell were written several decades ago,
+in different times, under more restrictive circumstances.  This
+confined perspective shows itself in the paradigm used by nearly all
+command-line shells since.  They are linear in conception, byte
+stream-based, sequential, and confined to movement within a single host
+machine.
+
+   Emacs, on the other hand, is more than just a limited translator
+that can invoke subprocesses and redirect file handles.  It also
+manages character buffers, windowing frames, network connections,
+registers, bookmarks, processes, etc.  In other words, it's a very
+multi-dimensional environment, within which eshell emulates a highly
+linear methodology.
+
+   Taking a moment, let's look at how this could affect the future of a
+shell allowed to develop in such a wider field of play:
+
+   * There is no reason why directory movement should be linear, and
+     confined to a single file-system.  Emacs, through w3 and ange-ftp,
+     has access to the entire Web.  Why not allow a user to cd to
+     multiple directories simultaneously, for example?  It might make
+     some tasks easier, such as diff'ing files separated by very long
+     pathnames.
+
+   * Data sources are available from anywhere Emacs can derive
+     information from: not just from files or the output of other
+     processes.
+
+   * Multiple shell invocations all share the same environment--even
+     the same process list!  It would be possible to have "process
+     views", so that one buffer is watching standard output, another
+     standard error, and another the result of standard output grep'd
+     through a regular expression...
+
+   * It is not necessary to "leave" the shell, losing all input and
+     output history, environment variables, directory stack, etc.
+     Emacs could save the contents of your eshell environment, and
+     restore all of it (or at least as much as possible) each time you
+     restart.  This could occur automatically, without requiring
+     complex initialization scripts.
+
+   * Typos occur all of the time; many of them are repeats of common
+     errors, such as `dri' for `dir'.  Since executing non-existent
+     programs is rarely the intention of the user, eshell could prompt
+     for the replacement string, and then record that in a database of
+     known misspellings. (Note: The typo at the beginning of this
+     paragraph wasn't discovered until two months after I wrote the
+     text; it was not intentional).
+
+   * Emacs' register and bookmarking facilities can be used for
+     remembering where you've been, and what you've seen--to varying
+     levels of persistence.  They could perhaps even be tied to
+     specific "moments" during eshell execution, which would include
+     the environment at that time, as well as other variables.
+     Although this would require functionality orthogonal to Emacs' own
+     bookmarking facilities, the interface used could be made to
+     operate very similarly.
+
+   This presents a brief idea of what the fuller dimensionality of an
+Emacs shell could offer.  It's not just the language of a shell that
+determines how it's used, but also the Weltanschauung underlying its
+design--and which is felt behind even the smallest feature.  I would
+hope the freedom provided by using Emacs as a parent environment will
+invite rich ideas from others.  It certainly feels as though all I've
+done so far is to tie down the horse, so to speak, so that he will run
+at a man's pace.
+
+Influences
+==========
+
+   The author of Eshell has been a long-time user of the following
+shells, all of which contributed to Eshell's design:
+
+   * rc
+
+   * bash
+
+   * zsh
+
+   * sh
+
+   * 4nt
+
+   * csh
+
+;;; em-alias --- creation and management of command aliases
+
+;; Copyright (C) 1999, 2000 Free Software Foundation
+
+;; Author: John Wiegley <johnw@gnu.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+(provide 'em-alias)
+
+(eval-when-compile (require 'esh-maint))
+
+(defgroup eshell-alias nil
+  "Command aliases allow for easy definition of alternate commands."
+  :tag "Command aliases"
+  :link '(info-link "(eshell)Command aliases")
+  :group 'eshell-module)
+
+;;; Commentary:
+
+;; Command aliases greatly simplify the definition of new commands.
+;; They exist as an alternative to alias functions, which are
+;; otherwise quite superior, being more flexible and natural to the
+;; Emacs Lisp environment (if somewhat trickier to define; [Alias
+;; functions]).
+;;
+;;;_* Creating aliases
+;;
+;; The user interface is simple: type 'alias' followed by the command
+;; name followed by the definition.  Argument references are made
+;; using '$1', '$2', etc., or '$*'.  For example:
+;;
+;;   alias ll 'ls -l $*'
+;;
+;; This will cause the command 'll NEWS' to be replaced by 'ls -l
+;; NEWS'.  This is then passed back to the command parser for
+;; reparsing.{Only the command text specified in the alias definition
+;; will be reparsed.  Argument references (such as '$*') are handled
+;; using variable values, which means that the expansion will not be
+;; reparsed, but used directly.}
+;;
+;; To delete an alias, specify its name without a definition:
+;;
+;;   alias ll
+;;
+;; Aliases are written to disk immediately after being defined or
+;; deleted.  The filename in which they are kept is defined by the
+;; following variable:
+
+(defcustom eshell-aliases-file (concat eshell-directory-name "alias")
+  "*The file in which aliases are kept.
+Whenever an alias is defined by the user, using the `alias' command,
+it will be written to this file.  Thus, alias definitions (and
+deletions) are always permanent.  This approach was chosen for the
+sake of simplicity, since that's pretty much the only benefit to be
+gained by using this module."
+  :type 'file
+  :group 'eshell-alias)
+
+;;;
+;; The format of this file is quite basic.  It specifies the alias
+;; definitions in almost exactly the same way that the user entered
+;; them, minus any argument quoting (since interpolation is not done
+;; when the file is read).  Hence, it is possible to add new aliases
+;; to the alias file directly, using a text editor rather than the
+;; `alias' command.  Or, this method can be used for editing aliases
+;; that have already defined.
+;;
+;; Here is an example of a few different aliases, and they would
+;; appear in the aliases file:
+;;
+;;   alias clean rm -fr **/.#*~
+;;   alias commit cvs commit -m changes $*
+;;   alias ll ls -l $*
+;;   alias info (info)
+;;   alias reindex glimpseindex -o ~/Mail
+;;   alias compact for i in ~/Mail/**/*~*.bz2(Lk+50) { bzip2 -9v $i }
+;;
+;;;_* Auto-correction of bad commands
+;;
+;; When a user enters the same unknown command many times during a
+;; session, it is likely that they are experiencing a spelling
+;; difficulty associated with a certain command.  To combat this,
+;; Eshell will offer to automatically define an alias for that
+;; mispelled command, once a given tolerance threshold has been
+;; reached.
+
+(defcustom eshell-bad-command-tolerance 3
+  "*The number of failed commands to ignore before creating an alias."
+  :type 'integer
+  :link '(custom-manual "(eshell)Auto-correction of bad commands")
+  :group 'eshell-alias)
+
+;;;
+;; Whenever the same bad command name is encountered this many times,
+;; the user will be prompted in the minibuffer to provide an alias
+;; name.  An alias definition will then be created which will result
+;; in an equal call to the correct name.  In this way, Eshell
+;; gradually learns about the commands that the user mistypes
+;; frequently, and will automatically correct them!
+;;
+;; Note that a '$*' is automatically appended at the end of the alias
+;; definition, so that entering it is unnecessary when specifying the
+;; corrected command name.
+
+;;; Code:
+
+(defcustom eshell-alias-load-hook '(eshell-alias-initialize)
+  "*A hook that gets run when `eshell-alias' is loaded."
+  :type 'hook
+  :group 'eshell-alias)
+
+(defvar eshell-command-aliases-list nil
+  "A list of command aliases currently defined by the user.
+Each element of this alias is a list of the form:
+
+  (NAME DEFINITION)
+
+Where NAME is the textual name of the alias, and DEFINITION is the
+command string to replace that command with.
+
+Note: this list should not be modified in your '.emacs' file.  Rather,
+any desired alias definitions should be declared using the `alias'
+command, which will automatically write them to the file named by
+`eshell-aliases-file'.")
+
+(put 'eshell-command-aliases-list 'risky-local-variable t)
+
+(defvar eshell-failed-commands-alist nil
+  "An alist of command name failures.")
+
+(defun eshell-alias-initialize ()
+  "Initialize the alias handling code."
+  (make-local-variable 'eshell-failed-commands-alist)
+  (make-local-hook 'eshell-alternate-command-hook)
+  (add-hook 'eshell-alternate-command-hook 'eshell-fix-bad-commands t t)
+  (eshell-read-aliases-list)
+  (make-local-hook 'eshell-named-command-hook)
+  (add-hook 'eshell-named-command-hook 'eshell-maybe-replace-by-alias t t)
+  (make-local-variable 'eshell-complex-commands)
+  (add-to-list 'eshell-complex-commands 'eshell-command-aliased-p))
+
+(defun eshell-command-aliased-p (name)
+  (member name eshell-command-aliases-list))
+
+(defun eshell/alias (&optional alias &rest definition)
+  "Define an ALIAS in the user's alias list using DEFINITION."
+  (if (not alias)
+      (eshell-for alias eshell-command-aliases-list
+	(eshell-print (apply 'format "alias %s %s\n" alias)))
+    (if (not definition)
+	(setq eshell-command-aliases-list
+	      (delq (assoc alias eshell-command-aliases-list)
+		    eshell-command-aliases-list))
+      (and (stringp definition)
+	   (set-text-properties 0 (length definition) nil definition))
+      (let ((def (assoc alias eshell-command-aliases-list))
+	    (alias-def (list alias
+			     (eshell-flatten-and-stringify definition))))
+	(if def
+	    (setq eshell-command-aliases-list
+		  (delq def eshell-command-aliases-list)))
+	(setq eshell-command-aliases-list
+	      (cons alias-def eshell-command-aliases-list))))
+    (eshell-write-aliases-list))
+  nil)
+
+(defun pcomplete/eshell-mode/alias ()
+  "Completion function for Eshell's `alias' command."
+  (pcomplete-here (eshell-alias-completions pcomplete-stub)))
+
+(defun eshell-read-aliases-list ()
+  "Read in an aliases list from `eshell-aliases-file'."
+  (let ((file eshell-aliases-file))
+    (when (file-readable-p file)
+      (setq eshell-command-aliases-list
+	    (with-temp-buffer
+	      (let (eshell-command-aliases-list)
+		(insert-file-contents file)
+		(while (not (eobp))
+		  (if (re-search-forward
+		       "^alias\\s-+\\(\\S-+\\)\\s-+\\(.+\\)")
+		      (setq eshell-command-aliases-list
+			    (cons (list (match-string 1)
+					(match-string 2))
+				  eshell-command-aliases-list)))
+		  (forward-line 1))
+		eshell-command-aliases-list))))))
+
+(defun eshell-write-aliases-list ()
+  "Write out the current aliases into `eshell-aliases-file'."
+  (if (file-writable-p (file-name-directory eshell-aliases-file))
+      (let ((eshell-current-handles
+	     (eshell-create-handles eshell-aliases-file 'overwrite)))
+	(eshell/alias)
+	(eshell-close-handles 0))))
+
+(defsubst eshell-lookup-alias (name)
+  "Check whether NAME is aliased.  Return the alias if there is one."
+  (assoc name eshell-command-aliases-list))
+
+(defvar eshell-prevent-alias-expansion nil)
+
+(defun eshell-maybe-replace-by-alias (command args)
+  "If COMMAND has an alias definition, call that instead using ARGS."
+  (unless (and eshell-prevent-alias-expansion
+	       (member command eshell-prevent-alias-expansion))
+    (let ((alias (eshell-lookup-alias command)))
+      (if alias
+	  (throw 'eshell-replace-command
+		 (list
+		  'let
+		  (list
+		   (list 'eshell-command-name
+			 (list 'quote eshell-last-command-name))
+		   (list 'eshell-command-arguments
+			 (list 'quote eshell-last-arguments))
+		   (list 'eshell-prevent-alias-expansion
+			 (list 'quote
+			       (cons command
+				     eshell-prevent-alias-expansion))))
+		  (eshell-parse-command (nth 1 alias))))))))
+
+(defun eshell-alias-completions (name)
+  "Find all possible completions for NAME.
+These are all the command aliases which begin with NAME."
+  (let (completions)
+    (eshell-for alias eshell-command-aliases-list
+      (if (string-match (concat "^" name) (car alias))
+	  (setq completions (cons (car alias) completions))))
+    completions))
+
+(defun eshell-fix-bad-commands (name)
+  "If the user repeatedly a bad command NAME, make an alias for them."
+  (ignore
+   (unless (file-name-directory name)
+     (let ((entry (assoc name eshell-failed-commands-alist)))
+       (if (not entry)
+	   (setq eshell-failed-commands-alist
+		 (cons (cons name 1) eshell-failed-commands-alist))
+	 (if (< (cdr entry) eshell-bad-command-tolerance)
+	     (setcdr entry (1+ (cdr entry)))
+	   (let ((alias (concat
+			 (read-string
+			  (format "Define alias for \"%s\": " name))
+			 " $*")))
+	     (eshell/alias name alias)
+	     (throw 'eshell-replace-command
+		    (list
+		     'let
+		     (list
+		      (list 'eshell-command-name
+			    (list 'quote name))
+		      (list 'eshell-command-arguments
+			    (list 'quote eshell-last-arguments))
+		      (list 'eshell-prevent-alias-expansion
+			    (list 'quote
+				  (cons name
+					eshell-prevent-alias-expansion))))
+		     (eshell-parse-command alias))))))))))
+
+;;; em-alias.el ends here
+;;; em-banner --- sample module that displays a login banner
+
+;; Copyright (C) 1999, 2000 Free Software Foundation
+
+;; Author: John Wiegley <johnw@gnu.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+(provide 'em-banner)
+
+(eval-when-compile (require 'esh-maint))
+
+(defgroup eshell-banner nil
+  "This sample module displays a welcome banner at login.
+It exists so that others wishing to create their own Eshell extension
+modules may have a simple template to begin with."
+  :tag "Login banner"
+  :link '(info-link "(eshell)Login banner")
+  :group 'eshell-module)
+
+;;; Commentary:
+
+;; There is nothing to be done or configured in order to use this
+;; module, other than to select it by customizing the variable
+;; `eshell-modules-list'.  It will then display a version information
+;; message whenever Eshell is loaded.
+;;
+;; This code is only an example of a how to write a well-formed
+;; extension module for Eshell.  The better way to display login text
+;; is to use the `eshell-script' module, and to echo the desired
+;; strings from the user's `eshell-login-script' file.
+;;
+;; There is one configuration variable, which demonstrates how to
+;; properly define a customization variable in an extension module.
+;; In this case, it allows the user to change the string which
+;; displays at login time.
+
+;;; User Variables:
+
+(defcustom eshell-banner-message "Welcome to the Emacs shell\n\n"
+  "*The banner message to be displayed when Eshell is loaded.
+This can be any sexp, and should end with at least two newlines."
+  :type 'sexp
+  :group 'eshell-banner)
+
+(put 'eshell-banner-message 'risky-local-variable t)
+
+;;; Code:
+
+(require 'esh-util)
+
+(defcustom eshell-banner-load-hook '(eshell-banner-initialize)
+  "*A list of functions to run when `eshell-banner' is loaded."
+  :type 'hook
+  :group 'eshell-banner)
+
+(defun eshell-banner-initialize ()
+  "Output a welcome banner on initialization."
+  ;; it's important to use `eshell-interactive-print' rather than
+  ;; `insert', because `insert' doesn't know how to interact with the
+  ;; I/O code used by Eshell
+  (unless eshell-non-interactive-p
+    (assert eshell-mode)
+    (assert eshell-banner-message)
+    (let ((msg (eval eshell-banner-message)))
+      (assert msg)
+      (eshell-interactive-print msg))))
+
+(eshell-deftest banner banner-displayed
+  "Startup banner is displayed at point-min"
+  (assert eshell-banner-message)
+  (let ((msg (eval eshell-banner-message)))
+    (assert msg)
+    (goto-char (point-min))
+    (looking-at msg)))
+
+;;; em-banner.el ends here
+;;; em-basic --- basic shell builtin commands
+
+;; Copyright (C) 1999, 2000 Free Software Foundation
+
+;; Author: John Wiegley <johnw@gnu.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+(provide 'em-basic)
+
+(eval-when-compile (require 'esh-maint))
+
+(defgroup eshell-basic nil
+  "The \"basic\" code provides a set of convenience functions which
+are traditionally considered shell builtins.  Since all of the
+functionality provided by them is accessible through Lisp, they are
+not really builtins at all, but offer a command-oriented way to do the
+same thing."
+  :tag "Basic shell commands"
+  :group 'eshell-module)
+
+;;; Commentary:
+
+;; There are very few basic Eshell commands -- so-called builtins.
+;; They are: echo, umask, and version.
+;;
+;;;_* `echo'
+;;
+;; The `echo' command repeats its arguments to the screen.  It is
+;; optional whether this is done in a Lisp-friendly fashion (so that
+;; the value of echo is useful to a Lisp command using the result of
+;; echo as an argument), or whether it should try to act like a normal
+;; shell echo, and always result in a flat string being returned.
+
+(defcustom eshell-plain-echo-behavior nil
+  "*If non-nil, `echo' tries to behave like an ordinary shell echo.
+This comes at some detriment to Lisp functionality.  However, the Lisp
+equivalent of `echo' can always be achieved by using `identity'."
+  :type 'boolean
+  :group 'eshell-basic)
+
+;;;
+;; An example of the difference is the following:
+;;
+;;   echo Hello world
+;;
+;; If `eshell-plain-echo-behavior' is non-nil, this will yield the
+;; string "Hello world".  If Lisp behavior is enabled, however, it
+;; will yield a list whose two elements are the strings "Hello" and
+;; "world".  The way to write an equivalent expression for both would
+;; be:
+;;
+;;   echo "Hello world"
+;;
+;; This always returns a single string.
+;;
+;;;_* `umask'
+;;
+;; The umask command changes the default file permissions for newly
+;; created files.  It uses the same syntax as bash.
+;;
+;;;_* `version'
+;;
+;; This command reports the version number for Eshell and all its
+;; dependent module, including the date when those modules were last
+;; modified.
+
+;;; Code:
+
+(require 'esh-opt)
+
+;;; Functions:
+
+(defun eshell-echo (args &optional output-newline)
+  "Implementation code for a Lisp version of `echo'.
+It returns a formatted value that should be passed to `eshell-print'
+or `eshell-printn' for display."
+  (if eshell-plain-echo-behavior
+      (concat (apply 'eshell-flatten-and-stringify args) "\n")
+    (let ((value
+	   (cond
+	    ((= (length args) 0) "")
+	    ((= (length args) 1)
+	     (car args))
+	    (t
+	     (mapcar
+	      (function
+	       (lambda (arg)
+		 (if (stringp arg)
+		     (set-text-properties 0 (length arg) nil arg))
+		 arg))
+	      args)))))
+      (if output-newline
+	  (cond
+	   ((stringp value)
+	    (concat value "\n"))
+	   ((listp value)
+	    (append value (list "\n")))
+	   (t
+	    (concat (eshell-stringify value) "\n")))
+	value))))
+
+(defun eshell/echo (&rest args)
+  "Implementation of `echo'.  See `eshell-plain-echo-behavior'."
+  (eshell-eval-using-options
+   "echo" args
+   '((?n nil nil output-newline "terminate with a newline")
+     (?h "help" nil nil "output this help screen")
+     :preserve-args
+     :usage "[-n] [object]")
+   (eshell-echo args output-newline)))
+
+(defun eshell/printnl (&rest args)
+  "Print out each of the argument, separated by newlines."
+  (let ((elems (eshell-flatten-list args)))
+    (while elems
+      (eshell-printn (eshell-echo (list (car elems))))
+      (setq elems (cdr elems)))))
+
+(defun eshell/listify (&rest args)
+  "Return the argument(s) as a single list."
+  (if (> (length args) 1)
+      args
+    (if (listp (car args))
+	(car args)
+      (list (car args)))))
+
+(defun eshell/umask (&rest args)
+  "Shell-like implementation of `umask'."
+  (eshell-eval-using-options
+   "umask" args
+   '((?S "symbolic" nil symbolic-p "display umask symbolically")
+     (?h "help" nil nil  "display this usage message")
+     :usage "[-S] [mode]")
+   (if (or (not args) symbolic-p)
+       (let ((modstr
+	      (concat "000"
+		      (format "%o"
+			      (logand (lognot (default-file-modes))
+				      511)))))
+	 (setq modstr (substring modstr (- (length modstr) 3)))
+	 (when symbolic-p
+	   (let ((mode (default-file-modes)))
+	     (setq modstr
+		   (format
+		    "u=%s,g=%s,o=%s"
+		    (concat (and (= (logand mode 64) 64) "r")
+			    (and (= (logand mode 128) 128) "w")
+			    (and (= (logand mode 256) 256) "x"))
+		    (concat (and (= (logand mode 8) 8) "r")
+			    (and (= (logand mode 16) 16) "w")
+			    (and (= (logand mode 32) 32) "x"))
+		    (concat (and (= (logand mode 1) 1) "r")
+			    (and (= (logand mode 2) 2) "w")
+			    (and (= (logand mode 4) 4) "x"))))))
+	 (eshell-printn modstr))
+     (setcar args (eshell-convert (car args)))
+     (if (numberp (car args))
+	 (set-default-file-modes
+	  (- 511 (car (read-from-string
+		       (concat "?\\" (number-to-string (car args)))))))
+       (error "setting umask symbolically is not yet implemented"))
+     (eshell-print
+      "Warning: umask changed for all new files created by Emacs.\n"))
+   nil))
+
+(eval-when-compile
+  (defvar print-func))
+
+;;; em-basic.el ends here
+;;; em-cmpl --- completion using the TAB key
+
+;; Copyright (C) 1999, 2000 Free Software Foundation
+
+;; Author: John Wiegley <johnw@gnu.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+(provide 'em-cmpl)
+
+(eval-when-compile (require 'esh-maint))
+
+(defgroup eshell-cmpl nil
+  "This module provides a programmable completion function bound to
+the TAB key, which allows for completing command names, file names,
+variable names, arguments, etc."
+  :tag "Argument completion"
+  :group 'eshell-module)
+
+;;; Commentary:
+
+;; Eshell, by using the pcomplete package, provides a full
+;; programmable completion facility that is comparable to shells like
+;; tcsh or zsh.
+;;
+;; Completions are context-sensitive, which means that pressing <TAB>
+;; after the command 'rmdir' will result in a list of directories,
+;; while doing so after 'rm' will result in a list of all file
+;; entries.
+;;
+;; Many builtin completion rules are provided, for commands such as
+;; `cvs', or RedHat's `rpm' utility.  Adding new completion rules is
+;; no more difficult than writing a plain Lisp functions, and they can
+;; be debugged, profiled, and compiled using exactly the same
+;; facilities (since in fact, they *are* just Lisp functions).  See
+;; the definition of the function `pcomplete/make' for an example of
+;; how to write a completion function.
+;;
+;; The completion facility is very easy to use.  Just press TAB.  If
+;; there are a large number of possible completions, a buffer will
+;; appear showing a list of them.  Completions may be selected from
+;; that buffer using the mouse.  If no completion is selected, and the
+;; user starts doing something else, the display buffer will
+;; automatically disappear.
+;;
+;; If the list of possible completions is very small, Eshell will
+;; "cycle" through them, selecting a different entry each time <TAB>
+;; is pressed.  <S-TAB> may be used to cycle in the opposite
+;; direction.
+;;
+;; Glob patterns can also be cycled.  For example, entering 'echo
+;; x*<tab>' will cycle through all the filenames beginning with 'x'.
+;; This is done because the glob list is treated as though it were a
+;; list of possible completions.  Pressing <C-c SPC> will insert all
+;; of the matching glob patterns at point.
+;;
+;; If a Lisp form is being entered, <TAB> will complete the Lisp
+;; symbol name, in exactly the same way that <M-TAB> does in Emacs
+;; Lisp mode.
+;;
+;; The list of possible completions can be viewed at any point by
+;; pressing <M-?>.
+;;
+;; Finally, context-related help can be accessed by pressing <C-c i>.
+;; This only works well if the completion function has provided Eshell
+;; with sufficient pointers to locate the relevant help text.
+
+;;; User Variables:
+
+(defcustom eshell-cmpl-load-hook '(eshell-cmpl-initialize)
+  "*A list of functions to run when `eshell-cmpl' is loaded."
+  :type 'hook
+  :group 'eshell-cmpl)
+
+(defcustom eshell-show-lisp-completions nil
+  "*If non-nil, include Lisp functions in the command completion list.
+If this variable is nil, Lisp completion can still be done in command
+position by using M-TAB instead of TAB."
+  :type 'boolean
+  :group 'eshell-cmpl)
+
+(defcustom eshell-show-lisp-alternatives t
+  "*If non-nil, and no other completions found, show Lisp functions.
+Setting this variable means nothing if `eshell-show-lisp-completions'
+is non-nil."
+  :type 'boolean
+  :group 'eshell-cmpl)
+
+(defcustom eshell-no-completion-during-jobs t
+  "*If non-nil, don't allow completion while a process is running."
+  :type 'boolean
+  :group 'eshell-cmpl)
+
+(defcustom eshell-command-completions-alist
+  '(("acroread" . "\\.pdf\\'")
+    ("xpdf"     . "\\.pdf\\'")
+    ("ar"       . "\\.[ao]\\'")
+    ("gcc"      . "\\.[Cc]\\([Cc]\\|[Pp][Pp]\\)?\\'")
+    ("g++"      . "\\.[Cc]\\([Cc]\\|[Pp][Pp]\\)?\\'")
+    ("cc"       . "\\.[Cc]\\([Cc]\\|[Pp][Pp]\\)?\\'")
+    ("CC"       . "\\.[Cc]\\([Cc]\\|[Pp][Pp]\\)?\\'")
+    ("acc"      . "\\.[Cc]\\([Cc]\\|[Pp][Pp]\\)?\\'")
+    ("bcc"      . "\\.[Cc]\\([Cc]\\|[Pp][Pp]\\)?\\'")
+    ("objdump"  . "\\(\\`[^.]*\\|\\.[ao]\\)\\'")
+    ("nm"       . "\\(\\`[^.]*\\|\\.[ao]\\)\\'")
+    ("gdb"      . "\\`\\([^.]*\\|a\\.out\\)\\'")
+    ("dbx"      . "\\`\\([^.]*\\|a\\.out\\)\\'")
+    ("sdb"      . "\\`\\([^.]*\\|a\\.out\\)\\'")
+    ("adb"      . "\\`\\([^.]*\\|a\\.out\\)\\'"))
+  "*An alist that defines simple argument type correlations.
+This is provided for common commands, as a simplistic alternative
+to writing a completion function."
+  :type '(repeat (cons string regexp))
+  :group 'eshell-cmpl)
+
+(defcustom eshell-cmpl-file-ignore "~\\'"
+  (documentation-property 'pcomplete-file-ignore
+			  'variable-documentation)
+  :type (get 'pcomplete-file-ignore 'custom-type)
+  :group 'eshell-cmpl)
+
+(defcustom eshell-cmpl-dir-ignore
+  (format "\\`\\(\\.\\.?\\|CVS\\)%c\\'" directory-sep-char)
+  (documentation-property 'pcomplete-dir-ignore
+			  'variable-documentation)
+  :type (get 'pcomplete-dir-ignore 'custom-type)
+  :group 'eshell-cmpl)
+
+(defcustom eshell-cmpl-ignore-case (eshell-under-windows-p)
+  (documentation-property 'pcomplete-ignore-case
+			  'variable-documentation)
+  :type (get 'pcomplete-ignore-case 'custom-type)
+  :group 'eshell-cmpl)
+
+(defcustom eshell-cmpl-autolist nil
+  (documentation-property 'pcomplete-autolist
+			  'variable-documentation)
+  :type (get 'pcomplete-autolist 'custom-type)
+  :group 'eshell-cmpl)
+
+(defcustom eshell-cmpl-suffix-list (list directory-sep-char ?:)
+  (documentation-property 'pcomplete-suffix-list
+			  'variable-documentation)
+  :type (get 'pcomplete-suffix-list 'custom-type)
+  :group 'pcomplete)
+
+(defcustom eshell-cmpl-recexact nil
+  (documentation-property 'pcomplete-recexact
+			  'variable-documentation)
+  :type (get 'pcomplete-recexact 'custom-type)
+  :group 'eshell-cmpl)
+
+(defcustom eshell-cmpl-man-function 'man
+  (documentation-property 'pcomplete-man-function
+			  'variable-documentation)
+  :type (get 'pcomplete-man-function 'custom-type)
+  :group 'eshell-cmpl)
+
+(defcustom eshell-cmpl-compare-entry-function 'file-newer-than-file-p
+  (documentation-property 'pcomplete-compare-entry-function
+			  'variable-documentation)
+  :type (get 'pcomplete-compare-entry-function 'custom-type)
+  :group 'eshell-cmpl)
+
+(defcustom eshell-cmpl-expand-before-complete nil
+  (documentation-property 'pcomplete-expand-before-complete
+			  'variable-documentation)
+  :type (get 'pcomplete-expand-before-complete 'custom-type)
+  :group 'eshell-cmpl)
+
+(defcustom eshell-cmpl-cycle-completions t
+  (documentation-property 'pcomplete-cycle-completions
+			  'variable-documentation)
+  :type (get 'pcomplete-cycle-completions 'custom-type)
+  :group 'eshell-cmpl)
+
+(defcustom eshell-cmpl-cycle-cutoff-length 5
+  (documentation-property 'pcomplete-cycle-cutoff-length
+			  'variable-documentation)
+  :type (get 'pcomplete-cycle-cutoff-length 'custom-type)
+  :group 'eshell-cmpl)
+
+(defcustom eshell-cmpl-restore-window-delay 1
+  (documentation-property 'pcomplete-restore-window-delay
+			  'variable-documentation)
+  :type (get 'pcomplete-restore-window-delay 'custom-type)
+  :group 'eshell-cmpl)
+
+(defcustom eshell-command-completion-function
+  (function
+   (lambda ()
+     (pcomplete-here (eshell-complete-commands-list))))
+  (documentation-property 'pcomplete-command-completion-function
+			  'variable-documentation)
+  :type (get 'pcomplete-command-completion-function 'custom-type)
+  :group 'eshell-cmpl)
+
+(defcustom eshell-cmpl-command-name-function
+  'eshell-completion-command-name
+  (documentation-property 'pcomplete-command-name-function
+			  'variable-documentation)
+  :type (get 'pcomplete-command-name-function 'custom-type)
+  :group 'eshell-cmpl)
+
+(defcustom eshell-default-completion-function
+  (function
+   (lambda ()
+     (while (pcomplete-here
+	     (pcomplete-dirs-or-entries
+	      (cdr (assoc (funcall eshell-cmpl-command-name-function)
+			  eshell-command-completions-alist)))))))
+  (documentation-property 'pcomplete-default-completion-function
+			  'variable-documentation)
+  :type (get 'pcomplete-default-completion-function 'custom-type)
+  :group 'eshell-cmpl)
+
+(defcustom eshell-cmpl-use-paring t
+  (documentation-property 'pcomplete-use-paring 'variable-documentation)
+  :type (get 'pcomplete-use-paring 'custom-type)
+  :group 'eshell-cmpl)
+
+;;; Functions:
+
+(defun eshell-cmpl-initialize ()
+  "Initialize the completions module."
+  (unless (fboundp 'pcomplete)
+    (load "pcmpl-auto" t t))
+  (set (make-local-variable 'pcomplete-command-completion-function)
+       eshell-command-completion-function)
+  (set (make-local-variable 'pcomplete-command-name-function)
+       eshell-cmpl-command-name-function)
+  (set (make-local-variable 'pcomplete-default-completion-function)
+       eshell-default-completion-function)
+  (set (make-local-variable 'pcomplete-parse-arguments-function)
+       'eshell-complete-parse-arguments)
+  (set (make-local-variable 'pcomplete-file-ignore)
+       eshell-cmpl-file-ignore)
+  (set (make-local-variable 'pcomplete-dir-ignore)
+       eshell-cmpl-dir-ignore)
+  (set (make-local-variable 'pcomplete-ignore-case)
+       eshell-cmpl-ignore-case)
+  (set (make-local-variable 'pcomplete-autolist)
+       eshell-cmpl-autolist)
+  (set (make-local-variable 'pcomplete-suffix-list)
+       eshell-cmpl-suffix-list)
+  (set (make-local-variable 'pcomplete-recexact)
+       eshell-cmpl-recexact)
+  (set (make-local-variable 'pcomplete-man-function)
+       eshell-cmpl-man-function)
+  (set (make-local-variable 'pcomplete-compare-entry-function)
+       eshell-cmpl-compare-entry-function)
+  (set (make-local-variable 'pcomplete-expand-before-complete)
+       eshell-cmpl-expand-before-complete)
+  (set (make-local-variable 'pcomplete-cycle-completions)
+       eshell-cmpl-cycle-completions)