PDA

View Full Version : Emacs, nXML, and lzx.rng


jbm
10-15-2004, 03:06 PM
Hello any Emacs bretheren out there, I'm having some difficulty authoring .lzx files with Emacs and nXML. I'm not a schemas guru, so bear with me here...

I ran Trang on lps-2.2/tools/lzx.rng and output it to lzx.rnc, then while editing a simple .lzx file in nxml-mode did a C-c,C-s,C-f to run the "rng set schema file and validate" routine. Here's my .lzx file:
<canvas width="600" height="400"
xmlns="http://www.laszlosystems.com/2003/05/lzx">
<window x="20" y="20" width="260" height="160">
<button>Test</button>
</window>
</canvas>
What happens is the opening window tag gets flagged as invalid. I didn't see "window" anywhere in the .rnc file, so I ran Trang on the lzx.dtd file instead. The resulting .rnc file was much larger than the first (presumably with more complete info, but with XML who knows) but this time it flagged the opening canvas tag as invalid.

The nXML emacs lisp module is excellent and I wish to get its features working with .lzx files. Any tips would be appreciated. I'm running 21.2.1 on WinXP along with the latest nXML mode.

antun
10-15-2004, 03:11 PM
Not an Emacs user myself, but the LPS does ship with a lzx.el file for Emacs, in the tools directory. Have you looked at that?

-Antun

jbm
10-15-2004, 03:36 PM
Thanks for the reply -- yes, I saw the shipped lzx.el, it's in the same directory as the schemas.

It's basically a light wrapper around the default xml-mode and mmm-mode, not really related to nXML. Which is fine, though I much prefer nXML over the batch validation setup in the more generic psgml-mode on which xml-mode is based. I think the setup performed by lzx.el would be useful in nxml-mode as well, but I haven't tried it.

My suspicion is that the Relax NG support in the .rng file is just out of date, or not quite up to where the .dtd is, but this doesn't explain why the canvas tag is being flagged when I generated a .rnc file from the .dtd. But I don't care to spend the time looking into it too deeply...

ptw
10-19-2004, 10:06 AM
Try this (substituting where you installed Laszlo for <wherever>):


(setq auto-mode-alist
(cons '("\\.lzx\\'" . nxml-mode)
auto-mode-alist))
(setq rng-auto-file-name-alist
(append
'((".*\\.lzx\\'" "<wherever>/tools/lzx+libraries-nons.rnc"))
rng-auto-file-name-alist))

ptw
10-19-2004, 10:37 AM
Or, perhaps more modernly:

(add-to-list 'rng-auto-file-name-alist
'(".*\\.lzx\\\'" "<wherever>/tools/lzx+libraries-nons.rnc"))

Or customize rng-auto-file-name-alist.

It seems that perhaps we do not distribute this .rnc file (which we should). I have attached it.

jbm
10-19-2004, 11:30 AM
Thanks, ptw -- the .rnc file you referred to does indeed come with the distribution. I tried it, but nXML still does not accept the window tag of my test example above. Does it work for you?

As to the elisp snippet, it appears that more recent versions of nXML have dropped the use of rng-auto-file-name-alist and there is a schema location facility now:

http://dpawson.co.uk/relaxng/nxml/nxmlmode.html#d0e524

ptw
10-19-2004, 01:55 PM
Right you are. My nxml mode was way out of date. I am up to date now, and see that there is even a tools/schemas.xml that you can add to your rng-schema-locating-files.

But you are also right: window does not seem to be accepted as a tag in that rnc file. Looks like a bug to me. I'll check it out.

synchromesh
12-10-2006, 03:19 AM
Hi, I realise this thread is a bit old, but this seems like as good a place as any to post. I've configured my Emacs 21.3 with nXML and MMM and ecmascript-mode. They seem to work fairly well, but there are still some issues. I'm using the MMM stuff from lzx.el.

Mainly, the syntax highlighting doesn't work consistently; no two adjacent major-/sub-mode regions are both correctly highlighted.

Also, I'm using the tools/lzx+libraries-nons.rnc schema but I'm getting some random validation errors (e.g. button and xmlrpc elements are unknown).

I don't suppose the good Mr. Withington or another Emacs-using OpenLaszlo staffer could post their relevant bits from their .emacs files? Or, dare I say it, update the manual?

FWIW, here's mine:

;; 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)

