comparison lisp/forms.el @ 307:7fede845e304

*** empty log message ***
author Richard M. Stallman <rms@gnu.org>
date Mon, 01 Jul 1991 18:06:13 +0000
parents e7eb71cbf478
children 994bb6dc9249
comparison
equal deleted inserted replaced
306:785babb5bb6f 307:7fede845e304
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 ;;; Last Modified By: Johan Vromans
6 ;;; Last Modified On: Mon Jul 1 14:13:20 1991
7 ;;; Update Count : 15
8 ;;; Status : OK
9
5 ;;; This file is part of GNU Emacs. 10 ;;; This file is part of GNU Emacs.
6
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
10 ;;; or for whether it serves any particular purpose or works at all, 14 ;;; or for whether it serves any particular purpose or works at all,
11 ;;; unless he says so in writing. Refer to the GNU Emacs General Public 15 ;;; unless he says so in writing. Refer to the GNU Emacs General Public
18 ;;; can know your rights and responsibilities. 22 ;;; can know your rights and responsibilities.
19 ;;; If you don't have this copy, write to the Free Software 23 ;;; If you don't have this copy, write to the Free Software
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.
26 ;;; 45 ;;;
27 ;;; === Naming conventions 46 ;;; === Naming conventions
73 ;;; 92 ;;;
74 ;;; forms-format-list [list] formatting instructions. 93 ;;; forms-format-list [list] formatting instructions.
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.
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.
83 ;;; 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]
87 ;;; The field separator used to separate the 114 ;;; The field separator used to separate the
109 ;;; forms-forms-jump [bool, default t] 136 ;;; forms-forms-jump [bool, default t]
110 ;;; If non-nil: redefine beginning/end-of-buffer 137 ;;; If non-nil: redefine beginning/end-of-buffer
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.
121 ;;; The data file (as designated by "forms-file") is visited in a buffer 160 ;;; The data file (as designated by "forms-file") is visited in a buffer
122 ;;; (forms--file-buffer) which will not normally be shown. 161 ;;; (forms--file-buffer) which will not normally be shown.
124 ;;; outside of this package while it's being visited! 163 ;;; outside of this package while it's being visited!
125 ;;; 164 ;;;
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
133 ;;; is left. The contents of the form are parsed using forms-format-list, 172 ;;; is left. The contents of the form are parsed using forms-format-list,
134 ;;; and the fields which are deduced from the form are modified. So, 173 ;;; and the fields which are deduced from the form are modified. So,
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
142 ;;; (which doesn't). However, if forms-exit-no-save is executed and the file 181 ;;; (which doesn't). However, if forms-exit-no-save is executed and the file
143 ;;; buffer has been modified, emacs will ask questions. 182 ;;; buffer has been modified, emacs will ask questions.
194 ;;; For convenience, TAB is always bound to forms-next-field, so you 233 ;;; For convenience, TAB is always bound to forms-next-field, so you
195 ;;; don't need the C-c prefix for this command. 234 ;;; don't need the C-c prefix for this command.
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
203 "If non-null: redefine scroll-up/down to be used with forms-mode.") 242 "If non-null: redefine scroll-up/down to be used with forms-mode.")
204 243
209 "Hook functions to be run upon entering forms mode.") 248 "Hook functions to be run upon entering forms mode.")
210 ;;; 249 ;;;
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.")
230 260
231 ;;; 261 ;;;
285 "Internal - keeps track of forms-mode being set-up.") 315 "Internal - keeps track of forms-mode being set-up.")
286 (make-variable-buffer-local 'forms--mode-setup) 316 (make-variable-buffer-local 'forms--mode-setup)
287 317
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.")
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.")
290 329
291 ;;; 330 ;;;
292 ;;; forms-mode 331 ;;; forms-mode
293 ;;; 332 ;;;
294 ;;; This is not a simple major mode, as usual. Therefore, forms-mode 333 ;;; This is not a simple major mode, as usual. Therefore, forms-mode
357 (make-local-variable 'forms--format) 396 (make-local-variable 'forms--format)
358 (forms--make-format) 397 (forms--make-format)
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)
372 427
373 ;; prevent accidental overwrite of the control file and autosave 428 ;; prevent accidental overwrite of the control file and autosave
443 ;;; Sets forms--number-of-markers and forms--markers. 498 ;;; Sets forms--number-of-markers and forms--markers.
444 499
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"))
451 ;; it must be a list ... 509 ;; it must be a list ...
452 (or (listp forms-format-list) 510 (or (listp forms-format-list)
453 (error "'forms-format-list' is not a list")) 511 (error "'forms-format-list' is not a list"))
454 512
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
518
519 (setq forms-format-list nil) ; gonna rebuild
459 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)))
525
526 ;; if it is a symbol, eval it first
527 (if (and (symbolp el)
528 (boundp el))
529 (setq el (eval el)))
464 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
496 ;; car must be string
497 ((not (stringp str))
498 (error "forms error: car of cons %s must be string"
499 (prin1-to-string el)))
500
501 ;; cdr must be number, > zero
502 ((or (not (numberp idx))
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
510 ;; passed the test - handle it
511 (setq forms--number-of-markers (1+ forms--number-of-markers))
512 (if (> idx field-num)
513 (setq field-num idx)))))
514 560
515 ;; advance to next element of the list 561 ;; advance to next element of the list
516 (setq the-list rem)))) 562 (setq the-list rem)
563 (setq forms-format-list
564 (append forms-format-list (list el) nil)))))
565
566 (forms--debug "forms-forms-list after 1st pass:\n"
567 'forms-format-list)
568
569 ;; concat adjacent strings
570 (setq forms-format-list (forms--concat-adjacent forms-format-list))
571
572 (forms--debug "forms-forms-list after 2nd pass:\n"
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
520 578
521 ;;; 579 ;;;
522 ;;; Build the format routine from forms-format-list. 580 ;;; Build the format routine from forms-format-list.
523 ;;; 581 ;;;
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
531 ;;; (aset forms--markers 0 (point-marker)) 589 ;;; (aset forms--markers 0 (point-marker))
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))
538 ;;; 601 ;;;
539 ;;; ... ) 602 ;;; ... )
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)
556 (` ((insert (, el))))) 620 (` ((insert (, el)))))
557 ((numberp el) 621 ((numberp el)
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)
565 "Concatenate adjacent strings in the-list and return the resulting list" 637 "Concatenate adjacent strings in the-list and return the resulting list"
566 (if (consp the-list) 638 (if (consp the-list)
582 ;;; (let (here) 654 ;;; (let (here)
583 ;;; (goto-char (point-min)) 655 ;;; (goto-char (point-min))
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)))
600 ;;; 678 ;;;
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))
617 (,@ (apply 'append 695 (,@ (apply 'append
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 ()
648 (setq minor-mode-alist 746 (setq minor-mode-alist
649 (if forms-read-only 747 (if forms-read-only
697 ;; 795 ;;
698 (if (fboundp 'forms--scroll-down) 796 (if (fboundp 'forms--scroll-down)
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)
706 (forms-prev-record arg) 804 (forms-prev-record arg)
707 (forms--scroll-down arg))))) 805 (forms--scroll-down arg)))))
710 ;; 808 ;;
711 (if (fboundp 'forms--scroll-up) 809 (if (fboundp 'forms--scroll-up)
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)
719 (forms-next-record arg) 817 (forms-next-record arg)
720 (forms--scroll-up arg))))) 818 (forms--scroll-up arg)))))
858 (- forms-number-of-fields 956 (- forms-number-of-fields
859 (length forms--the-record-list)) 957 (length forms--the-record-list))
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
866 (goto-char (point-min)) 965 (goto-char (point-min))
867 (set-buffer-modified-p nil) 966 (set-buffer-modified-p nil)
882 981
883 ;; build the vector 982 ;; build the vector
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))
888 987 (funcall forms--parser))
889 ;; transform to a list and return 988
890 (append the-recordv nil))) 989 (if forms--modified-record-filter
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
894 forms--the-record-list ." 1001 forms--the-record-list ."
895 (if forms-read-only 1002 (if forms-read-only
1063 (if (equal ro forms-read-only) 1170 (if (equal ro forms-read-only)
1064 nil 1171 nil
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
1081 (interactive "P") 1190 (interactive "P")
1082 1191
1191 (goto-char there) 1300 (goto-char there)
1192 (throw 'done t)))) 1301 (throw 'done t))))
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: