Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

help wanted with emacs mmm-mode support for noweb

56 views
Skip to first unread message

Norman Ramsey

unread,
Mar 20, 2006, 6:53:51 PM3/20/06
to
I really like what I read about mmm-mode for Emacs and its support for
noweb. But I can't seem to get mmm-mode to change modes properly when
the cursor enters a code chunk. It doesn't work even on the example
file from the mmm-mode info manual! (Curiously, that file does switch
to perl for the explicitly labelled perl chunk, but I can't get
similar labellings to work in my own code.)

Does anybody have any experience to report or suggestions to make?
--
Norman Ramsey
http://www.eecs.harvard.edu/~nr

Albert Reiner

unread,
Mar 21, 2006, 9:11:26 AM3/21/06
to
[n...@eecs.harvard.edu (Norman Ramsey), Mon, 20 Mar 2006 18:53:51 -0500 (EST)]:

> Does anybody have any experience to report or suggestions to make?

My only suggestion: you might get relevant answers at the MMM list,
mmm-mode...@lists.sourceforge.net .

Albert.

Joe Riel

unread,
Mar 22, 2006, 5:56:07 PM3/22/06
to
n...@eecs.harvard.edu (Norman Ramsey) writes:

> I really like what I read about mmm-mode for Emacs and its support for
> noweb. But I can't seem to get mmm-mode to change modes properly when
> the cursor enters a code chunk. It doesn't work even on the example
> file from the mmm-mode info manual! (Curiously, that file does switch
> to perl for the explicitly labelled perl chunk, but I can't get
> similar labellings to work in my own code.)

I've installed it, but couldn't get it to work. Have you tried the
noweb.el mode by Dave Lord? It uses indirect buffers to handle the
different major modes, so switching between the modes as you move
through the document is really fast. The downside, and it is
significant, is that when deleting text it will, on occasion, cause
emacs to crash. I don't know whether that is a more general issue
with using indirect buffers, or a specific problem with the
implementation.


--
Joe Riel

Norman Ramsey

unread,
Mar 23, 2006, 9:26:17 PM3/23/06
to
In article <dvskm7$1m4r$1...@bowser.eecs.harvard.edu>,
Joe Riel <jo...@k-online.com> wrote:
>I've installed [mmm-move], but couldn't get it to work. Have you

>tried the noweb.el mode by Dave Lord? It uses indirect buffers to
>handle the different major modes, so switching between the modes as
>you move through the document is really fast. The downside, and it
>is significant, is that when deleting text it will, on occasion,
>cause emacs to crash. I don't know whether that is a more general
>issue with using indirect buffers, or a specific problem with the
>implementation.

I haven't tried Dave Love's noweb.el, but the downside does indeed
sound significant. How well does it work with cc-mode syntax
highlighting? Will it support multiple code modes in one file?

Joe Riel

unread,
Mar 23, 2006, 10:19:21 PM3/23/06
to
n...@eecs.harvard.edu (Norman Ramsey) writes:

I don't write c code, so I haven't tried that, but it works fine with
the languages I do use (elisp, maple, python). That is, the syntax
highlighting is usually correct. It can get screwed up with
particular usages, for example, an unmatched dollar sign ($) in the
code triggers auctex's math highlighting which then effects the LaTeX
outside a code chunk. That might be fixable by tweaking auctex's
font-lock routine, but I just add a matching $ in a comment
immediately after the offending chunk.

I haven't tried multiple code modes; I don't believe, though, that it
will handle them. I see that mmm-mode should, which would be nice. I
wonder how fast it is (if it worked with noweb) when switching modes.
My experience with the noweb-model.el by Thorsten Ohl was that it was
just too slow in switching to be practical.

--
Joe Riel

Ralf Hemmecke

unread,
May 10, 2006, 3:44:52 AM5/10/06
to
Hello Norman,

