You are looking at historical revision 25499 of this page. It may differ significantly from its current revision.
This script will switch between scheme-mode and c-mode in Emacs, using the #> .. <# and <<ENDC .. ENDC delimiters.
Author: Dan Leslie
(require 'multi-mode) (defun scheme-c-mode () "Mode for editing C embedded in Scheme, using multi-mode." (interactive) (set (make-local-variable 'multi-alist) '((scheme-mode) (c-mode . scheme-c-header-region) (c-mode . scheme-c-inline-region))) (multi-mode-install-modes)) (defun scheme-c-header-region (pos) "Mode-selecting function for C embedded in Scheme." (let ((case-fold-search t) foreign-start foreign-end next-foreign) (save-excursion (save-restriction (widen) (goto-char pos) (save-excursion (let* ((p1 (save-excursion ;; Check whether we're on the processing ;; instruction start. Skip definitely clear of ;; it and then search backwards. (goto-char (min (point-max) (+ (point) 2))) (search-backward "#>" (- (point) 3) t))) (match-end (if p1 (match-end 0))) ;; Otherwise search backwards simply. (p2 (unless p1 (search-backward "#>" nil t)))) (if p2 (setq match-end (match-end 0))) (setq foreign-start (or p1 p2)) ;; Ready to search for matching terminator or next ;; processing instruction. (goto-char (or match-end pos))) (if foreign-start ;; Look forward for the FOREIGN terminator. (let* ((p1 (save-excursion ;; Check whether we're on the terminator. (backward-char 1) (search-backward "<#" (- (point) 2) t))) (p2 (unless p1 (search-forward "<#" nil t)))) (setq foreign-end (or p1 p2 (point-max))) (goto-char pos))) (if (and foreign-start foreign-end (< pos foreign-end)) ;; We were between FOREIGN start and terminator. (list 'c-mode foreign-start foreign-end) ;; Otherwise, look forward for a FOREIGN to delimit the Scheme ;; region. (setq next-foreign (if (search-forward "#>" nil t) (match-beginning 0) (point-max))) (if foreign-start (list 'scheme-mode (or foreign-end (point-min)) next-foreign) (list 'scheme-mode (point-min) next-foreign)))))))) (defun scheme-c-inline-region (pos) "Mode-selecting function for C embedded in Scheme." (let ((case-fold-search t) foreign-start foreign-end next-foreign) (save-excursion (save-restriction (widen) (goto-char pos) (save-excursion (let* ((p1 (save-excursion ;; Check whether we're on the processing ;; instruction start. Skip definitely clear of ;; it and then search backwards. (goto-char (min (point-max) (+ (point) 6))) (search-backward "<<ENDC" (- (point) 11) t))) (match-end (if p1 (match-end 0))) ;; Otherwise search backwards simply. (p2 (unless p1 (search-backward "<<ENDC" nil t)))) (if p2 (setq match-end (match-end 0))) (setq foreign-start (or p1 p2)) ;; Ready to search for matching terminator or next ;; processing instruction. (goto-char (or match-end pos))) (if foreign-start ;; Look forward for the FOREIGN terminator. (let* ((p1 (save-excursion ;; Check whether we're on the terminator. (backward-char 1) (search-backward "ENDC" (- (point) 4) t))) (p2 (unless p1 (search-forward "ENDC" nil t)))) (setq foreign-end (or p1 p2 (point-max))) (goto-char pos))) (if (and foreign-start foreign-end (< pos foreign-end)) ;; We were between FOREIGN start and terminator. (list 'c-mode foreign-start foreign-end) ;; Otherwise, look forward for a FOREIGN to delimit the Scheme ;; region. (setq next-foreign (if (search-forward "<<ENDC" nil t) (match-beginning 0) (point-max))) (if foreign-start (list 'scheme-mode (or foreign-end (point-min)) next-foreign) (list 'scheme-mode (point-min) next-foreign)))))))) (provide 'scheme-c-mode)