;; Ref: http://dpawson.co.uk/relaxng/nxml/schemaloc.html
(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")))

;; Ref: http://www.emacswiki.org/cgi-bin/wiki/ECMAScriptMode
;; Ref: http://emacsen.org/2005/09/26-javascript
(autoload 'ecmascript-mode "ecmascript-mode" "Major mode to edit EMCAScript/JavaScript files." t)
(add-to-list 'auto-mode-alist '("\\.lzs\\'" . ecmascript-mode))

(require 'mmm-mode)
(require 'jdp-lzx)

(setq mmm-global-mode 'maybe)


Cheers,

John :^P

P.S. I should add that I've patched my mmm-vars.el as described by ptw at http://www.emacswiki.org/cgi-bin/wiki/NxmlModeForXHTML, not that it seemed to make any difference.

P.P.S. I've written a more detailed (and generally more positive) summary of all this on my weblog: http://johnp.net/blog/2006/12/11#nxml-vs-mmm

gse
12-11-2006, 10:47 AM
very cool stuff! i've used nxml for quite a while (even switched from XEmacs to Emacs to get it), but i haven't gotten around to getting mmm-mode working yet.

as for the schema thing, i skip schemas altogether and edit LZX as regular old XML. since you'll always be defining your own classes, and therefore XML tags, a schema's never going to do much good.

gse
12-11-2006, 10:56 AM
pretty simple. again, i don't have any mmm stuff working (but i'm going to steal it from john's blog post).

i use this with Emacs 22.0.50.1.


;; nxml-mode setup
(setq load-path (cons (expand-file-name "~/src/elisp/packages/nxml") load-path))
(load "rng-auto")
(setq auto-mode-alist (cons '("\\.xml$" . nxml-mode) auto-mode-alist))
(setq auto-mode-alist (cons '("\\.rng$" . nxml-mode) auto-mode-alist))
(setq auto-mode-alist (cons '("\\.xhtml$" . nxml-mode) auto-mode-alist))
(setq auto-mode-alist (cons '("\\.lzx$" . nxml-mode) auto-mode-alist))
(setq auto-mode-alist (cons '("\\.xml.proto$" . nxml-mode) auto-mode-alist))

;; fix up magic-mode-alist, otherwise a bunch of files run in xml/sgml modes.
(when (boundp 'magic-mode-alist)
(setq magic-mode-alist
(delete-if (lambda (cell)
(memq (cdr cell) '(html-mode xml-mode)))
magic-mode-alist))
;; From `files.el', but without matching against "<xml?".
(push (let* ((incomment-re "\\(?:[^-]\\|-[^-]\\)")
(comment-re (concat "\\(?:!--" incomment-re "*-->\\s*<\\)")))
(cons (concat comment-re "*"
"\\(?:!DOCTYPE\\s +[^>]*>\\s *<\\s *"
comment-re "*\\)?"
"[Hh][Tt][Mm][Ll]")
'html-mode))
magic-mode-alist)
(push '("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML" . nxml-mode) magic-mode-alist)
(push '("<\\?xml" . nxml-mode) magic-mode-alist))

(set-default 'nxml-char-ref-extra-display nil)
(add-hook 'nxml-mode-hook '(lambda ()
(local-set-key "\C-m" 'newline-and-indent)
(local-set-key ">" 'gse-nxml-electric-greaterthan)
(local-set-key '[f8] 'gse-insert-line-equals)
(global-set-key [(control f8)] 'gse-insert-short-line-equals)))

;---------------------------------------------------------------------------

(defun gse-nxml-electric-greaterthan (arg)
(interactive "p")
(let ((token-end (nxml-token-before))
(pos (1+ (point))))
(if (or (eq xmltok-type 'partial-start-tag)
(and (memq xmltok-type '(start-tag
empty-element
partial-empty-element))
(>= token-end pos)))
(nxml-balanced-close-start-tag-block)
(self-insert-command (or arg)))))

;---------------------------------------------------------------------------

(defun gse-cdata()
(interactive)
(let ((origpoint (point-marker))
(tag ""))
(when (re-search-backward "<\\(method\\|handler\\|script\\)")
(setq tag (match-string 1))
(search-forward ">")
(insert "<![CDATA[")
(when (re-search-forward (concat "^\\( *\\)</" tag ">"))
(beginning-of-line)
(insert (match-string 1) "]]>\n")))
(goto-char (marker-position origpoint))))

ptw
12-11-2006, 01:11 PM
Thanks for the great post John. Looks like you have helped push emacs a little closer to being a useful LXZ IDE.

I also see the lossage with font-lock not working in MMM regions. I haven't had time to investigate further, due to crunch time here trying to get a beta out.

Here's my .emacs, FWIW. I recently switched to using Aquamacs, so I am still sorting out some issues...


;; Local customizations override system versions
(add-to-list 'load-path "/usr/share/emacs/site-lisp")
(add-to-list 'load-path "/usr/local/share/emacs/site-lisp")
(add-to-list 'load-path "~/.emacs.d/site-lisp")

;; PTW's c style preferences (from Harlequin MM Group)
(defconst mm-c-style
'(
(c-basic-offset . 2) ; ptw prefer's 2 but Laszlo seems to use 4
(c-comment-only-line-offset . (0 . 0))
(c-offsets-alist . ((statement-block-intro . +)
(knr-argdecl-intro . 5)
(substatement-open . 0) ; GNU uses +
(label . 0)
(case-label . +) ; GNU uses cc-mode default, (case-label 0)
(statement-case-open . +)
(statement-cont . +)
(arglist-intro . + ) ; c-lineup-arglist-intro-after-paren)
(arglist-cont . 0) ; Don't line up if no args after paren
(arglist-close . c-lineup-arglist)
))
(c-cleanup-list . (brace-else-brace scope-operator))
;; don't fill doc comment start lines
(c-hanging-comment-starter-p . nil)
(c-comment-continuation-stars . "* ") ; GNU uses ""
(c-hanging-comment-ender-p . nil) ; GNU uses t
(c-echo-syntactic-information-p . t)
)
"MM C Programming Style")


;; Customizations for all of c-mode, c++-mode, and objc-mode
(defun my-c-mode-common-hook ()
;; add my personal style and set it for the current buffer
(c-add-style "MM" mm-c-style c-buffer-is-cc-mode)
;; other customizations
(setq tab-width 8
;; this will make sure spaces are used instead of tabs
indent-tabs-mode nil)
;; I don't like auto-newline and hungry-delete
(c-toggle-auto-hungry-state -1)
(setq c-indent-comments-syntactically-p t)
;; keybindings for C, C++, and Objective-C. We can put these in
;; c-mode-map because c++-mode-map and objc-mode-map inherit it
(define-key c-mode-map "\C-m" 'newline-and-indent)
;;
(setq dabbrev-case-fold-search nil
dabbrev-case-replace nil)
(turn-on-auto-fill)
)

;; the following only works in Emacs 19
(add-hook 'c-mode-common-hook 'my-c-mode-common-hook)

;; whitespace
(require 'whitespace)

;; Text prefs
(add-hook 'text-mode-hook 'turn-on-auto-fill)
(setq require-final-newline 'ask)

;; was -alL, but then you can't see symlinks
(setq dired-listing-switches "-alh")

;; Need to add 'B' and 'K' as size suffixes to this for -h above
;; [From dired.el]
(setq dired-move-to-filename-regexp
(let* ((l "\\([A-Za-z]\\|[^\0-\177]\\)")
;; In some locales, month abbreviations are as short as 2 letters,
;; and they can be padded on the right with spaces.
;; weiand: changed: month ends potentially with . or , or .,
;;old (month (concat l l "+ *"))
(month (concat l l "+[.]?,? *"))
;; Recognize any non-ASCII character.
;; The purpose is to match a Kanji character.
(k "[^\0-\177]")
;; (k "[^\x00-\x7f\x80-\xff]")
(s " ")
(yyyy "[0-9][0-9][0-9][0-9]")
(mm "[ 0-1]?[0-9]")
;;old (dd "[ 0-3][0-9]")
(dd "[ 0-3][0-9][.]?")
(HH:MM "[ 0-2][0-9]:[0-5][0-9]")
(seconds "[0-6][0-9]\\([.,][0-9]+\\)?")
(zone "[-+][0-2][0-9][0-5][0-9]")
(iso-mm-dd "[01][0-9]-[0-3][0-9]")
(iso-time (concat HH:MM "\\(:" seconds "\\( ?" zone "\\)?\\)?"))
(iso (concat "\\(\\(" yyyy "-\\)?" iso-mm-dd "[ T]" iso-time
"\\|" yyyy "-" iso-mm-dd " ?\\)"))
(western (concat "\\(" month s dd "\\|" dd s month "\\)"
;; weiand: changed: year potentially unaligned
;;old s "\\(" HH:MM "\\|" s yyyy "\\|" yyyy s "\\)"))
s "\\(" HH:MM
"\\|" yyyy s s "?"
"\\|" s "?" yyyy
"\\)"))
(japanese
(concat mm k "?" s dd k "?" s "+"
"\\(" HH:MM "\\|" yyyy k "?" "\\)")))
;; The "[0-9]" below requires the previous column to end in a digit.
;; This avoids recognizing `1 may 1997' as a date in the line:
;; -r--r--r-- 1 may 1997 1168 Oct 19 16:49 README
;; The "[kMGTPEZY]?" below supports "ls -alh" output.
;; The ".*" below finds the last match if there are multiple matches.
;; This avoids recognizing `jservice 10 1024' as a date in the line:
;; drwxr-xr-x 3 jservice 10 1024 Jul 2 1997 esg-host
(concat ".*[0-9][BkKMGTPEZY]?"
s "\\(" western "\\|" japanese "\\|" iso "\\)" s)))

(load "ange-ftp")

;; I think the released version of this is broken
(defun x-cut-buffer-or-selection-value ()
(let (text)
(when x-select-enable-clipboard
(if (null text)
(condition-case c
(setq text (x-get-selection 'CLIPBOARD 'COMPOUND_TEXT))
(error nil)))
(if (null text)
(condition-case c
(setq text (x-get-selection 'CLIPBOARD 'STRING))
(error nil)))
(if (string= text "") (setq text nil)))

;; Don't die if x-get-selection signals an error.
(if (null text)
(condition-case c
(setq text (x-get-selection 'PRIMARY 'COMPOUND_TEXT))
(error nil)))
(if (null text)
(condition-case c
(setq text (x-get-selection 'PRIMARY 'STRING))
(error nil)))
(if (string= text "") (setq text nil))

; Filter out either of those it they are from us
(setq text
(cond
((not text) nil)
((eq text x-last-selected-text) nil)
((string= text x-last-selected-text)
;; Record the newer string, so subsequent calls can use the `eq' test.
(setq x-last-selected-text text)
nil)
(t
text)))

; Try the cut buffer
(or text (setq text (x-get-cut-buffer 0)))
(if (string= text "") (setq text nil))

; Now filter once again
(cond
((not text) nil)
((eq text x-last-selected-text) nil)
((string= text x-last-selected-text)
;; Record the newer string, so subsequent calls can use the `eq' test.
(setq x-last-selected-text text)
nil)
(t
(setq x-last-selected-text text)))))

;; My keybindings
(global-set-key "" (quote goto-line))

;; Check for Xemacs
(defvar running-xemacs (string-match "XEmacs\\|Lucid" emacs-version))
;; Start server
(if running-xemacs
(gnuserv-start)
(server-start)
)

;; Syntax highlighting
(global-font-lock-mode t)
(setq font-lock-maximum-decoration t)
;; Font-lock for all derivatives of c-mode
(add-hook 'c-mode-hook
(lambda ()
(font-lock-add-keywords
nil
'(
("//" ("\\<\\(TODO\\|FIXME\\|NOTE\\|XXX\\|---\\|+++\\)\\>" nil nil (0 'font-lock-warning-face t)))
)))
)
;; Ditto for Lisp modes
(add-hook 'lisp-mode-hook
(lambda ()
(font-lock-add-keywords
'lisp-mode
'(
(";" ("\\<\\(TODO\\|FIXME\\|NOTE\\|XXX\\|---\\|+++\\)\\>" nil nil (0 'font-lock-warning-face t))) ;
))))

;; Other modes
(font-lock-add-keywords
'nxml-mode
'(
("<!--" ("\\<\\(TODO\\|FIXME\\|NOTE\\|XXX\\|---\\|+++\\)\\>" nil nil (0 'font-lock-warning-face t)))
))

;; FIXME Test font lock for FIXME's

;; JavaScript
(autoload 'javascript-mode "javascript-mode" "Major mode to edit JavaScript files." t)
(add-to-list 'auto-mode-alist '("\\.js\\'" . javascript-mode))
;; ActionScript like JavaScript
(add-to-list 'auto-mode-alist '("\\.as\\'" . javascript-mode))
;; LaszloScript
(add-to-list 'auto-mode-alist '("\\.lzs\\'" . javascript-mode))


;; nxml
(add-to-list 'load-path "/usr/local/share/emacs/site-lisp/nxml-mode-20041004")
(load "rng-auto.el")
;; lzx handled below
(add-to-list
'auto-mode-alist
'("\\.\\(xml\\|xsl\\|rng\\|xhtml\\)\\'" . nxml-mode))

;; LZX
;;(load-library "mmm-mode")
(require 'mmm-mode)
(mmm-add-find-file-hook)
;; Don't interfere with font-lock
(setq mmm-submode-decoration-level 0)
;; Includes auto-mode-alist for lz[lx] files to be in nxml mode (above)
(require 'lzx)

;; PHP
(autoload 'php-mode "php-mode" "Major mode to edit PHP files." t)
(require 'mmm-mode)
;; (add-to-list 'auto-mode-alist '("\\.php\\'" . php-mode))
;; (require 'mmm-php)


;; Perforce
;;(load-library "p4")
(require 'p4)
(p4-set-p4-executable "/usr/local/bin/p4")

; These changes make indenting work properly in Perforce meta-data buffers.
; Tip o' the pin to: jik@kamens.brookline.ma.us.

(setq perforce-tmp-file-regexp "\\`\\(/var\\|/usr\\|/private\\)?/tmp/tmp\\.[0-9]+\\.[0-9]+$"
perforce-tmp-buffer-regexp "^# A Perforce .* Specification\\.$")

(setq auto-mode-alist
(append (list (cons perforce-tmp-file-regexp 'text-mode))
auto-mode-alist))

(defun maybe-perforce-text-mode ()
(save-excursion
(if (and buffer-file-name
(string-match perforce-tmp-file-regexp buffer-file-name)
(goto-char (point-min))
(looking-at perforce-tmp-buffer-regexp))
(progn
(setq indent-tabs-mode t
;; Does not seem to take?
whitespace-mode t
whitspace-check-buffer-indent t
fill-prefix "\t")))))

(add-hook 'text-mode-hook 'maybe-perforce-text-mode 'append)

; End perforce crap

;; Python
(autoload 'python-mode "python-mode" "Python editing mode." t)
(add-to-list 'auto-mode-alist '("\\.py\\'" . python-mode))

(setq interpreter-mode-alist
(cons '("python" . python-mode)
interpreter-mode-alist))

; --- Doesn't work yet
; (eval-after-load "python-mode"
; '(progn (load-library "python-fill")
; (load-library "python-outline")))
; (add-hook 'python-mode-hook
; (lambda ()
; (setq fill-paragraph-function 'python-fill-paragraph-new)))

;; svn
(require 'psvn)

;; Mouse wheel
(require 'mwheel)
(mouse-wheel-mode t)

;; ediff
(require 'ediff)

;; ps-print
(require 'ps-print)
(setq ps-lpr-command "~/bin/ps-print")

;; Customizations
(custom-set-faces
;; custom-set-faces was added by Custom -- don't edit or cut/paste it!
;; Your init file should contain only one such instance.
'(font-lock-warning-face ((((class color) (background light)) (:bold nil :foreground "White" :background "Red")))))

(custom-set-variables
;; custom-set-variables was added by Custom -- don't edit or cut/paste it!
;; Your init file should contain only one such instance.
'(adaptive-fill-regexp "[ ]*\\([-|#;>*]+[ ]*\\|(?[0-9]+[.)][ ]*\\)*")
'(auto-compression-mode t nil (jka-compr))
'(backup-by-copying-when-linked t)
'(backup-by-copying-when-mismatch t)
'(blink-cursor nil)
'(browse-url-browser-function (quote browse-url-generic))
'(browse-url-generic-program "open")
'(case-fold-search t)
'(cua-mode nil)
'(current-language-environment "English")
'(ediff-quit-hook (quote (ediff-toggle-wide-display ediff-cleanup-mess)))
'(ediff-split-window-function (quote split-window-horizontally))
'(ediff-startup-hook (quote (ediff-toggle-wide-display)))
'(ediff-whitespace "
" t)
'(ediff-window-setup-function (quote ediff-setup-windows-plain))
'(global-font-lock-mode t nil (font-lock))
'(indent-tabs-mode nil)
'(menu-bar-mode t nil (menu-bar))
'(nxml-sexp-element-flag t)
'(nxml-slash-auto-complete-flag t)
'(p4-file-refresh-timer-time 0)
'(p4-use-p4config-exclusively t)
'(rng-schema-locating-files (quote ("~/Laszlo/lps/tools/schemas.xml" "schemas.xml" "/usr/local/share/emacs/site-lisp/nxml-mode-20041004/schema/schemas.xml")))
'(scroll-bar-mode nil)
'(shell-prompt-pattern "^\\[[^]]*\\][#$>]")
'(show-paren-mode nil nil (paren))
'(show-trailing-whitespace t)
'(text-mode-hook (quote (turn-on-auto-fill text-mode-hook-identify maybe-perforce-text-mode)))
'(tool-bar-mode nil nil (tool-bar))
'(uniquify-buffer-name-style (quote post-forward) nil (uniquify))
'(vc-make-backup-files t)
'(version-control t)
'(view-mode-hook (quote (turn-on-auto-revert-mode)))
'(whitespace-abort-on-error nil)
'(whitespace-check-indent-whitespace t)
'(whitespace-global-mode nil nil (whitespace))
'(whitespace-indent-regexp "^\\( +\\) ")
'(whitespace-modes (quote (ada-mode asm-mode autoconf-mode awk-mode c-mode c++-mode cc-mode change-log-mode cperl-mode electric-nroff-mode emacs-lisp-mode f90-mode fortran-mode html-mode html3-mode java-mode jde-mode ksh-mode latex-mode LaTeX-mode lisp-mode m4-mode makefile-mode modula-2-mode nroff-mode objc-mode pascal-mode perl-mode prolog-mode python-mode scheme-mode sgml-mode sh-mode shell-script-mode simula-mode tcl-mode tex-mode texinfo-mode vrml-mode xml-mode javascript-mode nxml-mode))))

synchromesh
12-12-2006, 05:01 PM
Thanks guys, I'm glad you liked it. I've now generated a new .RNC file from the lzx.dtd DTD, which cures the validation problems I saw without slowing things down unduly. More info on my weblog: http://johnp.net/blog/2006/12/13#lzx-dtd-schema (the schema is at http://johnp.net/misc/lzx-dtd-schema.rnc).

Cheers,

John :^P