[comp.emacs] lispdir.el and lispdir.doc

dsill@RELAY.NSWC.NAVY.MIL (04/22/89)

I've received enough requests for these that it's easier for me to
send them to everyone. :-)

First is the doc file...

		 Answers to Commonly Asked Questions
	       About the GNU Emacs Lisp Code Directory


Q. What *is* the Lisp Code Directory?
A. Originally it was simply a list, in tabular form, of various
packages of GNU Emacs Lisp code that had been posted to one of the
Emacs-related Internet or USENET mailing lists or newsgroups.  Later
it became a flat-file database and associated formatting software.
Today it includes over 350 entries, also contains entries for the
packages in the standard GNU Emacs distribution, and there are three
different software packages available for use with it.

Q. Where can I get a copy of the Directory?
A. It's posted periodically to the aforementioned lists.  You can
request a copy directly from the custodian, Dave Sill, via
dsill@relay.nswc.navy.mil.  It is not currently available via ftp.

Q. How can I get a copy of a package listed in the Directory?
A. Good question.  There does not exist a repository of all the
packages in the Directory.  The "contact" field in the database
indicates where one can find the code.  In the case of a package
that's part of the standard Emacs distribution, you probably already
have it in your $EMACS/lisp directory.  Most of the other code is
available directly from the author or poster.  PLEASE don't ask the
custodian, Dave Sill, to send you code.  If you're unable to find a
copy through the listed contact, post a query to gnu.emacs,
info-gnu-emacs, or your favorite Emacs group.

Q. What are the three formatting packages?
A. There's the original `format' shell/awk script, an elisp package
called `lispdir', and a perl script (called `format.perl' for lack of
a better name).  Format and format.perl both produce a tabular format
similar to the original pre-database Directory.  Lispdir is a little
more flexible.  It currently produces a full-directory report in three
different formats, two of which are tabular.  It also provides a
function called lisp-dir-apropos that pops up a buffer containing
entries that relate to a given topic.  Lispdir is the preferred
formatting package.

Q. How can I get my package added to the Directory or get typos or
inaccuracies fixed?
A. Hopefully all packages posted to an Emacs group/list are added
automatically.  If you've posted something and don't see it in the
next release of the directory, or you have corrections or suggestions
of any kind, send them to Dave Sill, dsill@relay.nswc.navy.mil.

Now, lispdir.el...

;;;;;;;;;;;;;;;;;;;;;;;;;;; -*- Mode: Emacs-Lisp -*- ;;;;;;;;;;;;;;;;;;;;;;;;;;
;; lispdir.el --- Lisp code directory formatter and apropos
;; Authors         : Ashwin Ram (Ram-Ashwin@cs.yale.edu)
;;                 ; Dave Sill (dsill@relay.nswc.navy.mil)
;;                 ; David Lawrence (tale@pawl.rpi.edu)
;; Created On      : Wed Jan 25, 1989
;; Last Modified By: dsill
;; Last Modified On: Tue Feb 28 14:59:14 1989
;; Update Count    : 8
;; Status          : No known bugs.
;; Version         : 2.1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; History 		
;; 28-Feb-1989		dsill	
;;    Changed format-lcd-line-Sill to be smart about GNU-distributed code.
;;    Changed format-lcd-line-Sill to take advantage of 12-char max name.

;; 22-Feb-1989		dsill	
;;    Changed format-lisp-code-directory and lisp-dir-apropos to call the
;;      line formatter indirectly.  The variable 
;;      format-lisp-code-directory-line contains a function to format a single
;;      line, and format-lcd-line-Ram, format-lcd-line-tale, and
;;      format-lcd-line-Sill are the three possibilities at this time.

