forms

Homepage: https://www.gnu.org/software/emacs

Author: Johan Vromans

Summary

Forms mode: edit a file as a form to fill in

Commentary

Visit a file using a form.  See etc/forms for examples.

=== Naming conventions

The names of all variables and functions start with 'forms-'.
Names which start with 'forms--' are intended for internal use, and
should *NOT* be used from the outside.

All variables are buffer-local, to enable multiple forms visits
simultaneously.
Variable `forms--mode-setup' is local to *ALL* buffers, for it
controls if forms-mode has been enabled in a buffer.

=== How it works ===

Forms mode means visiting a data file which is supposed to consist
of records each containing a number of fields.  The records are
separated by a newline, the fields are separated by a user-defined
field separator (default: TAB).
When shown, a record is transferred to an Emacs buffer and
presented using a user-defined form.  One record is shown at a
time.

Forms mode is a composite mode.  It involves two files, and two
buffers.
The first file, called the control file, defines the name of the
data file and the forms format.  This file buffer will be used to
present the forms.
The second file holds the actual data.  The buffer of this file
will be buried, for it is never accessed directly.

Forms mode is invoked using M-x `forms-find-file' control-file.
Alternatively `forms-find-file-other-window' can be used.

You may also visit the control file, and switch to forms mode by hand
with M-x `forms-mode'.

Automatic mode switching is supported if you specify
"-*- forms -*-" in the first line of the control file.

The control file is visited, evaluated using `eval-buffer',
and should set at least the following variables:

	forms-file				[string]
			The name of the data file.

	forms-number-of-fields			[integer]
			The number of fields in each record.

	forms-format-list			[list]
			Formatting instructions.

`forms-format-list' should be a list, each element containing

  - a string, e.g. "hello".  The string is inserted in the forms
	"as is".

  - an integer, denoting a field number.
	The contents of this field are inserted at this point.
    Fields are numbered starting with number one.

  - a function call, e.g. (insert "text").
	This function call is dynamically evaluated and should return a
    string.  It should *NOT* have side-effects on the forms being
    constructed.  The current fields are available to the function
    in the variable `forms-fields', they should *NOT* be modified.

  - a Lisp symbol, that must evaluate to one of the above.

Optional variables which may be set in the control file:

	forms-field-sep				[string, default TAB]
			The field separator used to separate the
			fields in the data file.  It may be a string.

	forms-read-only				[bool, default nil]
			Non-nil means that the data file is visited
			read-only (view mode) as opposed to edit mode.
			If no write access to the data file is
			possible, view mode is enforced.

	forms-check-number-of-fields            [bool, default t]
			If non-nil, a warning will be issued whenever
			a record is found that does not have the number
			of fields specified by `forms-number-of-fields'.

	forms-multi-line			[string, default "^K"]
			If non-null, the records of the data file may
			contain fields that can span multiple lines in
			the form.
			This variable denotes the separator string
			to be used for this purpose.  Upon display, all
			occurrences of this string are translated
			to newlines.  Upon storage they are translated
			back to the separator string.

	forms-forms-scroll			[bool, default nil]
			Non-nil means: rebind locally the commands that
			perform `scroll-up' or `scroll-down' to use
			`forms-next-field' resp. `forms-prev-field'.

	forms-forms-jump			[bool, default nil]
			Non-nil means: rebind locally the commands
			`beginning-of-buffer' and `end-of-buffer' to
			perform, respectively, `forms-first-record' and
			`forms-last-record' instead.

	forms-insert-after			[bool, default nil]
			Non-nil means: insertions of new records go after
			current record, also initial position is at the
			last record.  The default is to insert before the
			current record and the initial position is at the
			first record.

	forms-read-file-filter			[symbol, default nil]
			If not nil: this should be the name of a
			function that is called after the forms data file
			has been read.  It can be used to transform
			the contents of the file into a format more suitable
			for forms-mode processing.

	forms-write-file-filter			[symbol, default nil]
			If not nil: this should be the name of a
			function that is called before the forms data file
			is written (saved) to disk.  It can be used to undo
			the effects of `forms-read-file-filter', if any.

	forms-new-record-filter			[symbol, default nil]
			If not nil: this should be the name of a
			function that is called when a new
			record is created.  It can be used to fill in
			the new record with default fields, for example.

	forms-modified-record-filter		[symbol, default nil]
			If not nil: this should be the name of a
			function that is called when a record has
			been modified.  It is called after the fields
			are parsed.  It can be used to register
			modification dates, for example.

	forms-use-text-properties		[bool, see text for default]
			This variable controls if forms mode should use
			text properties to protect the form text from being
			modified (using text-property `read-only').
			Also, the read-write fields are shown using a
			distinct face, if possible.
			The `intangible' text property is used to
			prevent moving into read-only fields.
			This variable defaults to t.
			The default face to show read-write fields is
			copied from face `region'.

	forms-ro-face 				[symbol, default 'default]
			This is the face that is used to show
			read-only text on the screen.  If used, this
			variable should be set to a symbol that is a
			valid face.
			E.g.
			  (make-face 'my-face)
			  (setq forms-ro-face 'my-face)

	forms-rw-face				[symbol, default 'region]
			This is the face that is used to show
			read-write text on the screen.

After evaluating the control file, its buffer is cleared and used
for further processing.
The data file (as designated by `forms-file') is visited in a buffer
`forms--file-buffer' which normally will not be shown.
Great malfunctioning may be expected if this file/buffer is modified
outside of this package while it is being visited!

Normal operation is to transfer one line (record) from the data file,
split it into fields (into `forms--the-record-list'), and display it
using the specs in `forms-format-list'.
A format routine `forms--format' is built upon startup to format
the records according to `forms-format-list'.

When a form is changed the record is updated as soon as this form
is left.  The contents of the form are parsed using information
obtained from `forms-format-list', and the fields which are
deduced from the form are modified.  Fields not shown on the forms
retain their original values.  The newly formed record then
replaces the contents of the old record in `forms--file-buffer'.
A parse routine `forms--parser' is built upon startup to parse
the records.

Two exit functions exist: `forms-exit' and `forms-exit-no-save'.
`forms-exit' saves the data to the file, if modified.
`forms-exit-no-save' does not.  However, if `forms-exit-no-save'
is executed and the file buffer has been modified, Emacs will ask
questions anyway.

Other functions provided by forms mode are:

	paging (forward, backward) by record
	jumping (first, last, random number)
	searching
	creating and deleting records
	reverting the form (NOT the file buffer)
	switching edit <-> view mode v.v.
	jumping from field to field

As a documented side-effect: jumping to the last record in the
file (using forms-last-record) will adjust forms--total-records if
needed.

The forms buffer can be in one of two modes: edit mode or view
mode.  View mode is a read-only mode, whereby you cannot modify the
contents of the buffer.

Edit mode commands:

TAB		 forms-next-field
\C-c TAB	 forms-next-field
\C-c <	 forms-first-record
\C-c >	 forms-last-record
\C-c ?	 describe-mode
\C-c \C-k	 forms-delete-record
\C-c \C-q	 forms-toggle-read-only
\C-c \C-o	 forms-insert-record
\C-c \C-l	 forms-jump-record
\C-c \C-n	 forms-next-record
\C-c \C-p	 forms-prev-record
\C-c \C-r	 forms-search-backward
\C-c \C-s	 forms-search-forward
\C-c \C-x	 forms-exit

Read-only mode commands:

SPC 	 forms-next-record
DEL	 forms-prev-record
?	 describe-mode
\C-q  forms-toggle-read-only
l	 forms-jump-record
n	 forms-next-record
p	 forms-prev-record
r	 forms-search-backward
s	 forms-search-forward
x	 forms-exit

Of course, it is also possible to use the \C-c prefix to obtain the
same command keys as in edit mode.

The following bindings are available, independent of the mode:

[next]	  forms-next-record
[prior]	  forms-prev-record
[begin]	  forms-first-record
[end]	  forms-last-record
[S-TAB]	  forms-prev-field
[backtab]	  forms-prev-field

For convenience, TAB is always bound to `forms-next-field', so you
don't need the C-c prefix for this command.

As mentioned above (see `forms-forms-scroll' and `forms-forms-jump'),
the bindings of standard functions `scroll-up', `scroll-down',
`beginning-of-buffer' and `end-of-buffer' can be locally replaced with
forms mode functions next/prev record and first/last
record.

`write-file-functions' is defined to save the actual data file
instead of the buffer data, `revert-buffer-function' is defined to
revert a forms to original.

Reverse dependencies