+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(defgroup ls-lisp nil
+ "Emulate the ls program completely in Emacs Lisp."
+ :version "21.1"
+ :group 'dired)
+
+(defcustom ls-lisp-emulation
+ (cond ((eq system-type 'macos) 'MacOS)
+ ;; ((eq system-type 'windows-nt) 'MS-Windows)
+ ((memq system-type
+ '(hpux dgux usg-unix-v unisoft-unix rtu irix berkeley-unix))
+ 'UNIX)) ; very similar to GNU
+ ;; Anything else defaults to nil, meaning GNU.
+ "*Platform to emulate: GNU (default), MacOS, MS-Windows, UNIX.
+Corresponding value is one of the atoms: nil, MacOS, MS-Windows, UNIX.
+Sets default values for: `ls-lisp-ignore-case', `ls-lisp-dirs-first',
+`ls-lisp-verbosity'. Need not match actual platform. Changing this
+option will have no effect until you restart Emacs."
+ :type '(choice (const :tag "GNU" nil)
+ (const MacOS)
+ (const MS-Windows)
+ (const UNIX))
+ :group 'ls-lisp)
+
+(defcustom ls-lisp-ignore-case
+ ;; Name change for consistency with other option names.
+ (or (memq ls-lisp-emulation '(MS-Windows MacOS))
+ (and (boundp 'ls-lisp-dired-ignore-case) ls-lisp-dired-ignore-case))
+ "*Non-nil causes ls-lisp alphabetic sorting to ignore case."
+ :type 'boolean
+ :group 'ls-lisp)
+
+(defcustom ls-lisp-dirs-first (eq ls-lisp-emulation 'MS-Windows)
+ "*Non-nil causes ls-lisp to sort directories first in any ordering.
+\(Or last if it is reversed.) Follows Microsoft Windows Explorer."
+ ;; Functionality suggested by Chris McMahan <cmcmahan@one.net>
+ :type 'boolean
+ :group 'ls-lisp)
+
+(defcustom ls-lisp-verbosity
+ (cond ((eq ls-lisp-emulation 'MacOS) nil)
+ ((eq ls-lisp-emulation 'MS-Windows)
+ (if (and (fboundp 'w32-using-nt) (w32-using-nt))
+ '(links))) ; distinguish NT/2K from 9x
+ ((eq ls-lisp-emulation 'UNIX) '(links uid)) ; UNIX ls
+ (t '(links uid gid))) ; GNU ls
+ "*A list of optional file attributes that ls-lisp should display.
+It should contain none or more of the symbols: links, uid, gid.
+nil (or an empty list) means display none of them.
+
+Concepts come from UNIX: `links' means count of names associated with
+the file\; `uid' means user (owner) identifier\; `gid' means group
+identifier.
+
+If emulation is MacOS then default is nil\;
+if emulation is MS-Windows then default is `(links)' if platform is
+Windows NT/2K, nil otherwise\;
+if emulation is UNIX then default is `(links uid)'\;
+if emulation is GNU then default is `(links uid gid)'."
+ ;; Functionality suggested by Howard Melman <howard@silverstream.com>
+ :type '(set (const :tag "Show Link Count" links)
+ (const :tag "Show User" uid)
+ (const :tag "Show Group" gid))
+ :group 'ls-lisp)
+
+(defcustom ls-lisp-use-insert-directory-program
+ (not (memq system-type '(macos ms-dos windows-nt)))
+ "*Non-nil causes ls-lisp to revert back to using `insert-directory-program'.
+This is useful on platforms where ls-lisp is dumped into Emacs, such as
+Microsoft Windows, but you would still like to use a program to list
+the contents of a directory."
+ :type 'boolean
+ :group 'ls-lisp)
+
+;;; Autoloaded because it is let-bound in `recover-session', `mail-recover-1'.
+;;;###autoload
+(defcustom ls-lisp-support-shell-wildcards t
+ "*Non-nil means ls-lisp treats file patterns as shell wildcards.
+Otherwise they are treated as Emacs regexps (for backward compatibility)."
+ :type 'boolean
+ :group 'ls-lisp)
+
+(defcustom ls-lisp-format-time-list
+ '("%b %e %H:%M"
+ "%b %e %Y")
+ "*List of `format-time-string' specs to display file time stamps.
+They are used whenever a locale is not specified to use instead.
+
+Syntax: (EARLY-TIME-FORMAT OLD-TIME-FORMAT)
+
+The EARLY-TIME-FORMAT is used if file has been modified within the
+current year. The OLD-TIME-FORMAT is used for older files. To use ISO
+8601 dates, you could set:
+
+\(setq ls-lisp-format-time-list
+ '(\"%Y-%m-%d %H:%M\"
+ \"%Y-%m-%d \"))"
+ :type '(list (string :tag "Early time format")
+ (string :tag "Old time format"))
+ :group 'ls-lisp)
+
+(defvar original-insert-directory nil
+ "This holds the original function definition of `insert-directory'.")
+
+;; Remember the original insert-directory function
+(or (featurep 'ls-lisp) ; FJW: unless this file is being reloaded!
+ (setq original-insert-directory (symbol-function 'insert-directory)))
+
+;; This stub is to allow ls-lisp to parse symbolic links via another
+;; library such as w32-symlinks.el from
+;; http://centaur.maths.qmw.ac.uk/Emacs/:
+(defun ls-lisp-parse-symlink (file-name)
+ "This stub may be redefined to parse FILE-NAME as a symlink.
+It should return nil or the link target as a string."
+ nil)
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun insert-directory (file switches &optional wildcard full-directory-p)
+ "Insert directory listing for FILE, formatted according to SWITCHES.
+Leaves point after the inserted text.
+SWITCHES may be a string of options, or a list of strings.
+Optional third arg WILDCARD means treat FILE as shell wildcard.