Further to yesterday's post
about editing OpenLaszlo with Emacs, I've had a look for a more
complete schema file than the
tools/lzx+libraries-nons.rnc that ships with OpenLaszlo
3.3.3.
I found a thread on the OpenLaszlo forums that mentioned a schema buried in the (currently moribund and possibly about to be mothballed) IDE for Laszlo project. I downloaded the source and schlepped through it, but I couldn't find anything that looked like a complete schema.
The same thread mentions generating a schema from the
tools/lzx.dtd DTD. So I gave that a go using James
Clark's Trang,
which produced a 1,462KB "compact" RELAX NG schema from the 1,523KB
DTD. By comparison, it also produced a 2,867KB XML syntax RELAX NG
schema and a 2,643KB W3C XML Schema (58,467 lines, 15,311 lines,
95,948 lines and 65,998 lines respectively).
Anyway, I modified my tools/nxml-schemas.xml file to
point to this new schema:
<?xml version="1.0"?> <locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0"> <!-- * X_LZ_COPYRIGHT_BEGIN *************************************************** * Copyright 2001-2004 Laszlo Systems, Inc. All Rights Reserved. * * Use is subject to license terms. * * X_LZ_COPYRIGHT_END ****************************************************** --> <namespace ns="http://www.laszlosystems.com/2003/05/lzx" uri="lzx+libraries.rnc"/> <uri pattern="*.lzx" uri="lzx-dtd-schema.rnc"/> <documentElement localName="canvas" typeId="lzx-dtd-schema.rnc"/> </locatingRules>
Then I loaded up my (admittedly small) LZX file, and lo! all my validation errors have gone. And the size of the schema didn't seem to slow Emacs/nXML down particularly.
Then I tried loading the W3C XML Schema into Microsoft Visual Studio 2005 Team Suite; it has a nice-looking Schema Designer for playing with such things. Well, the whole app blocked for over nine minutes and chewed through all my available RAM (2GB) before giving up with an "out of memory" exception (don't see many of those these days). So score one for Emacs there.
Here are the schema files, if you'd like to try this at home:
lzx-dtd-schema.rnc,
lzx-dtd-schema.xsd.
Update 13/12/06: I have found a better schema.
I spent a lot of hours yesterday trying to configure GNU Emacs 21.3 for editing OpenLaszlo .LZX files. As usual, there were various scraps of information scattered about the internet that had to be reconciled with each other, and I found it all very frustrating. I think I have things sorta-kinda mostly working now, but I'd be keen to receive feedback and suggestions for improvements. I've spent most of today writing it all up in order to earn some good internet karma and save the next person some time and suffering.
Here is the list of tools I have ended up using, along with the
Emacs Lisp I added to my .emacs:
nXML is 17,000 lines of Emacs Lisp from the mighty James Clark himself. The latest version is over two years old, but apparently it's still the best thing out there for editing (and validating) XML.
The basic .emacs additions for nXML are:
;; 10 Dec 06 JDP Ref: http://www.thaiopensource.com/nxml-mode/ ;; Ref: http://www.emacswiki.org/cgi-bin/wiki/NxmlMode (unless (boundp 'site-lisp-path) (setq site-lisp-path "c:/bin/emacs-21.3/site-lisp/")) (setq nxml-path (concat site-lisp-path "nxml-mode-20041004/")) (load (concat nxml-path "rng-auto.el")) (add-to-list 'auto-mode-alist '("\\.\\(xml\\|xsl\\|rng\\|xhtml\\|lzx\\|x3d\\)\\'" . nxml-mode)) (setq nxml-sexp-element-flag t)
The nXML info pages say that you can add your own filenames to the
rng-schema-locating-files list in order to provide
instructions for associating schemas with your documents. I wanted to
add (concat lps-path "tools/nxml-schemas.xml") to the
list, which would point to tools/lzx+libraries-nons.rnc,
the RELAX NG compact schema provided by Laszlo Systems.
I ended up "customising" rng-schema-locating-files in
a rather brute-force fashion, as follows:
(setq lps-path "c:/program files/openlaszlo server 3.3.3/server/lps-3.3.3/") (setq rng-schema-locating-files (list (concat lps-path "tools/nxml-schemas.xml") "schemas.xml" (concat nxml-path "schema/schemas.xml")))
rng-schema-locating-files isn't defined at this point,
so I set it to my value plus the two default values. I tried doing it
"properly" via (eval-after-load "rng-xsd" ...), but by
that point my .LZX file was already loaded and using the
"vacuous" schema...
There is more discussion of schema location available elsewhere.
To colourise the embedded JavaScript, another major mode is
needed. I found a summary of the major
JavaScript modes available and I have picked ecmascript-mode,
amending my .emacs thusly:
(autoload 'ecmascript-mode "ecmascript-mode" "Major mode to edit EMCAScript/JavaScript files." t)
(add-to-list 'auto-mode-alist '("\\.js\\'" . ecmascript-mode))
(add-to-list 'auto-mode-alist '("\\.as\\'" . ecmascript-mode))
(add-to-list 'auto-mode-alist '("\\.lzs\\'" . ecmascript-mode))
html-script
is one way to edit the embedded JavaScript in your .LZX files. It is
simple and works well, but it narrows your buffer rather than letting
you edit in-place. .emacs modifications required:
(require 'html-script)
(add-to-list 'html-script-regions
'("<\\(handler\\|method\\|script\\)[^>]*>\\([ \t\n]*<!\\[CDATA\\[\\)?"
"\\(\\]\\]>[ \t\n]*\\)?</\\(handler\\|method\\|script\\)>"
ecmascript-mode))
(setq html-script-start-regexp
(concat "\\(" (mapconcat (lambda (x) (car x)) html-script-regions "\\|") "\\)"))
I should add that I have commented out the above code in my
.emacs, because it doesn't seem to work with MMM Mode.
MMM Mode seems to be
the most popular way to have multiple modes in the same buffer
(although the Emacs
Wiki does list alternatives). I have installed it and patched the
mmm-vars.el file as described by P.Tucker Withington on the
Emacs Wiki.
All that's needed in the .emacs file is:
(require 'mmm-mode) (setq mmm-global-mode 'maybe)
Then you need to tell mmm-mode about the
sub-modes. The file tools/lzx.el contains code for this,
but it also expects xml-mode rather than
nxml-mode so I have had to copy it and hack it a
bit. Also, it knows about methods and
scripts, but not handlers, so I fixed that
as well. The resulting fragment looks like this:
(when (fboundp 'mmm-mode)
(mmm-add-group
'lzx
'((js-method-cdata
:submode ecmascript-mode
:face mmm-code-submode-face
:front "<method[^>]*>[ \t\n]*<!\\[CDATA\\[[ \t]*\n?"
:back "[ \t]*]]>[ \t\n]*</method>"
:insert ((?j js-tag nil @ "<method language=\"JavaScript\">"
@ "\n" _ "\n" @ "</method>" @)))
(js-method
:submode ecmascript-mode
:face mmm-code-submode-face
:front "<method[^>]*>[ \t]*\n?"
:back "[ \t]*</method>"
:insert ((?j js-tag nil @ "<method language=\"JavaScript\">"
@ "\n" _ "\n" @ "</method>" @)))
(js-handler-cdata
:submode ecmascript-mode
:face mmm-code-submode-face
:front "<handler[^>]*>[ \t\n]*<!\\[CDATA\\[[ \t]*\n?"
:back "[ \t]*]]>[ \t\n]*</handler>"
:insert ((?j js-tag nil @ "<handler language=\"JavaScript\">"
@ "\n" _ "\n" @ "</handler>" @)))
(js-handler
:submode ecmascript-mode
:face mmm-code-submode-face
:front "<handler[^>]*>[ \t]*\n?"
:back "[ \t]*</handler>"
:insert ((?j js-tag nil @ "<handler language=\"JavaScript\">"
@ "\n" _ "\n" @ "</handler>" @)))
(js-script-cdata
:submode ecmascript-mode
:face mmm-code-submode-face
:front "<script[^>]*>[ \t\n]*<!\\[CDATA\\[[ \t]*\n?"
:back "[ \t]*]]>[ \t\n]*</script>"
:insert ((?j js-tag nil @ "<script language=\"JavaScript\">"
@ "\n" _ "\n" @ "</script>" @)))
(js-script
:submode ecmascript-mode
:face mmm-code-submode-face
:front "<script[^>]*>[ \t]*\n?"
:back "[ \t]*</script>"
:insert ((?j js-tag nil @ "<script language=\"JavaScript\">"
@ "\n" _ "\n" @ "</script>" @)))
(js-inline
:submode ecmascript-mode
:face mmm-code-submode-face
:front "on\w+=\""
:back "\"")))
(mmm-add-mode-ext-class 'nxml-mode "\\.lz[lx]\\'" 'lzx))
When all this works, it looks very pretty:
One problem is immediately apparent: the document isn't validating
properly, even though it is correct. Presumably this is a problem with
the lzx+libraries-nons.rnc schema, and looking at it I
can't see any reference to button or xmlrpc
elements, but I don't have time to pick up enough RELAX NG compact
schema to debug it. I think I'll just email Oliver Steele and ask him whether a
more up-to-date schema is available. Dunno what the deal is with the
illegal "100%" attribute values, either.
Other than that, it's not too bad. The syntax colouring sort of blinks in and out as you edit stuff, but it's liveable. I've linked to this post from the OpenLaszlo forums, so hopefully somebody will find this useful in the future.
Python Paste