diff options
| author | Richard M. Stallman | 1991-07-01 18:06:13 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1991-07-01 18:06:13 +0000 |
| commit | 01a453133b73e130ac2415f07f6e9f63794d9efb (patch) | |
| tree | c57f4e8f180e136a4a864f4e2cd032dee1e38e00 | |
| parent | 5dd353d2d79162c2277aa43d231aa34171c5f95b (diff) | |
| download | emacs-01a453133b73e130ac2415f07f6e9f63794d9efb.tar.gz emacs-01a453133b73e130ac2415f07f6e9f63794d9efb.zip | |
*** empty log message ***
| -rw-r--r-- | lisp/forms.el | 363 |
1 files changed, 262 insertions, 101 deletions
diff --git a/lisp/forms.el b/lisp/forms.el index b0598da72f4..3690c7e9a4a 100644 --- a/lisp/forms.el +++ b/lisp/forms.el | |||
| @@ -1,9 +1,13 @@ | |||
| 1 | ;;; Forms Mode - A GNU Emacs Major Mode ; @(#)@ forms 1.2.2 | 1 | ;;; forms.el -- Forms Mode - A GNU Emacs Major Mode |
| 2 | ;;; Created 1989 - Johan Vromans <jv@mh.nl> | 2 | ;;; SCCS Status : @(#)@ forms 1.2.7 |
| 3 | ;;; See the docs for a list of other contributors. | 3 | ;;; Author : Johan Vromans |
| 4 | ;;; | 4 | ;;; Created On : 1989 |
| 5 | ;;; This file is part of GNU Emacs. | 5 | ;;; Last Modified By: Johan Vromans |
| 6 | ;;; Last Modified On: Mon Jul 1 14:13:20 1991 | ||
| 7 | ;;; Update Count : 15 | ||
| 8 | ;;; Status : OK | ||
| 6 | 9 | ||
| 10 | ;;; This file is part of GNU Emacs. | ||
| 7 | ;;; GNU Emacs is distributed in the hope that it will be useful, | 11 | ;;; GNU Emacs is distributed in the hope that it will be useful, |
| 8 | ;;; but WITHOUT ANY WARRANTY. No author or distributor | 12 | ;;; but WITHOUT ANY WARRANTY. No author or distributor |
| 9 | ;;; accepts responsibility to anyone for the consequences of using it | 13 | ;;; accepts responsibility to anyone for the consequences of using it |
| @@ -20,6 +24,21 @@ | |||
| 20 | ;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 24 | ;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 21 | ;;; | 25 | ;;; |
| 22 | 26 | ||
| 27 | ;;; HISTORY | ||
| 28 | ;;; 1-Jul-1991 Johan Vromans | ||
| 29 | ;;; Normalized error messages. | ||
| 30 | ;;; 30-Jun-1991 Johan Vromans | ||
| 31 | ;;; Add support for forms-modified-record-filter. | ||
| 32 | ;;; Allow the filter functions to be the name of a function. | ||
| 33 | ;;; Fix: parse--format used forms--dynamic-text destructively. | ||
| 34 | ;;; Internally optimized the forms-format-list. | ||
| 35 | ;;; Added support for debugging. | ||
| 36 | ;;; Stripped duplicate documentation. | ||
| 37 | ;;; | ||
| 38 | ;;; 29-Jun-1991 Johan Vromans | ||
| 39 | ;;; Add support for functions and lisp symbols in forms-format-list. | ||
| 40 | ;;; Add function forms-enumerate. | ||
| 41 | |||
| 23 | (provide 'forms-mode) | 42 | (provide 'forms-mode) |
| 24 | 43 | ||
| 25 | ;;; Visit a file using a form. | 44 | ;;; Visit a file using a form. |
| @@ -75,12 +94,20 @@ | |||
| 75 | ;;; | 94 | ;;; |
| 76 | ;;; The forms-format-list should be a list, each element containing | 95 | ;;; The forms-format-list should be a list, each element containing |
| 77 | ;;; | 96 | ;;; |
| 78 | ;;; - either a string, e.g. "hello" (which is inserted \"as is\"), | 97 | ;;; - a string, e.g. "hello" (which is inserted \"as is\"), |
| 79 | ;;; | 98 | ;;; |
| 80 | ;;; - an integer, denoting a field number. The contents of the field | 99 | ;;; - an integer, denoting a field number. The contents of the field |
| 81 | ;;; are inserted at this point. | 100 | ;;; are inserted at this point. |
| 82 | ;;; The first field has number one. | 101 | ;;; The first field has number one. |
| 83 | ;;; | 102 | ;;; |
| 103 | ;;; - a function call, e.g. (insert "text"). This function call is | ||
| 104 | ;;; dynamically evaluated and should return a string. It should *NOT* | ||
| 105 | ;;; have side-effects on the forms being constructed. | ||
| 106 | ;;; The current fields are available to the function in the variable | ||
| 107 | ;;; forms-fields, they should *NOT* be modified. | ||
| 108 | ;;; | ||
| 109 | ;;; - a lisp symbol, that must evaluate to one of the above. | ||
| 110 | ;;; | ||
| 84 | ;;; Optional variables which may be set in the control file: | 111 | ;;; Optional variables which may be set in the control file: |
| 85 | ;;; | 112 | ;;; |
| 86 | ;;; forms-field-sep [string, default TAB] | 113 | ;;; forms-field-sep [string, default TAB] |
| @@ -111,10 +138,22 @@ | |||
| 111 | ;;; to performs forms-first/last-field if in | 138 | ;;; to performs forms-first/last-field if in |
| 112 | ;;; forms mode. | 139 | ;;; forms mode. |
| 113 | ;;; | 140 | ;;; |
| 114 | ;;; forms-new-record-filter [function, no default] | 141 | ;;; forms-new-record-filter [symbol, no default] |
| 115 | ;;; If defined: this function is called when a new | 142 | ;;; If defined: this should be the name of a |
| 143 | ;;; function that is called when a new | ||
| 116 | ;;; record is created. It can be used to fill in | 144 | ;;; record is created. It can be used to fill in |
| 117 | ;;; the new record with default fields, for example. | 145 | ;;; the new record with default fields, for example. |
| 146 | ;;; Instead of the name of the function, it may | ||
| 147 | ;;; be the function itself. | ||
| 148 | ;;; | ||
| 149 | ;;; forms-modified-record-filter [symbol, no default] | ||
| 150 | ;;; If defined: this should be the name of a | ||
| 151 | ;;; function that is called when a record has | ||
| 152 | ;;; been modified. It is called after the fields | ||
| 153 | ;;; are parsed. It can be used to register | ||
| 154 | ;;; modification dates, for example. | ||
| 155 | ;;; Instead of the name of the function, it may | ||
| 156 | ;;; be the function itself. | ||
| 118 | ;;; | 157 | ;;; |
| 119 | ;;; After evaluating the control file, its buffer is cleared and used | 158 | ;;; After evaluating the control file, its buffer is cleared and used |
| 120 | ;;; for further processing. | 159 | ;;; for further processing. |
| @@ -126,7 +165,7 @@ | |||
| 126 | ;;; A record from the data file is transferred from the data file, | 165 | ;;; A record from the data file is transferred from the data file, |
| 127 | ;;; split into fields (into forms--the-record-list), and displayed using | 166 | ;;; split into fields (into forms--the-record-list), and displayed using |
| 128 | ;;; the specs in forms-format-list. | 167 | ;;; the specs in forms-format-list. |
| 129 | ;;; A format routine 'forms--format' is build upon startup to format | 168 | ;;; A format routine 'forms--format' is built upon startup to format |
| 130 | ;;; the records. | 169 | ;;; the records. |
| 131 | ;;; | 170 | ;;; |
| 132 | ;;; When a form is changed the record is updated as soon as this form | 171 | ;;; When a form is changed the record is updated as soon as this form |
| @@ -135,7 +174,7 @@ | |||
| 135 | ;;; fields not shown on the forms retain their origional values. | 174 | ;;; fields not shown on the forms retain their origional values. |
| 136 | ;;; The newly formed record and replaces the contents of the | 175 | ;;; The newly formed record and replaces the contents of the |
| 137 | ;;; old record in forms--file-buffer. | 176 | ;;; old record in forms--file-buffer. |
| 138 | ;;; A parse routine 'forms--parser' is build upon startup to parse | 177 | ;;; A parse routine 'forms--parser' is built upon startup to parse |
| 139 | ;;; the records. | 178 | ;;; the records. |
| 140 | ;;; | 179 | ;;; |
| 141 | ;;; Two exit functions exist: forms-exit (which saves) and forms-exit-no-save | 180 | ;;; Two exit functions exist: forms-exit (which saves) and forms-exit-no-save |
| @@ -196,7 +235,7 @@ | |||
| 196 | ;;; | 235 | ;;; |
| 197 | ;;; Global variables and constants | 236 | ;;; Global variables and constants |
| 198 | 237 | ||
| 199 | (defconst forms-version "1.2.2" | 238 | (defconst forms-version "1.2.7" |
| 200 | "Version of forms-mode implementation") | 239 | "Version of forms-mode implementation") |
| 201 | 240 | ||
| 202 | (defvar forms-forms-scrolls t | 241 | (defvar forms-forms-scrolls t |
| @@ -211,19 +250,10 @@ | |||
| 211 | ;;; Mandatory variables - must be set by evaluating the control file | 250 | ;;; Mandatory variables - must be set by evaluating the control file |
| 212 | 251 | ||
| 213 | (defvar forms-file nil | 252 | (defvar forms-file nil |
| 214 | "Name of the file holding the data.") | 253 | "Name of the file holding the data.") |
| 215 | 254 | ||
| 216 | (defvar forms-format-list nil | 255 | (defvar forms-format-list nil |
| 217 | "Formatting specifications: | 256 | "List of formatting specifications.") |
| 218 | |||
| 219 | It should be a list, each element containing | ||
| 220 | |||
| 221 | - either a string, e.g. "hello" (which is inserted \"as is\"), | ||
| 222 | |||
| 223 | - an integer, denoting the number of a field which contents are | ||
| 224 | inserted at this point. | ||
| 225 | The first field has number one. | ||
| 226 | ") | ||
| 227 | 257 | ||
| 228 | (defvar forms-number-of-fields nil | 258 | (defvar forms-number-of-fields nil |
| 229 | "Number of fields per record.") | 259 | "Number of fields per record.") |
| @@ -288,6 +318,15 @@ It should be a list, each element containing | |||
| 288 | (defvar forms--new-record-filter nil | 318 | (defvar forms--new-record-filter nil |
| 289 | "Internal - set if a new record filter has been defined.") | 319 | "Internal - set if a new record filter has been defined.") |
| 290 | 320 | ||
| 321 | (defvar forms--modified-record-filter nil | ||
| 322 | "Internal - set if a modified record filter has been defined.") | ||
| 323 | |||
| 324 | (defvar forms--dynamic-text nil | ||
| 325 | "Internal - holds dynamic text to insert between fields.") | ||
| 326 | |||
| 327 | (defvar forms-fields nil | ||
| 328 | "List with fields of the current forms. First field has number 1.") | ||
| 329 | |||
| 291 | ;;; | 330 | ;;; |
| 292 | ;;; forms-mode | 331 | ;;; forms-mode |
| 293 | ;;; | 332 | ;;; |
| @@ -359,13 +398,29 @@ It should be a list, each element containing | |||
| 359 | (make-local-variable 'forms--parser) | 398 | (make-local-variable 'forms--parser) |
| 360 | (forms--make-parser) | 399 | (forms--make-parser) |
| 361 | 400 | ||
| 362 | ;; check if a new record filter was defined | 401 | ;; check if record filters are defined |
| 363 | (make-local-variable 'forms--new-record-filter) | 402 | (make-local-variable 'forms--new-record-filter) |
| 364 | (setq forms--new-record-filter | 403 | (setq forms--new-record-filter |
| 365 | (and (fboundp 'forms-new-record-filter) | 404 | (cond |
| 366 | (symbol-function 'forms-new-record-filter))) | 405 | ((fboundp 'forms-new-record-filter) |
| 406 | (symbol-function 'forms-new-record-filter)) | ||
| 407 | ((and (boundp 'forms-new-record-filter) | ||
| 408 | (fboundp forms-new-record-filter)) | ||
| 409 | forms-new-record-filter))) | ||
| 367 | (fmakunbound 'forms-new-record-filter) | 410 | (fmakunbound 'forms-new-record-filter) |
| 368 | 411 | (make-local-variable 'forms--modified-record-filter) | |
| 412 | (setq forms--modified-record-filter | ||
| 413 | (cond | ||
| 414 | ((fboundp 'forms-modified-record-filter) | ||
| 415 | (symbol-function 'forms-modified-record-filter)) | ||
| 416 | ((and (boundp 'forms-modified-record-filter) | ||
| 417 | (fboundp forms-modified-record-filter)) | ||
| 418 | forms-modified-record-filter))) | ||
| 419 | (fmakunbound 'forms-modified-record-filter) | ||
| 420 | |||
| 421 | ;; dynamic text support | ||
| 422 | (make-local-variable 'forms--dynamic-text) | ||
| 423 | (make-local-variable 'forms-fields) | ||
| 369 | 424 | ||
| 370 | ;; prepare this buffer for further processing | 425 | ;; prepare this buffer for further processing |
| 371 | (setq buffer-read-only nil) | 426 | (setq buffer-read-only nil) |
| @@ -445,6 +500,9 @@ It should be a list, each element containing | |||
| 445 | (defun forms--process-format-list () | 500 | (defun forms--process-format-list () |
| 446 | "Validate forms-format-list and set some global variables." | 501 | "Validate forms-format-list and set some global variables." |
| 447 | 502 | ||
| 503 | (forms--debug "forms-forms-list before 1st pass:\n" | ||
| 504 | 'forms-format-list) | ||
| 505 | |||
| 448 | ;; it must be non-nil | 506 | ;; it must be non-nil |
| 449 | (or forms-format-list | 507 | (or forms-format-list |
| 450 | (error "'forms-format-list' has not been set")) | 508 | (error "'forms-format-list' has not been set")) |
| @@ -455,65 +513,65 @@ It should be a list, each element containing | |||
| 455 | (setq forms--number-of-markers 0) | 513 | (setq forms--number-of-markers 0) |
| 456 | 514 | ||
| 457 | (let ((the-list forms-format-list) ; the list of format elements | 515 | (let ((the-list forms-format-list) ; the list of format elements |
| 516 | (this-item 0) ; element in list | ||
| 458 | (field-num 0)) ; highest field number | 517 | (field-num 0)) ; highest field number |
| 459 | 518 | ||
| 519 | (setq forms-format-list nil) ; gonna rebuild | ||
| 520 | |||
| 460 | (while the-list | 521 | (while the-list |
| 461 | 522 | ||
| 462 | (let ((el (car-safe the-list)) | 523 | (let ((el (car-safe the-list)) |
| 463 | (rem (cdr-safe the-list))) | 524 | (rem (cdr-safe the-list))) |
| 464 | 525 | ||
| 526 | ;; if it is a symbol, eval it first | ||
| 527 | (if (and (symbolp el) | ||
| 528 | (boundp el)) | ||
| 529 | (setq el (eval el))) | ||
| 530 | |||
| 465 | (cond | 531 | (cond |
| 466 | 532 | ||
| 467 | ;; try string ... | 533 | ;; try string ... |
| 468 | ((stringp el)) ; string is OK | 534 | ((stringp el)) ; string is OK |
| 469 | 535 | ||
| 470 | ;; try int ... | 536 | ;; try numeric ... |
| 471 | ((numberp el) ; check it | 537 | ((numberp el) |
| 472 | 538 | ||
| 473 | (if (or (<= el 0) | 539 | (if (or (<= el 0) |
| 474 | (> el forms-number-of-fields)) | 540 | (> el forms-number-of-fields)) |
| 475 | (error | 541 | (error |
| 476 | "forms error: field number %d out of range 1..%d" | 542 | "Forms error: field number %d out of range 1..%d" |
| 477 | el forms-number-of-fields)) | 543 | el forms-number-of-fields)) |
| 478 | 544 | ||
| 479 | (setq forms--number-of-markers (1+ forms--number-of-markers)) | 545 | (setq forms--number-of-markers (1+ forms--number-of-markers)) |
| 480 | (if (> el field-num) | 546 | (if (> el field-num) |
| 481 | (setq field-num el))) | 547 | (setq field-num el))) |
| 482 | 548 | ||
| 549 | ;; try function | ||
| 550 | ((listp el) | ||
| 551 | (or (fboundp (car-safe el)) | ||
| 552 | (error | ||
| 553 | "Forms error: not a function: %s" | ||
| 554 | (prin1-to-string (car-safe el))))) | ||
| 555 | |||
| 483 | ;; else | 556 | ;; else |
| 484 | (t | 557 | (t |
| 485 | (error "invalid element in 'forms-format-list': %s" | 558 | (error "Invalid element in 'forms-format-list': %s" |
| 486 | (prin1-to-string el))) | 559 | (prin1-to-string el)))) |
| 487 | |||
| 488 | ;; dead code - we'll need it in the future | ||
| 489 | ((consp el) ; check it | ||
| 490 | |||
| 491 | (let ((str (car-safe el)) | ||
| 492 | (idx (cdr-safe el))) | ||
| 493 | |||
| 494 | (cond | ||
| 495 | 560 | ||
| 496 | ;; car must be string | 561 | ;; advance to next element of the list |
| 497 | ((not (stringp str)) | 562 | (setq the-list rem) |
| 498 | (error "forms error: car of cons %s must be string" | 563 | (setq forms-format-list |
| 499 | (prin1-to-string el))) | 564 | (append forms-format-list (list el) nil))))) |
| 500 | 565 | ||
| 501 | ;; cdr must be number, > zero | 566 | (forms--debug "forms-forms-list after 1st pass:\n" |
| 502 | ((or (not (numberp idx)) | 567 | 'forms-format-list) |
| 503 | (<= idx 0) | ||
| 504 | (> idx forms-number-of-fields)) | ||
| 505 | (error | ||
| 506 | "forms error: cdr of cons %s must be a number between 1 and %d" | ||
| 507 | (prin1-to-string el) | ||
| 508 | forms-number-of-fields))) | ||
| 509 | 568 | ||
| 510 | ;; passed the test - handle it | 569 | ;; concat adjacent strings |
| 511 | (setq forms--number-of-markers (1+ forms--number-of-markers)) | 570 | (setq forms-format-list (forms--concat-adjacent forms-format-list)) |
| 512 | (if (> idx field-num) | ||
| 513 | (setq field-num idx))))) | ||
| 514 | 571 | ||
| 515 | ;; advance to next element of the list | 572 | (forms--debug "forms-forms-list after 2nd pass:\n" |
| 516 | (setq the-list rem)))) | 573 | 'forms-format-list |
| 574 | 'forms--number-of-markers) | ||
| 517 | 575 | ||
| 518 | (setq forms--markers (make-vector forms--number-of-markers nil))) | 576 | (setq forms--markers (make-vector forms--number-of-markers nil))) |
| 519 | 577 | ||
| @@ -524,7 +582,7 @@ It should be a list, each element containing | |||
| 524 | ;;; The format routine (forms--format) will look like | 582 | ;;; The format routine (forms--format) will look like |
| 525 | ;;; | 583 | ;;; |
| 526 | ;;; (lambda (arg) | 584 | ;;; (lambda (arg) |
| 527 | ;;; | 585 | ;;; (setq forms--dynamic-text nil) |
| 528 | ;;; ;; "text: " | 586 | ;;; ;; "text: " |
| 529 | ;;; (insert "text: ") | 587 | ;;; (insert "text: ") |
| 530 | ;;; ;; 6 | 588 | ;;; ;; 6 |
| @@ -532,6 +590,11 @@ It should be a list, each element containing | |||
| 532 | ;;; (insert (elt arg 5)) | 590 | ;;; (insert (elt arg 5)) |
| 533 | ;;; ;; "\nmore text: " | 591 | ;;; ;; "\nmore text: " |
| 534 | ;;; (insert "\nmore text: ") | 592 | ;;; (insert "\nmore text: ") |
| 593 | ;;; ;; (tocol 40) | ||
| 594 | ;;; (let ((the-dyntext (tocol 40))) | ||
| 595 | ;;; (insert the-dyntext) | ||
| 596 | ;;; (setq forms--dynamic-text (append forms--dynamic-text | ||
| 597 | ;;; (list the-dyntext)))) | ||
| 535 | ;;; ;; 9 | 598 | ;;; ;; 9 |
| 536 | ;;; (aset forms--markers 1 (point-marker)) | 599 | ;;; (aset forms--markers 1 (point-marker)) |
| 537 | ;;; (insert (elt arg 8)) | 600 | ;;; (insert (elt arg 8)) |
| @@ -540,16 +603,17 @@ It should be a list, each element containing | |||
| 540 | ;;; | 603 | ;;; |
| 541 | 604 | ||
| 542 | (defun forms--make-format () | 605 | (defun forms--make-format () |
| 543 | "Generate parser function for forms" | 606 | "Generate format function for forms" |
| 544 | (setq forms--format (forms--format-maker forms-format-list))) | 607 | (setq forms--format (forms--format-maker forms-format-list)) |
| 608 | (forms--debug 'forms--format)) | ||
| 545 | 609 | ||
| 546 | (defun forms--format-maker (the-format-list) | 610 | (defun forms--format-maker (the-format-list) |
| 547 | "Returns the parser function for forms" | 611 | "Returns the parser function for forms" |
| 548 | (let ((the-marker 0)) | 612 | (let ((the-marker 0)) |
| 549 | (` (lambda (arg) | 613 | (` (lambda (arg) |
| 614 | (setq forms--dynamic-text nil) | ||
| 550 | (,@ (apply 'append | 615 | (,@ (apply 'append |
| 551 | (mapcar 'forms--make-format-elt | 616 | (mapcar 'forms--make-format-elt the-format-list))))))) |
| 552 | (forms--concat-adjacent the-format-list)))))))) | ||
| 553 | 617 | ||
| 554 | (defun forms--make-format-elt (el) | 618 | (defun forms--make-format-elt (el) |
| 555 | (cond ((stringp el) | 619 | (cond ((stringp el) |
| @@ -558,7 +622,15 @@ It should be a list, each element containing | |||
| 558 | (prog1 | 622 | (prog1 |
| 559 | (` ((aset forms--markers (, the-marker) (point-marker)) | 623 | (` ((aset forms--markers (, the-marker) (point-marker)) |
| 560 | (insert (elt arg (, (1- el)))))) | 624 | (insert (elt arg (, (1- el)))))) |
| 561 | (setq the-marker (1+ the-marker)))))) | 625 | (setq the-marker (1+ the-marker)))) |
| 626 | ((listp el) | ||
| 627 | (prog1 | ||
| 628 | (` ((let ((the-dyntext (, el))) | ||
| 629 | (insert the-dyntext) | ||
| 630 | (setq forms--dynamic-text (append forms--dynamic-text | ||
| 631 | (list the-dyntext))))) | ||
| 632 | ))) | ||
| 633 | )) | ||
| 562 | 634 | ||
| 563 | 635 | ||
| 564 | (defun forms--concat-adjacent (the-list) | 636 | (defun forms--concat-adjacent (the-list) |
| @@ -584,16 +656,22 @@ It should be a list, each element containing | |||
| 584 | ;;; | 656 | ;;; |
| 585 | ;;; ;; "text: " | 657 | ;;; ;; "text: " |
| 586 | ;;; (if (not (looking-at "text: ")) | 658 | ;;; (if (not (looking-at "text: ")) |
| 587 | ;;; (error "parse error: cannot find \"text: \"")) | 659 | ;;; (error "Parse error: cannot find \"text: \"")) |
| 588 | ;;; (forward-char 6) ; past "text: " | 660 | ;;; (forward-char 6) ; past "text: " |
| 589 | ;;; | 661 | ;;; |
| 590 | ;;; ;; 6 | 662 | ;;; ;; 6 |
| 591 | ;;; ;; "\nmore text: " | 663 | ;;; ;; "\nmore text: " |
| 592 | ;;; (setq here (point)) | 664 | ;;; (setq here (point)) |
| 593 | ;;; (if (not (search-forward "\nmore text: " nil t nil)) | 665 | ;;; (if (not (search-forward "\nmore text: " nil t nil)) |
| 594 | ;;; (error "parse error: cannot find \"\\nmore text: \"")) | 666 | ;;; (error "Parse error: cannot find \"\\nmore text: \"")) |
| 595 | ;;; (aset the-recordv 5 (buffer-substring here (- (point) 12))) | 667 | ;;; (aset the-recordv 5 (buffer-substring here (- (point) 12))) |
| 596 | ;;; ... | 668 | ;;; |
| 669 | ;;; ;; (tocol 40) | ||
| 670 | ;;; (let ((the-dyntext (car-safe forms--dynamic-text))) | ||
| 671 | ;;; (if (not (looking-at (regexp-quote the-dyntext))) | ||
| 672 | ;;; (error "Parse error: not looking at \"%s\"" the-dyntext)) | ||
| 673 | ;;; (forward-char (length the-dyntext)) | ||
| 674 | ;;; (setq forms--dynamic-text (cdr-safe forms--dynamic-text))) | ||
| 597 | ;;; ... | 675 | ;;; ... |
| 598 | ;;; ;; final flush (due to terminator sentinel, see below) | 676 | ;;; ;; final flush (due to terminator sentinel, see below) |
| 599 | ;;; (aset the-recordv 7 (buffer-substring (point) (point-max))) | 677 | ;;; (aset the-recordv 7 (buffer-substring (point) (point-max))) |
| @@ -601,16 +679,16 @@ It should be a list, each element containing | |||
| 601 | 679 | ||
| 602 | (defun forms--make-parser () | 680 | (defun forms--make-parser () |
| 603 | "Generate parser function for forms" | 681 | "Generate parser function for forms" |
| 604 | (setq forms--parser (forms--parser-maker forms-format-list))) | 682 | (setq forms--parser (forms--parser-maker forms-format-list)) |
| 683 | (forms--debug 'forms--parser)) | ||
| 605 | 684 | ||
| 606 | (defun forms--parser-maker (the-format-list) | 685 | (defun forms--parser-maker (the-format-list) |
| 607 | "Returns the parser function for forms" | 686 | "Returns the parser function for forms" |
| 608 | (let ((the-field nil) | 687 | (let ((the-field nil) |
| 609 | (seen-text nil) | 688 | (seen-text nil) |
| 610 | the--format-list) | 689 | the--format-list) |
| 611 | ;; concat adjacent strings and add a terminator sentinel | 690 | ;; add a terminator sentinel |
| 612 | (setq the--format-list | 691 | (setq the--format-list (append the-format-list (list nil))) |
| 613 | (append (forms--concat-adjacent the-format-list) (list nil))) | ||
| 614 | (` (lambda nil | 692 | (` (lambda nil |
| 615 | (let (here) | 693 | (let (here) |
| 616 | (goto-char (point-min)) | 694 | (goto-char (point-min)) |
| @@ -618,30 +696,50 @@ It should be a list, each element containing | |||
| 618 | (mapcar 'forms--make-parser-elt the--format-list)))))))) | 696 | (mapcar 'forms--make-parser-elt the--format-list)))))))) |
| 619 | 697 | ||
| 620 | (defun forms--make-parser-elt (el) | 698 | (defun forms--make-parser-elt (el) |
| 621 | (cond ((stringp el) | 699 | (cond |
| 622 | (prog1 | 700 | ((stringp el) |
| 623 | (if the-field | 701 | (prog1 |
| 624 | (` ((setq here (point)) | 702 | (if the-field |
| 625 | (if (not (search-forward (, el) nil t nil)) | 703 | (` ((setq here (point)) |
| 626 | (error "Parse error: cannot find %s" (, el))) | 704 | (if (not (search-forward (, el) nil t nil)) |
| 627 | (aset the-recordv (, (1- the-field)) | 705 | (error "Parse error: cannot find \"%s\"" (, el))) |
| 628 | (buffer-substring here | 706 | (aset the-recordv (, (1- the-field)) |
| 629 | (- (point) (, (length el))))))) | 707 | (buffer-substring here |
| 630 | (` ((if (not (looking-at (, (regexp-quote el)))) | 708 | (- (point) (, (length el))))))) |
| 631 | (error "Parse error: not looking at %s" (, el))) | 709 | (` ((if (not (looking-at (, (regexp-quote el)))) |
| 632 | (forward-char (, (length el)))))) | 710 | (error "Parse error: not looking at \"%s\"" (, el))) |
| 633 | (setq seen-text t) | 711 | (forward-char (, (length el)))))) |
| 634 | (setq the-field nil))) | 712 | (setq seen-text t) |
| 635 | ((numberp el) | 713 | (setq the-field nil))) |
| 636 | (if the-field | 714 | ((numberp el) |
| 637 | (error "Cannot parse adjacent fields %d and %d" | 715 | (if the-field |
| 638 | the-field el) | 716 | (error "Cannot parse adjacent fields %d and %d" |
| 639 | (setq the-field el) | 717 | the-field el) |
| 640 | nil)) | 718 | (setq the-field el) |
| 641 | ((null el) | 719 | nil)) |
| 642 | (if the-field | 720 | ((null el) |
| 643 | (` ((aset the-recordv (, (1- the-field)) | 721 | (if the-field |
| 644 | (buffer-substring (point) (point-max))))))))) | 722 | (` ((aset the-recordv (, (1- the-field)) |
| 723 | (buffer-substring (point) (point-max))))))) | ||
| 724 | ((listp el) | ||
| 725 | (prog1 | ||
| 726 | (if the-field | ||
| 727 | (` ((let ((here (point)) | ||
| 728 | (the-dyntext (car-safe forms--dynamic-text))) | ||
| 729 | (if (not (search-forward the-dyntext nil t nil)) | ||
| 730 | (error "Parse error: cannot find \"%s\"" the-dyntext)) | ||
| 731 | (aset the-recordv (, (1- the-field)) | ||
| 732 | (buffer-substring here | ||
| 733 | (- (point) (length the-dyntext)))) | ||
| 734 | (setq forms--dynamic-text (cdr-safe forms--dynamic-text))))) | ||
| 735 | (` ((let ((the-dyntext (car-safe forms--dynamic-text))) | ||
| 736 | (if (not (looking-at (regexp-quote the-dyntext))) | ||
| 737 | (error "Parse error: not looking at \"%s\"" the-dyntext)) | ||
| 738 | (forward-char (length the-dyntext)) | ||
| 739 | (setq forms--dynamic-text (cdr-safe forms--dynamic-text)))))) | ||
| 740 | (setq seen-text t) | ||
| 741 | (setq the-field nil))) | ||
| 742 | )) | ||
| 645 | ;;; | 743 | ;;; |
| 646 | 744 | ||
| 647 | (defun forms--set-minor-mode () | 745 | (defun forms--set-minor-mode () |
| @@ -699,7 +797,7 @@ It should be a list, each element containing | |||
| 699 | nil | 797 | nil |
| 700 | (fset 'forms--scroll-down (symbol-function 'scroll-down)) | 798 | (fset 'forms--scroll-down (symbol-function 'scroll-down)) |
| 701 | (fset 'scroll-down | 799 | (fset 'scroll-down |
| 702 | '(lambda (arg) | 800 | '(lambda (&optional arg) |
| 703 | (interactive "P") | 801 | (interactive "P") |
| 704 | (if (and forms--mode-setup | 802 | (if (and forms--mode-setup |
| 705 | forms-forms-scroll) | 803 | forms-forms-scroll) |
| @@ -712,7 +810,7 @@ It should be a list, each element containing | |||
| 712 | nil | 810 | nil |
| 713 | (fset 'forms--scroll-up (symbol-function 'scroll-up)) | 811 | (fset 'forms--scroll-up (symbol-function 'scroll-up)) |
| 714 | (fset 'scroll-up | 812 | (fset 'scroll-up |
| 715 | '(lambda (arg) | 813 | '(lambda (&optional arg) |
| 716 | (interactive "P") | 814 | (interactive "P") |
| 717 | (if (and forms--mode-setup | 815 | (if (and forms--mode-setup |
| 718 | forms-forms-scroll) | 816 | forms-forms-scroll) |
| @@ -860,6 +958,7 @@ It should be a list, each element containing | |||
| 860 | ""))))) | 958 | ""))))) |
| 861 | 959 | ||
| 862 | ;; call the formatter function | 960 | ;; call the formatter function |
| 961 | (setq forms-fields (append (list nil) forms--the-record-list nil)) | ||
| 863 | (funcall forms--format forms--the-record-list) | 962 | (funcall forms--format forms--the-record-list) |
| 864 | 963 | ||
| 865 | ;; prepare | 964 | ;; prepare |
| @@ -884,10 +983,18 @@ It should be a list, each element containing | |||
| 884 | (setq the-recordv (vconcat forms--the-record-list)) | 983 | (setq the-recordv (vconcat forms--the-record-list)) |
| 885 | 984 | ||
| 886 | ;; parse the form and update the vector | 985 | ;; parse the form and update the vector |
| 887 | (funcall forms--parser) | 986 | (let ((forms--dynamic-text forms--dynamic-text)) |
| 987 | (funcall forms--parser)) | ||
| 888 | 988 | ||
| 889 | ;; transform to a list and return | 989 | (if forms--modified-record-filter |
| 890 | (append the-recordv nil))) | 990 | ;; As a service to the user, we add a zeroth element so she |
| 991 | ;; can use the same indices as in the forms definition. | ||
| 992 | (let ((the-fields (vconcat [nil] the-recordv))) | ||
| 993 | (setq the-fields (funcall forms--modified-record-filter the-fields)) | ||
| 994 | (cdr (append the-fields nil))) | ||
| 995 | |||
| 996 | ;; transform to a list and return | ||
| 997 | (append the-recordv nil)))) | ||
| 891 | 998 | ||
| 892 | (defun forms--update () | 999 | (defun forms--update () |
| 893 | "Update current record with contents of form. As a side effect: sets | 1000 | "Update current record with contents of form. As a side effect: sets |
| @@ -1065,16 +1172,18 @@ forms--the-record-list ." | |||
| 1065 | (forms-mode)))) | 1172 | (forms-mode)))) |
| 1066 | 1173 | ||
| 1067 | ;; Sample: | 1174 | ;; Sample: |
| 1068 | ;; (defun forms-new-record-filter (the-fields) | 1175 | ;; (defun my-new-record-filter (the-fields) |
| 1069 | ;; ;; numbers are relative to 1 | 1176 | ;; ;; numbers are relative to 1 |
| 1070 | ;; (aset the-fields 4 (current-time-string)) | 1177 | ;; (aset the-fields 4 (current-time-string)) |
| 1071 | ;; (aset the-fields 6 (user-login-name)) | 1178 | ;; (aset the-fields 6 (user-login-name)) |
| 1072 | ;; the-list) | 1179 | ;; the-list) |
| 1180 | ;; (setq forms-new-record-filter 'my-new-record-filter) | ||
| 1073 | 1181 | ||
| 1074 | (defun forms-insert-record (arg) | 1182 | (defun forms-insert-record (arg) |
| 1075 | "Create a new record before the current one. With ARG: store the | 1183 | "Create a new record before the current one. With ARG: store the |
| 1076 | record after the current one. | 1184 | record after the current one. |
| 1077 | If a function forms-new-record-filter is defined, is is called to | 1185 | If a function forms-new-record-filter is defined, or forms-new-record-filter |
| 1186 | contains the name of a function, it is called to | ||
| 1078 | fill (some of) the fields with default values." | 1187 | fill (some of) the fields with default values." |
| 1079 | ; The above doc is not true, but for documentary purposes only | 1188 | ; The above doc is not true, but for documentary purposes only |
| 1080 | 1189 | ||
| @@ -1193,3 +1302,55 @@ forms--the-record-list ." | |||
| 1193 | (setq i (1+ i)))) | 1302 | (setq i (1+ i)))) |
| 1194 | nil | 1303 | nil |
| 1195 | (goto-char (aref forms--markers 0))))) | 1304 | (goto-char (aref forms--markers 0))))) |
| 1305 | |||
| 1306 | ;;; | ||
| 1307 | ;;; Special service | ||
| 1308 | ;;; | ||
| 1309 | (defun forms-enumerate (the-fields) | ||
| 1310 | "Take a quoted list of symbols, and set their values to the numbers | ||
| 1311 | 1, 2 and so on. Returns the higest number. | ||
| 1312 | |||
| 1313 | Usage: (setq forms-number-of-fields | ||
| 1314 | (forms-enumerate | ||
| 1315 | '(field1 field2 field2 ...)))" | ||
| 1316 | |||
| 1317 | (let ((the-index 0)) | ||
| 1318 | (while the-fields | ||
| 1319 | (setq the-index (1+ the-index)) | ||
| 1320 | (let ((el (car-safe the-fields))) | ||
| 1321 | (setq the-fields (cdr-safe the-fields)) | ||
| 1322 | (set el the-index))) | ||
| 1323 | the-index)) | ||
| 1324 | |||
| 1325 | ;;; | ||
| 1326 | ;;; Debugging | ||
| 1327 | ;;; | ||
| 1328 | (defvar forms--debug nil | ||
| 1329 | "*Enables forms-mode debugging if not nil.") | ||
| 1330 | |||
| 1331 | (defun forms--debug (&rest args) | ||
| 1332 | "Internal - debugging routine" | ||
| 1333 | (if forms--debug | ||
| 1334 | (let ((ret nil)) | ||
| 1335 | (while args | ||
| 1336 | (let ((el (car-safe args))) | ||
| 1337 | (setq args (cdr-safe args)) | ||
| 1338 | (if (stringp el) | ||
| 1339 | (setq ret (concat ret el)) | ||
| 1340 | (setq ret (concat ret (prin1-to-string el) " = ")) | ||
| 1341 | (if (boundp el) | ||
| 1342 | (let ((vel (eval el))) | ||
| 1343 | (setq ret (concat ret (prin1-to-string vel) "\n"))) | ||
| 1344 | (setq ret (concat ret "<unbound>" "\n"))) | ||
| 1345 | (if (fboundp el) | ||
| 1346 | (setq ret (concat ret (prin1-to-string (symbol-function el)) | ||
| 1347 | "\n")))))) | ||
| 1348 | (save-excursion | ||
| 1349 | (set-buffer (get-buffer-create "*forms-mode debug*")) | ||
| 1350 | (goto-char (point-max)) | ||
| 1351 | (insert ret))))) | ||
| 1352 | |||
| 1353 | ;;; Local Variables: | ||
| 1354 | ;;; eval: (headers) | ||
| 1355 | ;;; eval: (setq comment-start ";;; ") | ||
| 1356 | ;;; End: | ||