🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: gnu.emacs.sources
Article #301

GNU Emacs forms-mode version 1.2.9 (part 2 of 3)

#301
From: Johan Vromans
Date: Tue, 14 Jan 1992 14:36
972 lines
31907 bytes
---- Cut Here and feed the following to sh ----
#!/bin/sh
# this is forms.shr.02 (part 2 of forms)
# do not concatenate these parts, unpack them in order with /bin/sh
# file forms.el continued
#
if test ! -r _shar_seq_.tmp; then
	echo 'Please unpack part 1 first!'
	exit 1
fi
(read Scheck
 if test "$Scheck" != 2; then
	echo Please unpack part "$Scheck" next!
	exit 1
 else
	exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
	echo 'x - still skipping forms.el'
else
echo 'x - continuing file forms.el'
sed 's/^X//' << 'SHAR_EOF' >> 'forms.el' &&
X		     (set-buffer forms--file-buffer)
X		     (forms--save-buffer arg)))
X	       (forms--save-buffer arg)))))
X  ;;
X  )
X
X(defun forms--help ()
X  "Initial help."
X  ;; We should use
X  ;;(message (substitute-command-keys (concat
X  ;;"\\[forms-next-record]:next"
X  ;;"   \\[forms-prev-record]:prev"
X  ;;"   \\[forms-first-record]:first"
X  ;;"   \\[forms-last-record]:last"
X  ;;"   \\[describe-mode]:help"
X  ;;"   \\[forms-exit]:exit")))
X  ;; but it's too slow ....
X  (if forms-read-only
X      (message "SPC:next   DEL:prev   <:first   >:last   ?:help   q:exit")
X    (message "C-c n:next   C-c p:prev   C-c <:first   C-c >:last   C-c ?:help   C-c q:exit")))
X
X(defun forms--trans (subj arg rep)
X  "Translate in SUBJ all chars ARG into char REP. ARG and REP should
X be single-char strings."
X  (let ((i 0)
X	(x (length subj))
X	(re (regexp-quote arg))
X	(k (string-to-char rep)))
X    (while (setq i (string-match re subj i))
X      (aset subj i k)
X      (setq i (1+ i)))))
X
X(defun forms--exit (query &optional save)
X  (let ((buf (buffer-name forms--file-buffer)))
X    (forms--checkmod)
X    (if (and save
X	     (buffer-modified-p forms--file-buffer))
X	(save-excursion
X	  (set-buffer forms--file-buffer)
X	  (save-buffer)))
X    (save-excursion
X      (set-buffer forms--file-buffer)
X      (delete-auto-save-file-if-necessary)
X      (kill-buffer (current-buffer)))
X    (if (get-buffer buf)	; not killed???
X      (if save
X	  (progn
X	    (beep)
X	    (message "Problem saving buffers?")))
X      (delete-auto-save-file-if-necessary)
X      (kill-buffer (current-buffer)))))
X
X(defun forms--get-record ()
X  "Fetch the current record from the file buffer."
X  ;;
X  ;; This function is executed in the context of the forms--file-buffer.
X  ;;
X  (or (bolp)
X      (beginning-of-line nil))
X  (let ((here (point)))
X    (prog2
X     (end-of-line)
X     (buffer-substring here (point))
X     (goto-char here))))
X
X(defun forms--show-record (the-record)
X  "Format THE-RECORD according to forms-format-list,
X and display it in the current buffer."
X
X  ;; split the-record
X  (let (the-result
X	(start-pos 0)
X	found-pos
X	(field-sep-length (length forms-field-sep)))
X    (if forms-multi-line
X	(forms--trans the-record forms-multi-line "\n"))
X    ;; add an extra separator (makes splitting easy)
X    (setq the-record (concat the-record forms-field-sep))
X    (while (setq found-pos (string-match forms-field-sep the-record start-pos))
X      (let ((ent (substring the-record start-pos found-pos)))
X	(setq the-result
X	      (append the-result (list ent)))
X	(setq start-pos (+ field-sep-length found-pos))))
X    (setq forms--the-record-list the-result))
X
X  (setq buffer-read-only nil)
X  (erase-buffer)
X
X  ;; verify the number of fields, extend forms--the-record-list if needed
X  (if (= (length forms--the-record-list) forms-number-of-fields)
X      nil
X    (beep)
X    (message "Record has %d fields instead of %d."
X	     (length forms--the-record-list) forms-number-of-fields)
X    (if (< (length forms--the-record-list) forms-number-of-fields)
X	(setq forms--the-record-list 
X	      (append forms--the-record-list
X		      (make-list 
X		       (- forms-number-of-fields 
X			  (length forms--the-record-list))
X		       "")))))
X
X  ;; call the formatter function
X  (setq forms-fields (append (list nil) forms--the-record-list nil))
X  (funcall forms--format forms--the-record-list)
X
X  ;; prepare
X  (goto-char (point-min))
X  (set-buffer-modified-p nil)
X  (setq buffer-read-only forms-read-only)
X  (setq mode-line-process
X	(concat " " forms--current-record "/" forms--total-records)))
X
X(defun forms--parse-form ()
X  "Parse contents of form into list of strings."
X  ;; The contents of the form are parsed, and a new list of strings
X  ;; is constructed.
X  ;; A vector with the strings from the original record is 
X  ;; constructed, which is updated with the new contents. Therefore
X  ;; fields which were not in the form are not modified.
X  ;; Finally, the vector is transformed into a list for further processing.
X
X  (let (the-recordv)
X
X    ;; build the vector
X    (setq the-recordv (vconcat forms--the-record-list))
X
X    ;; parse the form and update the vector
X    (let ((forms--dynamic-text forms--dynamic-text))
X      (funcall forms--parser))
X
X    (if forms--modified-record-filter
X	;; As a service to the user, we add a zeroth element so she
X	;; can use the same indices as in the forms definition.
X	(let ((the-fields (vconcat [nil] the-recordv)))
X	  (setq the-fields (funcall forms--modified-record-filter the-fields))
X	  (cdr (append the-fields nil)))
X
X      ;; transform to a list and return
X      (append the-recordv nil))))
X
X(defun forms--update ()
X  "Update current record with contents of form. As a side effect: sets
Xforms--the-record-list ."
X  (if forms-read-only
X      (progn
X	(message "Read-only buffer!")
X	(beep))
X
X    (let (the-record)
X      ;; build new record
X      (setq forms--the-record-list (forms--parse-form))
X      (setq the-record
X	    (mapconcat 'identity forms--the-record-list forms-field-sep))
X
X      ;; handle multi-line fields, if allowed
X      (if forms-multi-line
X	  (forms--trans the-record "\n" forms-multi-line))
X
X      ;; a final sanity check before updating
X      (if (string-match "\n" the-record)
X	  (progn
X	    (message "Multi-line fields in this record - update refused!")
X	    (beep))
X
X	(save-excursion
X	  (set-buffer forms--file-buffer)
X	  ;; Insert something before kill-line is called. See kill-line
X	  ;; doc. Bugfix provided by Ignatios Souvatzis.
X	  (insert "*")
X	  (beginning-of-line)
X	  (kill-line nil)
X	  (insert the-record)
X	  (beginning-of-line))))))
X
X(defun forms--checkmod ()
X  "Check if this form has been modified, and call forms--update if so."
X  (if (buffer-modified-p nil)
X      (let ((here (point)))
X	(forms--update)
X	(set-buffer-modified-p nil)
X	(goto-char here))))
X
X;;;
X;;; Start and exit
X(defun forms-find-file (fn)
X  "Visit file FN in forms mode"
X  (interactive "fForms file: ")
X  (find-file-read-only fn)
X  (or forms--mode-setup (forms-mode t)))
X
X(defun forms-find-file-other-window (fn)
X  "Visit file FN in form mode in other window"
X  (interactive "fFbrowse file in other window: ")
X  (find-file-other-window fn)
X  (eval-current-buffer)
X  (or forms--mode-setup (forms-mode t)))
X
X(defun forms-exit (query)
X  "Normal exit. Modified buffers are saved."
X  (interactive "P")
X  (forms--exit query t))
X
X(defun forms-exit-no-save (query)
X  "Exit without saving buffers."
X  (interactive "P")
X  (forms--exit query nil))
X
X;;;
X;;; Navigating commands
X
X(defun forms-next-record (arg)
X  "Advance to the ARGth following record."
X  (interactive "P")
X  (forms-jump-record (+ forms--current-record (prefix-numeric-value arg)) t))
X
X(defun forms-prev-record (arg)
X  "Advance to the ARGth previous record."
X  (interactive "P")
X  (forms-jump-record (- forms--current-record (prefix-numeric-value arg)) t))
X
X(defun forms-jump-record (arg &optional relative)
X  "Jump to a random record."
X  (interactive "NRecord number: ")
X
X  ;; verify that the record number is within range
X  (if (or (> arg forms--total-records)
X	  (<= arg 0))
X    (progn
X      (beep)
X      ;; don't give the message if just paging
X      (if (not relative)
X	  (message "Record number %d out of range 1..%d"
X		   arg forms--total-records))
X      )
X
X    ;; flush
X    (forms--checkmod)
X
X    ;; calculate displacement
X    (let ((disp (- arg forms--current-record))
X	  (cur forms--current-record))
X
X      ;; forms--show-record needs it now
X      (setq forms--current-record arg)
X
X      ;; get the record and show it
X      (forms--show-record
X       (save-excursion
X	 (set-buffer forms--file-buffer)
X	 (beginning-of-line)
X
X	 ;; move, and adjust the amount if needed (shouldn't happen)
X	 (if relative
X	     (if (zerop disp)
X		 nil
X	       (setq cur (+ cur disp (- (forward-line disp)))))
X	   (setq cur (+ cur disp (- (goto-line arg)))))
X
X	 (forms--get-record)))
X
X      ;; this shouldn't happen
X      (if (/= forms--current-record cur)
X	  (progn
X	    (setq forms--current-record cur)
X	    (beep)
X	    (message "Stuck at record %d." cur))))))
X
X(defun forms-first-record ()
X  "Jump to first record."
X  (interactive)
X  (forms-jump-record 1))
X
X(defun forms-last-record ()
X  "Jump to last record. As a side effect: re-calculates the number
X of records in the data file."
X  (interactive)
X  (let
X      ((numrec 
X	(save-excursion
X	  (set-buffer forms--file-buffer)
X	  (count-lines (point-min) (point-max)))))
X    (if (= numrec forms--total-records)
X	nil
X      (beep)
X      (setq forms--total-records numrec)
X      (message "Number of records reset to %d." forms--total-records)))
X  (forms-jump-record forms--total-records))
X
X;;;
X;;; Other commands
X(defun forms-view-mode ()
X  "Visit buffer read-only."
X  (interactive)
X  (if forms-read-only
X      nil
X    (forms--checkmod)			; sync
X    (setq forms-read-only t)
X    (forms-mode)))
X
X(defun forms-edit-mode ()
X  "Make form suitable for editing, if possible."
X  (interactive)
X  (let ((ro forms-read-only))
X    (if (save-excursion
X	  (set-buffer forms--file-buffer)
X	  buffer-read-only)
X	(progn
X	  (setq forms-read-only t)
X	  (message "No write access to \"%s\"" forms-file)
X	  (beep))
X      (setq forms-read-only nil))
X    (if (equal ro forms-read-only)
X	nil
X      (forms-mode))))
X
X;; Sample:
X;; (defun my-new-record-filter (the-fields)
X;;   ;; numbers are relative to 1
X;;   (aset the-fields 4 (current-time-string))
X;;   (aset the-fields 6 (user-login-name))
X;;   the-list)
X;; (setq forms-new-record-filter 'my-new-record-filter)
X
X(defun forms-insert-record (arg)
X  "Create a new record before the current one. With ARG: store the
X record after the current one.
X If a function forms-new-record-filter is defined, or forms-new-record-filter
X contains the name of a function, it is called to
X fill (some of) the fields with default values."
X ; The above doc is not true, but for documentary purposes only
X
X  (interactive "P")
X
X  (let ((ln (if arg (1+ forms--current-record) forms--current-record))
X        the-list the-record)
X
X    (forms--checkmod)
X    (if forms--new-record-filter
X	;; As a service to the user, we add a zeroth element so she
X	;; can use the same indices as in the forms definition.
X	(let ((the-fields (make-vector (1+ forms-number-of-fields) "")))
X	  (setq the-fields (funcall forms--new-record-filter the-fields))
X	  (setq the-list (cdr (append the-fields nil))))
X      (setq the-list (make-list forms-number-of-fields "")))
X
X    (setq the-record
X	  (mapconcat
X	  'identity
X	  the-list
X	  forms-field-sep))
X
X    (save-excursion
X      (set-buffer forms--file-buffer)
X      (goto-line ln)
X      (open-line 1)
X      (insert the-record)
X      (beginning-of-line))
X    
X    (setq forms--current-record ln))
X
X  (setq forms--total-records (1+ forms--total-records))
X  (forms-jump-record forms--current-record))
X
X(defun forms-delete-record (arg)
X  "Deletes a record. With ARG: don't ask."
X  (interactive "P")
X  (forms--checkmod)
X  (if (or arg
X	  (y-or-n-p "Really delete this record? "))
X      (let ((ln forms--current-record))
X	(save-excursion
X	  (set-buffer forms--file-buffer)
X	  (goto-line ln)
X	  (kill-line 1))
X	(setq forms--total-records (1- forms--total-records))
X	(if (> forms--current-record forms--total-records)
X	    (setq forms--current-record forms--total-records))
X	(forms-jump-record forms--current-record)))
X  (message ""))
X
X(defun forms-search (regexp)
X  "Search REGEXP in file buffer."
X  (interactive 
X   (list (read-string (concat "Search for" 
X				  (if forms--search-regexp
X				   (concat " ("
X					   forms--search-regexp
X					   ")"))
X				  ": "))))
X  (if (equal "" regexp)
X      (setq regexp forms--search-regexp))
X  (forms--checkmod)
X
X  (let (the-line the-record here
X		 (fld-sep forms-field-sep))
X    (if (save-excursion
X	  (set-buffer forms--file-buffer)
X	  (setq here (point))
X	  (end-of-line)
X	  (if (null (re-search-forward regexp nil t))
X	      (progn
X		(goto-char here)
X		(message (concat "\"" regexp "\" not found."))
X		nil)
X	    (setq the-record (forms--get-record))
X	    (setq the-line (1+ (count-lines (point-min) (point))))))
X	(progn
X	  (setq forms--current-record the-line)
X	  (forms--show-record the-record)
X	  (re-search-forward regexp nil t))))
X  (setq forms--search-regexp regexp))
X
X(defun forms-revert-buffer (&optional arg noconfirm)
X  "Reverts current form to un-modified."
X  (interactive "P")
X  (if (or noconfirm
X	  (yes-or-no-p "Revert form to unmodified? "))
X      (progn
X	(set-buffer-modified-p nil)
X	(forms-jump-record forms--current-record))))
X
X(defun forms-next-field (arg)
X  "Jump to ARG-th next field."
X  (interactive "p")
X
X  (let ((i 0)
X	(here (point))
X	there
X	(cnt 0))
X
X    (if (zerop arg)
X	(setq cnt 1)
X      (setq cnt (+ cnt arg)))
X
X    (if (catch 'done
X	  (while (< i forms--number-of-markers)
X	    (if (or (null (setq there (aref forms--markers i)))
X		    (<= there here))
X		nil
X	      (if (<= (setq cnt (1- cnt)) 0)
X		  (progn
X		    (goto-char there)
X		    (throw 'done t))))
X	    (setq i (1+ i))))
X	nil
X      (goto-char (aref forms--markers 0)))))
X
X;;;
X;;; Special service
X;;;
X(defun forms-enumerate (the-fields)
X  "Take a quoted list of symbols, and set their values to the numbers
X1, 2 and so on. Returns the higest number.
X
XUsage: (setq forms-number-of-fields
X             (forms-enumerate
X              '(field1 field2 field2 ...)))"
X
X  (let ((the-index 0))
X    (while the-fields
X      (setq the-index (1+ the-index))
X      (let ((el (car-safe the-fields)))
X	(setq the-fields (cdr-safe the-fields))
X	(set el the-index)))
X    the-index))
X
X;;;
X;;; Debugging
X;;;
X(defvar forms--debug nil
X  "*Enables forms-mode debugging if not nil.")
X
X(defun forms--debug (&rest args)
X  "Internal - debugging routine"
X  (if forms--debug
X      (let ((ret nil))
X	(while args
X	  (let ((el (car-safe args)))
X	    (setq args (cdr-safe args))
X	    (if (stringp el)
X		(setq ret (concat ret el))
X	      (setq ret (concat ret (prin1-to-string el) " = "))
X	      (if (boundp el)
X		  (let ((vel (eval el)))
X		    (setq ret (concat ret (prin1-to-string vel) "\n")))
X		(setq ret (concat ret "<unbound>" "\n")))
X	      (if (fboundp el)
X		  (setq ret (concat ret (prin1-to-string (symbol-function el)) 
X				    "\n"))))))
X	(save-excursion
X	  (set-buffer (get-buffer-create "*forms-mode debug*"))
X	  (goto-char (point-max))
X	  (insert ret)))))
X
X;;; Local Variables:
X;;; eval: (headers)
X;;; eval: (setq comment-start ";;; ")
X;;; End:
SHAR_EOF
echo 'File forms.el is complete' &&
chmod 0444 forms.el ||
echo 'restore of forms.el failed'
Wc_c="`wc -c < 'forms.el'`"
test 42028 -eq "$Wc_c" ||
	echo 'forms.el: original size 42028, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= forms.texinfo ==============
if test -f 'forms.texinfo' -a X"$1" != X"-c"; then
	echo 'x - skipping forms.texinfo (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting forms.texinfo (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'forms.texinfo' &&
X\input texinfo			@c -*-texinfo-*-
X
X@c  forms.texinfo -- documentation for forms-mode
X@c  SCCS Status     : @(#)@ forms	1.2.9
X@c  Author          : Johan Vromans
X@c  Created On      : 1989
X@c  Last Modified By: Johan Vromans
X@c  Last Modified On: Tue Jan 14 15:03:02 1992
X@c  Update Count    : 23
X@c  Status          : OK
X
X@c  HISTORY 
X@c  14-Jan-1992		Johan Vromans	
X@c     Change file names as requested by rms.
X@c  1-Jul-1991		Johan Vromans	
X@c     Restructured parts of the doc.
X@c  30-Jun-1991		Johan Vromans	
X@c     Add doc for forms-modified-record-filter.
X@c     Doc that the filters may be the name of a function.
X@c     Clarified the use of quoted lists and symbols in
X@c     forms-format-list.
X@c
X@c  29-Jun-1991         Johan Vromans   
X@c     Inserted these headers.
X@c     Added doc to use lisp lists and symbols in forms-forms-list. 
X
X@comment %**start of header (This is for running Texinfo on a region.)
X@setfilename forms.info
X@settitle Forms Mode User's Manual
X@iftex
X@finalout
X@setchapternewpage odd
X@end iftex
X@c      @smallbook
X@comment %**end of header (This is for running Texinfo on a region.)
X
X@tex
X\global\chapno=30
X@end tex
X
X@ifinfo
XThis file documents forms-mode, a forms based major mode for GNU Emacs.
X
XPermission is granted to make and distribute verbatim copies of this
Xmanual provided the copyright notice and this permission notice are
Xpreserved on all copies.
X
X@ignore
XPermission is granted to process this file through TeX and print the
Xresults, provided the printed document carries copying permission notice
Xidentical to this one except for the removal of this paragraph (this
Xparagraph not being relevant to the printed manual).
X
X@end ignore
X@end ifinfo
X
X@iftex
X@titlepage
X@sp 6
X@center @titlefont{Forms Mode User's Manual}
X@sp 4
X@center Forms-Mode version 1.2, patchlevel 9
X@sp 1
X@center July 1991
X@sp 5
X@center Johan Vromans
X@center @i{jv@@mh.nl}
X@page
X
X@vskip 0pt plus 1filll
XCopyright @copyright{} 1989,1990,1991 Free Software Foundation, Inc.
X
XPermission is granted to make and distribute verbatim copies of
Xthis manual provided the copyright notice and this permission notice
Xare preserved on all copies.
X
X@end titlepage
X@page
X@end iftex
X
X@ifinfo
X@node Top, What is in a Forms, , (DIR)
X@end ifinfo
X
X@iftex
X@chapter Forms mode
X@end iftex
X
XForms mode is an Emacs major mode for working with simple plain-text
Xdatabases in a forms-oriented manner. In forms mode, the information in
Xthese files is presented in an Emacs window in a user-defined format,
Xone record at a time. Forms can be inspected read-only (viewing) or
Xmodified and updated.
X@cindex forms-mode
X
XForms mode is not a simple major mode, but requires two files to do its
Xjob: a control file and a data file. The data file holds the
Xactual data which will be presented. The control file describes
Xhow it will be presented.
X
X@menu
X* What is in a Forms::	Introduction.
X* Data File Format::	How to format the data file.
X* Control File Format::	How to control forms mode.
X* Forms Format Description::
X			How to define the forms layout.
X* Modifying Forms Contents::
X			How to modify.
X* Forms Mode Commands::	The commands available, and how to use them.
X* Key Bindings::	Which keys are bound to what commands.
X* Miscellaneous::	Forms mode messages and other remarks.
X* Examples::		Some examples.
X* Credits::		Thanks everyone.
X* Concept Index::	Index of Concepts
X* Variable Index::	Index of Variables.
X* Function Index::	Index of Functions.
X@end menu
X
X@node What is in a Forms, Data File Format, Top, Top
X@section What is in a forms
X
XLet's illustrate forms mode with an example. Suppose you are looking at
Xyour @file{/etc/passwd} file, and your screen looks as follows:
X
X@example
X====== /etc/passwd ======
X
XUser : root   Uid: 0   Gid: 1
X
XName : Super User
X
XHome : /
X
XShell: /bin/sh
X@end example
X
XAs you can see, the familiar fields from the entry for the super user
Xare all there, but instead of being colon-separated on one single line,
Xthey make up a forms.
X
XThe contents of the forms consists of the contents of the fields of the
Xrecord (e.g. ``root'', ``0'', ``1'', ``Super User'')
Xinterspersed with normal text (e.g ``User : '', ``Uid: '').
X
XYou can define yourself how text and fields will be used to make up the
Xforms.
X
XWhen you modifiy the contents of the forms, it will be analyzed and the
Xnew contents of the fields of this record will be extracted. If
Xpossible, the file will be updated with the new contents.
X
X@node Data File Format, Control File Format, What is in a Forms, Top
X@section Data file format
X
XFiles for use with forms mode are very simple -- each record (line)
Xforms the contents of one form.  Each record is supposed to consist of a
Xnumber of fields. These fields are separated by the value of the string
X@code{forms-field-sep}, which is a @code{TAB} by default.
X
X@cindex pseudo-newline
XFields may contain text which shows up in the forms in multiple lines.
XThese lines are separated in the field using a @var{pseudo-newline}
Xcharacter which is defined by the value of the string
X@code{forms-multi-line}. Its default value is a Control-K character. If
Xit is set to @code{nil} multiple line fields are prohibited.
X
X@node Control File Format, Forms Format Description, Data File Format, Top
X@section Control file format
X
XThe control file serves two purposes.
X
XFirst, it defines the data file to use, and its properties.
X
XSecond, the Emacs buffer it occupies will be used by the forms mode to
Xdisplay the forms.
X
X@findex eval-current-buffer
XThe contents of the control file are evaluated using the Emacs command
X@code{eval-current-buffer}, hence must contain valid Emacs-lisp expressions.
XThese expressions must set the following lisp variables to a suitable
Xvalue:
X
X@table @code
X@vindex forms-file
X@item forms-file
XThis variable must be set to the name of the data file.@*
XExample:
X@example
X(setq forms-file "my/data-file")
X@end example
X
X@vindex forms-format-list
X@item forms-format-list
XThis variable describes the way the fields of the record are formatted on
Xthe screen. See the next section for details.
X
X@vindex forms-number-of-fields
X@item forms-number-of-fields
XThis variable holds the number of fields in each record of the data
Xfile.@*
XExample:
X@example
X(setq forms-number-of-fields 10)
X@end example
X
X@end table
X
XAn error will be given if one of the above values has not been set.
X
XOther variables that may be set from the control file are optional. Most
Xof them have suitable default values.
X
X@table @code
X@vindex forms-field-sep
X@item forms-field-sep
XThis variable may be used to designate the string which separates the fields
Xin the records of the data file. If not set, it defaults to a string
Xcontaining a single @code{TAB} character. @*
XExample:
X@example
X(setq forms-field-sep "\t")
X@end example
X
X@vindex forms-read-only
X@item forms-read-only
XIf set to a value other than @code{nil}, the data file is treated
Xread-only. If the data file can not be written into, read-only mode is
Xenforced. The default value for @code{forms-read-only} is derieved from
Xthe access permissions of the data file.@*
XExample:
X@example
X(set forms-read-only t)
X@end example
X
X@vindex forms-multi-line
X@item forms-multi-line
XThis variable may be set to allow multi-line text in fields. It should
Xbe set to a string of one character, which denotes the pseudo new-line
Xcharacter to be used to separate the text lines.@*
XIts default value is Control-K (octal 013). If set to @code{nil},
Xmulti-line text fields are prohibited.@*
XIt may not be a character contained in @code{forms-field-sep}.@*
XExample:
X@example
X(setq forms-multi-line "\C-k")
X@end example
X
X@vindex forms-forms-scroll
X@item forms-forms-scroll
X@xref{Forms Mode Commands} for the description.
X
X@vindex forms-forms-jump
X@item forms-forms-jump
X@xref{Forms Mode Commands} for the description.
X
X@findex{forms-new-record-filter}
X@item forms-new-record-filter
XThe control file may define a function @code{forms-new-record-filter},
Xor set @code{forms-new-record-filter} to such a function. If so, this
Xfunction is called when a new record is created to supply default values
Xfor fields.
X
X@findex{forms-modified-record-filter}
X@item  forms-modified-record-filter
XThe control file may define a function
X@code{forms-modified-record-filter}, or set
X@code{forms-modified-record-filter} to such a function.  If so, this
Xfunction is called when a record is modified, just before writing the
Xmodified record back to the data file.
X
X@end table
X
X@node Forms Format Description, Modifying Forms Contents, Control File Format, Top
X@section The forms format description
X
X@vindex forms-format-list
XThe value of the variable @code{forms-format-list} is used to specify
Xthe format of the forms. It must be a list of formatting elements, each
Xof which can be a string, number, lisp list or a lisp symbol that
Xevaluates to one of these. The formatting elements are processed in the
Xorder they appear in the list.
X
XA @code{string} formatting element is inserted in the forms ``as is''.
X
XA @code{number} element selects a field of the record. The contents of
Xthis field are inserted. The first field of the record has number 1
X(one).
X
XA @code{lisp list} specifies a function call. This function is called
Xevery time a record is displayed, and its result, that must be a
Xstring, is inserted in the forms. The function should do nothing
Xbut returning a string. The fields of the record being displayed are
X@vindex forms-fields
Xavailable to this function as the list @code{forms-fields} and can be
Xaccessed using @code{(nth }@var{FIELD NUMBER}@code{ forms-fields)}.
XFields are numbered starting from 1 (one).
X
XA @code{lisp symbol} must evaluate to one of the above possibilities.
X
XIf a record does not contain the number of fields as specified in
X@code{forms-number-of-fields}, a warning message will be printed. Excess
Xfields are ignored, missing fields are set to empty.
X
XThe control file which shows your @file{/etc/passwd} file as demonstrated
Xin the beginning of this document might look as follows:
X@example
X;; This demo visits /etc/passwd.
X
X(setq forms-file "/etc/passwd")
X(setq forms-number-of-fields 7)
X(setq forms-read-only t)                 ; to make sure
X(setq forms-field-sep ":")
X(setq forms-multi-line nil)              ; not allowed
X
X(setq forms-format-list
X      (list
X       "====== /etc/passwd ======\n\n"
X       "User : "    1
X       "   Uid: "   3
X       "   Gid: "   4
X       "\n\n"
X       "Name : "    5
X       "\n\n"
X       "Home : "    6
X       "\n\n"
X       "Shell: "    7
X       "\n"))
X@end example
X
XWhen functions are to be used in @code{forms-format-list} they must be
Xquoted to prevent them from being evaluated too early:
X
X@example
X(setq forms-format-list
X      (list
X       "====== " forms-file " ======\n\n"
X       "User : "    1
X       '(make-string 20 ?-)
X       ...
X      ))
X@end example
X
XAlternativily, instead of quoting the functions, the whole list may be
Xquoted: 
X
X@example
X(setq forms-format-list
X     '(
X       "====== " forms-file " ======\n\n"
X       "User : "    1
X       (make-string 20 ?-)
X       ...
X      ))
X@end example
X
XUpon startup, the contents of @code{forms-format-list} are
Xvalidated. If errors are encountered, processing is aborted with 
Xan error message which includes a descriptive text. @xref{Error
XMessages}, for a detailed list of error messages.
X
X@node Modifying Forms Contents, Forms Mode Commands, Forms Format Description, Top
X@section Modifying A Form-mode Buffer's Contents
X
XIf a forms is not read-only, its contents can be modified.
X
XAll normal editor commands may be used to change the forms. There is no
Xdistinction between the ``fixed'' text and the text from the fields of
Xthe records. However, upon completion, the forms is parsed to extract
Xthe new contents of the fields. The ``fixed'' portions of the forms are
Xused to delimit the fields, these portions should therefore not be
Xmodified to avoid the risk that the field contents cannot be determined.
XMoreover, ambiguous field contents, which can not be discriminated from
X``fixed'' text, must be avoided.
X
XIf the contents of the forms cannot be recognized properly, this is
Xsignaled using a descriptive text. @xref{Error Messages}, for more info.
XThe cursor will indicate the last part of the forms which was
Xsuccessfully parsed.
X
X@findex{forms-modified-record-filter}
XIf @code{forms-modified-record-filter} has been set, this function is
Xcalled before the new data is written to the data file. The function
Xis called with one argument: a vector that contains the contents of the
Xfields of a record. Fields can be referenced or modified using the lisp
Xfunctions @code{aref} and @code{aset}. The first field has number 1
X(one). The function must return the (possibly modified) vector to the
Xcalling environment.
X
X@example
X(defun my-modified-record-filter (record)
X  ;; modify second field
X  (aset record 2 (current-time-string))
X  record		; return it
X)
X(setq forms-modified-record-filter 'my-modified-record-filter)
X@end example
X
X@node Forms Mode Commands, Key Bindings, Modifying Forms Contents, Top
X@section Forms mode commands
X
X@table @kbd
X@findex forms-find-file
X@item M-x forms-find-file @var{file}
X@end table
X
XVisits @var{file}, runs @code{eval-current-buffer} on it, and puts the
Xbuffer into forms-mode. The first record of the data file will be loaded
Xand shown.
X
XThe modeline will display the major mode @code{"Forms"} followed by the
Xminor mode @code{"View"} if the file is visited read-only.  The number
Xof the current record (@var{n}) and the total number of records
X(@var{t}) in the file is shown in the modeline as @code{"n/t"}.@*
XFor example:
X@example
X--%%-Emacs: forms-passwd          (Forms View 1/54)----All-------
X@end example
X
X@table @kbd
X@findex forms-find-file-other-window
SHAR_EOF
true || echo 'restore of forms.texinfo failed'
fi
echo 'End of forms part 2'
echo 'File forms.texinfo is continued in part 3'
echo 3 > _shar_seq_.tmp
exit 0
-- 
Johan Vromans				       jv@mh.nl via internet backbones
Multihouse Automatisering bv		       uucp:..!{uunet,sun4nl}!mh.nl!jv
Doesburgweg 7, 2803 PL Gouda, The Netherlands  phone/fax: +31 1820 62911/62500
------------------------ "Arms are made for hugging" -------------------------
Technical Details
Message-ID: <1992Jan14.143633.7682@pronto.mh.nl>
Path: arc1-ca.pugleaf.net!wupost!zaphod.mps.ohio-state.edu!think.com!yale.edu!jvnc.net!darwin.sura.net!europa.asd.contel.com!uunet!mcsun!sun4nl!mhres!pronto!jv

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!wupost!zaphod.mps.ohio-state.edu!think.com!yale.edu!jvnc.net!darwin.sura.net!europa.asd.contel.com!uunet!mcsun!sun4nl!mhres!pronto!jv
From: jv@mh.nl (Johan Vromans)
Newsgroups: gnu.emacs.sources,alt.sources
Subject: GNU Emacs forms-mode version 1.2.9 (part 2 of 3)
Message-ID: <1992Jan14.143633.7682@pronto.mh.nl>
Date: 14 Jan 92 14:36:33 GMT
Sender: jv@pronto.mh.nl (Johan Vromans)
Distribution: gnu
Organization: Multihouse Automation, the Netherlands
Lines: 972
X-Md4-Signature: c7b73c3029dc5195296e8df4170ffe6e