emacselisppython-sphinxrestructuredtextnxhtml

Set a mode from regexp to regexp?


This is a question about MuMaMo. If one adds to the end of the nxhtml/util/mumamo-fun.el the following code:

(defun rst-bk-latex-directive-chunk (pos min max)
  "Find math chunks. Return range and 'latex-mode.
See `mumamo-find-possible-chunk' for POS, MIN and MAX."
  (mumamo-quick-static-chunk pos min max ".. math::\n\n" ".." nil 'latex-mode t))

;;;###autoload
(define-mumamo-multi-major-mode rst-bk-mumamo-mode
 "Turn on multiple major modes for Python with RestructuredText docstrings."
 ("ReST" rst-mode
  (
   rst-bk-latex-directive-chunk
   )))

(add-to-list 'auto-mode-alist '("\\.rst\\'" . rst-bk-mumamo-mode))

And also

(load "~/.emacs.d/site-lisp/nxhtml/autostart.el")
(require 'mumamo)
(require 'mumamo-fun)

to ~/.emacs

One gets chunks between strings .. math::\n\n and .. be of latex-mode.

My question is — how do I make a chunk between two given regexp of the given mode?

Edit:

I've added the follosing to the end of the mumamo-fun.el:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; ReST + math + bash + python + cl

;; LaTeX:

(defun rst-bk-mumamo-math-regexp-chunk-start (pos max)
  (let ((where (mumamo-chunk-start-fw-re pos max 
                                         "\\.\\. math::\\(.?\\|\n\\)*?\n\n"
                                         )))
    (when where
      (list where 'latex-mode))))

(defun rst-bk-mumamo-math-regexp-chunk-end (pos max)
  (save-match-data
    (mumamo-chunk-end-fw-re pos max 
                            "\\(^[[:blank:]]+$\\|\n\\)+[^[:blank:]\n]"
                            )))

(defun rst-bk-mumamo-math-quick-regexp-chunk (pos
                                  min
                                  max)
  (save-match-data
    (mumamo-possible-chunk-forward pos max 'rst-bk-mumamo-math-regexp-chunk-start
                                           'rst-bk-mumamo-math-regexp-chunk-end)))

(defun rst-bk-mumamo-math-directive (pos min max)
  "Find math chunks. Return range and 'math-mode.
   See `mumamo-find-possible-chunk' for POS, MIN and MAX."
  (rst-bk-mumamo-math-quick-regexp-chunk pos min max))


(defun rst-bk-mumamo-math-inline-chunk (pos min max)
 "Find math chunks.  Return range and 'math-mode.
See `mumamo-find-possible-chunk' for POS, MIN and MAX."
 (mumamo-quick-static-chunk pos min max ":math:`" "`" nil 'math-mode t))


;; bash:

(defun rst-bk-mumamo-sh-regexp-chunk-start (pos max)
  (let ((where (mumamo-chunk-start-fw-re pos max "\\.\\. code-block:: bash\\(.\\|\n\\)*?\n\n")))
    (when where
      (list where 'sh-mode))))

(defun rst-bk-mumamo-sh-regexp-chunk-end (pos max)
  (save-match-data
    (mumamo-chunk-end-fw-re pos max 
                            "\\(^[[:blank:]]+$\\|\n\\)+[^[:blank:]\n]"
                            )))

(defun rst-bk-mumamo-sh-quick-regexp-chunk (pos
                                  min
                                  max)
  (save-match-data
    (mumamo-possible-chunk-forward pos max 'rst-bk-mumamo-sh-regexp-chunk-start
                                           'rst-bk-mumamo-sh-regexp-chunk-end)))

(defun rst-bk-mumamo-sh-directive (pos min max)
  "Find math chunks. Return range and 'sh-mode.
   See `mumamo-find-possible-chunk' for POS, MIN and MAX."
  (rst-bk-mumamo-sh-quick-regexp-chunk pos min max))


;; python:

