nXML: Use font lock
[bpt/emacs.git] / lisp / nxml / nxml-util.el
1 ;;; nxml-util.el --- utility functions for nxml-*.el
2
3 ;; Copyright (C) 2003, 2007, 2008 Free Software Foundation, Inc.
4
5 ;; Author: James Clark
6 ;; Keywords: XML
7
8 ;; This file is part of GNU Emacs.
9
10 ;; GNU Emacs is free software: you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation, either version 3 of the License, or
13 ;; (at your option) any later version.
14
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
22
23 ;;; Commentary:
24
25 ;;; Code:
26
27 (defconst nxml-debug nil
28 "enable nxml debugging. effective only at compile time")
29
30 (eval-when-compile
31 (require 'cl))
32
33 (defsubst nxml-debug (format &rest args)
34 (when nxml-debug
35 (apply #'message format args)))
36
37 (defmacro nxml-debug-change (name start end)
38 (when nxml-debug
39 `(nxml-debug "%s: %S" ,name
40 (buffer-substring-no-properties ,start ,end))))
41
42 (defmacro nxml-debug-set-inside (start end)
43 (when nxml-debug
44 `(let ((overlay (make-overlay ,start ,end)))
45 (overlay-put overlay 'face '(:background "red"))
46 (overlay-put overlay 'nxml-inside-debug t)
47 (nxml-debug-change "nxml-set-inside" ,start ,end))))
48
49 (defmacro nxml-debug-clear-inside (start end)
50 (when nxml-debug
51 `(loop for overlay in (overlays-in ,start ,end)
52 if (overlay-get overlay 'nxml-inside-debug)
53 do (delete-overlay overlay)
54 finally (nxml-debug-change "nxml-clear-inside" ,start ,end))))
55
56 (defun nxml-make-namespace (str)
57 "Return a symbol for the namespace URI STR.
58 STR must be a string. If STR is the empty string, return nil.
59 Otherwise, return the symbol whose name is STR prefixed with a colon."
60 (if (string-equal str "")
61 nil
62 (intern (concat ":" str))))
63
64 (defun nxml-namespace-name (ns)
65 "Return the namespace URI corresponding to the symbol NS.
66 This is the inverse of `nxml-make-namespace'."
67 (and ns (substring (symbol-name ns) 1)))
68
69 (defconst nxml-xml-namespace-uri
70 (nxml-make-namespace "http://www.w3.org/XML/1998/namespace"))
71
72 (defconst nxml-xmlns-namespace-uri
73 (nxml-make-namespace "http://www.w3.org/2000/xmlns/"))
74
75 (defmacro nxml-with-degradation-on-error (context &rest body)
76 (if (not nxml-debug)
77 (let ((error-symbol (make-symbol "err")))
78 `(condition-case ,error-symbol
79 (progn ,@body)
80 (error
81 (nxml-degrade ,context ,error-symbol))))
82 `(progn ,@body)))
83
84 (defmacro nxml-with-unmodifying-text-property-changes (&rest body)
85 "Evaluate BODY without any text property changes modifying the buffer.
86 Any text properties changes happen as usual but the changes are not treated as
87 modifications to the buffer."
88 (let ((modified (make-symbol "modified")))
89 `(let ((,modified (buffer-modified-p))
90 (inhibit-read-only t)
91 (inhibit-modification-hooks t)
92 (buffer-undo-list t)
93 (deactivate-mark nil)
94 ;; Apparently these avoid file locking problems.
95 (buffer-file-name nil)
96 (buffer-file-truename nil))
97 (unwind-protect
98 (progn ,@body)
99 (unless ,modified
100 (restore-buffer-modified-p nil))))))
101
102 (put 'nxml-with-unmodifying-text-property-changes 'lisp-indent-function 0)
103 (def-edebug-spec nxml-with-unmodifying-text-property-changes t)
104
105 (defmacro nxml-with-invisible-motion (&rest body)
106 "Evaluate body without calling any point motion hooks."
107 `(let ((inhibit-point-motion-hooks t))
108 ,@body))
109
110 (put 'nxml-with-invisible-motion 'lisp-indent-function 0)
111 (def-edebug-spec nxml-with-invisible-motion t)
112
113 (defun nxml-display-file-parse-error (err)
114 (let* ((filename (nth 1 err))
115 (buffer (find-file-noselect filename))
116 (pos (nth 2 err))
117 (message (nth 3 err)))
118 (pop-to-buffer buffer)
119 ;; What's the right thing to do if the buffer's modified?
120 ;; The position in the saved file could be completely different.
121 (goto-char (if (buffer-modified-p) 1 pos))
122 (error "%s" message)))
123
124 (defun nxml-signal-file-parse-error (file pos message &optional error-symbol)
125 (signal (or error-symbol 'nxml-file-parse-error)
126 (list file pos message)))
127
128 (put 'nxml-file-parse-error
129 'error-conditions
130 '(error nxml-file-parse-error))
131
132 (put 'nxml-parse-file-error
133 'error-message
134 "Error parsing file")
135
136 (provide 'nxml-util)
137
138 ;; arch-tag: 7d3b3af4-de2b-4410-bf67-94d64824324b
139 ;;; nxml-util.el ends here