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

Last change on this file since 25500 was 25500, checked in by svnwiki, 8 years ago

Anonymous wiki edit for IP [70.71.179.201]: Added tags

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