;; 20-Feb-1989		tale	
;;    changed file's name to lispdir.el
;;    format-lisp-code-directory makes separate buffer
;;    removed lisp-dir-apropos-buffer -- why use more space in memory?
;;    added lisp-dir-[apropos-]hook
;;      (I like (setq lisp-dir-hook 'delete-other-windows))
;;    other aesthetic changes

;; 16-Feb-1989		dsill	
;;    Added lisp-dir-apropos function

(require 'picture)			;provides move-to-column-force

(defvar lisp-code-directory "~/gelcd/datafile"
  "Database of free lisp code.  Entries are in the form:
Name|Author|Contact|Description|Date|Version")

(defvar format-lisp-code-directory-line 'format-lcd-line-Sill
  "Function that formats one line of GNU Emacs Lisp code directory.\n
Provided as a variable for customizability.  Should not insert
final newline.")

(defvar lisp-code-directory-header 'lcd-header-Sill
  "Function that inserts header appropriate for 
format-lisp-code-directory-line.")

(defun format-lisp-code-directory ()
   "Convert GNU Emacs Lisp code directory into something a human could read.
Calls value of lisp-dir-hook with no args if that value is non-nil."
   (interactive)
   (pop-to-buffer "*Lisp Code Directory*")
   (fundamental-mode)
   (setq buffer-read-only nil)
   (erase-buffer)
   (buffer-flush-undo (current-buffer))
   (insert-file lisp-code-directory)
   (insert " GNU Emacs Lisp code directory.  " (current-time-string) ".\n\n")
   (message "Formatting %s ..." lisp-code-directory)
   (delete-region (progn (beginning-of-line) (point))
		  (progn (end-of-line) (point)))
   (funcall lisp-code-directory-header)
   (while (re-search-forward
	   "\\(.*\\)|\\(.*\\)|\\(.*\\)|\\(.*\\)|\\(.*\\)|\\(.*\\)" nil t)
      (let ((name (buffer-substring (match-beginning 1) (match-end 1)))
            (author (buffer-substring (match-beginning 2) (match-end 2)))
            (contact (buffer-substring (match-beginning 3) (match-end 3)))
            (description (buffer-substring (match-beginning 4) (match-end 4)))
            (date (buffer-substring (match-beginning 5) (match-end 5)))
            (version (buffer-substring (match-beginning 6) (match-end 6))))
         (delete-region (progn (beginning-of-line) (point))
			(progn (end-of-line) (point)))
         (funcall format-lisp-code-directory-line
	  name author contact description date version)))
   (goto-char (point-min))
   (center-line)
   (message "Formatting %s ... done" lisp-code-directory)
   (set-buffer-modified-p nil)
   (run-hooks 'lisp-dir-hook))

(defun lisp-dir-apropos (topic)
  "Display entries in Lisp Code Directory for TOPIC in separate window.
Calls value of lisp-dir-apropos-hook with no args if that value is non-nil."
  (interactive (list
		(read-string
		 (concat "Lisp Directory apropos (" (current-word) "): "))))
  (if (equal "" topic) (setq topic (current-word)))
  (save-excursion
    (set-buffer (get-buffer-create "*Lisp Directory Apropos*"))
    (fundamental-mode)
    (setq buffer-read-only nil)
    (erase-buffer)
    (buffer-flush-undo (current-buffer))
    (insert-file lisp-code-directory)
    (message "Searching for %s ..." topic)
    (delete-non-matching-lines topic)
    (insert "Emacs Lisp Code Apropos -- \"" topic "\"\n\n\n")
    (backward-char 1)
    (funcall lisp-code-directory-header)
    (while (re-search-forward
	    "\\(.*\\)|\\(.*\\)|\\(.*\\)|\\(.*\\)|\\(.*\\)|\\(.*\\)" nil t)
      (let ((name (buffer-substring (match-beginning 1) (match-end 1)))
	    (author (buffer-substring (match-beginning 2) (match-end 2)))
	    (contact (buffer-substring (match-beginning 3) (match-end 3)))
	    (description (buffer-substring (match-beginning 4) (match-end 4)))
	    (date (buffer-substring (match-beginning 5) (match-end 5)))
	    (version (buffer-substring (match-beginning 6) (match-end 6))))
	(delete-region (progn (beginning-of-line) (point))
		       (progn (end-of-line) (point)))
	(funcall format-lisp-code-directory-line
	 name author contact description date version)))
    (goto-char (point-min))
    (center-line)
    (message "Searching for %s ... done" topic)
    (set-buffer-modified-p nil))
  (display-buffer "*Lisp Directory Apropos*")
  (run-hooks 'lisp-dir-apropos-hook))

(defun format-lcd-line-Ram
  (name author contact description date version)
  "Columnar formatter for Lisp code directory that tries to use as few lines
as possible.  Doesn't fit Contact within first 80 columns."
   (insert-at-column 1  name)
   (insert-at-column 17 description)
   (insert-at-column 49 author)
   (insert-at-column 65 date)
   (insert-at-column 74 "/")
   (insert-at-column 75 version)
   (insert-at-column 84 contact))

(defun format-lcd-line-tale
  (name author contact description date version)
  "Multi-line columnar formatter for Lisp code directory that tries not
to write anything past column 79."
   (insert-at-column 0  name)
   (insert-at-column 17 description)
   (insert-at-column 56 author)
   (insert-at-column 4  contact)
   (insert-at-column 56 date)
   (insert-at-column 72 version))

(defun format-lcd-line-Sill
  (name author contact description date version)
  "Multi-line non-columnar line formatter for Lisp code directory."
  (insert-at-column 0 name)
  (if (not (equal version ""))
      (insert " (" version ")"))
  (insert-at-column 18 date)
  (insert "\n")
  (if (and (string-match "[0-9]+\.[0-9]+ dist" contact)
	   (equal author "FSF"))
      (insert-at-column 5 contact)
    (progn
      (insert-at-column 5 author)
      (insert ", <" contact ">\n")))
  (insert-at-column 5 description))

(defun lcd-header-Ram/tale ()
  "Inserts header for column-formatted Lisp code directory."
  (funcall format-lisp-code-directory-line
    "Name" "Author" "Contact" "Description" "Date" "Version")
  (insert "\n")
  (insert-char ?- 79)
)

(defun lcd-header-Sill ()
  "Inserts empty header for non-columnar Lisp code directory"
)

(defun insert-at-column (col string)
   (if (> (current-column) col) (insert "\n"))
   (move-to-column-force col)
   (insert string))

;; Snatched from unix-apropos by Henry Kautz
(defun current-word ()
   "Word cursor is over, as a string."
   (save-excursion
      (let (beg end)
	 (re-search-backward "\\w" nil 2)
	 (re-search-backward "\\b" nil 2)
	 (setq beg (point))
	 (re-search-forward "\\w*\\b" nil 2)
	 (setq end (point))
	 (buffer-substring beg end))))