File: 0fwmode.fwi

package info (click to toggle)
funnelweb-doc 3.2d-4.2
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,744 kB
  • sloc: perl: 241; makefile: 23
file content (874 lines) | stat: -rw-r--r-- 28,901 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
@=#
@! fwmode.fw - FunnelWeb major mode for Emacs (Elisp).

@p typesetter = tex

\documentstyle{report}

\title{
  An Emacs/Elisp Major Mode for FunnelWeb
}

\author{
  A.B.Coates \\
  Department of Physics \\
  The University of Queensland \\
  QLD\ \ 4072 \\
  Australia \\
  Email: {\tt coates@@physics.uq.oz.au}
}

\begin{document}

\maketitle

\tableofcontents

\chapter{Major and Minor Modes}

\section{The FunnelWeb Major Mode}
This is the definition of the function which defines the FunnelWeb
mode.  A brief (and not exhaustive) description of the functions
available is given in its description string.

@$@<fw-mode Function Definitions@>+=@{
(defun fw-mode ()
  "Major mode for editing FunnelWeb files.  Built on top of
tex-mode.  Makes @@} , @@) , and @@> display their matching
opening braces @@{ , @@( , or @@< .

Use \\[fw-buffer] to run FunnelWeb on the current buffer
*without* saving it.
Use \\[fw-file] to be prompted to save the buffer to a file
first, before running FunnelWeb on the file.
Use \\[fw-tex] to run the (La)TeX output file through TeX or
LaTeX as appropriate.
Use \\[fw-print] to print a .dvi file.
Use \\[fw-show-print-queue] to show the print queue that
\\[fw-print] put your job on.
Commands from tex-mode (or a similar selected mode) are
mapped to operate on the (La)TeX file produced by FunnelWeb.

Key sequences:

see documentation for `switch-mode' for key sequences
relating to mode switching.

Mode variables:
fw-autofill-mode
        Whether autofill-mode is automatically invoked for
        FunnelWeb files.  Set to 0 for no, to a positive
        number for yes.
fw-TeX-mode
        The major (La)TeX mode on which fw-mode is based.
        Typically either 'tex-mode or 'latex-mode
        (or perhaps 'tex-init for Auc-TeX
         or 'html-mode for hypertext ...).
fw-directory
        Directory in which to create temporary files for
        TeX jobs run by \\[fw-buffer] or \\[fw-file].
fw-use-TeX-quote-style
        Set this to nil so the the \" key produces the
        normal \" character.  If set to true, the \" key
        works as for (La)TeX mode, producing either
        `` or ''.
fw-dvi-print-command
        Command string used by \\[fw-print] to print a
        .dvi file.
fw-show-queue-command
        Command string used by \\[fw-show-print-queue] to
        show the print queue that \\[fw-print] put your
        job on.

Entering FunnelWeb-mode calls the value of fw-mode-hook."
  (interactive)
  (funcall fw-TeX-mode)
  (hack-local-variables)
  (setq mode-name "FunnelWeb")
  (setq major-mode 'fw-mode)
  (auto-fill-mode fw-auto-fill-mode)
  (if fw-mode-map (use-local-map fw-mode-map))
  (setq fw-buffer-p t)
  (switch-mode fw-switch-minor-mode-init)
  (run-hooks 'fw-mode-hook))
@}

\section{The Switch Minor Mode}

This is the definition of the function which defines the Switch
minor mode.  A brief (and not exhaustive) description of the functions
available is given in its description string.

@$@<switch-mode Function Definitions 2@>+=@{
(defun switch-mode
  ( &optional set-mode-p
              no-check-p
              region-open-string
              region-close-string
              region-boundary-pattern )
  "With no arguments, toggle whether the region mode
checking is activated or not.  Optional first argument
SET-MODE-P can be used to definitely switch the region
mode checking on or off: a positive number for on, off
otherwise.
    Optional second argument NO-CHECK-P is nil for a
check of whether the point is in a code region or not
to be taken immediately.  With any other value, no check
is done.
    Optional third and fourth arguments REGION-OPEN-STRING
and REGION-CLOSE-STRING define the boundaries by which a
code region is recognised.
    Optional fourth argument REGION-BOUNDARY_PATTERN should
be a pattern equivalent to
    \\(REGION-OPEN-STRING\\|REGION-CLOSE-STRING\\)
i.e. a pattern which recognises either an opening or closing
pattern.

Key sequences:

\\C-x\\C-a key sequences are used for the \"Switch\" minor
mode, which allows modes to be swapped while editing a file.

\\C-x \\C-a t : toggle Switch minor-mode on and off
\\C-x \\C-a c : check whether in macro region or not
\\C-x \\C-a p : toggles whether the default macro region
                mode is used with or without prompting
\\C-x \\C-a s : set the current macro region mode"
  (interactive)
@}

A variable, local to each buffer, is needed to note whether
switch-mode is active or not.

@$@<switch-mode Variable Definitions 1@>+=@{
(defvar switch-mode nil
  "Whether the region checking minor mode is active or not.")
(make-variable-buffer-local 'switch-mode)
@}

The boolean value {\tt switch-on-p} is given the value {\tt t} if the
switch minor mode should be turned on, {\tt nil} otherwise.  The value
depends on when the function call toggles the state or sets it
directly.

@$@<switch-mode Function Definitions 2@>+=@{@-
  (let ((switch-on-p
         (or (and (numberp set-mode-p)
                  (> set-mode-p 0))
             (not switch-mode))))
    (if switch-on-p
        (let ((old-switch-mode-value
               switch-mode))
          (setq switch-mode t
                switch-force-region-check-p t)
          (if (not (or no-check-p old-switch-mode-value))
              (switch-check-if-in-region)))
      (setq switch-mode nil))
@}

Three variables, with local values in each buffer, are required to
hold the values of the region opening and closing strings and a
combined pattern.

@$@<switch-mode Variable Definitions 1@>+=@{
(defvar switch-open-region-string "@@{"
  "String defining the beginning of a code region.")
(make-variable-buffer-local 'switch-open-region-string)

(defvar switch-close-region-string "@@}"
  "String defining the end of a code region.")
(make-variable-buffer-local 'switch-close-region-string)

(defvar switch-boundary-region-pattern "@@\\({\\|}\\)"
  "Regular expression defining the beginning or end of a code
region.")
(make-variable-buffer-local 'switch-boundary-region-pattern)
@}

@$@<switch-mode Function Definitions 2@>+=@{@-
    (if region-open-string
        (setq switch-open-region-string
              region-open-string))
    (if region-close-string
        (setq switch-close-region-string
              region-close-string))
    (if region-boundary-pattern
        (setq switch-boundary-region-pattern
              region-boundary-pattern))
    (force-mode-line-update t)))
@}

\section{Invocation of the FunnelWeb mode}
To cause FunnelWeb to be invoked for {\tt .fw} and {\tt .fwi} files,
the following lines should be added to the user's ``{\tt .emacs}''
file.

@$@<Emacs initialisation file additions@>@Z==@{
(autoload 'fw-mode "fw-mode")
(setq
 auto-mode-alist
 (reverse
  (append
   (reverse auto-mode-alist)
   (list
    (append
     (list "\\.fw$")
     'fw-mode
     )
    (append
     (list "\\.fwi$")
     'fw-mode
     )
    )
   )
  )
 )
@}

\chapter{Function and Variable Definitions for the FunnelWeb Mode}
An alternative command for saving buffers converts all tabs to spaces
before saving, since FunnelWeb does not accept tab characters in .fw
files by default.  Because mode-switching is expected to be used when
editing FunnelWeb files, a local variable in each buffer is set to
define whether a buffer is a FunnelWeb buffer or not.  A global
variable is also provided to switch off the replacement of tabs by
spaces.  The string used to replace tabs with spaces can also be
changed from the default of 8 spaces.  Another global variable also
controls the removal of trailing spaces, since these are also not
accepted by FunnelWeb by default.

@$@<fw-mode Variable Definitions2@>+=@{
(defvar fw-untabify-before-saving-p t
  "*Whether to convert tabs to spaces before saving FunnelWeb
buffers.")

(defvar fw-tab-string "@^D(009)"
  "Tab character as string.")

(defvar fw-tab-space-replacement "        "
  "*String of spaces for replacing tabs.")
(make-variable-buffer-local 'fw-tab-space-replacement)

(defvar fw-remove-trailing-spaces-before-saving-p t
  "*Whether to remove trailing spaces on lines before saving
FunnelWeb buffers.")

(defvar fw-space (string-to-char " ")
  "Space character, used in removing trailing spaces.")

(defvar fw-trailing-space-pattern " +$"
  "*Pattern used to identify trailing spaces on lines.")

(defvar fw-null-string ""
  "Empty string used for replacing trailing spaces.")
@}

@$@<fw-mode Function Definitions@>+=@{
(defun fw-untabify-save-buffer ()
  "Save the buffer, optionally removing tabs and trailing spaces
first if the buffer is a FunnelWeb buffer."
  (interactive)
  (if fw-buffer-p
      (progn
        (if fw-untabify-before-saving-p
            (progn
              (message "Removing tabs ...")
              (save-excursion
                (goto-char (point-min))
                (while (search-forward fw-tab-string nil t)
                  (replace-match fw-tab-space-replacement nil t)))))
        (if fw-remove-trailing-spaces-before-saving-p
            (progn
              (message "Removing trailing spaces ...")
              (save-excursion
                (goto-char (point-min))
                (while (< (point) (point-max))
                  (end-of-line)
                  (while (eq (preceding-char) fw-space)
                    (backward-delete-char 1))
                  (forward-line 1)))))))
  (save-buffer))
@}

Other variable definitions follows.  Those for which the decription
text begins with a \verb$*$ can be changed on the command line by the
user, and all can be set in the users {\tt .emacs} file.

@$@<fw-mode Variable Definitions1@>+=@{
(defvar fw-TeX-mode 'tex-mode
  "*The default TeX-based foundation for FunnelWeb mode.")
@}

@$@<fw-mode Variable Definitions2@>+=@{
(defvar fw-switch-minor-mode-init 1
  "*Whether to activate the Switch minor mode automatically
on entering FunnelWeb mode.  A positive integer for yes.")

(defvar fw-buffer-p nil
  "Whether a buffer is a FunnelWeb buffer or not.")
(make-variable-buffer-local 'fw-buffer-p)
(switch-add-to-preservation-list 'fw-buffer-p)

(defvar fw-quote-style t
  "*Whether to map \" to a single character or use (La)TeX
mapping to `` or '' as appropriate.  Can be set to nil to
remove the (La)TeX mapping, or anything else to enable it.")

(defvar fw-auto-fill-mode 1
  "*Whether autofill-mode is automatically invoked for
FunnelWeb files.  Set to 0 for no, to a positive number
for yes.")

(defvar fw-command "fw"
  "*The command to run FunnelWeb on a file.
Any pre-options (fw-command-pre-options) will be appended
to this string, separated by a space, followed by the
filename, also separated by a space, and finally any
post-options (fw-command-post-options), again separated
by a space.")

(defvar fw-command-pre-options nil
  "*Options which go before the filename when
calling FunnelWeb.")
(make-variable-buffer-local 'fw-command-pre-options)

(defvar fw-command-post-options "+t +D"
  "*Options which go after the filename when
calling FunnelWeb.")
(make-variable-buffer-local 'fw-command-post-options)

(defvar fw-shell-cd-command "cd"
  "*Command to give to shell running FunnelWeb to
change directory.  The value of fw-directory will be
appended to this, separated by a space.")

(defvar fw-mode-syntax-table nil
  "Syntax table used while in FunnelWeb mode.")

(defvar fw-mode-map nil
  "Keymap for FunnelWeb mode.")

(defvar fw-close-definition-block-additive t
  "*Whether definitions should be closed using \"+=\" (t) or
\"==\" (nil).")
(make-variable-buffer-local
 'fw-close-definition-block-additive)

(defvar fw-close-definition-block-newline-suppress t
  "*Whether definitions should be closed using \"@@-\".")
(make-variable-buffer-local
 'fw-close-definition-block-newline-suppress)

(defvar fw-close-definition-block-blank-line t
  "Whether definitions should be closed leaving
a blank line.")
(make-variable-buffer-local
 'fw-close-definition-block-blank-line)
@}

\chapter{Key Definitions for the FunnelWeb Mode}
These are the special key definitions for FunnelWeb commands.

@$@<fw-mode Key Definitions@>==@{
@!(define-key fw-mode-map "\C-c\C-f" 'fw-close-definition-block)
(global-set-key "\C-x\C-s" 'fw-untabify-save-buffer)
@}

\chapter{Function and Variable Definitions for the Switch Minor Mode}
The Switch minor mode works by adding a function, run after each emacs
command, which checks the position of point.  If point is outside of
the current region, each code or text, a function is run to determine
whether point lies in a code or text region.  Note that for speed, the
code does not update the boundaries of the current region after each
command, and so the checking may be fooled when and if sections are
deleted from a code or text region.

Variables are needed to hold the bounds of the current region and the
whether flag marking whether a region check is in progress or not (to
avoid an infinite recursion).

@$@<switch-mode Variable Definitions 1@>+=@{
(defvar switch-region-min nil
  "Start of current macro or text region, or nil.")
(make-variable-buffer-local 'switch-region-min)

(defvar switch-region-max nil
  "End of current macro or text region, or nil.")
(make-variable-buffer-local 'switch-region-max)

(defvar switch-not-in-region-check-routine-p t
  "Whether a region check is not in progress.")
(make-variable-buffer-local
 'switch-not-in-region-check-routine-p)
@}

@$@<switch-mode Function Definitions 2@>+=@{
(defun switch-post-command-hook-function ()
  "Function to check if the user is in a code definition
region or not."
  (if (and (not isearch-mode)
           switch-mode
           switch-not-in-region-check-routine-p
           (or (not switch-region-min)
               (not switch-region-max)
               (let ((the-point (point)))
                 (or
                  (< the-point switch-region-min)
                  (> the-point switch-region-max)))))
      (let ((switch-not-in-region-check-routine-p nil))
            (switch-check-if-in-region))))
@}

The function for checking whether the point is in a code or text
region or not is as follows.

@$@<switch-mode Function Definitions 2@>+=@{
(defun switch-check-if-in-region ()
  "Check if point is inside or outside a FunnelWeb macro
definition. If outside, switch to (Auc/La)TeX mode.
If inside, either ask the user for a mode, defaulting
to the last mode used in a macro definition, or directly
use the last mode chosen (depends on value of variable
switch-mode-prompt-p)."
  (interactive)
@}

First, searches are carried out forwards and backwards from point to
determine what sort of region point is in.

@$@<switch-mode Function Definitions 2@>+=@{@-
  (let ((backward-search-result
        (switch-search-backward-check
         switch-boundary-region-pattern
         switch-open-region-string))
        (forward-search-result
        (switch-search-forward-check
         switch-boundary-region-pattern
         switch-close-region-string))
        (backward-search-value)
        (forward-search-value))
    (setq backward-search-value
          (car backward-search-result))
    (setq forward-search-value
          (car forward-search-result))
    (setq switch-region-min
          (car (cdr backward-search-result)))
    (setq switch-region-max
          (car (cdr forward-search-result)))
    (if (not (or (< backward-search-value 0)
                 (< forward-search-value 0)
                 (and (eq backward-search-value 0)
                      (eq forward-search-value 0))))
@}

The following code determines what is done if point is inside a code
region.  Variables are required to define the behaviour, and to store
the current code region mode, as well as to store whether point was
last in a code or text region.

@$@<switch-mode Variable Definitions 1@>+=@{
(defvar switch-force-region-check-p nil
  "Whether a region check should be forced or not,
regardless of whether it seems to be required or not.")
(make-variable-buffer-local 'switch-force-region-check-p)

(defvar switch-mode-prompt-p t
  "*Whether the user should be prompted for a new
major mode type each time point enters a code region.")
(make-variable-buffer-local 'switch-mode-prompt-p)

(defvar switch-current-mode nil
  "The current mode for a code region.")
(make-variable-buffer-local 'switch-current-mode)

(defvar switch-currently-in-region-p nil
  "Whether point is in a code region or not.")
(make-variable-buffer-local 'switch-currently-in-region-p)

(defvar switch-highlight-p nil
  "Whether to highlight regions as they are entered.
(This requires the `hilit19' library to be loaded.)")
(make-variable-buffer-local 'switch-highlight-p)
@}

@$@<switch-mode Function Definitions 2@>+=@{@-
        (if (or (not switch-currently-in-region-p)
                switch-force-region-check-p)
            (progn
              (switch-select-mode (not switch-mode-prompt-p))
              (if switch-current-mode
                  (progn
                    (message (concat "Changed to "
                                     (prin1-to-string
                                      switch-current-mode)))
                    (setq switch-currently-in-region-p t)))))
@}

Now the code for the case where point is {\em not} in a code region,
but in a text region.

@$@<switch-mode Function Definitions 2@>+=@{@-
      (if switch-currently-in-region-p
          (let ((preservation-list
                 (switch-get-preservation-values)))
            (fw-mode)
            (switch-set-preservation-values
             preservation-list)
            (message "Changed to fw-mode")
            (setq switch-currently-in-region-p nil))))
    (setq switch-force-region-check-p nil)))
