[comp.sources.unix] v11i037: Test system for GNU Emacs, Part02/03

rs@uunet.UU.NET (Rich Salz) (09/10/87)

Submitted-by: "Mark A. Ardis" <maa@sei.cmu.edu>
Posting-number: Volume 11, Issue 37
Archive-name: test.el/Part02



#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	user.texinfo
#	example.texinfo
#	hooks.el
#	tst-utilities.el
#	box.script
#	test.el
#	tst-achieve.el
#	tst-analyze.el
#	tst-annotate.el
#	tst-capture.el
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'user.texinfo'" '(554 characters)'
if test -f 'user.texinfo'
then
	echo shar: "will not over-write existing file 'user.texinfo'"
else
sed 's/^X//' << \SHAR_EOF > 'user.texinfo'
X\input texinfo @c -*-texinfo-*-
X@settitle Using the Test Package
X@titlepage
X@center @titlefont{The GNU Emacs Test Package}
X@sp 3
X@center Mark Ardis
X@center Andy Bliven
X@center Tony Bolt
X@center Franklin Davis
X@center Carl Lagoze
X@center Lorri Menard
X@center Richard Rosenthal
X@center Mike Vilot
X@center Don Zaremba
X@sp 1
X@center Wang Institute of Graduate Studies
X@center Tyngsboro, Massachusetts 01879
X@sp 1
X@center August 4, 1987
X@sp 3
X@center @copyright{} 1987 Wang Institute of Graduate Studies
X
X@end titlepage
X
X@include test.texinfo
X
X@contents
X@bye
SHAR_EOF
if test 554 -ne "`wc -c < 'user.texinfo'`"
then
	echo shar: "error transmitting 'user.texinfo'" '(should have been 554 characters)'
fi
fi
echo shar: "extracting 'example.texinfo'" '(6208 characters)'
if test -f 'example.texinfo'
then
	echo shar: "will not over-write existing file 'example.texinfo'"
else
sed 's/^X//' << \SHAR_EOF > 'example.texinfo'
X@example
X
X  1: ;;; box.el -- Place a box around some text
X  2: ;;; Mark Ardis, Wang Institute of Graduate Studies
X  3:
X  4: (defvar box-top-left-pattern "/*"
X  5:   "* Top left corner of box as a string."
X  6: ) ; box-top-left-pattern
X  7:
X  8: (defvar box-top-right-pattern "*\"
X  9:   "* Top right corner of box as a string."
X 10: ) ; box-top-left-pattern
X 11:
X 12: (defvar box-bottom-left-pattern "\*"
X 13:   "* Bottom left corner of box as a string."
X 14: ) ; box-top-left-pattern
X 15:
X 16: (defvar box-bottom-right-pattern "*/"
X 17:   "* Bottom right corner of box as a string."
X 18: ) ; box-top-left-pattern
X 19:
X 20: ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X 21:
X 22: (defun box-region (arg)
X 23:   "Enclose the region between point and mark with a box.  With an
X 24:    argument, center the region after boxing.
X 25:    The region is 'untabify'ed as a side effect of this command.
X 26:    This function may give unexpected results if the beginning and
X 27:    end of the region are not at the beginning and end of their
X 28:    respective lines."
X 29:   (interactive "P")
X 30:                                         ; Local Variables
X 31:   (let (width)
X 32:                                         ; Body
X 33:     (save-excursion
X 34:       (narrow-to-region (point) (mark))
X 35:       (untabify (point-min) (point-max))
X 36:                                         ; Find the widest line
X 37:       (goto-char (point-min))
X 38:       (setq width 0)
X 39:       (end-of-line 1)
X 40:       (setq width (max width (current-column)))
X 41:       (while (not (eobp))
X 42:         (end-of-line 2)
X 43:         (setq width (max width (current-column)))
X 44:       ) ; while (not (eobp))
X 45:                                         ; Adjust the width for the
X 46:                                         ;   left side of the box
X 47:       (setq width (+ width 2))
X 48:                                         ; Insert beginning of box
X 49:       (goto-char (point-min))
X 50:       (open-line 1)
X 51:       (insert box-top-left-pattern)
X 52:       (box-make-wide-enough width "*")
X 53:       (insert box-top-right-pattern)
X 54:                                         ; Add vertical bars
X 55:       (while (not (eobp))
X 56:         (beginning-of-line 2)
X 57:         (insert "* ")
X 58:         (box-make-wide-enough width " ")
X 59:         (insert " *")
X 60:       ) ; while (not (eobp))
X 61:                                         ; Insert end of box
X 62:       (newline)
X 63:       (insert box-bottom-left-pattern)
X 64:       (box-make-wide-enough width "*")
X 65:       (insert box-bottom-right-pattern)
X 66:                                         ; Check for prefix argument
X 67:       (if arg
X 68:         (progn
X 69:           (goto-char (point-min))
X 70:           (center-line)
X 71:           (end-of-line 1)
X 72:           (while (not (eobp))
X 73:             (next-line 1)
X 74:             (center-line)
X 75:             (end-of-line 1)
X 76:           ) ; while (not (eobp))
X 77:         ) ; progn
X 78:       ) ; if arg
X 79:                                         ; restore initial state
X 80:       (widen)
X 81:     ) ; save-excursion
X 82:   ) ; let
X 83: ) ; defun box-region
X 84:
X 85: ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X 86:
X 87: (defun box-make-wide-enough (length char)
X 88:   "Increase the length of the current line to LENGTH,
X 89:    by padding with CHAR at the end."
X 90:                                         ; Local Variables
X 91:   (let ()
X 92:                                         ; Body
X 93:     (end-of-line 1)
X 94:     (while (< (current-column) length)
X 95:       (insert char)
X 96:     ) ; while (< (current-column) length)
X 97:   ) ; let
X 98: ) ; defun box-make-wide-enough
X 99:
X100: ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X101:
X102: (defun unbox (arg)
X103:   "Remove the box around the text that includes point.
X104:    With an argument, left-justify lines, also.
X105:    Lines unboxed have all trailing blankspace removed.
X106:    Sets region around unboxed area."
X107:   (interactive "P")
X108:                                         ; Local Variables
X109:   (let (start start-marker stop-marker)
X110:                                         ; Body
X111:                                         ; Find the beginning
X112:     (if (search-backward box-top-left-pattern (point-min) t)
X113:       (progn
X114:         (setq start (point))
X115:         (beginning-of-line 2)
X116:         (re-search-forward "\\(\\s \\)*")
X117:         (setq start-marker (make-marker))
X118:         (set-marker start-marker (+ (point) 2))
X119:       ) ; progn
X120:     ; else
X121:       (progn
X122:         (error "Cannot find the box!")
X123:       ) ; progn
X124:     ) ; if
X125:                                         ; Find the end
X126:     (if (search-forward box-bottom-right-pattern (point-max) t)
X127:       (progn
X128:         (end-of-line 0)
X129:         (backward-char 2)
X130:         (setq stop-marker (make-marker))
X131:         (set-marker stop-marker (point))
X132:       ) ; progn
X133:                                         ; else
X134:       (progn
X135:         (error "Cannot find the box!")
X136:       ) ; progn
X137:     ) ; if
X138:                                         ; Remove the top line
X139:     (goto-char start)
X140:     (beginning-of-line)
X141:     (kill-line 1)
X142:                                         ; Remove the vertical bars
X143:     (while (< (point) (marker-position stop-marker))
X144:       (if arg
X145:         (delete-horizontal-space)
X146:       ; else
X147:         (re-search-forward "\\(\\s \\)*")
X148:       ) ; if arg
X149:       (delete-char 2)
X150:       (end-of-line 1)
X151:       (delete-backward-char 2)
X152:                                         ; Trim the end of the line
X153:       (delete-horizontal-space)
X154:       (beginning-of-line 2)
X155:     ) ; while
X156:                                         ; Remove the end of the box
X157:     (kill-line 1)
X158:                                         ; Set the region
X159:     (end-of-line 0)
X160:     (set-mark (marker-position start-marker))
X161:   ) ; let
X162: ) ; defun unbox
X
X@end example
SHAR_EOF
if test 6208 -ne "`wc -c < 'example.texinfo'`"
then
	echo shar: "error transmitting 'example.texinfo'" '(should have been 6208 characters)'