(defun rst-bk-mumamo-py-regexp-chunk-start (pos max)
  (let ((where (mumamo-chunk-start-fw-re pos max "\\.\\. code-block:: py\\(thon\\)?\\(.\\|\n\\)*?\n\n")))
    (when where
      (list where 'python-mode))))

(defun rst-bk-mumamo-py-regexp-chunk-end (pos max)
  (save-match-data
    (mumamo-chunk-end-fw-re pos max "\\(^[[:blank:]]+$\\|\n\\)+[^[:blank:]\n]")))

(defun rst-bk-mumamo-py-quick-regexp-chunk (pos
                                  min
                                  max)
  (save-match-data
    (mumamo-possible-chunk-forward pos max 'rst-bk-mumamo-py-regexp-chunk-start
                                           'rst-bk-mumamo-py-regexp-chunk-end)))

(defun rst-bk-mumamo-py-directive (pos min max)
  "Find math chunks. Return range and 'py-mode.
   See `mumamo-find-possible-chunk' for POS, MIN and MAX."
  (rst-bk-mumamo-py-quick-regexp-chunk pos min max))


;; cl:

(defun rst-bk-mumamo-cl-regexp-chunk-start (pos max)
  (let ((where (mumamo-chunk-start-fw-re pos max "\\.\\. code-block:: cl\\(.\\|\n\\)*?\n\n")))
    (when where
      (list where 'emacs-lisp-mode))))

(defun rst-bk-mumamo-cl-regexp-chunk-end (pos max)
  (save-match-data
    (mumamo-chunk-end-fw-re pos max "\\(^[[:blank:]]+$\\|\n\\)+[^[:blank:]\n]")))

(defun rst-bk-mumamo-cl-quick-regexp-chunk (pos
                                  min
                                  max)
  (save-match-data
    (mumamo-possible-chunk-forward pos max 'rst-bk-mumamo-cl-regexp-chunk-start
                                           'rst-bk-mumamo-cl-regexp-chunk-end)))

(defun rst-bk-mumamo-cl-directive (pos min max)
  "Find math chunks. Return range and 'cl-mode.
   See `mumamo-find-possible-chunk' for POS, MIN and MAX."
  (rst-bk-mumamo-cl-quick-regexp-chunk pos min max))


;;;###autoload
(define-mumamo-multi-major-mode rst-bk-mumamo-mode
  "Turn on multiple major modes for Python with RestructuredText docstrings."
  ("ReST" rst-mode (
                    rst-bk-mumamo-math-directive
                    rst-bk-mumamo-math-inline-chunk
                    rst-bk-mumamo-sh-directive
                    rst-bk-mumamo-py-directive
                    )))

Just before the (provide 'mumamo-fun).

And then in .emacs:

(load "~/.emacs.d/site-lisp/nxhtml/autostart.el")
;; Mumamo is making emacs 23.3 freak out:
(when (and (equal emacs-major-version 23)
           (equal emacs-minor-version 3))
  (eval-after-load "bytecomp"
    '(add-to-list 'byte-compile-not-obsolete-vars
                  'font-lock-beginning-of-syntax-function))
  ;; tramp-compat.el clobbers this variable!
  (eval-after-load "tramp-compat"
    '(add-to-list 'byte-compile-not-obsolete-vars
                  'font-lock-beginning-of-syntax-function)))
(require 'mumamo)
(load "mumamo-fun")

(add-to-list 'auto-mode-alist '("\\.rst\\'" . rst-bk-mumamo-mode))

And now when I open ReST files I have:

math:`TEXT`

of LaTeX mode

.. math:

   TEXT

of LaTeX mode

.. code-block: bash

   TEXT

of sh-mode, and

.. code-block: py

   TEXT

of python-mode.

Edit 2:

Also if one adds

("^   \\(.+\\)" 1 'font-latex-math-face)

after

(dolist (item
         '(("\\(^\\|[^\\]\\)\\(&+\\)" 2 'font-latex-warning-face)
           ("\\$\\$\\([^$]+\\)\\$\\$" 1 'font-latex-math-face)
           ;; HERE
           ...

to font-latex-make-user-keywords in font-latex.el of AUCTeX, then one would get math-mode under .. math::.


Solution

  • The key functions are mumamo-possible-chunk-forward in combination with mumamo-chunk-start-fw-re andmumamo-chunk-end-fw-re - the latter two do the regexp matching.

    The following does the trick:

    (defun regexp-chunk-start (pos max)
      (let ((where (mumamo-chunk-start-fw-re pos max "math:\n\n")))
        (when where
          (list where 'latex-mode))))
    
    (defun regexp-chunk-end (pos max)
      (save-match-data
        (mumamo-chunk-end-fw-re pos max "\\.\\.")))
    
    
    (defun mumamo-quick-regexp-chunk (pos
                                      min
                                      max)
      (save-match-data
        (mumamo-possible-chunk-forward pos max 'regexp-chunk-start
                                               'regexp-chunk-end)))
    
    
    (defun rst-bk-latex-directive (pos min max)
      "Find math chunks. Return range and 'latex-mode.
       See `mumamo-find-possible-chunk' for POS, MIN and MAX."
      (mumamo-quick-regexp-chunk pos min max))
    
    ;;;###autoload
    (define-mumamo-multi-major-mode rst-bk-mumamo-mode
      "Turn on multiple major modes for Python with RestructuredText docstrings."
      ("ReST" rst-mode (rst-bk-latex-directive)))
    
    (add-to-list 'auto-mode-alist '("\\.rst\\'" . rst-bk-mumamo-mode))
    

    I've copied the autoload stuff you provided. Frankly, I don't understand how MuMaMo major modes are supposed to be loaded. However, I was able to test the feature by manually invoking mumamo-alias-rst-bk-latex-directive in a ReST file.

    MuMaMo's API is a bit unfortunate. The functionality to match a region of the buffer is sprinkled over three separate functions, which makes it difficult to reuse. I expect that you probably want to define many regexps once you have pattern-matching working.

    So here's another version which wraps everything in the marco define-quick-regexp-chunk:

    (defmacro define-quick-regexp-chunk (regexp-chunk-fun begin-mark end-mark mode)
      (let ((regexp-chunk-start-fun (gensym))
            (regexp-chunk-end-fun (gensym)))
        `(progn
           (defun ,regexp-chunk-start-fun (pos max)
             (let ((where (mumamo-chunk-start-fw-re pos max ,begin-mark)))
               (when where
                 (list where ,mode))))
    
           (defun ,regexp-chunk-end-fun (pos max)
             (save-match-data
               (mumamo-chunk-end-fw-re pos max ,end-mark)))
    
    
           (defun ,regexp-chunk-fun (pos
                                     min
                                     max)
             (save-match-data
               (mumamo-possible-chunk-forward pos max ',regexp-chunk-start-fun
                                                      ',regexp-chunk-end-fun))))))
    
    ;; switch to latex-mode in between "math:\n\n" ".." 
    ;; defines a function named "rst-bk-latex-directive" which should be called by MuMaMo
    (define-quick-regexp-chunk rst-bk-latex-directive "math:\n\n" "\\.\\." 'latex-mode)
    
    ;;;###autoload
    (define-mumamo-multi-major-mode rst-bk-mumamo-mode
      "Turn on multiple major modes for Python with RestructuredText docstrings."
      ("ReST" rst-mode (rst-bk-latex-directive)))
    
    (add-to-list 'auto-mode-alist '("\\.rst\\'" . rst-bk-mumamo-mode))
    

    It does exactly the same thing, but now I can use define-quick-regexp-chunk to easily define many regexp-delimited regions. Note that you have to double escape the dots (.).

    Check out the definition of noweb2 chunk in the nxHtml sources (in /util/mumamo-fun.el) for a more advanced example of how to use MuMaMo's regexp functions.