I think polymode can provide some help for this. By itself,
framework for combining multiple major modes in a systematic way. Among the the
examples, there is a
polymode available that creates a new major mode based on
markdown-mode that can display any other major-mode recognized by Emacs. The
example can be seen here and is installed with
polymode by default from
There are some caveats though,
polymode needs to figure out which major-mode somehow and thus the name must match the major mode used by Emacs. E.g., instead of writing
you have to write
sh-script. See the samples folder on polymode for an some examples of this.
It is probably possible to fix that however by using some kind of look-up
function, but that would require non-trivial changes. Furthermore, I believe it
would be possible to create a
polymode in a similar fashion, but that
would probably require a significant amount of hacking.
The configuration I ended up using for getting all of this to work is this:
:mode ("\\.md" . poly-markdown-mode))
A word of warning though: It is important to know that mixing major-modes can
cause a wide variety of issues. Usually, this means that font-locking or
indenting can start to behave strangely, or the performance might degrade
significantly. Personally though, I haven't run into any issues yet but then
again, I haven't worked with any really large markdown files either.
After getting slightly bored at work, I actually implemented the ReST equivalent to the
;;; poly-rest-mode.el -- Polymode for ReST. -*- lexical-binding: t -*-
;; A mode for interacting with multiple kinds of code inside a ReST host-mode.
"Restructued Text host chunkmode."
(regexp-opt '("code" "code-block" "sourcecode" "highlight"))
"Regular expression to match all possible ReST code blocks.")
(concat "^[^ ]*\\( *\.\. +" pm-ReST-code-regexp "::.*\n"
"\\(?: +:.+\n\\)*\\)") ;; Match 0 or more option lines.
"Regular expression to match the `head' of a ReST code block.")
(concat "^[^ ]*\\(?: *\.\. +" pm-ReST-code-regexp ":: \\(.+\\)\\)$")
"Regular expression to retrieve the mode of the code block.")
(pm-create-indented-block-matchers "ReST" pm-ReST-head-regexp)
"Restructured Text inner code block mode."
"Restructured Text typical `polymode' configuration."
;;;###autoload (autoload #'poly-rest-mode "poly-rest-mode")
(define-polymode poly-rest-mode pm-poly/ReST)
(defun poly-rest-fixes ()
"Fix various minor issues that can occur in the poly-ReST-mode."
(remove-hook 'prog-mode-hook #'whitespace-mode)
(remove-hook 'python-mode-hook #'mmm-mode))
;;; poly-rest-mode.el ends here
Now, it is likely that I've missed some detail where this doesn't work perfectly, I'm simply not familiar enough with ReST to tell.
It does seem to work fairly well on a rather complete example:
The concerns mentioned in the comments regarding nested indentations have been fixed in the above code snippet.