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