fi
fi
echo shar: "extracting 'hooks.el'" '(452 characters)'
if test -f 'hooks.el'
then
	echo shar: "will not over-write existing file 'hooks.el'"
else
sed 's/^X//' << \SHAR_EOF > 'hooks.el'
X;;; hooks.el -- A number of example hooks
X;;;             for testing gnutest
X
X(setq tst-equ-point-hook 'ignore-point)
X(setq tst-equ-contents-hook 'less-white)
X
X; return t if point2 > point1
X(defun ignore-point ()
X  (setq tst-equ-result (> tst-equ-point2 tst-equ-point1))
X)
X
X
X; if contents fails then compare again but less whitespace
X(defun     less-white ()
X  (setq tst-equ-result 
X	(string-equal-less-white tst-equ-contents1 tst-equ-contents2))
X)
X
X
SHAR_EOF
if test 452 -ne "`wc -c < 'hooks.el'`"
then
	echo shar: "error transmitting 'hooks.el'" '(should have been 452 characters)'
fi
fi
echo shar: "extracting 'tst-utilities.el'" '(568 characters)'
if test -f 'tst-utilities.el'
then
	echo shar: "will not over-write existing file 'tst-utilities.el'"
else
sed 's/^X//' << \SHAR_EOF > 'tst-utilities.el'
X;;; tst-utilities.el - handy defuns from the GnuTest project -*- emacs-lisp -*-
X;;; Copyright (c) 1987 wang Institute of Graduate Studies
X
X(defun last-line (&optional buffer)
X  "Returns number of lines in BUFFER (current-buffer if nil)"
X  (save-excursion
X   (set-buffer (or buffer (current-buffer)))
X   (count-lines (point-min) (point-max))
X   )
X  )
X  
X(defun current-line ()
X  "Returns current line number"
X  (1+ (count-lines (point-min) (point)))
X  )
X
X(defun debug-on-error ()
X  "Sets the variable debug-on-error to t."
X  (interactive)
X  (setq debug-on-error t)
X  )
SHAR_EOF
if test 568 -ne "`wc -c < 'tst-utilities.el'`"
then
	echo shar: "error transmitting 'tst-utilities.el'" '(should have been 568 characters)'
fi
fi
echo shar: "extracting 'box.script'" '(2719 characters)'
if test -f 'box.script'
then
	echo shar: "will not over-write existing file 'box.script'"
else
sed 's/^X//' << \SHAR_EOF > 'box.script'
X;;; box.script - test script for box.el -*- emacs-lisp -*-
X
X(defun test-script ()
X  (interactive)
X					; Local Variables
X  (let (pre
X	post
X	actual
X	(tst-vars-exclude-default (cons "tst-ann-tricorder"
X					tst-vars-exclude-default))
X	)
X					; Body
X    (get-buffer-create "box.el")
X    (set-buffer "box.el")
X    (erase-buffer)
X    (insert-file "/project/gnutest/src/box.el")
X    (goto-char (point-min))
X    (emacs-lisp-mode)
X    (test-mode)
X    (tst-instrument)
X					; 1st test run
X    (get-buffer-create "box.demo")
X    (set-buffer "box.demo")
X    (erase-buffer)
X    (insert-file "/project/gnutest/test/box.demo")
X
X    (tst-capture-state-to-file "/project/gnutest/test/prebox.state" nil nil)
X    (goto-char (point-min))
X    (set-mark (point-max))
X    (box-region nil)
X    (tst-capture-state-to-file "/project/gnutest/test/boxed.state" nil nil)
X    (goto-char (point-max))		; cannot unbox from point-min
X    (unbox nil)
X    (tst-capture-state 'post nil nil)
X    (tst-read-state-from-file 'pre "/project/gnutest/test/prebox.state")
X
X    (tst-equ-state pre post "Compare before box to after unbox")
X
X    (set-buffer "*equal-log*")
X    (write-file "box.equallog.1")
X    (erase-buffer)
X
X    (message "Compared box state - 1")
X
X    (set-buffer "box.demo")
X    (goto-char (point-min))
X    (set-mark (point-max))
X    (box-region 1)			; centered box-region
X    (tst-capture-state-to-file "/project/gnutest/test/cboxed.state" nil nil)
X    (goto-char (point-max))		; cannot unbox from point-min
X    (unbox nil)
X    (tst-capture-state 'post nil nil)
X    (tst-equ-state pre post "Compare before cen-box to after unbox")
X    (set-buffer "*equal-log*")
X    (write-file "box.equallog.2")
X    (erase-buffer)
X
X    (message "Compared box state - 2")
X
X    (tst-read-state-from-file 'pre "/project/gnutest/test/cboxed.state")
X    (tst-read-state-from-file 'post "/project/gnutest/test/boxed.state")
X    (tst-equ-state pre post "Compare centered boxed to boxed")
X
X    (set-buffer "*equal-log*")
X    (write-file "box.equallog.3")
X    (erase-buffer)
X    (message "Compared box state - 3")
X
X;;; do some cleaning up
X    (delete-file "/project/gnutest/test/cboxed.state")
X    (delete-file "/project/gnutest/test/boxed.state")
X    (delete-file "/project/gnutest/test/prebox.state")
X
X;;; now, check the coverage
X    (set-buffer "box.demo")
X    (goto-char (point-min))
X    (set-mark (point-max))
X    (box-region 1)			; centered box-region
X    (goto-char (point-max))
X    (unbox 1)				;Now, everything should be covered!
X    (set-buffer "box.el")
X    (tst-analyze)
X    (set-variable 'tst-batch-results "box.results")
X    (tst-display-batch)
X;;    (kill-emacs 0)
X    )					; let
X  )					; defun
X
X(load-file "/project/gnutest/src/test.el")
X(test-script)
echo shar: "a missing newline was added to 'box.script'"
SHAR_EOF
if test 2719 -ne "`wc -c < 'box.script'`"
then
	echo shar: "error transmitting 'box.script'" '(should have been 2719 characters)'
fi
fi
echo shar: "extracting 'test.el'" '(5185 characters)'
if test -f 'test.el'
then
	echo shar: "will not over-write existing file 'test.el'"
else
sed 's/^X//' << \SHAR_EOF > 'test.el'
X;;; test.el - the GnuTest package
X;;; Michael J. Vilot, Wang Institute, <vilot@wanginst> 7/16/87
X;;; $Header: test.el,v 1.1 87/07/23 14:38:27 ardis Exp $
X
X(require 'tst-achieve)
X(require 'tst-analyze)
X(require 'tst-capture)
X(require 'tst-display)
X(require 'tst-equal)
X(require 'tst-inequal)
X(require 'tst-instrument)
X
X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X
X(defvar test-mode nil
X  "Minor mode symbol."
X) ; test-mode
X(make-variable-buffer-local 'test-mode)
X
X(defvar test-mode-map nil
X  "Keymap for test-mode."
X) ; test-mode-map
X
X(defvar tst-saved-map nil
X  "Local keymap to restore when turning off test-mode."
X) ; tst-saved-map
X(make-variable-buffer-local 'tst-saved-map)
X
X(defvar tst-function nil
X  "* Name of function to call to execute a set of tests."
X) ; tst-function
X(make-variable-buffer-local 'tst-function)
X
X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X
X(defun test-mode ()
X  "Toggle test-mode, a minor mode.  Calls 'test-mode-hook' if it is defined.
X   \\{test-mode-map}"
X  (interactive)
X					; Local Variables
X  (let ()
X					; Body
X    (setq test-mode (not test-mode))
X    (set-buffer-modified-p (buffer-modified-p))	; Idiom to reset modeline.
X    (if test-mode			; customise the keymap, run hooks
X	(progn
X	  (tst-make-keymap)
X	  (and (boundp 'test-mode-hook)
X	       test-mode-hook
X	       (funcall test-mode-hook))
X	  ) ; progn
X      ; else
X      (progn				; exit test mode
X	(use-local-map tst-saved-map)	; restore original bindings
X	) ; progn
X      ) ; if
X    ) ; let
X  ) ; defun test-mode
X
X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X;;; Functions to support metatest top-level
X
X(defun tst-execute ()
X  "Execute the test script."
X  (interactive)
X					; Local Variables
X  (let ()
X					; Body
X    (if (null tst-function)
X	(setq tst-function
X	      (read-string "tst-execute: tst-function = "))
X      ) ; if
X    (funcall tst-function)
X    ) ; let
X  ) ; defun tst-execute
X
X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X
X(defun tst-make-keymap ()
X  "Make keymap for test-mode."
X					; Local Variables
X  (let ()
X					; Body
X    (setq tst-saved-map (current-local-map))
X    (if (not test-mode-map)
X	(progn
X	  (setq test-mode-map tst-saved-map)
X	  (define-key test-mode-map "\^c\^a" 'tst-achieve-state-from-file)
X	  (define-key test-mode-map "\^c\^c" 'tst-capture-state-to-file)
X	  (define-key test-mode-map "\^c\^r" 'tst-read-state-from-file)
X	  (define-key test-mode-map "\^c\^w" 'tst-write-state-to-file)
X	  (define-key test-mode-map "\^ca" 'tst-achieve-state)
X	  (define-key test-mode-map "\^cc" 'tst-capture-state)
X	  (define-key test-mode-map "\^cd" 'tst-display-mode)
X	  (define-key test-mode-map "\^ci" 'tst-instrument)
X	  (define-key test-mode-map "\^cf" 'tst-analyze) ; "filter"
X	  (define-key test-mode-map "\^cn" 'tst-new-script-buffer)
X	  (define-key test-mode-map "\^cq" 'test-mode) ; exit
X	  (define-key test-mode-map "\^cx" 'tst-execute)
X	  ) ; progn
X      ) ; if
X    (use-local-map test-mode-map)
X    ) ; let
X  ) ; defun tst-make-keymap
X
X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X
X(defun tst-initialize ()
X  "Create minor mode symbol and perform any other initialization."
X					; Local Variables
X  (let ()
X					; Body
X    (or (assq 'test-mode minor-mode-alist)
X	(setq minor-mode-alist
X	      (cons '(test-mode " Test") minor-mode-alist)))
X    ) ; let
X  ) ; defun tst-initialize
X
X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X
X(defvar tst-script-buffer "*test-script*"
X  "Buffer containing user's test script."
X  ) ; defvar tst-script-buffer
X
X(defconst tst-initial-script
X  (concat
X   "(defun test-script ()\n"
X   "  (interactive)\n"
X   "					; Local Variables\n"
X   "  (let (pre post actual)\n"
X   "					; Body\n"
X   "    (switch-to-buffer foo)\n"
X   "    (erase-buffer)\n"
X   "    (insert-file foo)\n"
X   "    (goto-char (point-min))\n"
X   "    (emacs-lisp-mode)\n"
X   "    (test-mode)\n"
X   "    (tst-instrument)\n"
X   "					; 1st test run\n"
X   "    (tst-read-state-from-file post expected-state-file1)\n"
X   "    (tst-achieve-state-from-file pre initial-state-file1)\n"
X   "    (foo args)\n"
X   "    (tst-capture-state actual nil nil)\n"
X   ";;; If you have a lot of tests, consider a while loop\n"
X   "  ) ; let\n"
X   ") ; defun\n"
X   ) ; concat
X  "Initial contents of the test script buffer."
X  ) ; defconst tst-initial-script
X
X(defun tst-new-script-buffer ()
X  "Create the test script buffer and initialise its contents."
X					; Local Variables
X  (let (old-buffer (current-buffer))
X					; Body
X    (get-buffer-create tst-script-buffer) ; make the buffer
X    (save-excursion
X      (set-buffer tst-script-buffer)	; work on it
X      (emacs-lisp-mode)			; in the right mode
X      (test-mode)			; 
X      (erase-buffer)			; start fresh
X      (insert tst-initial-script)	; start with something interesting
X      (goto-char (point-min))
X      ) ; save-excursion
X;    (set-buffer old-buffer)		; switch back
X    ) ; let
X  ) ; defun tst-new-script-buffer
X
X;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X;; Things to do when the package is first loaded
X
X(tst-initialize)
X
X;;; end of test.el
SHAR_EOF
if test 5185 -ne "`wc -c < 'test.el'`"
then
	echo shar: "error transmitting 'test.el'" '(should have been 5185 characters)'
fi
fi
echo shar: "extracting 'tst-achieve.el'" '(12466 characters)'
if test -f 'tst-achieve.el'
then
	echo shar: "will not over-write existing file 'tst-achieve.el'"
else
sed 's/^X//' << \SHAR_EOF > 'tst-achieve.el'
X;; achieve.el -- functions to achieve a captured state of an emacs session
X;; This is file 2 of two files in the "regression" part of the "test" package.
X;; See also capture.el
X;; Carl Lagoze, Franklin Davis
X;; Copyright 1987 Wang Institute of Graduate Studies
X;; $Header: tst-achieve.el,v 1.8 87/07/29 22:50:12 bliven Exp $
X
X(provide 'tst-achieve)
X
X(defun member (elt list)
X  "Returns non-nil if ELT is an element of LIST.  Comparison done with equal.
XThe value is actually the tail of LIST whose car is ELT."
X  (while (and list (not (equal elt (car list))))
X    (setq list (cdr list)))
X  list)
X
X(defmacro cadr (l)
X  (list 'car (list 'cdr l)))
X
X(defmacro cddr (l)
X  (list 'cdr (list 'cdr l)))
X
X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
X;; interactive functions
X
X(defun tst-read-state-from-file (statevar file)
X  "Read a captured emacs session state into STATE VARIABLE from FILE."
X  (interactive "xState variable to read into: \nfFile Name: ")
X  (let ()
X    (save-excursion
X      (message "Reading file...")
X      (switch-to-buffer (make-temp-name "state"))
X      (insert-file file)
X      (goto-char (point-min))
X      (message "Getting state from file...")
X      (set statevar (read (current-buffer)))
X      (kill-buffer (current-buffer))
X      statevar
X      )					; save-excursion
X    )					; let
X  )					; defun tst-read-state-from-file
X
X(defun tst-achieve-state-from-file (file &optional no-process)
X  "Achieve a captured emacs session state from a FILE."
X  (interactive "fFile Name: ")
X  (let (state)
X    (tst-read-state-from-file 'state file)
X    (tst-achieve-state state no-process)
X    )					; let
X  )					; defun tst-achieve-state-from-file
X
X
X(defun tst-achieve-state (state &optional no-process)
X  "Achieve the saved state of an emacs session from variable STATE.
XIf tst-achieve-buffers-nondestructively is non nil, buffers not in
XSTATE are not killed.  If NO_PROCESS is non nil, processes are not achieved."
X  (interactive "XState to achieve: ")
X  (let ()
X    (tst-achieve-bufs-state (cadr (assoc 'buffers state)))
X    (message "Achieving state of windows...")
X    (delete-other-windows)
X    (tst-achieve-windows-state (cadr (assoc 'windows state)))
X    (or no-process
X	(tst-achieve-processes-state (cadr (assoc 'processes state))))
X    (tst-achieve-globals-state (cadr (assoc 'session state)))
X    (if (interactive-p)
X	(message (concat "Achieved state from " state ".")))
X    )					;let
X  )					;defun tst-achieve-state
X
X
X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
X;; globals
X
X(defun tst-achieve-globals-state (ses-state)
X  "Achieve global attributes saved in STATE"
X  (message "Achieving state of globals...")
X  (tst-achieve-syms (cadr (assoc 'global-bound-syms ses-state)) nil)
X  ;; (tst-achieve-ses-functions-state)
X  ;; (tst-achieve-recursive-level-state) ; only the level is captured, not 
X					; the actual stack, so useless
X  (ding) (ding)
X  )					;defun tst-achieve-globals-state
X    
X(defun tst-achieve-syms (pairs localflag)
X  "Set the value of symbols to those values in the list of PAIRS.  Make
Xvariable local first if LOCALFLAG non nil.
XEach element of PAIRS looks like (symbol-name . symbol-value)"
X    (mapcar
X					; the lambda here allows
X					; mapcar to pass a second
X					; argument localflag to
X					; function tst-achieve-sym,
X					; while applying it to every
X					; element in list pairs
X     '(lambda (pair)
X	(tst-achieve-sym pair localflag))
X     pairs)
X  ) ;defun tst-achieve-syms
X
X(defun tst-achieve-sym (pair localflag)
X  "Set the variable named by SYMBOL-NAME-PAIR to value.  Make variable
Xlocal first if LOCALFLAG not nil. 
XSYMBOL-NAME-PAIR looks like (symbol-name . symbol-value)."
X  (if localflag (make-local-variable (car pair)))
X  (cond ((equal (car pair) t) nil)	; no-op on "t" or "nil"
X	((equal (car pair) nil) nil)
X	(t (set (car pair) (tst-convert-object (cdr pair))))
X	)				; cond
X  )					; defun tst-achieve-sym
X
X(defun tst-convert-object (object)
X  "Convert all descriptions of compound objects, e.g. markers,
Xprocesses, windows, into the actual objects." 
X  (cond ((null object) object)
X	((vectorp object) object)
X	((atom object) object)
X	((equal (car object) 'marker) (tst-convert-marker object))
X	((equal (car object) 'process) (tst-convert-process object))
X	((equal (car object) 'window) nil) ; can't do anything here with window
X	((and (listp object)
X	      (atom (cdr object))
X	      (cdr object))
X					; object is a dotted pair
X	 (cons (tst-convert-object (car object))
X	       (tst-convert-object (cdr object))))
X	((listp object) (mapcar 'tst-convert-object object))
X	(t object)
X	)				; cond
X  )					; defun tst-convert-object
X
X
X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
X;;; processes
X
X(defun tst-achieve-processes-state (processes-desc)
X  "Achieve processes captured in a state, but only if interactive."
X  (message "Achieving state of processes...")
X  (mapcar 'tst-convert-process processes-desc)
X  )					; tst-achieve-processes-state
X
X(defun tst-convert-process (process-desc)
X  "Create the process described by PROCESS-DESC.  
XPROCESS-DESC looks like (process (command (comstring argstrings))
X;(exit-status 0) (filter filter-func) (name namestring) 
X;(sentinel sentinel-func) (status runstat))"
X  (let (proc live procname) 
X    (setq procname (cadr (assoc 'name (cddr process-desc))))
X    (setq live (and 
X		(car (read-from-string procname))
X		(eq (process-status procname) 'run)))
X    (if live
X	(get-process (cadr (assoc 'name (cdr process-desc))))
X					; else
X      (save-excursion
X	(setq proc
X	      (apply 'start-process 
X		     (cadr (assoc 'name (cdr process-desc)))
X		     (cadr (assoc 'buffer (cdr process-desc)))
X		     (cadr (assoc 'command (cdr process-desc)))
X		     )			; apply
X	      )				; setq
X	(set-process-filter
X	 proc
X	 (cadr (assoc 'filter (cdr process-desc))))
X	(set-process-sentinel
X	 proc
X	 (cadr (assoc 'sentinel (cdr process-desc))))
X;;;	(set-marker
X;;;	 (process-mark proc) 
X;;;	 (cadr (assoc 'position
X;;;		      (cadr (assoc 'process-mark (cdr process-desc)))))
X;;;	 (process-buffer proc))
X	proc
X	)				; save-excursion
X      )					; if
X    )					; let
X  )					; defun tst-convert-process
X
X(defun tst-convert-marker (marker-desc)
X  "Create the marker described by MARKER-DESC.  
XMARKER-DESC looks like (marker (position 23) (buffer bufname)).
XBufname is a string, and the list (buffer bufname) may be nil if no
Xbuffer is associated."
X  (set-marker (make-marker)
X	      (cadr (assoc 'position (cdr marker-desc)))
X	      (if (null (cadr (assoc 'buffer (cdr marker-desc)))) nil
X		(get-buffer (cadr (assoc 'buffer (cdr marker-desc)))))
X	      )				; set-marker
X  )					; defun tst-convert-marker
X
X
X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
X;; buffers
X
X(defun tst-achieve-bufs-state (bufs-states)
X  "Achieve the buffer states as saved in BUFS-STATES.
XSee tst-capture-buffers-state for definition of BUFS-STATES.
XIf tst-achieve-buffers-nondestructively is t, buffers not in state are
Xnot killed." 
X					; Local Variables
X  (let ((state-buf-list) (buf-list))
X    
X    ;; setup each buffer that's in bufs-states
X    (message "Achieving state of buffers...")
X    (mapcar 'tst-achieve-buf-state bufs-states) 
X
X    ;; delete superfluous buffers
X    (setq state-buf-list (mapcar 'tst-state-get-buf-name bufs-states))
X    (setq buf-list (mapcar 'buffer-name (buffer-list)))
X    (if (and (boundp tst-achieve-buffers-nondestructively)
X	     tst-achieve-buffers-nondestructively)
X	nil
X      ;; else
X      (while buf-list 
X	(if (not (member (car buf-list) state-buf-list))
X	    (progn
X	      (kill-buffer (car buf-list))
X	      (message (concat "Killing buffer " (car buf-list) "...")))
X	  (setq buf-list (cdr buf-list))
X	  )				; if
X	)				; while
X      )					; if
X    )					; let
X  )					; defun tst-achieve-bufs-state
X
X
X(defun tst-achieve-buf-state (buf-state)
X  "Achieve the buffer state in BUF-STATE.  See tst-capture-buffer-state
Xfor definition of BUF-STATE."
X                                        ; Local Variables
X  (let ()
X                                        ; create buffer, set file
X    (set-buffer (get-buffer-create (cadr (assoc 'buf-state-name buf-state))))
X    (set-visited-file-name (cadr (assoc 'buf-state-file buf-state)))
X
X                                        ; clear buffer contents and refill
X    (if buffer-read-only (toggle-read-only))
X    (delete-region (point-min) (point-max))
X    (insert (cadr (assoc 'buf-state-contents buf-state)))
X
X                                        ; set point and mark
X    (set-mark (cadr (assoc 'buf-state-mark buf-state)))
X    (goto-char (cadr (assoc 'buf-state-point buf-state)))
X
X					; set buffer flag(s)
X    (set-buffer-modified-p (cadr (assoc 'buf-state-modified buf-state)))
X
X                                        ; set local variables
X    (kill-all-local-variables)
X    (tst-achieve-local-vars (cadr (assoc 'buf-state-local-vars buf-state)))
X    (use-local-map (cadr (assoc 'buf-state-local-map buf-state)))
X    ) ; let
X  ) ; defun tst-achieve-buf-state
X
X(defun tst-achieve-local-vars (pairs)
X  "Take list of (VARIABLE . VALUE) pairs and makes local variables 
Xinitialized to the value." 
X  (let ((localflag t))
X    (mapcar
X					; the lambda here allows
X					; mapcar to pass a second
X					; argument localflag to
X					; function tst-achieve-sym
X					; while applying it to every
X					; element in list pairs
X     '(lambda (pair)
X	(tst-achieve-sym pair localflag))
X     pairs)
X    )					; let
X  )					; defun tst-achieve-local-vars
X
X(defun tst-state-get-buf-name (bufstate)
X  "Get name of buffer from BUFSTATE.  See tst-capture-buffer-state for 
Xdefinition fo BUFSTATE."
X  (cadr (assoc 'buf-state-name bufstate))
X  ) ; defun tst-state-get-buf-name
X
X
X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
X;; windows
X
X(defun tst-achieve-windows-state (wstates)
X  "Set the state of all windows to that described in the input list"
X  (let ((sibling) (leftc-edges))
X    (if (assoc 'split wstates)
X	(progn
X	  (setq leftc-edges
X		(cadr (assoc 'window-edges
X			     (car (cadr (assoc 'children wstates))))))
X	  (if (equal 'h (cadr (assoc 'split wstates)))
X	      (split-window-horizontally
X	       (-
X		(cadr (cdr leftc-edges))
X		(car leftc-edges)
X		)
X	       )
X	    ;else vertical split
X	    (split-window-vertically
X	     (-
X	      (cadr (cddr leftc-edges))
X	      (cadr leftc-edges)
X	      )
X	     )
X	    )				;if
X	  (setq sibling (next-window))
X	  ;descend to the left child
X	  (tst-achieve-windows-state (car (cadr (assoc 'children wstates))))
X	  ;go to the right child and achieve that
X	  (select-window sibling)
X	  (tst-achieve-windows-state
X	   (cadr (cadr (assoc 'children wstates))))
X	  )				;progn
X      (tst-achieve-window-state wstates)
X      )					;if assoc splits...
X    )					;let
X  )					;defun
X
X(defun tst-achieve-window-state (wstate)
X  "Set the state of the current window to that discribed in the input
X   a-list"
X  (let ()
X    (set-window-buffer (selected-window) (cadr (assoc 'window-buffer wstate)))
X    (set-window-point (selected-window) (cadr (assoc 'window-point wstate)))
X    (set-window-start (selected-window) (cadr (assoc 'window-start wstate)))
X    )					;let
X  )					;defun tst-achieve-window-state
X
X(defun tst-find-cur-window (wstates)
X  "Given an input list of WINDOW STATES, find the one that is the current
X   window of the of the state.  This window has the attribute 'current-window
X   set to t.  Return t when this window is found."
X  (let ()
X    (if (assoc 'children wstates) ;if is is a compound window
X	; descend down the left subtree
X	(if (not (tst-find-cur-window (car (cadr (assoc 'children wstates)))))
X	    ;now only descend down right subtree if left was unsuccessful
X	    (tst-find-cur-window (cadr (cadr (assoc 'children wstates))))
X	  )				;if goto-cur...
X      ; if it is a single window go to it if current-window is true
X      (if (cadr (assoc 'current-window wstates))
X	  (tst-goto-described-window wstates)
X	)				;if assoc 'current-window
X      )					;if assoc 'children...
X    )					;let
X  )					;defun
X
X(defun tst-goto-described-window (wstate)
X  "Given an input WINDOW STATE, cycle through existing windows until we
X   settle in the one with edges of the one described in the state"
X  (let ()
X    (while (not (equal (window-edges (selected-window))
X		       (cadr (assoc 'window-edges wstate))
X		       )
X		)
X      (select-window (next-window))
X      )					;while
X    )					;let
X  )					;defun tst-goto-described-window
X
SHAR_EOF
if test 12466 -ne "`wc -c < 'tst-achieve.el'`"
then
	echo shar: "error transmitting 'tst-achieve.el'" '(should have been 12466 characters)'
fi
fi
echo shar: "extracting 'tst-analyze.el'" '(2317 characters)'
if test -f 'tst-analyze.el'
then
	echo shar: "will not over-write existing file 'tst-analyze.el'"
else
sed 's/^X//' << \SHAR_EOF > 'tst-analyze.el'
X;;; tst-analyze.el -- analyze test results
X;;; Copyright (c) 1987 Wang Institute of Graduate Studies
X
X;;; Tony Bolt
X
X(require 'tst-annotate)
X(provide 'tst-analyze)
X
X(defun tst-analyze ()
X  "Driver for test analysis functions.
X   Invokes tst-anl-zero-counts and tst-anl-constant-values"
X  (interactive)
X  (message "Analyze test results (counts) ...")
X  (tst-anl-zero-counts)
X  (message "Analyze test results (values) ...")
X  (tst-anl-constant-values)
X  (message "Analyze test results (values) ... done") t)
X  
X(defun tst-anl-zero-counts ()
X  "Examines the test results stored in the annotation database looking
X   for lines with a zero count value, i.e. those that were not executed"
X  (let ((lines (tst-ann-get-lines)))
X    (cond ((null lines) nil)
X	  (t (mapcar 'tst-anl-zero-count lines)))))
X
X(defconst tst-anl-zero-count 'NEVER->>
X  "* The value used by the display package to indicate a zero count value")
X
X(defun tst-anl-zero-count (line)
X  "Given a LINE id, retrieves the value of that line's count field from
X   the annotation database.  If the value is zero, stores a new attribute, 
X   called zero, with value a string for use by the display package.
X   Otherwise remove attribute zero."
X  (let ((count (car (tst-ann-get line 'count))))
X    (cond ((equal count 0)
X	   (tst-ann-put line 'zero (list tst-anl-zero-count)))
X	  (t (tst-ann-remove-attribute line 'zero)))))
X
X(defun tst-anl-constant-values ()
X  "Examines the test results stored in the annotation database looking
X   for lines which returned a constant count value every time they were
X   executed"
X  (let ((lines (tst-ann-get-lines)))
X	(cond ((null lines) nil)
X		  (t (mapcar 'tst-anl-constant-value lines)))))
X
X(defun tst-anl-constant-value (line)
X  "Given a LINE id, retrieves the values field and examines the list to
X   determine if all the values are equal.  If they are equal, stores a 
X   new attribute, called constant, with the value of one of those elements.
X
X  If the list contains a single element then it is considered to be constant"
X
X  (let ((values (tst-ann-get line 'values)))
X    (while (and (not (null (cdr values)))
X		(equal (car values) (car (cdr values))))
X      (setq values (cdr values)))
X    (if (= 1 (length values))
X	(tst-ann-put line 'constant  values)
X      ;; else
X      (tst-ann-remove-attribute line 'constant))))
X
SHAR_EOF
if test 2317 -ne "`wc -c < 'tst-analyze.el'`"
then
	echo shar: "error transmitting 'tst-analyze.el'" '(should have been 2317 characters)'
fi
fi
echo shar: "extracting 'tst-annotate.el'" '(7532 characters)'
if test -f 'tst-annotate.el'
then
	echo shar: "will not over-write existing file 'tst-annotate.el'"
else
sed 's/^X//' << \SHAR_EOF > 'tst-annotate.el'
X;;; tst-annotate.el --GnuTest Annotation Package
X;;; Copyright (c) 1987 Wang Institute of Graduate Studies
X
X;;; Andy Bliven <bliven@wanginst>
X;;; and Mike Vilot <vilot@wanginst>
X
X(provide 'tst-annotate)
X
X;;; ---------------------------------------------------------------------------
X;;; Private Variables--
X
X(defvar tst-ann-tricorder nil
X  "* The Annotation Database.  A recursive alist implementing a
Xdatabase indexed by line-number and attribute-name.  Intended to be
Xaccessed only through the tst-ann-* functions."
X  )					; defvar tst-ann-tricorder
X
X
X;;; ---------------------------------------------------------------------------
X;;; Public Functions--
X
X(defun tst-ann-append (line-id attribute value)
X  "Appends  VALUE to the list of values for the <LINE-ID ATTRIBUTE> key."
X  (let ((oldvalue (tst-ann-get line-id attribute)))
X    (if (nlistp oldvalue)
X	(error "value must be a list"))
X    (tst-ann-put line-id attribute (append oldvalue value))
X    )					; let
X  )
X
X(defun tst-ann-format (line-id attribute)
X  "Returns a string of format \"LINE-ID: ATTRIBUTE = value\""
X  (let ((value (tst-ann-get line-id attribute)))
X    (if (null value)
X	""				; return "" for undefined
X      ;; else
X      (concat
X       (prin1-to-string line-id) ": "
X       (prin1-to-string attribute) " = "
X       (prin1-to-string value)
X       )				; concat
X      )					; if
X    )					; let
X  )
X
X(defun tst-ann-format-line (line-id)
X  "Returns the concatenation of tst-ann-format for every attribute in LINE-ID."
X  (mapconcat
X   '(lambda (attr)
X      (tst-ann-format line-id attr))
X   (tst-ann-get-attributes line-id)
X   "\n"
X   )					; concat
X  )
X
X(defun tst-ann-get (line-id attribute)
X  "Retrieves a value for <LINE-ID ATTRIBUTE> key."
X  (tst-alist-get (tst-alist-get tst-ann-tricorder line-id) attribute)
X  )
X
X(defun tst-ann-get-attributes (line-id)
X  "Returns a list of attributes defined for LINE-ID."
X  (mapcar 'car (tst-alist-get tst-ann-tricorder line-id))
X  )
X
X(defun tst-ann-get-lines ()
X  "Returns a list of lines defined in the anotation database."
X  (mapcar 'car tst-ann-tricorder)
X  )
X
X(defun tst-ann-get-db ()
X  "Get database value."
X  tst-ann-tricorder
X  )
X
X(defun tst-ann-inc (line-id attribute)
X  "Increments the (assumed numeric) value for <LINE-ID ATTRIBUTE> key."
X  (let ((value (car (tst-ann-get line-id attribute))))
X    (if (not (numberp value))
X	(error "value must be numeric"))
X    (tst-ann-put line-id attribute (list (1+ value)))
X    )
X  )
X
X(defun tst-ann-put (line-id attribute value)
X  "Associates <LINE-ID ATTRIBUTE> key with VALUE."
X  (let ((attr-alist (assoc line-id tst-ann-tricorder)))
X    (if (null attr-alist)
X	(progn
X	  (setq tst-ann-tricorder
X		(tst-alist-put tst-ann-tricorder line-id nil))
X	  (setq attr-alist
X		(assoc line-id tst-ann-tricorder))
X	  )				; progn
X      )					; if
X    (setq attr-alist (tst-alist-put attr-alist attribute value))
X    value
X    )					; let
X  )
X
X(defun tst-ann-remove (line-id)
X  "Removes all data associated with LINE-ID from the database."
X  (setq tst-ann-tricorder
X	(delq tst-ann-tricorder
X	      (assoc line-id tst-ann-tricorder)))
X  )
X
X(defun tst-ann-remove-attribute (line-id attribute)
X  "Removes all data associated with both LINE-ID and ATTRIBUTE from the
X   database."
X  (tst-ann-put line-id attribute nil)
X  )
X
X(defun tst-ann-set-db (value)
X  "Set database to VALUE (either nil or obtained from tst-ann-get-db)."
X  (setq tst-ann-tricorder value)
X  )
X
X
X;;; ---------------------------------------------------------------------------
X;;; ALIST FUNCTIONS
X
X;;; This is a collection of functions for operating on association
X;;; lists (alists).
X
X;;; SPECIFICATION:  Axiomatic specification of type alist
X;;; 
X
X;;; types--
X;;;   A = association list
X;;;   K = key
X;;;   V = value
X
X;;; signatures--
X;;;   c pre:              -> A   "creates a new alist"
X;;;     post:           A ->     "deletes an alist"
X;;;   c put:    A x K x V -> A   "associate a value with a key"
X;;;     get:        A x K -> V   "retrieve the value associated with a key"
X;;;     rem:        A x K -> A   "remove a key from the list"
X;;;   c app:    A x K x V -> A   "append a key to the list"
X
X;;; rules--
X;;;   (post (pre))            = nil          "successful termination"
X;;;   (post (put A K1 V))     = (post A)
X;;;   (post (app A K1 V))     = (post A)
X;;;   (get (pre) K)           = nil
X;;;   (get (put A K1 V) K2)   = (if (= K1 K2) V (get A K2))
X;;;   (get (app A K1 V) K2)   = (if (= K1 K2) (append (get A K1) V)
X;;;                                           (get A K2))
X;;;   (rem (pre) K1)          = nil
X;;;   (rem (put A K1 V) K2)   = (if (= K1 K2) (rem A K2) (put (rem A K2) K1 V))
X;;;   (rem (app A K1 V) K2)   = (if (= K1 K2) (rem A K2) (app (rem A K2) K1 V))
X
X;;; implementation--
X;;;   an ALIST is represented as a Lisp list, each element of which is a
X;;;     list whose first element is the KEY and the remainder is the VALUE.
X
X
X;;; ----------------------------------------------------------------------
X;;; Alist Functions--
X
X(defun tst-alist-get (alist key)
X  "generic routine to retrieve from an ALIST the value for KEY."
X  (cdr (assoc key alist))
X  )					; defun tst-alist-get
X
X(defun  tst-alist-put (alist key value)
X  "Enter into ALIST a <KEY VALUE> pair.  Returns the revised alist; use
X   (setq alist (tst-alist-put alist key value)."
X
X  (cond ((assoc key alist) (setcdr (assoc key alist) value) alist)
X	(t                 (tst-alist-app alist key value))
X	)				; cond
X  )					; defun tst-alist-put
X
X(defmacro tst-alist-rem (alist key)
X  "Delete from ALIST the element (KEY value)."
X  (list 'setq alist (list 'delq (list 'assoc key alist) alist))
X  )					; defmacro
X
X(defun tst-alist-app (alist key value)
X  "Append the <KEY VALUE> pair to ALIST.  Returns a new alist--
X   use (setq alist (tst-alist-app alist key value))."
X  (nreverse				; by making the tail the head
X   (cons				; after inserting the new item
X    (cons key value)			; which is a list
X    (nreverse alist)			; placed before the old tail
X    )					; cons
X   )					; nreverse
X  )					; defun tst-alist-app
X
X
X;;; ---------------------------------------------------------------------------
X;;; LIST PRETTY-PRINT FUNCTIONS
X
X(defun tst-alist-print (list)
X  "Print LIST using prin1 with regular indentation and lots of newlines."
X  (interactive "xExpression: ")
X  (tst-alist-print-element list (current-column))
X  nil
X  )
X
X(defun tst-alist-print-element (list indent)
X  (cond
X   ((atom list) (princ list)) 
X   ((stringp list) (prin1 list))
X   ((vectorp list)
X    (princ "[")
X    (tst-alist-print-interior list (1+ indent))
X    (princ "]"))
X   ((listp list)
X    (princ "(")
X    (tst-alist-print-interior list (1+ indent))
X    (princ ")"))
X   (t (error "what are you trying to print?"))
X   )
X  (current-column)
X  )
X
X(defun tst-alist-print-interior (list indent)
X  (let (next)
X    (cond
X     ((atom list) (tst-alist-print-element list indent))
X     ((null (cdr list)) (tst-alist-print-element (car list) indent))
X     (t (setq next (tst-alist-print-element (car list) indent))
X	(cond		
X	 ((atom (car list))		; special case for list of atoms
X	  (princ " ")
X	  (setq indent (1+ next))
X	  ) ; (atom (car list))
X	 (t				; normal case--newline between elements
X	  (princ "\n")
X	  (tst-alist-print-spaces indent)
X	  )				; t
X	 )				; cond
X	(tst-alist-print-interior (cdr list) indent)
X	)				; t
X     )					; cond
X    )					; let
X  )
X
X
X(defun tst-alist-print-spaces (n)
X  (interactive "nColumn:")
X  (princ (substring "                                                                                " 0 n))
X  nil
X  )
X	
echo shar: "a missing newline was added to 'tst-annotate.el'"
SHAR_EOF
if test 7532 -ne "`wc -c < 'tst-annotate.el'`"
then
	echo shar: "error transmitting 'tst-annotate.el'" '(should have been 7532 characters)'
fi
fi
echo shar: "extracting 'tst-capture.el'" '(18305 characters)'
if test -f 'tst-capture.el'
then
	echo shar: "will not over-write existing file 'tst-capture.el'"
else
sed 's/^X//' << \SHAR_EOF > 'tst-capture.el'
X;; capture.el -- functions to capture the state of an emacs session 
X;; This is file 1 of two files in the "regression" part of the "test" package.
X;; See also achieve.el
X;; Carl Lagoze, Franklin Davis
X;; Copyright 1987 Wang Institute of Graduate Studies
X;; $Header: tst-capture.el,v 1.21 87/07/29 17:24:58 davis Exp $
X
X(provide 'tst-capture)
X
X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
X;;; some utilities
X
X(defmacro cadr (l)
X  (list 'car (list 'cdr l)))
X
X(defun member (elt list)
X  "Returns non-nil if ELT is an element of LIST.  Comparison done with equal.
XThe value is actually the tail of LIST whose car is ELT."
X  (while (and list (not (equal elt (car list))))
X    (setq list (cdr list)))
X  list)
X
X
X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
X;; variables
X
X(defvar tst-vars-exclude-default (list "values" "obarray")
X  "* Default list of global variable names to be excluded by 
Xtst-capture-state and tst-capture-state-to-file")
X
X
X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
X;; the interactive functions
X
X(defun tst-capture-state-to-file (file bufs-list vars-exclude)
X  "Write the current state of the emacs session to FILE.
XBUFS-LIST is a list of buffer names to capture; if nil all buffers
Xwill be captured.  
XVARS-EXCLUDE is a list of global variables to exclude.  See 
Xtst-capture-state for documentation."
X  (interactive "FFile name to write current state to:
XxList of buffers to capture (nil for all): 
XxList global vars to exclude (all; none; nil for default excl. list): ")
X  (let (state)
X     (tst-capture-state 'state bufs-list vars-exclude)
X     (tst-write-state-to-file state file)
X    )					;let
X  )					;defun tst-capture-state-to-file
X
X(defun tst-write-state-to-file (state file)
X  "Write variable STATE containing captured emacs session state to FILE."
X  (interactive "XState Name: \nFFile name to write state to: ")
X  (let ()
X    (message "Writing state to file...")
X    (save-excursion
X      (switch-to-buffer (make-temp-name "state"))
X      (prin1 state (current-buffer))
X      (write-file file)
X      (kill-buffer (current-buffer))
X      )					; save-excursion
X    )					; let
X  )					; defun tst-write-state-to-file
X
X
X(defun tst-capture-state (statevar bufs-list vars-exclude)
X  "Set variable STATE to the current state of the emacs session.
XBUFS-LIST is a list of buffer names to capture; if nil all buffers
Xwill be captured.  
XVARS-EXCLUDE is a list of global variables to exclude; 
Xif value is nil, default list tst-vars-exclude-default will be used; 
Xif value is 'all' all global variables will be excluded (not captured); 
Xif value is 'none' no global variables will be excluded (everything captured).
Xnil is returned in place of excluded variable if it exists.
X
XAn exclude-list rather than an include-list is used because it's 
Xmost important to exclude particularly nasty variables.  Would be nice to
Xextend this to have an include-list; perhaps also reg-exp for buffer names."
X  (interactive "SState Variable: 
XxList of buffers to capture (nil for all): 
XxList global vars to exclude (all; none; nil for default excl. list): ")
X  (let ()
X    (makunbound statevar)		; don't want to capture old state var.
X    (if (not (listp bufs-list))
X	     (error "Buffer-list must be a list of strings or nil")
X      ) ; if
X    (set statevar (list (tst-capture-globals-state vars-exclude)
X                        (tst-capture-processes-state)
X                        (tst-capture-buffers-state bufs-list)
X                        (tst-capture-windows-state)
X                        ))
X    (message "Capturing state...done")
X    ) ;let
X  ) ;defun tst-capture-state
X
X
X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
X;; globals capture
X
X(defun tst-capture-globals-state (vars-exclude)
X  "Capture global attributes of an Emacs session. 
XVARS-EXCLUDE is a list of global variables to exclude; 
Xif value is nil, default list tst-vars-exclude-default will be used; 
Xif value is 'all' all global variables will be excluded (not captured); 
Xif value is 'none' no global variables will be excluded (everything captured)."
X  (let ()
X    (message "Capturing state of globals...")
X    (cond ((null vars-exclude)
X	   (setq vars-exclude tst-vars-exclude-default))
X	  ((equal vars-exclude 'none) (setq vars-exclude nil))
X	  )
X    (list 'session
X          (list
X           (if (equal vars-exclude 'all)
X	       nil
X					; else
X	     (tst-capture-global-syms-state vars-exclude))
X;;	   (tst-capture-recursive-level-state)
X           )				; list
X          )				;list 'session
X    )					;let
X  )					;defun tst-capture-globals-state
X
X(defun tst-capture-global-syms-state (vars-exclude)
X  "Return the names and values of all global variables except VARS-EXCLUDE
X   as a single element a-list with the key 'global-vars.  The second element 
X   of the alist is a list of two element lists.  Each two element list 
X   consists of a global variable name and its value."
X  (list 'global-bound-syms
X	(delq nil			; remove "nil" from results
X	      (mapcar
X					; the lambda here allows
X					; mapcar to pass a second
X					; argument vars-exclude to
X					; function
X					; tst-get-bound-val-from-string
X					; while applying it to every
X					; element in list (all-completions...) 
X	       '(lambda (sym-string)
X		  (tst-get-bound-val-from-string sym-string vars-exclude))
X	       (all-completions "" obarray 'boundp))
X	      )				; delq
X	)				; list
X  )					; defun tst-capture-global-vars-state
X
X(defun tst-get-bound-val-from-string (sym-string vars-exclude)
X  "Given a SYMBOL-NAME return a cons of the symbol and its value.  The cons
Xlooks like (symbol . value).  Note that storing new values in this cons does 
Xnot change the symbol's value.  Returns nil if SYMBOL-NAME in VARS-EXCLUDE."
X  (cond ((not (stringp sym-string)) nil)
X	((member sym-string vars-exclude) nil) ; return nil for excluded vars
X	(t (cons (car (read-from-string sym-string))
X		 (tst-convert-compound-symbols
X		  (eval (car (read-from-string sym-string))))))
X	) ; cond
X  ) ;defun tst-get-bound-val-from-string
X     
X(defun tst-convert-compound-symbols (sym)
X  "Given a SYMBOL, convert all marker or process objects to descriptions
Xof these objects.  SYMBOL may be a list or atom or dotted pair."
X  (cond ((null sym) sym)
X	((vectorp sym) sym)
X	((numberp sym) sym)
X	((and (listp sym)
X	      (atom (cdr sym))
X	      (cdr sym))		; be sure it's not nil
X	 (cons				; sym is a dotted pair
X	  (tst-convert-compound-symbols (car sym))
X	  (tst-convert-compound-symbols (cdr sym))))
X	((and (listp sym) (atom (car (cdr sym)))) ; simple list
X	 (mapcar 'tst-convert-compound-symbols sym))
X	((atom sym)
X	 (cond ((markerp  sym) (tst-convert-marker-symbol sym))
X	       ((processp sym) (tst-convert-process-symbol sym))
X	       ((windowp  sym) (list 'window
X				     (tst-capture-window-state sym nil)))
X	       (t  sym)			; not a complex object
X	       )			; cond
X	 )
X	(t sym)
X	)				; cond
X  )					; defun tst-convert-compound-symbols
X
X
X;;; the following function is not used, but could be if someone wanted this 
X(defun tst-capture-recursive-level-state ()
X  "Capture the current recursive editing state (only the level)"
X  (let ()
X    (list 'recursive-level (recursion-depth))
X    ) ;let
X  ) ;tst-capture-recursive-level-state
X
X
X
X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
X;; processes
X
X(defun tst-capture-processes-state ()
X  "Capture processes attributes of an EMACS session"
X  (message "Capturing state of processes...")
X  (list 'processes (tst-convert-compound-symbols (process-list)))
X  )					;defun tst-capture-processes-state
X
X(defun tst-convert-process-symbol (p)
X  "Convert a process object into a list ('process <process-command>
X   <process-exit-status> <process-filter> <process-name> <process-sentenel>
X   <process-status>"
X  (if (processp p)
X      (list
X       'process
X       (list 'buffer (if (process-buffer p) (buffer-name (process-buffer p))
X		       nil))
X       (list 'process-mark (tst-convert-marker-symbol (process-mark p)))
X       (list 'command (process-command p))
X       (list 'exit-status (process-exit-status p))
X       (list 'filter (process-filter p))
X       (list 'name (process-name p))
X       (list 'sentinel (process-sentinel p))
X       (list 'status (process-status p))
X       )				; list
X    )					;if 
X  )					;defun tst-convert-process-symbol
X
X
X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
X;; buffers
X
X(defun tst-capture-buffers-state (capture-bufs-list)
X  "Return the states of all the active buffers in this session as a 
X   single element a-list with the key 'buffers.  The second element of the
X   alist is a list, each element of which is the state of an active buffer."
X					; Local Variables
X  (let ((bufflist) (buff-state))
X    (message "Capturing state of buffers...")
X    (setq bufflist (buffer-list))
X    (save-excursion
X      (while bufflist
X	(if (or (null capture-bufs-list) ; get all if no capture-bufs-list
X					; or get this buffer if in list
X		(member (buffer-name (car bufflist)) capture-bufs-list))
X	    (progn
X	      (set-buffer (car bufflist))
X	      (setq buff-state
X		    (append buff-state
X			    (list (tst-capture-buffer-state))))
X	      )				; progn
X	  )				; if
X	(setq bufflist (cdr bufflist))
X        )				; while
X      )					; save-excursion
X    (cons 'buffers (list buff-state))
X    )					; let
X  )					; defun tst-capture-buffers-state
X
X
X(defun tst-capture-buffer-state ()
X  "Return the state of the current buffer.  The state is returned as an
X   a-list"
X                                        ; Local Variables
X  (let ()
X    (list
X     (list 'buf-state-name (buffer-name))
X     (list 'buf-state-file (buffer-file-name))
X     (list 'buf-state-point (point))
X     (list 'buf-state-mark (mark))
X     (list 'buf-state-contents (buffer-string))
X     (list 'buf-state-modified (buffer-modified-p))
X     (list 'buf-state-local-map (current-local-map))
X     (list 'buf-state-local-vars
X           (mapcar 'tst-convert-compound-symbols (buffer-local-variables)))
X     ) ; list
X    ) ; let
X  ) ; defun tst-capture-buffer-state
X
X
X(defun tst-convert-marker-symbol (marker-symbol)
X  "Convert a marker object into a list (marker <point-value> <buffer>)"
X  (if (markerp marker-symbol)
X      (list
X       'marker
X       (list 'position (marker-position marker-symbol))
X       (if (null (marker-position marker-symbol)) nil ; no buf name if nil pos.
X	 (list 'buffer (buffer-name (marker-buffer marker-symbol))))
X       )				; list
X    )					; if
X  )					;defun tst-convert-marker-symbol
X
X
X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
X;; windows
X
X(defun tst-capture-windows-state ()
X  "Return the state of emacs windows as a two element a-list.  The first
X   element is the key 'windows.  The second element is a list 
X   representation of the binary tree abstraction of the window state.  This
X   tree is built by walking the windows (starting at the window positioned
X   at 0,0) and doing a shift-reduce parse on the window-list.  This parse
X   has two productions:
X     0: reduce two windows to a combined window when their top/bottom
X        edges are common.
X     1: reduce two windows to a combined window when their right/left
X        edges are common.
X   The parser has three states:
X     0: The start state.  The stack is empty
X     1: 1 element on the stack
X     2: >1 element on the stack"
X  (let ((stack) (state) (cur-window))
X    (message "Capturing state of windows...")
X    (save-window-excursion
X      (setq cur-window (selected-window))
X      (while (not (equal '(0 0) ;go to the upper left window
X                         (list (car (window-edges)) (cadr (window-edges)))))
X        (select-window (next-window))
X         )                              ;while
X					;always shift first window
X      (setq stack (tst-shift-window-stack stack cur-window))
X      (setq state 1)                    ;state 1 when 1 element on stack
X      ; At this point the base (0,0) window is on the stack and we are in
X      ; state 1.  Loop until we return to the condition where the state is
X      ; 1 and the next window is the base window (reduced to the final state)
X      (while (not (and (equal '(0 0) 
X                         (list
X			  (car (window-edges (next-window)))
X			  (cadr (window-edges (next-window)))
X			  )
X			 )
X                       (= state 1)
X		       ))
X        (if (= state 1)             ;always shift
X             (progn
X               (select-window (next-window))
X               (setq stack (tst-shift-window-stack stack cur-window))
X               (setq state 2)
X               )                        ;progn
X          (progn                        ;state 2
X            (if (equal
X                 (tst-get-window-bottom-edge (cadr stack))
X                 (tst-get-window-top-edge (car stack)))
X                (progn                  ;reduce by v rule
X                  (setq stack (tst-reduce-window-stack stack 'v))
X                  (if (= 1 (length stack))
X                      (progn
X                        (setq state 1)
X                        )               ;progn
X                    )                   ;if
X                  )                     ;progn
X              (progn
X                (if (equal
X                     (tst-get-window-right-edge (cadr stack))
X                     (tst-get-window-left-edge (car stack)))
X                    (progn
X                      (setq stack (tst-reduce-window-stack stack 'h))
X                      (if (= 1 (length stack))
X                          (progn
X                            (setq state 1)
X                            )           ;progn
X                        )                       ;if
X                      )
X                  (progn
X                    (select-window (next-window))
X                    (setq stack (tst-shift-window-stack stack cur-window))
X                    )                     ;progn
X                  )                     ;if equal left and right edge
X                )                       ;progn-else of if top and bottom equal
X              )                         ;if equal top and bottom edge
X            )                           ;progn - state 2
X          )                             ;if equal state 1
X        )                               ;while not accept state
X      )                                 ;save window excursion
X    (list 'windows (car stack))
X    )                                   ;let
X  )                                     ;defun tst-capture-windows-state
X  
X(defun tst-shift-window-stack (stack cur-window)
X  "Perform a shift in the LR parse of the window configuration tree (i.e. put
X   the state of the current window on top of the parse stack"
X  (let ()
X    (cons (tst-capture-window-state (selected-window) cur-window) stack)
X    )                                   ;let
X  )                                     ;shift-window-state
X
X(defun tst-reduce-window-stack (stack rule)
X  "Perform a reduce in the LR parse of the window configuration tree.  A reduce
X   always pops two elements off the parse stack and pushes a new element that
X   is a description of the 'combined' elements that were popped.  The input 
X   argument rule is either 'v' if the two items at the top of the stack were 
X   split vertically, or 'h' if the two items at the top of the stack were
X   split horizontally"
X   (let ((wstatet) (wstatet-1) (combined) (edgest) (edgest-1))
X     (setq wstatet (car stack))
X     (setq wstatet-1 (cadr stack))
X     (setq stack (cdr (cdr stack)))
X     (setq combined (list
X                     (list 'children (list wstatet-1 wstatet))
X                     (list 'split rule)))
X     (setq edgest (cadr (assoc 'window-edges wstatet)))
X     (setq edgest-1 (cadr (assoc 'window-edges wstatet-1)))
X     (setq combined (cons (list 'window-edges (list
X                                (car edgest-1)
X                                (cadr edgest-1)
X                                (cadr (cdr edgest))
X                                (cadr (cdr (cdr edgest)))
X                                )
X                 )
X           combined))
X
X     (setq stack (cons combined stack))
X     )                                  ;let
X   )                                    ;defun tst-reduce-window-stack
X
X(defun tst-get-window-top-edge (wstate)
X  "Return the coordinates of the top edge of input window as a three element
X   list consisting of (left-column row right-column)"
X  (let ((edges))
X    (setq edges (cadr (assoc 'window-edges wstate)))
X    (list (car edges) (cadr edges) (cadr (cdr edges)))
X    )                                   ;let
X  )                                     ;defun tst-reg-get-top-edge
X
X(defun tst-get-window-bottom-edge (wstate)
X  "Return the coordinates of the bottom edge of nput window as a three element
X   list consisting of (left-column row right-column)"
X  (let ((edges))
X    (setq edges (cadr (assoc 'window-edges wstate)))
X    (list (car edges) (cadr (cdr (cdr edges))) (cadr (cdr edges)))
X    )                                   ;let
X  )                                     ;defun tst-reg-get-top-edge
X
X(defun tst-get-window-left-edge (wstate)
X  "Return the coordinates of the left edge of input window as a three element
X   list consisting of (top-row column bottom-row)"
X  (let ((edges))
X    (setq edges (cadr (assoc 'window-edges wstate)))
X    (list (cadr edges) (car edges) (cadr (cdr (cdr edges))))
X    )                                   ;let
X  )                                     ;defun tst-reg-get-left-edge
X
X(defun tst-get-window-right-edge (wstate)
X  "Return the coordinates of the right edge of input window as a three element
X   list consisting of (top-row column bottom-row)"
X  (let ((edges))
X    (setq edges (cadr (assoc 'window-edges wstate)))
X    (list (cadr edges) (cadr (cdr edges)) (cadr (cdr (cdr edges))))
X    )                                   ;let
X  )                                     ;defun tst-reg-get-right-edge
X
X(defun tst-capture-window-state (window cur-window)
X  "Return the state of the window as an a-list."
X  (let ()
X    (list
X     (list 'window-edges (window-edges))
X     (list 'window-buffer (buffer-name))
X     (list 'window-start (window-start))
X     (list 'window-point (window-point))
X     (list 'current-window (equal window cur-window))
X     )
X    )
X  )
X
SHAR_EOF
if test 18305 -ne "`wc -c < 'tst-capture.el'`"
then
	echo shar: "error transmitting 'tst-capture.el'" '(should have been 18305 characters)'
fi
fi
exit 0
#	End of shell archive


-- 

Rich $alz
Cronus Project, BBN Labs			rsalz@bbn.com
Moderator, comp.sources.unix			sources@uunet.uu.net