source: project/wiki/emacs-multi-mode @ 25499

Last change on this file since 25499 was 25499, checked in by svnwiki, 9 years ago

Anonymous wiki edit for IP [70.71.179.201]: Added attribution

File size: 3.9 KB
Line 
1This script will switch between scheme-mode and c-mode in Emacs, using the #> .. <# and <<ENDC .. ENDC delimiters.
2
3Author: [[http://www.ironoxide.ca/|Dan Leslie]]
4
5<enscript highlight="elisp">
6(require 'multi-mode)
7
8(defun scheme-c-mode ()
9  "Mode for editing C embedded in Scheme, using multi-mode."
10  (interactive)
11  (set (make-local-variable 'multi-alist)
12       '((scheme-mode)
13         (c-mode . scheme-c-header-region)
14         (c-mode . scheme-c-inline-region)))
15  (multi-mode-install-modes))
16
17(defun scheme-c-header-region (pos)
18  "Mode-selecting function for C embedded in Scheme."
19  (let ((case-fold-search t)
20        foreign-start foreign-end next-foreign)
21    (save-excursion
22      (save-restriction
23        (widen)
24        (goto-char pos)
25        (save-excursion
26          (let* ((p1 (save-excursion
27                       ;; Check whether we're on the processing
28                       ;; instruction start.  Skip definitely clear of
29                       ;; it and then search backwards.
30                       (goto-char (min (point-max) (+ (point) 2)))
31                       (search-backward "#>" (- (point) 3) t)))
32                 (match-end (if p1 (match-end 0)))
33                 ;; Otherwise search backwards simply.
34                 (p2 (unless p1 (search-backward "#>" nil t))))
35            (if p2 (setq match-end (match-end 0)))
36            (setq foreign-start (or p1 p2))
37            ;; Ready to search for matching terminator or next
38            ;; processing instruction.
39            (goto-char (or match-end pos)))
40          (if foreign-start
41              ;; Look forward for the FOREIGN terminator.
42              (let* ((p1 (save-excursion
43                           ;; Check whether we're on the terminator.
44                           (backward-char 1)
45                           (search-backward "<#" (- (point) 2) t)))
46                     (p2 (unless p1 (search-forward "<#" nil t))))
47                (setq foreign-end (or p1 p2 (point-max)))
48                (goto-char pos)))
49          (if (and foreign-start foreign-end (< pos foreign-end))
50              ;; We were between FOREIGN start and terminator.
51              (list 'c-mode foreign-start foreign-end)
52            ;; Otherwise, look forward for a FOREIGN to delimit the Scheme
53            ;; region.
54            (setq next-foreign
55                  (if (search-forward "#>" nil t)
56                      (match-beginning 0)
57                    (point-max)))
58            (if foreign-start
59                (list 'scheme-mode (or foreign-end (point-min)) next-foreign)
60              (list 'scheme-mode (point-min) next-foreign))))))))
61
62(defun scheme-c-inline-region (pos)
63  "Mode-selecting function for C embedded in Scheme."
64  (let ((case-fold-search t)
65        foreign-start foreign-end next-foreign)
66    (save-excursion
67      (save-restriction
68        (widen)
69        (goto-char pos)
70        (save-excursion
71          (let* ((p1 (save-excursion
72                       ;; Check whether we're on the processing
73                       ;; instruction start.  Skip definitely clear of
74                       ;; it and then search backwards.
75                       (goto-char (min (point-max) (+ (point) 6)))
76                       (search-backward "<<ENDC" (- (point) 11) t)))
77                 (match-end (if p1 (match-end 0)))
78                 ;; Otherwise search backwards simply.
79                 (p2 (unless p1 (search-backward "<<ENDC" nil t))))
80            (if p2 (setq match-end (match-end 0)))
81            (setq foreign-start (or p1 p2))
82            ;; Ready to search for matching terminator or next
83            ;; processing instruction.
84            (goto-char (or match-end pos)))
85          (if foreign-start
86              ;; Look forward for the FOREIGN terminator.
87              (let* ((p1 (save-excursion
88                           ;; Check whether we're on the terminator.
89                           (backward-char 1)
90                           (search-backward "ENDC" (- (point) 4) t)))
91                     (p2 (unless p1 (search-forward "ENDC" nil t))))
92                (setq foreign-end (or p1 p2 (point-max)))
93                (goto-char pos)))
94          (if (and foreign-start foreign-end (< pos foreign-end))
95              ;; We were between FOREIGN start and terminator.
96              (list 'c-mode foreign-start foreign-end)
97            ;; Otherwise, look forward for a FOREIGN to delimit the Scheme
98            ;; region.
99            (setq next-foreign
100                  (if (search-forward "<<ENDC" nil t)
101                      (match-beginning 0)
102                    (point-max)))
103            (if foreign-start
104                (list 'scheme-mode (or foreign-end (point-min)) next-foreign)
105              (list 'scheme-mode (point-min) next-foreign))))))))
106
107(provide 'scheme-c-mode)
108</enscript>
Note: See TracBrowser for help on using the repository browser.