Daniel Colascione | 24 May 00:26 2008

[patch] use font-lock

[Originally sent to the nxml mailing list]

I've converted nxml to font-lock. I used the existing fontification machinery 
and put it inside a cc-mode-style matcher. Efficiency and output are the 
same, but:

1) hi-lock-mode works now
2) all conventional font-locking functions work as expected. For example, you 
can turn fontification on and off with M-x font-lock-mode.
3) font-lock-add-keywords DTRT
4) multiple-major-modes modes should be able to use nXML fontification now, 
though this remains untested

I've also added a new function:
nxml-debug-region: Interactive function. Activate the region and call 
nxml-debug-region. The new region is what nxml thinks should be re-fontified 
if the original region is changed.

The new code probably works only on Emacs 22. Lightly tested, but it seems to 
handle corner highlighting cases fine. I removed a bunch of code that 
was "for redisplay", since I'm assuming font-lock handles those funky bits.

In addition to the patch, I've attached a set of files that demonstrates 
extending nXML mode to work with the Genshi template engine. The examples 
ought to work with some slight modification of the embedded paths.

(Does the Relax NG compact syntax offer a way to say "include the next file 
for this document type"?)

;;;; Customization for nXML mode

(setq rng-schema-locating-files
      (append '("~/emacs/nxml-schema/schemas.xml")

(defface nxml-template
  '((t (:bold t
        :foreground "blue"
        :background "#ddddff")))
  "Face used to highlight embedded template constructs"
  :group 'nxml-highlighting-faces)

(defun qtmstr-nxml-hook ()
  (when (string-match "\\.html$" buffer-file-name)
    (let ((py-prefix-re

       `(("\\$\\([a-zA-Z_][a-zA-Z0-9_]*\\)" 1
          'nxml-template prepend)

         ("\\${\\([^}\"]+\\)}" 1
          'nxml-template prepend)

         (,(concat py-prefix-re "=\"\\([^\"]*\\)\"") 1
          'nxml-template prepend))))))

(add-hook 'nxml-mode-hook #'qtmstr-nxml-hook)

namespace py = "http://genshi.edgewall.org/"

genshi.expr-type    = xsd:string { minLength = "1" }
genshi.with-type    = xsd:string { minLength = "1" }
genshi.choose-type  = xsd:string
genshi.def-type   = xsd:string
genshi.xpath-type = xsd:anyURI

genshi.attrib = attribute py:if        { genshi.expr-type   }?,
                attribute py:choose    { genshi.choose-type }?,
                attribute py:when      { genshi.expr-type   }?,
                attribute py:otherwise { genshi.expr-type   }?,
                attribute py:for       { genshi.expr-type   }?,
                attribute py:def       { genshi.def-type    }?,
                attribute py:match     { genshi.xpath-type  }?,
                attribute py:with      { genshi.with-type   }?,
                attribute py:attrs     { genshi.expr-type   }?,
                attribute py:content   { genshi.expr-type   }?,
                attribute py:replace   { genshi.expr-type   }?,
                attribute py:strip     { genshi.expr-type   }?

genshi.if.attlist   = attribute expr { genshi.expr-type }
genshi.for.attlist  = attribute each { genshi.expr-type }
genshi.def.attlist  = attribute each { genshi.expr-type }
genshi.with.attlist = attribute vars { genshi.with-type }

Attachment (qtmstr-xhtml.rnc): text/x-c++src, 2110 bytes
Attachment (schemas.xml): text/xml, 136 bytes
Attachment (xinclude.rnc): text/x-c++src, 345 bytes

Hello from hello! Test ${name}