| 1 | \input texinfo @c -*-texinfo-*- |
| 2 | @c documentation for forms-mode |
| 3 | @c Written by Johan Vromans, and edited by Richard Stallman |
| 4 | |
| 5 | @comment %**start of header (This is for running Texinfo on a region.) |
| 6 | @setfilename ../../info/forms.info |
| 7 | @settitle Forms Mode User's Manual |
| 8 | @syncodeindex vr cp |
| 9 | @syncodeindex fn cp |
| 10 | @syncodeindex ky cp |
| 11 | @iftex |
| 12 | @finalout |
| 13 | @setchapternewpage odd |
| 14 | @end iftex |
| 15 | @c @smallbook |
| 16 | @comment %**end of header (This is for running Texinfo on a region.) |
| 17 | @documentencoding UTF-8 |
| 18 | |
| 19 | @copying |
| 20 | This file documents Forms mode, a form-editing major mode for GNU Emacs. |
| 21 | |
| 22 | Copyright @copyright{} 1989, 1997, 2001--2014 Free Software Foundation, Inc. |
| 23 | |
| 24 | @quotation |
| 25 | Permission is granted to copy, distribute and/or modify this document |
| 26 | under the terms of the GNU Free Documentation License, Version 1.3 or |
| 27 | any later version published by the Free Software Foundation; with no |
| 28 | Invariant Sections, with the Front-Cover Texts being ``A GNU Manual,'' |
| 29 | and with the Back-Cover Texts as in (a) below. A copy of the license |
| 30 | is included in the section entitled ``GNU Free Documentation License''. |
| 31 | |
| 32 | (a) The FSF's Back-Cover Text is: ``You have the freedom to copy and |
| 33 | modify this GNU manual.'' |
| 34 | @end quotation |
| 35 | @end copying |
| 36 | |
| 37 | @dircategory Emacs misc features |
| 38 | @direntry |
| 39 | * Forms: (forms). Emacs package for editing data bases |
| 40 | by filling in forms. |
| 41 | @end direntry |
| 42 | |
| 43 | @titlepage |
| 44 | @sp 6 |
| 45 | @center @titlefont{Forms Mode User's Manual} |
| 46 | @sp 4 |
| 47 | @center Forms-Mode version 2 |
| 48 | @sp 1 |
| 49 | @center for GNU Emacs 22.1 |
| 50 | @sp 1 |
| 51 | @center April 2007 |
| 52 | @sp 5 |
| 53 | @center Johan Vromans |
| 54 | @center @i{jvromans@@squirrel.nl} |
| 55 | @page |
| 56 | @vskip 0pt plus 1filll |
| 57 | @insertcopying |
| 58 | @end titlepage |
| 59 | |
| 60 | @contents |
| 61 | |
| 62 | @ifnottex |
| 63 | @node Top |
| 64 | @top Forms Mode |
| 65 | |
| 66 | Forms mode is an Emacs major mode for working with simple textual data |
| 67 | bases in a forms-oriented manner. In Forms mode, the information in |
| 68 | these files is presented in an Emacs window in a user-defined format, |
| 69 | one record at a time. The user can view records or modify their |
| 70 | contents. |
| 71 | |
| 72 | Forms mode is not a simple major mode, but requires two files to do its |
| 73 | job: a control file and a data file. The data file holds the |
| 74 | actual data to be presented. The control file describes |
| 75 | how to present it. |
| 76 | |
| 77 | @insertcopying |
| 78 | |
| 79 | @menu |
| 80 | * Forms Example:: An example: editing the password data base. |
| 81 | * Entering and Exiting Forms Mode:: |
| 82 | How to visit a file in Forms mode. |
| 83 | * Forms Commands:: Special commands to use while in Forms mode. |
| 84 | * Data File Format:: How to format the data file. |
| 85 | * Control File Format:: How to control forms mode. |
| 86 | * Format Description:: How to define the forms layout. |
| 87 | * Modifying Forms Contents:: How to modify. |
| 88 | * Miscellaneous:: Forms mode messages and other remarks. |
| 89 | * Error Messages:: List of error messages forms mode can produce. |
| 90 | * Long Example:: A more complex control file example. |
| 91 | * Credits:: Thanks everyone. |
| 92 | * GNU Free Documentation License:: The license for this documentation. |
| 93 | * Index:: Index to this manual. |
| 94 | @end menu |
| 95 | @end ifnottex |
| 96 | |
| 97 | @node Forms Example |
| 98 | @chapter Forms Example |
| 99 | |
| 100 | Let's illustrate Forms mode with an example. Suppose you are looking at |
| 101 | the @file{/etc/passwd} file, and the screen looks like this: |
| 102 | |
| 103 | @example |
| 104 | ====== /etc/passwd ====== |
| 105 | |
| 106 | User : root Uid: 0 Gid: 1 |
| 107 | |
| 108 | Name : Super User |
| 109 | |
| 110 | Home : / |
| 111 | |
| 112 | Shell: /bin/sh |
| 113 | @end example |
| 114 | |
| 115 | As you can see, the familiar fields from the entry for the super user |
| 116 | are all there, but instead of being colon-separated on one single line, |
| 117 | they make up a forms. |
| 118 | |
| 119 | The contents of the forms consist of the contents of the fields of the |
| 120 | record (e.g., @samp{root}, @samp{0}, @samp{1}, @samp{Super User}) |
| 121 | interspersed with normal text (e.g., @samp{User : }, @samp{Uid: }). |
| 122 | |
| 123 | If you modify the contents of the fields, Forms mode will analyze your |
| 124 | changes and update the file appropriately. You cannot modify the |
| 125 | interspersed explanatory text (unless you go to some trouble about it), |
| 126 | because that is marked read-only (@pxref{Text Properties,,, elisp, The |
| 127 | Emacs Lisp Reference Manual}). |
| 128 | |
| 129 | The Forms mode control file specifies the relationship between the |
| 130 | format of @file{/etc/passwd} and what appears on the screen in Forms |
| 131 | mode. @xref{Control File Format}. |
| 132 | |
| 133 | @node Entering and Exiting Forms Mode |
| 134 | @chapter Entering and Exiting Forms Mode |
| 135 | |
| 136 | @table @kbd |
| 137 | @findex forms-find-file |
| 138 | @item M-x forms-find-file @key{RET} @var{control-file} @key{RET} |
| 139 | Visit a database using Forms mode. Specify the name of the |
| 140 | @strong{control file}, not the data file! |
| 141 | |
| 142 | @findex forms-find-file-other-window |
| 143 | @item M-x forms-find-file-other-window @key{RET} @var{control-file} @key{RET} |
| 144 | Similar, but displays the file in another window. |
| 145 | @end table |
| 146 | |
| 147 | The command @code{forms-find-file} evaluates the file |
| 148 | @var{control-file}, and also visits it in Forms mode. What you see in |
| 149 | its buffer is not the contents of this file, but rather a single record |
| 150 | of the corresponding data file that is visited in its own buffer. So |
| 151 | there are two buffers involved in Forms mode: the @dfn{forms buffer} |
| 152 | that is initially used to visit the control file and that shows the |
| 153 | records being browsed, and the @dfn{data buffer} that holds the data |
| 154 | file being visited. The latter buffer is normally not visible. |
| 155 | |
| 156 | Initially, the first record is displayed in the forms buffer. |
| 157 | The mode line displays the major mode name @samp{Forms}, followed by the |
| 158 | minor mode @samp{View} if the data base is read-only. The number of the |
| 159 | current record (@var{n}) and the total number of records in the |
| 160 | file(@var{t}) are shown in the mode line as @samp{@var{n}/@var{t}}. For |
| 161 | example: |
| 162 | |
| 163 | @example |
| 164 | --%%-Emacs: passwd-demo (Forms View 1/54)----All------- |
| 165 | @end example |
| 166 | |
| 167 | If the buffer is not read-only, you may change the buffer to modify the |
| 168 | fields in the record. When you move to a different record, the contents |
| 169 | of the buffer are parsed using the specifications in |
| 170 | @code{forms-format-list}, and the data file is updated. If the record |
| 171 | has fields that aren't included in the display, they are not changed. |
| 172 | |
| 173 | @vindex forms-mode-hook |
| 174 | Entering Forms mode runs the normal hook @code{forms-mode-hook} to |
| 175 | perform user-defined customization. |
| 176 | |
| 177 | To save any modified data, you can use @kbd{C-x C-s} |
| 178 | (@code{forms-save-buffer}). This does not save the forms buffer (which would |
| 179 | be rather useless), but instead saves the buffer visiting the data file. |
| 180 | |
| 181 | To terminate Forms mode, you can use @kbd{C-x C-s} (@code{forms-save-buffer}) |
| 182 | and then kill the forms buffer. However, the data buffer will still |
| 183 | remain. If this is not desired, you have to kill this buffer too. |
| 184 | |
| 185 | @node Forms Commands |
| 186 | @chapter Forms Commands |
| 187 | |
| 188 | The commands of Forms mode belong to the @kbd{C-c} prefix, with one |
| 189 | exception: @key{TAB}, which moves to the next field. Forms mode uses |
| 190 | different key maps for normal mode and read-only mode. In read-only |
| 191 | Forms mode, you can access most of the commands without the @kbd{C-c} |
| 192 | prefix, but you must type ordinary letters instead of control |
| 193 | characters; for example, type @kbd{n} instead of @kbd{C-c C-n}. |
| 194 | |
| 195 | If your Emacs has been built with X-toolkit support, Forms mode will |
| 196 | provide its own menu with a number of Forms mode commands. |
| 197 | |
| 198 | @table @kbd |
| 199 | @findex forms-next-record |
| 200 | @kindex C-c C-n |
| 201 | @item C-c C-n |
| 202 | Show the next record (@code{forms-next-record}). With a numeric |
| 203 | argument @var{n}, show the @var{n}th next record. |
| 204 | |
| 205 | @findex forms-prev-record |
| 206 | @kindex C-c C-p |
| 207 | @item C-c C-p |
| 208 | Show the previous record (@code{forms-prev-record}). With a numeric |
| 209 | argument @var{n}, show the @var{n}th previous record. |
| 210 | |
| 211 | @findex forms-jump-record |
| 212 | @kindex C-c C-l |
| 213 | @item C-c C-l |
| 214 | Jump to a record by number (@code{forms-jump-record}). Specify |
| 215 | the record number with a numeric argument. |
| 216 | |
| 217 | @findex forms-first-record |
| 218 | @kindex C-c < |
| 219 | @item C-c < |
| 220 | Jump to the first record (@code{forms-first-record}). |
| 221 | |
| 222 | @findex forms-last-record |
| 223 | @kindex C-c > |
| 224 | @item C-c > |
| 225 | Jump to the last record (@code{forms-last-record}). This command also |
| 226 | recalculates the number of records in the data file. |
| 227 | |
| 228 | @findex forms-next-field |
| 229 | @kindex TAB |
| 230 | @item @key{TAB} |
| 231 | @kindex C-c TAB |
| 232 | @itemx C-c @key{TAB} |
| 233 | Jump to the next field in the current record (@code{forms-next-field}). |
| 234 | With a numeric argument @var{n}, jump forward @var{n} fields. If this command |
| 235 | would move past the last field, it wraps around to the first field. |
| 236 | |
| 237 | @findex forms-toggle-read-only |
| 238 | @kindex C-c C-q |
| 239 | @item C-c C-q |
| 240 | Toggles read-only mode (@code{forms-toggle-read-only}). In read-only |
| 241 | Forms mode, you cannot edit the fields; most Forms mode commands can be |
| 242 | accessed without the prefix @kbd{C-c} if you use the normal letter |
| 243 | instead (for example, type @kbd{n} instead of @kbd{C-c C-n}). In edit |
| 244 | mode, you can edit the fields and thus change the contents of the data |
| 245 | base; you must begin Forms mode commands with @code{C-c}. Switching |
| 246 | to edit mode is allowed only if you have write access to the data file. |
| 247 | |
| 248 | @findex forms-insert-record |
| 249 | @kindex C-c C-o |
| 250 | @item C-c C-o |
| 251 | Create a new record and insert it before the current record |
| 252 | (@code{forms-insert-record}). It starts out with empty (or default) |
| 253 | contents for its fields; you can then edit the fields. With a numeric |
| 254 | argument, the new record is created @emph{after} the current one. |
| 255 | See also @code{forms-modified-record-filter} in @ref{Modifying Forms |
| 256 | Contents}. |
| 257 | |
| 258 | @findex forms-delete-record |
| 259 | @kindex C-c C-k |
| 260 | @item C-c C-k |
| 261 | Delete the current record (@code{forms-delete-record}). You are |
| 262 | prompted for confirmation before the record is deleted unless a numeric |
| 263 | argument has been provided. |
| 264 | |
| 265 | @findex forms-search-forward |
| 266 | @kindex C-c C-s @var{regexp} @key{RET} |
| 267 | @item C-c C-s @var{regexp} @key{RET} |
| 268 | Search forward for @var{regexp} in all records following this one |
| 269 | (@code{forms-search-forward}). If found, this record is shown. |
| 270 | If you give an empty argument, the previous regexp is used again. |
| 271 | |
| 272 | @findex forms-search-backward |
| 273 | @kindex C-c C-r @var{regexp} @key{RET} |
| 274 | @item C-c C-r @var{regexp} @key{RET} |
| 275 | Search backward for @var{regexp} in all records following this one |
| 276 | (@code{forms-search-backward}). If found, this record is shown. |
| 277 | If you give an empty argument, the previous regexp is used again. |
| 278 | |
| 279 | @ignore |
| 280 | @findex forms-exit |
| 281 | @kindex C-c C-x |
| 282 | @item C-c C-x |
| 283 | Terminate Forms mode processing (@code{forms-exit}). The data file is |
| 284 | saved if it has been modified. |
| 285 | |
| 286 | @findex forms-exit-no-save |
| 287 | @item M-x forms-exit-no-save |
| 288 | Terminates forms mode processing without saving modified data first. |
| 289 | @end ignore |
| 290 | |
| 291 | @findex forms-prev-field |
| 292 | @item M-x forms-prev-field |
| 293 | Similar to @code{forms-next-field} but moves backwards. |
| 294 | |
| 295 | @findex forms-save-buffer |
| 296 | @item M-x forms-save-buffer |
| 297 | @kindex C-x C-s |
| 298 | @itemx C-x C-s |
| 299 | Forms mode replacement for @code{save-buffer}. When executed in the |
| 300 | forms buffer it will save the contents of the (modified) data buffer |
| 301 | instead. In Forms mode this function will be bound to @kbd{C-x C-s}. |
| 302 | |
| 303 | @findex forms-print |
| 304 | @item M-x forms-print |
| 305 | This command can be used to make a formatted print |
| 306 | of the contents of the data file. |
| 307 | |
| 308 | @end table |
| 309 | |
| 310 | In addition the command @kbd{M-x revert-buffer} is useful in Forms mode |
| 311 | just as in other modes. |
| 312 | |
| 313 | @ignore |
| 314 | @vindex forms-forms-scroll |
| 315 | @findex scroll-up |
| 316 | @findex scroll-down |
| 317 | If the variable @code{forms-forms-scrolls} is set to a value other |
| 318 | than @code{nil} (which it is, by default), the Emacs functions |
| 319 | @code{scroll-up} and @code{scroll-down} will perform a |
| 320 | @code{forms-next-record} and @code{forms-prev-record} when in forms |
| 321 | mode. So you can use your favorite page commands to page through the |
| 322 | data file. |
| 323 | |
| 324 | @vindex forms-forms-jump |
| 325 | @findex beginning-of-buffer |
| 326 | @findex end-of-buffer |
| 327 | Likewise, if the variable @code{forms-forms-jump} is not @code{nil} |
| 328 | (which it is, by default), Emacs functions @code{beginning-of-buffer} |
| 329 | and @code{end-of-buffer} will perform @code{forms-first-record} and |
| 330 | @code{forms-last-record} when in forms mode. |
| 331 | @end ignore |
| 332 | |
| 333 | The following function key definitions are set up in Forms mode |
| 334 | (whether read-only or not): |
| 335 | |
| 336 | @table @kbd |
| 337 | @kindex next |
| 338 | @item next |
| 339 | forms-next-record |
| 340 | |
| 341 | @kindex prior |
| 342 | @item prior |
| 343 | forms-prev-record |
| 344 | |
| 345 | @kindex begin |
| 346 | @item begin |
| 347 | forms-first-record |
| 348 | |
| 349 | @kindex end |
| 350 | @item end |
| 351 | forms-last-record |
| 352 | |
| 353 | @kindex S-Tab |
| 354 | @findex forms-prev-field |
| 355 | @item S-Tab |
| 356 | forms-prev-field |
| 357 | @end table |
| 358 | |
| 359 | @node Data File Format |
| 360 | @chapter Data File Format |
| 361 | |
| 362 | @cindex record |
| 363 | @cindex field |
| 364 | @vindex forms-field-sep |
| 365 | Files for use with Forms mode are very simple---each @dfn{record} |
| 366 | (usually one line) forms the contents of one form. Each record consists |
| 367 | of a number of @dfn{fields}, which are separated by the value of the |
| 368 | string @code{forms-field-sep}, which is @code{"\t"} (a Tab) by default. |
| 369 | |
| 370 | @vindex forms-read-file-filter |
| 371 | @vindex forms-write-file-filter |
| 372 | If the format of the data file is not suitable enough you can define the |
| 373 | filter functions @code{forms-read-file-filter} and |
| 374 | @code{forms-write-file-filter}. @code{forms-read-file-filter} is called |
| 375 | when the data file is read from disk into the data buffer. It operates |
| 376 | on the data buffer, ignoring read-only protections. When the data file |
| 377 | is saved to disk @code{forms-write-file-filter} is called to cancel the |
| 378 | effects of @code{forms-read-file-filter}. After being saved, |
| 379 | @code{forms-read-file-filter} is called again to prepare the data buffer |
| 380 | for further processing. |
| 381 | |
| 382 | @cindex pseudo-newline |
| 383 | @vindex forms-multi-line |
| 384 | Fields may contain text which shows up in the forms in multiple lines. |
| 385 | These lines are separated in the field using a ``pseudo-newline'' |
| 386 | character which is defined by the value of the string |
| 387 | @code{forms-multi-line}. Its default value is @code{"\^k"} (a Control-K |
| 388 | character). If it is |
| 389 | set to @code{nil}, multiple line fields are prohibited. |
| 390 | |
| 391 | If the data file does not exist, it is automatically created. |
| 392 | |
| 393 | @node Control File Format |
| 394 | @chapter Control File Format |
| 395 | |
| 396 | @cindex control file |
| 397 | The Forms mode @dfn{control file} serves two purposes. First, it names |
| 398 | the data file to use, and defines its format and properties. Second, |
| 399 | the Emacs buffer it occupies is used by Forms mode to display the forms. |
| 400 | |
| 401 | The contents of the control file are evaluated as a Lisp program. It |
| 402 | should set the following Lisp variables to suitable values: |
| 403 | |
| 404 | @table @code |
| 405 | @vindex forms-file |
| 406 | @item forms-file |
| 407 | This variable specifies the name of the data file. Example: |
| 408 | |
| 409 | @example |
| 410 | (setq forms-file "my/data-file") |
| 411 | @end example |
| 412 | |
| 413 | If the control file doesn't set @code{forms-file}, Forms mode |
| 414 | reports an error. |
| 415 | |
| 416 | @vindex forms-format-list |
| 417 | @item forms-format-list |
| 418 | This variable describes the way the fields of the record are formatted on |
| 419 | the screen. For details, see @ref{Format Description}. |
| 420 | |
| 421 | @vindex forms-number-of-fields |
| 422 | @item forms-number-of-fields |
| 423 | This variable holds the number of fields in each record of the data |
| 424 | file. Example: |
| 425 | |
| 426 | @example |
| 427 | (setq forms-number-of-fields 10) |
| 428 | @end example |
| 429 | @end table |
| 430 | |
| 431 | If the control file does not set @code{forms-format-list} a default |
| 432 | format is used. In this situation, Forms mode will deduce the number of |
| 433 | fields from the data file providing this file exists and |
| 434 | @code{forms-number-of-records} has not been set in the control file. |
| 435 | |
| 436 | The control file can optionally set the following additional Forms mode |
| 437 | variables. Most of them have default values that are good for most |
| 438 | applications. |
| 439 | |
| 440 | @table @code |
| 441 | @vindex forms-field-sep |
| 442 | @item forms-field-sep |
| 443 | This variable may be used to designate the string which separates the |
| 444 | fields in the records of the data file. If not set, it defaults to the |
| 445 | string @code{"\t"} (a Tab character). Example: |
| 446 | |
| 447 | @example |
| 448 | (setq forms-field-sep "\t") |
| 449 | @end example |
| 450 | |
| 451 | @vindex forms-read-only |
| 452 | @item forms-read-only |
| 453 | If the value is non-@code{nil}, the data file is treated read-only. (Forms |
| 454 | mode also treats the data file as read-only if you don't have access to |
| 455 | write it.) Example: |
| 456 | |
| 457 | @example |
| 458 | (set forms-read-only t) |
| 459 | @end example |
| 460 | |
| 461 | @vindex forms-multi-line |
| 462 | @item forms-multi-line |
| 463 | This variable specifies the @dfn{pseudo newline} separator that allows |
| 464 | multi-line fields. This separator goes between the ``lines'' within a |
| 465 | field---thus, the field doesn't really contain multiple lines, but it |
| 466 | appears that way when displayed in Forms mode. If the value is |
| 467 | @code{nil}, multi-line text fields are prohibited. The pseudo newline |
| 468 | must not be a character contained in @code{forms-field-sep}. |
| 469 | |
| 470 | The default value is @code{"\^k"}, the character Control-K@. Example: |
| 471 | |
| 472 | @example |
| 473 | (setq forms-multi-line "\^k") |
| 474 | @end example |
| 475 | |
| 476 | @ignore |
| 477 | @vindex forms-forms-scroll |
| 478 | @item forms-forms-scroll |
| 479 | @xref{Forms Mode Commands}, for details. |
| 480 | |
| 481 | @vindex forms-forms-jump |
| 482 | @item forms-forms-jump |
| 483 | @xref{Forms Mode Commands}, for details. |
| 484 | @end ignore |
| 485 | |
| 486 | @findex forms-read-file-filter |
| 487 | @item forms-read-file-filter |
| 488 | This variable holds the name of a function to be called after the data |
| 489 | file has been read in. This can be used to transform the contents of the |
| 490 | data file into a format more suitable for forms processing. |
| 491 | If it is @code{nil}, no function is called. For example, to maintain a |
| 492 | gzipped database: |
| 493 | |
| 494 | @example |
| 495 | (defun gzip-read-file-filter () |
| 496 | (shell-command-on-region (point-min) (point-max) |
| 497 | "gzip -d" t t)) |
| 498 | (setq forms-read-file-filter 'gzip-read-file-filter) |
| 499 | @end example |
| 500 | |
| 501 | @findex forms-write-file-filter |
| 502 | @item forms-write-file-filter |
| 503 | This variable holds the name of a function to be called before writing |
| 504 | out the contents of the data file. |
| 505 | This can be used to undo the effects of @code{forms-read-file-filter}. |
| 506 | If it is @code{nil}, no function is called. Example: |
| 507 | |
| 508 | @example |
| 509 | (defun gzip-write-file-filter () |
| 510 | (make-variable-buffer-local 'require-final-newline) |
| 511 | (setq require-final-newline nil) |
| 512 | (shell-command-on-region (point-min) (point-max) |
| 513 | "gzip" t t)) |
| 514 | (setq forms-write-file-filter 'gzip-write-file-filter) |
| 515 | @end example |
| 516 | |
| 517 | @findex forms-new-record-filter |
| 518 | @item forms-new-record-filter |
| 519 | This variable holds a function to be called whenever a new record is created |
| 520 | to supply default values for fields. If it is @code{nil}, no function is |
| 521 | called. |
| 522 | @xref{Modifying Forms Contents}, for details. |
| 523 | |
| 524 | @findex forms-modified-record-filter |
| 525 | @item forms-modified-record-filter |
| 526 | This variable holds a function to be called whenever a record is |
| 527 | modified, just before updating the Forms data file. If it is |
| 528 | @code{nil}, no function is called. |
| 529 | @xref{Modifying Forms Contents}, for details. |
| 530 | |
| 531 | @findex forms-insert-after |
| 532 | @item forms-insert-after |
| 533 | If this variable is not @code{nil}, new records are created @emph{after} the |
| 534 | current record. Also, upon visiting a file, the initial position will be |
| 535 | at the last record instead of the first one. |
| 536 | |
| 537 | @findex forms-check-number-of-fields |
| 538 | @item forms-check-number-of-fields |
| 539 | Normally each record is checked to contain the correct number of fields. |
| 540 | Under certain circumstances, this can be undesirable. |
| 541 | If this variable is set to @code{nil}, these checks will be bypassed. |
| 542 | @end table |
| 543 | |
| 544 | @node Format Description |
| 545 | @chapter The Format Description |
| 546 | |
| 547 | @vindex forms-format-list |
| 548 | The variable @code{forms-format-list} specifies the format of the data |
| 549 | in the data file, and how to convert the data for display in Forms mode. |
| 550 | Its value must be a list of Forms mode @dfn{formatting elements}, each |
| 551 | of which can be a string, a number, a Lisp list, or a Lisp symbol that |
| 552 | evaluates to one of those. The formatting elements are processed in the |
| 553 | order they appear in the list. |
| 554 | |
| 555 | @table @var |
| 556 | @item string |
| 557 | A string formatting element is inserted in the forms ``as is,'' as text |
| 558 | that the user cannot alter. |
| 559 | |
| 560 | @item number |
| 561 | A number element selects a field of the record. The contents of this |
| 562 | field are inserted in the display at this point. Field numbers count |
| 563 | starting from 1 (one). |
| 564 | |
| 565 | @item list |
| 566 | A formatting element that is a list specifies a function call. This |
| 567 | function is called every time a record is displayed, and its result, |
| 568 | which must be a string, is inserted in the display text. The function |
| 569 | should do nothing but returning a string. |
| 570 | |
| 571 | @vindex forms-fields |
| 572 | The function you call can access the fields of the record as a list in |
| 573 | the variable |
| 574 | @code{forms-fields}. |
| 575 | |
| 576 | @item symbol |
| 577 | A symbol used as a formatting element should evaluate to a string, number, |
| 578 | or list; the value is interpreted as a formatting element, as described |
| 579 | above. |
| 580 | @end table |
| 581 | |
| 582 | If a record does not contain the number of fields as specified in |
| 583 | @code{forms-number-of-fields}, a warning message will be printed. Excess |
| 584 | fields are ignored, missing fields are set to empty. |
| 585 | |
| 586 | The control file which displays @file{/etc/passwd} file as demonstrated |
| 587 | in the beginning of this manual might look as follows: |
| 588 | |
| 589 | @example |
| 590 | ;; @r{This demo visits @file{/etc/passwd}.} |
| 591 | |
| 592 | (setq forms-file "/etc/passwd") |
| 593 | (setq forms-number-of-fields 7) |
| 594 | (setq forms-read-only t) ; @r{to make sure} |
| 595 | (setq forms-field-sep ":") |
| 596 | ;; @r{Don't allow multi-line fields.} |
| 597 | (setq forms-multi-line nil) |
| 598 | |
| 599 | (setq forms-format-list |
| 600 | (list |
| 601 | "====== /etc/passwd ======\n\n" |
| 602 | "User : " 1 |
| 603 | " Uid: " 3 |
| 604 | " Gid: " 4 |
| 605 | "\n\n" |
| 606 | "Name : " 5 |
| 607 | "\n\n" |
| 608 | "Home : " 6 |
| 609 | "\n\n" |
| 610 | "Shell: " 7 |
| 611 | "\n")) |
| 612 | @end example |
| 613 | |
| 614 | When you construct the value of @code{forms-format-list}, you should |
| 615 | usually either quote the whole value, like this, |
| 616 | |
| 617 | @example |
| 618 | (setq forms-format-list |
| 619 | '( |
| 620 | "====== " forms-file " ======\n\n" |
| 621 | "User : " 1 |
| 622 | (make-string 20 ?-) |
| 623 | @dots{} |
| 624 | )) |
| 625 | @end example |
| 626 | |
| 627 | @noindent |
| 628 | or quote the elements which are lists, like this: |
| 629 | |
| 630 | @example |
| 631 | (setq forms-format-list |
| 632 | (list |
| 633 | "====== " forms-file " ======\n\n" |
| 634 | "User : " 1 |
| 635 | '(make-string 20 ?-) |
| 636 | @dots{} |
| 637 | )) |
| 638 | @end example |
| 639 | |
| 640 | Forms mode validates the contents of @code{forms-format-list} when you |
| 641 | visit a database. If there are errors, processing is aborted with an |
| 642 | error message which includes a descriptive text. @xref{Error Messages}, |
| 643 | for a detailed list of error messages. |
| 644 | |
| 645 | If no @code{forms-format-list} is specified, Forms mode will supply a |
| 646 | default format list. This list contains the name of the file being |
| 647 | visited, and a simple label for each field indicating the field number. |
| 648 | |
| 649 | @node Modifying Forms Contents |
| 650 | @chapter Modifying The Forms Contents |
| 651 | |
| 652 | If @code{forms-read-only} is @code{nil}, the user can modify the fields |
| 653 | and records of the database. |
| 654 | |
| 655 | All normal editing commands are available for editing the contents of the |
| 656 | displayed record. You cannot delete or modify the fixed, explanatory |
| 657 | text that comes from string formatting elements, but you can modify the |
| 658 | actual field contents. |
| 659 | |
| 660 | @ignore |
| 661 | @c This is for the Emacs 18 version only. |
| 662 | If the contents of the forms cannot be recognized properly, this is |
| 663 | signaled using a descriptive text. @xref{Error Messages}, for more info. |
| 664 | The cursor will indicate the last part of the forms which was |
| 665 | successfully parsed. It's important to avoid entering field contents |
| 666 | that would cause confusion with the field-separating fixed text. |
| 667 | @end ignore |
| 668 | |
| 669 | If the variable @code{forms-modified-record-filter} is non-@code{nil}, |
| 670 | it is called as a function before the new data is written to the data |
| 671 | file. The function receives one argument, a vector that contains the |
| 672 | contents of the fields of the record. |
| 673 | |
| 674 | The function can refer to fields with @code{aref} and modify them with |
| 675 | @code{aset}. The first field has number 1 (one); thus, element 0 of the |
| 676 | vector is not used. The function should return the same vector it was |
| 677 | passed; the (possibly modified) contents of the vector determine what is |
| 678 | actually written in the file. Here is an example: |
| 679 | |
| 680 | @example |
| 681 | (defun my-modified-record-filter (record) |
| 682 | ;; @r{Modify second field.} |
| 683 | (aset record 2 (current-time-string)) |
| 684 | ;; @r{Return the field vector.} |
| 685 | record) |
| 686 | |
| 687 | (setq forms-modified-record-filter 'my-modified-record-filter) |
| 688 | @end example |
| 689 | |
| 690 | If the variable @code{forms-new-record-filter} is non-@code{nil}, its |
| 691 | value is a function to be called to fill in default values for the |
| 692 | fields of a new record. The function is passed a vector of empty |
| 693 | strings, one for each field; it should return the same vector, with |
| 694 | the desired field values stored in it. Fields are numbered starting |
| 695 | from 1 (one). Example: |
| 696 | |
| 697 | @example |
| 698 | (defun my-new-record-filter (fields) |
| 699 | (aset fields 5 (login-name)) |
| 700 | (aset fields 1 (current-time-string)) |
| 701 | fields) |
| 702 | |
| 703 | (setq forms-new-record-filter 'my-new-record-filter) |
| 704 | @end example |
| 705 | |
| 706 | @node Miscellaneous |
| 707 | @chapter Miscellaneous |
| 708 | |
| 709 | @vindex forms-version |
| 710 | The global variable @code{forms-version} holds the version information |
| 711 | of the Forms mode software. |
| 712 | |
| 713 | @findex forms-enumerate |
| 714 | It is very convenient to use symbolic names for the fields in a record. |
| 715 | The function @code{forms-enumerate} provides an elegant means to define |
| 716 | a series of variables whose values are consecutive integers. The |
| 717 | function returns the highest number used, so it can be used to set |
| 718 | @code{forms-number-of-fields} also. For example: |
| 719 | |
| 720 | @example |
| 721 | (setq forms-number-of-fields |
| 722 | (forms-enumerate |
| 723 | '(field1 field2 field3 @dots{}))) |
| 724 | @end example |
| 725 | |
| 726 | This sets @code{field1} to 1, @code{field2} to 2, and so on. |
| 727 | |
| 728 | Care has been taken to keep the Forms mode variables buffer-local, so it |
| 729 | is possible to visit multiple files in Forms mode simultaneously, even |
| 730 | if they have different properties. |
| 731 | |
| 732 | @findex forms-mode |
| 733 | If you have visited the control file in normal fashion with |
| 734 | @code{find-file} or a like command, you can switch to Forms mode with |
| 735 | the command @code{M-x forms-mode}. If you put @samp{-*- forms -*-} in |
| 736 | the first line of the control file, then visiting it enables Forms mode |
| 737 | automatically. But this makes it hard to edit the control file itself, |
| 738 | so you'd better think twice before using this. |
| 739 | |
| 740 | The default format for the data file, using @code{"\t"} to separate |
| 741 | fields and @code{"\^k"} to separate lines within a field, matches the |
| 742 | file format of some popular database programs, e.g., FileMaker. So |
| 743 | @code{forms-mode} can decrease the need to use proprietary software. |
| 744 | |
| 745 | @node Error Messages |
| 746 | @chapter Error Messages |
| 747 | |
| 748 | This section describes all error messages which can be generated by |
| 749 | forms mode. Error messages that result from parsing the control file |
| 750 | all start with the text @samp{Forms control file error}. Messages |
| 751 | generated while analyzing the definition of @code{forms-format-list} |
| 752 | start with @samp{Forms format error}. |
| 753 | |
| 754 | @table @code |
| 755 | @item Forms control file error: `forms-file' has not been set |
| 756 | The variable @code{forms-file} was not set by the control file. |
| 757 | |
| 758 | @item Forms control file error: `forms-number-of-fields' has not been set |
| 759 | The variable @code{forms-number-of-fields} was not set by the control |
| 760 | file. |
| 761 | |
| 762 | @item Forms control file error: `forms-number-of-fields' must be a number > 0 |
| 763 | The variable @code{forms-number-of-fields} did not contain a positive |
| 764 | number. |
| 765 | |
| 766 | @item Forms control file error: `forms-field-sep' is not a string |
| 767 | @itemx Forms control file error: `forms-multi-line' must be nil or a one-character string |
| 768 | The variable @code{forms-multi-line} was set to something other than |
| 769 | @code{nil} or a single-character string. |
| 770 | |
| 771 | @item Forms control file error: `forms-multi-line' is equal to 'forms-field-sep' |
| 772 | The variable @code{forms-multi-line} may not be equal to |
| 773 | @code{forms-field-sep} for this would make it impossible to distinguish |
| 774 | fields and the lines in the fields. |
| 775 | |
| 776 | @item Forms control file error: `forms-new-record-filter' is not a function |
| 777 | @itemx Forms control file error: `forms-modified-record-filter' is not a function |
| 778 | The variable has been set to something else than a function. |
| 779 | |
| 780 | @item Forms control file error: `forms-format-list' is not a list |
| 781 | The variable @code{forms-format-list} was not set to a Lisp list |
| 782 | by the control file. |
| 783 | |
| 784 | @item Forms format error: field number @var{xx} out of range 1..@var{nn} |
| 785 | A field number was supplied in @code{forms-format-list} with a value of |
| 786 | @var{xx}, which was not greater than zero and smaller than or equal to |
| 787 | the number of fields in the forms, @var{nn}. |
| 788 | |
| 789 | @item Forms format error: @var{fun} is not a function |
| 790 | The first element of a list which is an element of |
| 791 | @code{forms-format-list} was not a valid Lisp function. |
| 792 | |
| 793 | @item Forms format error: invalid element @var{xx} |
| 794 | A list element was supplied in @code{forms-format-list} which was not a |
| 795 | string, number or list. |
| 796 | |
| 797 | @ignore |
| 798 | @c This applies to Emacs 18 only. |
| 799 | @c Error messages generated while a modified form is being analyzed. |
| 800 | |
| 801 | @item Parse error: not looking at `...' |
| 802 | When re-parsing the contents of a forms, the text shown could not |
| 803 | be found. |
| 804 | |
| 805 | @item Parse error: cannot find `...' |
| 806 | When re-parsing the contents of a forms, the text shown, which |
| 807 | separates two fields, could not be found. |
| 808 | |
| 809 | @item Parse error: cannot parse adjacent fields @var{xx} and @var{yy} |
| 810 | Fields @var{xx} and @var{yy} were not separated by text, so could not be |
| 811 | parsed again. |
| 812 | @end ignore |
| 813 | |
| 814 | @item Warning: this record has @var{xx} fields instead of @var{yy} |
| 815 | The number of fields in this record in the data file did not match |
| 816 | @code{forms-number-of-fields}. Missing fields will be made empty. |
| 817 | |
| 818 | @item Multi-line fields in this record - update refused! |
| 819 | The current record contains newline characters, hence can not be written |
| 820 | back to the data file, for it would corrupt it. Probably you inserted a |
| 821 | newline in a field, while @code{forms-multi-line} was @code{nil}. |
| 822 | |
| 823 | @item Field separator occurs in record - update refused! |
| 824 | The current record contains the field separator string inside one of the |
| 825 | fields. It can not be written back to the data file, for it would |
| 826 | corrupt it. Probably you inserted the field separator string in a field. |
| 827 | |
| 828 | @item Record number @var{xx} out of range 1..@var{yy} |
| 829 | A jump was made to non-existing record @var{xx}. @var{yy} denotes the |
| 830 | number of records in the file. |
| 831 | |
| 832 | @item Stuck at record @var{xx} |
| 833 | An internal error prevented a specific record from being retrieved. |
| 834 | |
| 835 | @item No write access to @code{"}@var{file}@code{"} |
| 836 | An attempt was made to enable edit mode on a file that has been write |
| 837 | protected. |
| 838 | |
| 839 | @item Search failed: @var{regexp} |
| 840 | The @var{regexp} could not be found in the data file. Forward searching |
| 841 | is done from the current location until the end of the file, then |
| 842 | retrying from the beginning of the file until the current location. |
| 843 | Backward searching is done from the current location until the beginning |
| 844 | of the file, then retrying from the end of the file until the current |
| 845 | location. |
| 846 | |
| 847 | @item Wrapped |
| 848 | A search completed successfully after wrapping around. |
| 849 | |
| 850 | @item Warning: number of records changed to @var{nn} |
| 851 | Forms mode's idea of the number of records has been adjusted to the |
| 852 | number of records actually present in the data file. |
| 853 | |
| 854 | @item Problem saving buffers? |
| 855 | An error occurred while saving the data file buffer. Most likely, Emacs |
| 856 | did ask to confirm deleting the buffer because it had been modified, and |
| 857 | you said `no'. |
| 858 | @end table |
| 859 | |
| 860 | @node Long Example |
| 861 | @chapter Long Example |
| 862 | |
| 863 | The following example exploits most of the features of Forms mode. |
| 864 | This example is included in the distribution as file @file{etc/forms/forms-d2.el}. |
| 865 | |
| 866 | @example |
| 867 | ;; demo2 -- demo forms-mode -*- emacs-lisp -*- |
| 868 | |
| 869 | ;; @r{This sample forms exploit most of the features of forms mode.} |
| 870 | |
| 871 | ;; @r{Set the name of the data file.} |
| 872 | (setq forms-file |
| 873 | (expand-file-name "forms/forms-d2.dat" data-directory)) |
| 874 | |
| 875 | ;; @r{Use @code{forms-enumerate} to set field names and number thereof.} |
| 876 | (setq forms-number-of-fields |
| 877 | (forms-enumerate |
| 878 | '(arch-newsgroup ; 1 |
| 879 | arch-volume ; 2 |
| 880 | arch-issue ; and ... |
| 881 | arch-article ; ... so |
| 882 | arch-shortname ; ... ... on |
| 883 | arch-parts |
| 884 | arch-from |
| 885 | arch-longname |
| 886 | arch-keywords |
| 887 | arch-date |
| 888 | arch-remarks))) |
| 889 | |
| 890 | ;; @r{The following functions are used by this form for layout purposes.} |
| 891 | ;; |
| 892 | (defun arch-tocol (target &optional fill) |
| 893 | "Produces a string to skip to column TARGET. |
| 894 | Prepends newline if needed. |
| 895 | The optional FILL should be a character, used to fill to the column." |
| 896 | (if (null fill) |
| 897 | (setq fill ? )) |
| 898 | (if (< target (current-column)) |
| 899 | (concat "\n" (make-string target fill)) |
| 900 | (make-string (- target (current-column)) fill))) |
| 901 | ;; |
| 902 | (defun arch-rj (target field &optional fill) |
| 903 | "Produces a string to skip to column TARGET\ |
| 904 | minus the width of field FIELD. |
| 905 | Prepends newline if needed. |
| 906 | The optional FILL should be a character, |
| 907 | used to fill to the column." |
| 908 | (arch-tocol (- target (length (nth field forms-fields))) fill)) |
| 909 | |
| 910 | ;; @r{Record filters.} |
| 911 | ;; |
| 912 | (defun new-record-filter (the-record) |
| 913 | "Form a new record with some defaults." |
| 914 | (aset the-record arch-from (user-full-name)) |
| 915 | (aset the-record arch-date (current-time-string)) |
| 916 | the-record) ; return it |
| 917 | (setq forms-new-record-filter 'new-record-filter) |
| 918 | |
| 919 | ;; @r{The format list.} |
| 920 | (setq forms-format-list |
| 921 | (list |
| 922 | "====== Public Domain Software Archive ======\n\n" |
| 923 | arch-shortname |
| 924 | " - " arch-longname |
| 925 | "\n\n" |
| 926 | "Article: " arch-newsgroup |
| 927 | "/" arch-article |
| 928 | " " |
| 929 | '(arch-tocol 40) |
| 930 | "Issue: " arch-issue |
| 931 | " " |
| 932 | '(arch-rj 73 10) |
| 933 | "Date: " arch-date |
| 934 | "\n\n" |
| 935 | "Submitted by: " arch-from |
| 936 | "\n" |
| 937 | '(arch-tocol 79 ?-) |
| 938 | "\n" |
| 939 | "Keywords: " arch-keywords |
| 940 | "\n\n" |
| 941 | "Parts: " arch-parts |
| 942 | "\n\n====== Remarks ======\n\n" |
| 943 | arch-remarks |
| 944 | )) |
| 945 | |
| 946 | ;; @r{That's all, folks!} |
| 947 | @end example |
| 948 | |
| 949 | @node Credits |
| 950 | @chapter Credits |
| 951 | |
| 952 | Bug fixes and other useful suggestions were supplied by |
| 953 | Harald Hanche-Olsen (@code{hanche@@imf.unit.no}), |
| 954 | @code{cwitty@@portia.stanford.edu}, |
| 955 | Jonathan I. Kamens, |
| 956 | Per Cederqvist (@code{ceder@@signum.se}), |
| 957 | Michael Lipka (@code{lipka@@lip.hanse.de}), |
| 958 | Andy Piper (@code{ajp@@eng.cam.ac.uk}), |
| 959 | Frederic Pierresteguy (@code{F.Pierresteguy@@frcl.bull.fr}), |
| 960 | Ignatios Souvatzis |
| 961 | and Richard Stallman (@code{rms@@gnu.org}). |
| 962 | |
| 963 | This documentation was slightly inspired by the documentation of ``rolo |
| 964 | mode'' by Paul Davis at Schlumberger Cambridge Research |
| 965 | (@code{davis%scrsu1%sdr.slb.com@@relay.cs.net}). |
| 966 | |
| 967 | None of this would have been possible without GNU Emacs of the Free |
| 968 | Software Foundation. Thanks, Richard! |
| 969 | |
| 970 | @node GNU Free Documentation License |
| 971 | @appendix GNU Free Documentation License |
| 972 | @include doclicense.texi |
| 973 | |
| 974 | @node Index |
| 975 | @unnumbered Index |
| 976 | @printindex cp |
| 977 | |
| 978 | @bye |