@}

A function is provided to allow the user to toggle whether the mode is
prompted for each time a code region is entered or not.

@$@<switch-mode Function Definitions 2@>+=@{
(defun switch-mode-prompt-toggle ()
  "Toggle whether the user is prompted for the major mode
each time a code region is entered."
  (interactive)
  (setq switch-mode-prompt-p (not switch-mode-prompt-p))
  (if switch-mode-prompt-p
      (message "Mode prompting switched on.")
    (message "Mode prompting switched off.")))
@}

It is also sometimes useful to be able to force a major mode to be
asked for.  This is necessary when editing changes cause the program
to mistake the boundaries of the current region.

@$@<switch-mode Function Definitions 2@>+=@{
(defun switch-mode-force-prompt ()
  "Cause the user to be prompted for a mode type for
the current region, if a code region."
  (interactive)
  (let ((switch-force-region-check-p t))
    (switch-check-if-in-region)))
@}

The mode selection function allows the user to choose from any command
which ends with string \"-mode\".  It optionally beeps on activation,
to note to the user that a mode selection is necessary.

@$@<switch-mode Variable Definitions 2@>+=@{
(defvar switch-mode-list (make-switch-mode-list)
  "Return a list of strings of all possible major modes
from which the user can choose.")

(defvar switch-beep-on-mode-selection-p t
  "*Whether to beep when a mode selection is necessary.")
@}

@$@<switch-mode Function Definitions 2@>+=@{
(defun switch-select-mode ( &optional no-prompt-p )
  "Interactively get the user to select a macro mode,
giving the last-used macro mode as a default, and allowing
the user to select from all possible major mode commands
with name completion.
    Optional parameter NO-PROMPT-P, if non-nil, stops
prompting from taking place unless the current mode
(switch-current-mode) is nil."
  (let ((old-switch-mode-value
         (if switch-mode 1 0)))
    (if (not (and no-prompt-p switch-current-mode))
        (progn
          (if switch-beep-on-mode-selection-p (beep))
          (let ((new-mode (completing-read
                           "Mode: "
                           switch-mode-list
                           nil
                           nil
                           (switch-convert-to-default-string
                            switch-current-mode)
                           nil)))
            (setq switch-current-mode
                  (car (read-from-string new-mode))))))
    (let ((preservation-list
           (switch-get-preservation-values))
          (region-min switch-region-min)
          (region-max switch-region-max))
      (message "Changing to %s"
               (prin1-to-string switch-current-mode))
      (if switch-current-mode (funcall switch-current-mode))
      (if (and switch-highlight-p region-min region-max)
          (progn
            (hilit-unhighlight-region region-min region-max)
            (hilit-highlight-region region-min region-max)))
      (switch-set-preservation-values preservation-list))
    (switch-mode old-switch-mode-value t)
    (force-mode-line-update)))
@}

A short function to convert an object to a string if non-nil.

@$@<switch-mode Function Definitions 1@>+=@{
(defun switch-convert-to-default-string ( object )
  "Convert an object into a default string for
name completion."
  (if object (prin1-to-string object)))
@}

The following function returns a list of possible modes, in the form
of an Emacs ``alist''.  A second function allows the user to update
the list.

@$@<switch-mode Function Definitions 1@>+=@{
(defun make-switch-mode-list ()
  "Return a list of all commands ending in \"-mode\",
in the form of an alist."
  (let ((mode-list (apropos-internal "-mode$")))
    (mapcar 'switch-convert-to-alist-string mode-list)))
@}

@$@<switch-mode Function Definitions 2@>+=@{
(defun update-switch-mode-list ()
  "Update the mode list used for the switch minor-mode."
  (interactive)
  (setq switch-mode-list (make-switch-mode-list)))
@}

This simple function converts objects to a form suitable for an Elisp
``alist''.

@$@<switch-mode Function Definitions 1@>+=@{
(defun switch-convert-to-alist-string ( object )
  "Convert an object to a string in its own list,
the format appropriate for an alist."
  (list (prin1-to-string object)))
@}

Two functions are used to search for code region boundaries, one for
searching forwards from point, the other for searching backwards.
Each searches for the given regexp, and if found, compares it to the
given string.  A list is returned containing an integer value
describing the search result and the position of the string which was
matched.

@$@<switch-mode Function Definitions 1@>+=@{
(defun switch-search-forward-check ( regexp string )
  "Search forward for the given regexp, and if the matching
pattern is found and it matches the given string, return `1'
and the beginning of the pattern, else return `-1' and the
beginning of the pattern.  If the pattern is not found when
the end of the buffer is reached, return `0' and the end of
the buffer."
  (save-excursion
    (if (search-forward-regexp regexp (point-max) t)
        (if (string-equal
             string
             (buffer-substring
              (match-beginning 0)
              (match-end 0)))
            (list 1 (match-beginning 0))
          (list -1 (match-beginning 0)))
      (list 0 (point-max)))))

(defun switch-search-backward-check ( regexp string )
  "Search backward for the given regexp, and if the matching
pattern is found and it matches the given string, return `1'
and the end of the pattern, else return `-1' and the end of
the pattern.  If the pattern is not found when the beginning
of the buffer is reached, return `0' and the beginning of the
buffer."
  (save-excursion
    (if (search-backward-regexp regexp (point-min) t)
        (if (string-equal
             string
             (buffer-substring
              (match-beginning 0)
              (match-end 0)))
            (list 1 (match-end 0))
          (list -1 (match-end 0)))
      (list 0 (point-min)))))
@}

It is useful to allow functions to maintain a list of variables which
should be preserved by switch-mode operations.  This list can be
changed by the user.

@$@<switch-mode Variable Definitions 1@>+=@{
(defvar switch-preservation-list
  (list 'switch-current-mode 'switch-mode-prompt-p)
  "List of names of variables that need to be specially
preserved by switch-mode operations.")
@}

@$@<switch-mode Function Definitions 2@>+=@{
(defun switch-add-to-preservation-list ( var )
  "Add a variable to the switch-mode preservation list."
  (if (not (memq var switch-preservation-list))
      (setq switch-preservation-list
            (append switch-preservation-list (list var)))))

(defun switch-get-preservation-values ()
  "Returns a list of current values which can be used by
switch-set-preservation-values to restore the values of
the variables in the preservation list
(switch-preservation-list)."
  (if switch-preservation-list
      (mapcar
       'switch-preserve-form
       switch-preservation-list)))

(defun switch-preserve-form ( var )
  "Return a list of the variable name and its value."
  (list var (eval var)))

(defun switch-set-preservation-values ( vallist )
  "Reset the variables in the preservation value list
using the value list previously created by
switch-get-preservation-values."
  (mapcar 'switch-apply-set vallist))

(defun switch-apply-set ( varpair )
  "Given a list of the form (NAME . VALUE), assign the value
to the name."
  (apply 'set varpair))
@}

\chapter{Key Definitions for the Switch Minor Mode}
These are the special key definitions for Switch minor-mode commands.

@$@<switch-mode Key Definitions@>==@{
(defvar switch-prefix nil
  "Switch minor-mode region check \\C-x\\C-a keymap.")

(define-prefix-command 'switch-prefix)

(global-set-key "\C-x\C-a" 'switch-prefix)

(define-key switch-prefix "c" 'switch-check-if-in-region)

(define-key switch-prefix "t" 'switch-mode)

(define-key switch-prefix "p" 'switch-mode-prompt-toggle)

(define-key switch-prefix "s" 'switch-mode-force-prompt)
@}

\chapter{Construction of the elisp files}
The file ``{\tt switch-mode.el}'' requires the standard Emacs
distribution provides the new minor mode function `{\tt switch-mode}'.

The variable and function definitions are each divided up into two
lots, in the order
\begin{itemize}
  \item variables which don't rely on functions for their default
        values
  \item functions which don't rely on variables in their definitions
  \item variables which rely on functions for their default
        values
  \item functions which rely on variables in their definitions.
\end{itemize}

@$@<switch-mode Constructed Code@>+=@{@-
(provide 'switch-mode)

@<switch-mode Variable Definitions 1@>

@<switch-mode Function Definitions 1@>

@<switch-mode Variable Definitions 2@>

@<switch-mode Function Definitions 2@>

@<switch-mode Key Definitions@>
@}

The following code installs the minor mode and runs any user-provided
hook function.

@$@<switch-mode Constructed Code@>+=@{@-
(setq minor-mode-alist
      (reverse
       (append (reverse minor-mode-alist)
               (list (list
                      'switch-mode
                      " Switch")))))
(force-mode-line-update t)

(add-hook 'post-command-hook
          'switch-post-command-hook-function)

(run-hooks 'switch-mode-hook)@}

@$@<Standard Header@>@M==@{@-
; A.B.Coates
; Department of Physics
; The University of Queensland  QLD  4072
; Australia
; Standard GNU copyleft provisions apply to this file.@}

@O@<switch-mode.el@>==@{
@<Standard Header@>

@<switch-mode Constructed Code@>
@}

The file ``{\tt fw-mode.el}'' requires the switch minor mode file
``{\tt switch-mode.el}'', and provides the new mode function
`{\tt fw-mode}'.  Calling the selected \TeX-mode is a way of making
sure that the required definitions are loaded, since the
mode-selection function may be defined as an {\em autoload} function.

@$@<fw-mode Constructed Code@>+=@{@-
(require 'switch-mode)

(provide 'fw-mode)

@<fw-mode Variable Definitions1@>

(funcall fw-TeX-mode)

@<fw-mode Variable Definitions2@>
@}

\noindent In case the user forgets the precise name, some synonyms for
`{\tt fw-mode}' are provided.

@$@<fw-mode Constructed Code@>+=@{@-
(fset 'FW-mode 'fw-mode)
(fset 'funnelweb-mode 'fw-mode)
(fset 'FunnelWeb-mode 'fw-mode)

@<fw-mode Function Definitions@>@}

\noindent If the keymap has not already been set in the user's
``{\tt .emacs}'' file, then a TeX-mode keymap is copied and
used if possible.

@$@<fw-mode Constructed Code@>+=@{@-
(if fw-mode-map
 (progn
  (defvar tex-mode-map nil)
  (if tex-mode-map
      (setq fw-mode-map tex-mode-map)
    (progn
      (defvar latex-mode-map nil)
      (if latex-mode-map
          (setq fw-mode-map latex-mode-map)
        (progn
          (defvar LaTeX-mode-map nil)
          (if LaTeX-mode-map
              (setq fw-mode-map LaTeX-mode-map)
            (progn
              (defvar TeX-mode-map nil)
              (if TeX-mode-map
                  (setq fw-mode-map TeX-mode-map))))))))))

@<fw-mode Key Definitions@>@}

@O@<fw-mode.el@>==@{
@<Standard Header@>

@<fw-mode Constructed Code@>
@}

\end{document}

% Local Variables:
% TeX-master: fwmode
% End:

@! end of fwmode.fw