Homepage: https://www.gnu.org/software/emacs
Author: Johan Vromans
Forms mode: edit a file as a form to fill in
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.