Search code examples
emacsliterate-programmingnowebpweave

Emacs polymode for Markdown and Python


I use the python3 pweave library (http://mpastell.com/pweave/usage.html) for literate programming.

pweave uses as text mode markdown, as code mode python3, and it is possible to use noweb (https://en.wikipedia.org/wiki/Noweb) literate programming syntax.

For correct syntax highlighting in emacs I aimed to use the polymode library (https://polymode.github.io/ and https://github.com/polymode).

I use emacs version26.1. And I was able to install polymode from melpa.

Unfortunate there is no pre-existing polymode for host-mode: markdown, inner-mode: python3, syntax: noweb so I tried, based on documentation and the existing code, to write my one poly-pweave-mode, by putting the following lisp code into my .emacs file.

(require 'polymode-classes)

(defcustom pm-host/pweave-text
  (pm-host-chunkmode :name "pweave-text"
                     :mode 'markdown-mode)
  "markdown host chunkmode"
  :group 'poly-hostmodes
  :type 'object)

(defcustom  pm-inner/pweave-code
  (pm-inner-chunkmode :name "pweave-code"
                      :head-matcher "^[ \t]*<<\\(.*\\)>>="
                      :tail-matcher "^[ \t]*@.*$"
                      :mode 'python-mode)
  "noweb static python3 inner chunkmode."
  :group 'poly-innermodes
  :type 'object)

(define-polymode poly-pweave-mode
  :hostmode 'pm-host/pweave-text
  :innermode 'pm-inner/pweave-code)

(add-to-list 'auto-mode-alist '("\\.pymd" . poly-pweave-mode))

But somehow emacs is not eating this. When I open emacs I get the following error:

Warning (initialization): An error occurred while loading `/Users/abc/.emacs':

Symbol's function definition is void: pm-host-chunkmode

To ensure normal operation, you should investigate and remove the
cause of the error in your initialization file.  Start Emacs with
the `--debug-init' option to view a complete error backtrace.

What do I wrong? How I could get the desired polymode running?


Solution

  • This is the solution how to specify a markdown-python3-noweb polymode

    ;; define pwn polymode
    (require 'poly-noweb)
    (require 'poly-markdown)
    
    (defcustom pm-inner/noweb-python
      (clone pm-inner/noweb
             :name "noweb-python"
             :mode 'python-mode)
      "Noweb for Python"
      :group 'poly-innermodes
      :type 'object)
    
    (define-polymode poly-pweave-mode poly-markdown-mode
      :innermodes '(pm-inner/noweb-python :inherit))
    
    (add-to-list 'auto-mode-alist '("\\.pymd" . poly-pweave-mode))
    

    My thank goes to Vitalie Spinu, the author of the polymode package, who helped me resolving this question! For a detailed discussion have a look at polymode issue 180 at github.

    Alternatively I found this post at emacs stack exchange: https://emacs.stackexchange.com/questions/20136/pythontex-and-auctex So, following this post, this is the solution to get to a markdown-python3-noweb mmm-mode

    ;; define pwn multi major modes mode
    (require 'mmm-auto)
    
    (mmm-add-classes
     '((noweb-python
        :submode python-mode
        :face mmm-default-submode-face
        :front "^<<.*>>=\n"
        :back "^@$")))
    
    (setq mmm-global-mode 'maybe)
    (mmm-add-mode-ext-class 'markdown-mode nil 'noweb-python)
    
    (add-to-list 'auto-mode-alist '("\\.pymd" . markdown-mode))
    

    My thank belongs to Jean Pierre, whose detailed explanation in the post made it a piece of cake to get it running for my case!