I don't know whether you have succeded in makeing mmm-mode work, but I
have described it in a section in ALLPROSE, see below.

Of course, you have to set the emacs variable auto-mode-alist yourself,
for example...

(setq auto-mode-alist (append '(
("\\.as$" . aldor-mode)
("Makefile.*\\.\\(allprose\\|def\\|inc\\)$" . makefile-mode)
("\\.\\(nw\\|pamphlet\\)$" . latex-mode)
("\\.\\(mpl\\|maple\\)$" . maple-mode)
("\\.\\(mma\\|mathematica\\)$" . mathematica-mode)
) auto-mode-alist))

Look at http://www.hemmecke.de/aldor. Get allprose-0.2.0.tar.gz unpack
it, then say

notangle -Remacscode allprose*/allprose.tex.nw > emacs.el

and single out what might be useful for you. (You'll get a bit more than
what is given below.

I hope that helps.

Ralf

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsubsection{Setup \xmmmode{} for \xEmacs{}}%
\label{sec:ALLPROSE:mmm-mode}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
The multiple major mode (\xmmmode{}) is useful for editing code and
documentation of \srcextension{} files in \xEmacs{}.

Setup can be done as follows.

\begin{enumerate}
\item Install \xmmmode{} into the \directory{~/elisp/mmm}.
%
Go to the directory where the extracted mmm archive is. Then type
the following.
\begin{verbatim}
EMACS=/usr/bin/emacs ./configure --prefix ~/elisp/mmm
make
make install
\end{verbatim}
Be careful to compile for the flavour (\xEmacs{} or \xXEmacs{}) you
use, see below.

\item Add the following lines to your \path{~/.emacs} file. Or,
better, select the appropriate lines.

First, the setup for \xmmmode{} in general and its association to
certain file types.
%CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
<<emacs: mmm-mode>>=
(setq load-path (append '("~/elisp/mmm") load-path)) ;-- path to mmm-mode
(require 'mmm-mode)
(setq mmm-global-mode 'maybe)
(mmm-add-mode-ext-class 'latex-mode "\\.nw$" 'noweb)
(mmm-add-mode-ext-class 'latex-mode "\\.pamphlet$" 'noweb)
@
%TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT

The following code is partly taken from \xEmacs{} (\texttt{subr.el}
\texttt{assoc-default}), because the function \texttt{assoc-default}
is not available in \xXEmacs{}.

It takes a string (\texttt{key}) and tries to string-match the car
(first of a list) of an element of \useterm{auto-mode-alist} against
\texttt{key}. If found, it returns the cdr (rest of the list) of the
matching pair. If not found then \texttt{fundamental-mode} is
returned.

Note that an element of \useterm{auto-mode-alist} can either be a
dotted pair or an atom. In the latter case, this atom is returned if
it matches \texttt{key}. (Maybe that makes not much sense here, but we
did not want to deviate too much from \texttt{assoc-default}.
%CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
<<emacs: mmm-mode>>=
(defun get-auto-mode (key)
(let (found (tail auto-mode-alist) value)
(while (and tail (not found))
(let ((elt (car tail)))
(when (string-match (if (consp elt) (car elt) elt) key)
(setq found t value (if (consp elt) (cdr elt) 'fundamental-mode))))
(setq tail (cdr tail)))
value))
@ %def get-auto-mode
%TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT

We need \useterm{get-auto-mode} to set the
\texttt{mmm-noweb-code-mode} depending on the file type. Whenever
\xmmmode{} is switched on, the hook below tests whether the filename
ends in \extension{pamphlet} or \extension{nw}. This extension is
removed and the filename is matched against the
\useterm{auto-mode-alist}. From the latter we get via the function
\useterm{get-auto-mode} the corresponding mode that will then be
assigned to \texttt{mmm-noweb-code-mode}.
%CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
<<emacs: mmm-mode>>=
(add-hook 'mmm-major-mode-hook
'(lambda () (setq mmm-noweb-code-mode
(get-auto-mode (substring buffer-file-name 0
(string-match "\\.\\(pamphlet\\|nw\\)$" buffer-file-name))))))
@
%$
%TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT


\item This step is actually unnecessary if \useterm{get-auto-mode} is
used. It is only left in order to document how
\texttt{mmm-noweb-code-mode} would have to be set if the function
\useterm{get-auto-mode} would not be hooked into
\texttt{mmm-major-mode-hook}.

You could put
\begin{verbatim}
% -*- mode: latex; mmm-noweb-code-mode: makefile-mode; -*-
\end{verbatim}
at the beginning of your file.

Or, at the end of a \srcextension{} file say something like
\begin{verbatim}
%EMACS Local Variables:
%EMACS mmm-noweb-code-mode: makefile-mode
%EMACS End:
\end{verbatim}
where, of course, \verb'makefile-mode' has to be replaced by the
mode that is appropriate for the code inside the code chunks, \eg,
\xaldormode{}.

Of course, it is undesirable to put extra \xEmacs{} specific code
into a source file, since one cannot expect that everyone is using
\xEmacs{}.
\end{enumerate}

Unfortunately, for \xXEmacs{} the setup is not identical. First of
all, you will have to say
\begin{verbatim}
EMACS=/usr/bin/xemacs ./configure --prefix ~/elisp/mmm
\end{verbatim}
and the above code goes into the file \path{~/.xemacs/init.el}.

\emph{I have not investigated the reason for the following.
Additionally, I had to add the \xpreviewlatex{} package
(version~0.7.8) into the directory
\directory{~/.xemacs/xemacs-packages} in order to make \xmmmode{}
work.}

Christian Lynbech

unread,
Feb 14, 2007, 10:29:15 PM2/14/07
to

I have been looking a bit into emacs noweb'ing vs. font-lock.

I am working on a small tool that involves both shell and lisp code
and the combinations of shells dollars and pipes and common lisps
symbol quoting and latexs math highlighting was driving me slightly
mad.

I looked briefly into mmm-mode but allthough it seemed to solve some
of the problem, dollars inside shell code chunks would still affect
the latex coming after. After staring at font-lock and mmm-mode, I
decided that this was too complicated for me.

I then went back to noweb-mode and made a quick fix. It is quite
simple, narrow to the current chunk before calling the appropriate
mode function. If one also sets `font-lock-dont-widen' to true, the
effect is that highlighting only is done inside each chunk.

The diff follows below, in case this could be of help to someone. It
is against noweb-mode.el labelled v2_11b as distributed in Debian
Linux.

Index: noweb-mode.el
===================================================================
--- noweb-mode.el (revision 1343)
+++ noweb-mode.el (working copy)
@@ -344,6 +344,10 @@

;;; Chunks

+(defvar *noweb-chunk-regexp*
+ "^\\(@\\( \\|$\\|\\( %def\\)\\)\\|<<\\(.*\\)>>=\\)"
+ "Regular expression usuable for finding chunk boundaries.")
+
(defun noweb-update-chunk-vector ()
"Scan the whole buffer and place a marker at each \"^@\" and \"^<<\".
Record them in NOWEB-CHUNK-VECTOR."
@@ -351,7 +355,7 @@
(save-excursion
(goto-char (point-min))
(let ((chunk-list (list (cons 'doc (point-marker)))))
- (while (re-search-forward "^\\(@\\( \\|$\\|\\( %def\\)\\)\\|<<\\(.*\\)>>=\\)" nil t)
+ (while (re-search-forward *noweb-chunk-regexp* nil t)
(goto-char (match-beginning 0))
;; If the 3rd subexpression matched @ %def, we're still in a code
;; chunk (sort of), so don't place a marker here.
@@ -886,22 +890,43 @@

;;; Modes

+(defun noweb-chunk-boundary-backward ()
+ "Find beginning of current chunk."
+ (save-match-data
+ (save-excursion
+ (when (re-search-backward *noweb-chunk-regexp* nil 'move)
+ (goto-char (match-beginning 0)))
+ (point))))
+
+(defun noweb-chunk-boundary-forward ()
+ "Find beginning of next chunk."
+ (save-match-data
+ (save-excursion
+ (when (re-search-forward *noweb-chunk-regexp* nil 'move)
+ (goto-char (match-beginning 0)))
+ (point))))
+
+
(defun noweb-select-mode ()
"Select NOWEB-DOC-MODE or NOWEB-CODE-MODE, as appropriate."
(interactive)
- (if (stringp (car (noweb-find-chunk)))
- ;; Inside a code chunk
- (if (equal major-mode noweb-code-mode)
- nil
- (funcall noweb-code-mode)
- (run-hooks 'noweb-select-code-mode-hook)
- (run-hooks 'noweb-select-mode-hook))
- ;; Inside a documentation chunk
- (if (equal major-mode noweb-doc-mode)
- nil
- (funcall noweb-doc-mode)
- (run-hooks 'noweb-select-doc-mode-hook)
- (run-hooks 'noweb-select-mode-hook))))
+ (let ((beg (noweb-chunk-boundary-backward))
+ (end (noweb-chunk-boundary-forward)))
+ (save-restriction
+ (narrow-to-region beg end)
+ (if (= (char-after beg) ?<)
+ ;; Inside a code chunk
+ (if (equal major-mode noweb-code-mode)
+ nil
+ (funcall noweb-code-mode)
+ (run-hooks 'noweb-select-code-mode-hook)
+ (run-hooks 'noweb-select-mode-hook))
+ ;; Inside a documentation chunk
+ (if (equal major-mode noweb-doc-mode)
+ nil
+ (funcall noweb-doc-mode)
+ (run-hooks 'noweb-select-doc-mode-hook)
+ (run-hooks 'noweb-select-mode-hook))))))

(defun noweb-set-doc-mode (mode)
"Change the major mode for editing documentation chunks."


------------------------+-----------------------------------------------------
Christian Lynbech | christian #\@ defun #\. dk
------------------------+-----------------------------------------------------
Hit the philistines three times over the head with the Elisp reference manual.
- pet...@hal.com (Michael A. Petonic)

Christian Lynbech

unread,
Feb 15, 2007, 5:12:47 AM2/15/07
to
>>>>> "Christian" == Christian Lynbech <chri...@defun.dk> writes:

Christian> I have been looking a bit into emacs noweb'ing vs. font-lock.

The posted patch does not work as intended. Please discard for now.

-- Christian

Sven Kloppenburg

unread,
Feb 15, 2007, 10:26:03 PM2/15/07
to
Christian Lynbech <christia...@ericsson.com> writes:

> Christian> I have been looking a bit into emacs noweb'ing vs. font-lock.

maybe you want to take a look at mmm-mode (http://mmm-mode.sourceforge.net/)
wich contains support for noweb. AFAIR it does fontlock in the major modes it
switches.
--
bye, sven

Christian Lynbech

unread,
Feb 16, 2007, 4:38:20 AM2/16/07
to
>>>>> "Sven" == Sven Kloppenburg <klopp...@informatik.tu-darmstadt.de> writes:

Sven> maybe you want to take a look at mmm-mode (http://mmm-mode.sourceforge.net/)
Sven> wich contains support for noweb. AFAIR it does fontlock in the major modes it
Sven> switches.

Yes, but unfortunately it too has the problem I try to avoid.

The font-locking of the code chunks work well, here the fontification
only takes the actual chunk into account, but for the documentation
chunks it still fontifies the whole buffer, so to speak, such that a
single dollar in a code chunk "bleeds" through to colorize the
following documentation chunks, and there is a lot of dollars in a
typical Bourne shell script.

-- Christian

0 new messages