86361
|
1 ;;; nxml-outln.el --- outline support for nXML mode
|
|
2
|
86540
|
3 ;; Copyright (C) 2004, 2007 Free Software Foundation, Inc.
|
86361
|
4
|
|
5 ;; Author: James Clark
|
|
6 ;; Keywords: XML
|
|
7
|
86540
|
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, or (at your option)
|
|
13 ;; any later version.
|
86361
|
14
|
86540
|
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.
|
86361
|
19
|
86540
|
20 ;; You should have received a copy of the GNU General Public License
|
|
21 ;; along with GNU Emacs; see the file COPYING. If not, write to the
|
|
22 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
23 ;; Boston, MA 02110-1301, USA.
|
86361
|
24
|
|
25 ;;; Commentary:
|
|
26
|
|
27 ;; A section can be in one of three states
|
|
28 ;; 1. display normally; this displays each child section
|
|
29 ;; according to its state; anything not part of child sections is also
|
|
30 ;; displayed normally
|
|
31 ;; 2. display just the title specially; child sections are not displayed
|
|
32 ;; regardless of their state; anything not part of child sections is
|
|
33 ;; not displayed
|
|
34 ;; 3. display the title specially and display child sections
|
|
35 ;; according to their state; anything not part of the child section is
|
|
36 ;; not displayed
|
|
37 ;; The state of a section is determined by the value of the
|
|
38 ;; nxml-outline-state text property of the < character that starts
|
|
39 ;; the section.
|
|
40 ;; For state 1 the value is nil or absent.
|
|
41 ;; For state 2 it is the symbol hide-children.
|
|
42 ;; For state 3 it is t.
|
|
43 ;; The special display is achieved by using overlays. The overlays
|
|
44 ;; are computed from the nxml-outline-state property by
|
|
45 ;; `nxml-refresh-outline'. There overlays all have a category property
|
|
46 ;; with an nxml-outline-display property with value t.
|
|
47 ;;
|
|
48 ;; For a section to be recognized as such, the following conditions must
|
|
49 ;; be satisfied:
|
|
50 ;; - its start-tag must occur at the start of a line (possibly indented)
|
|
51 ;; - its local name must match `nxml-section-element-name-regexp'
|
|
52 ;; - it must have a heading element; a heading element is an
|
|
53 ;; element whose name matches `nxml-heading-element-name-regexp',
|
|
54 ;; and that occurs as, or as a descendant of, the first child element
|
|
55 ;; of the section
|
|
56 ;;
|
|
57 ;; XXX What happens if an nxml-outline-state property is attached to a
|
|
58 ;; character that doesn't start a section element?
|
|
59 ;;
|
|
60 ;; An outlined section (an section with a non-nil nxml-outline-state
|
|
61 ;; property) can be displayed in either single-line or multi-line
|
|
62 ;; form. Single-line form is used when the outline state is hide-children
|
|
63 ;; or there are no child sections; multi-line form is used otherwise.
|
|
64 ;; There are two flavors of single-line form: with children and without.
|
|
65 ;; The with-childen flavor is used when there are child sections.
|
|
66 ;; Single line with children looks like
|
|
67 ;; <+section>A section title...</>
|
|
68 ;; Single line without children looks like
|
|
69 ;; <-section>A section title...</>
|
|
70 ;; Multi line looks likes
|
|
71 ;; <-section>A section title...
|
|
72 ;; [child sections displayed here]
|
|
73 ;; </-section>
|
|
74 ;; The indent of an outlined section is computed relative to the
|
|
75 ;; outermost containing outlined element. The indent of the
|
|
76 ;; outermost containing element comes from the non-outlined
|
|
77 ;; indent of the section start-tag.
|
|
78
|
|
79 ;;; Code:
|
|
80
|
|
81 (require 'xmltok)
|
|
82 (require 'nxml-util)
|
|
83 (require 'nxml-rap)
|
|
84
|
|
85 (defcustom nxml-section-element-name-regexp
|
|
86 "article\\|\\(sub\\)*section\\|chapter\\|div\\|appendix\\|part\\|preface\\|reference\\|simplesect\\|bibliography\\|bibliodiv\\|glossary\\|glossdiv"
|
|
87 "*Regular expression matching the name of elements used as sections.
|
|
88 An XML element is treated as a section if:
|
|
89
|
|
90 - its local name (that is, the name without the prefix) matches
|
|
91 this regexp;
|
|
92
|
|
93 - either its first child element or a descendant of that first child
|
|
94 element has a local name matching the variable
|
|
95 `nxml-heading-element-name-regexp'; and
|
|
96
|
|
97 - its start-tag occurs at the beginning of a line (possibly indented)."
|
|
98 :group 'nxml
|
|
99 :type 'regexp)
|
|
100
|
|
101 (defcustom nxml-heading-element-name-regexp "title\\|head"
|
|
102 "*Regular expression matching the name of elements used as headings.
|
|
103 An XML element is only recognized as a heading if it occurs as or
|
|
104 within the first child of an element that is recognized as a section.
|
|
105 See the variable `nxml-section-element-name-regexp' for more details."
|
|
106 :group 'nxml
|
|
107 :type 'regexp)
|
|
108
|
|
109 (defcustom nxml-outline-child-indent 2
|
|
110 "*Indentation in an outline for child element relative to parent element."
|
|
111 :group 'nxml
|
|
112 :type 'integer)
|
|
113
|
|
114 (defface nxml-heading-face
|
|
115 '((t (:weight bold)))
|
|
116 "Face used for the contents of abbreviated heading elements."
|
|
117 :group 'nxml-highlighting-faces)
|
|
118
|
|
119 (defface nxml-outline-indicator-face
|
|
120 '((t (:inherit default)))
|
|
121 "Face used for `+' or `-' before element names in outlines."
|
|
122 :group 'nxml-highlighting-faces)
|
|
123
|
|
124 (defface nxml-outline-active-indicator-face
|
|
125 '((t (:box t :inherit nxml-outline-indicator-face)))
|
|
126 "Face used for clickable `+' or `-' before element names in outlines."
|
|
127 :group 'nxml-highlighting-faces)
|
|
128
|
|
129 (defface nxml-outline-ellipsis-face
|
|
130 '((t (:bold t :inherit default)))
|
|
131 "Face used for `...' in outlines."
|
|
132 :group 'nxml-highlighting-faces)
|
|
133
|
|
134 (defvar nxml-heading-scan-distance 1000
|
|
135 "Maximum distance from section to scan for heading.")
|
|
136
|
|
137 (defvar nxml-outline-prefix-map
|
|
138 (let ((map (make-sparse-keymap)))
|
|
139 (define-key map "\C-a" 'nxml-show-all)
|
|
140 (define-key map "\C-t" 'nxml-hide-all-text-content)
|
|
141 (define-key map "\C-r" 'nxml-refresh-outline)
|
|
142 (define-key map "\C-c" 'nxml-hide-direct-text-content)
|
|
143 (define-key map "\C-e" 'nxml-show-direct-text-content)
|
|
144 (define-key map "\C-d" 'nxml-hide-subheadings)
|
|
145 (define-key map "\C-s" 'nxml-show)
|
|
146 (define-key map "\C-k" 'nxml-show-subheadings)
|
|
147 (define-key map "\C-l" 'nxml-hide-text-content)
|
|
148 (define-key map "\C-i" 'nxml-show-direct-subheadings)
|
|
149 (define-key map "\C-o" 'nxml-hide-other)
|
|
150 map))
|
|
151
|
|
152 ;;; Commands for changing visibility
|
|
153
|
|
154 (defun nxml-show-all ()
|
|
155 "Show all elements in the buffer normally."
|
|
156 (interactive)
|
|
157 (nxml-with-unmodifying-text-property-changes
|
|
158 (remove-text-properties (point-min)
|
|
159 (point-max)
|
|
160 '(nxml-outline-state nil)))
|
|
161 (nxml-outline-set-overlay nil (point-min) (point-max)))
|
|
162
|
|
163 (defun nxml-hide-all-text-content ()
|
|
164 "Hide all text content in the buffer.
|
|
165 Anything that is in a section but is not a heading will be hidden.
|
|
166 The visibility of headings at any level will not be changed. See the
|
|
167 variable `nxml-section-element-name-regexp' for more details on how to
|
|
168 customize which elements are recognized as sections and headings."
|
|
169 (interactive)
|
|
170 (nxml-transform-buffer-outline '((nil . t))))
|
|
171
|
|
172 (defun nxml-show-direct-text-content ()
|
|
173 "Show the text content that is directly part of the section containing point.
|
|
174 Each subsection will be shown according to its individual state, which
|
|
175 will not be changed. The section containing point is the innermost
|
|
176 section that contains the character following point. See the variable
|
|
177 `nxml-section-element-name-regexp' for more details on how to
|
|
178 customize which elements are recognized as sections and headings."
|
|
179 (interactive)
|
|
180 (nxml-outline-pre-adjust-point)
|
|
181 (nxml-set-outline-state (nxml-section-start-position) nil)
|
|
182 (nxml-refresh-outline)
|
|
183 (nxml-outline-adjust-point))
|
|
184
|
|
185 (defun nxml-show-direct-subheadings ()
|
|
186 "Show the immediate subheadings of the section containing point.
|
|
187 The section containing point is the innermost section that contains
|
|
188 the character following point. See the variable
|
|
189 `nxml-section-element-name-regexp' for more details on how to
|
|
190 customize which elements are recognized as sections and headings."
|
|
191 (interactive)
|
|
192 (let ((pos (nxml-section-start-position)))
|
|
193 (when (eq (nxml-get-outline-state pos) 'hide-children)
|
|
194 (nxml-set-outline-state pos t)))
|
|
195 (nxml-refresh-outline)
|
|
196 (nxml-outline-adjust-point))
|
|
197
|
|
198 (defun nxml-hide-direct-text-content ()
|
|
199 "Hide the text content that is directly part of the section containing point.
|
|
200 The heading of the section will remain visible. The state of
|
|
201 subsections will not be changed. The section containing point is the
|
|
202 innermost section that contains the character following point. See the
|
|
203 variable `nxml-section-element-name-regexp' for more details on how to
|
|
204 customize which elements are recognized as sections and headings."
|
|
205 (interactive)
|
|
206 (let ((pos (nxml-section-start-position)))
|
|
207 (when (null (nxml-get-outline-state pos))
|
|
208 (nxml-set-outline-state pos t)))
|
|
209 (nxml-refresh-outline)
|
|
210 (nxml-outline-adjust-point))
|
|
211
|
|
212 (defun nxml-hide-subheadings ()
|
|
213 "Hide the subheadings that are part of the section containing point.
|
|
214 The text content will also be hidden, leaving only the heading of the
|
|
215 section itself visible. The state of the subsections will also be
|
|
216 changed to hide their headings, so that \\[nxml-show-direct-text-content]
|
|
217 would show only the heading of the subsections. The section containing
|
|
218 point is the innermost section that contains the character following
|
|
219 point. See the variable `nxml-section-element-name-regexp' for more
|
|
220 details on how to customize which elements are recognized as sections
|
|
221 and headings."
|
|
222 (interactive)
|
|
223 (nxml-transform-subtree-outline '((nil . hide-children)
|
|
224 (t . hide-children))))
|
|
225
|
|
226 (defun nxml-show ()
|
|
227 "Show the section containing point normally, without hiding anything.
|
|
228 This includes everything in the section at any level. The section
|
|
229 containing point is the innermost section that contains the character
|
|
230 following point. See the variable `nxml-section-element-name-regexp'
|
|
231 for more details on how to customize which elements are recognized as
|
|
232 sections and headings."
|
|
233 (interactive)
|
|
234 (nxml-transform-subtree-outline '((hide-children . nil)
|
|
235 (t . nil))))
|
|
236
|
|
237 (defun nxml-hide-text-content ()
|
|
238 "Hide text content at all levels in the section containing point.
|
|
239 The section containing point is the innermost section that contains
|
|
240 the character following point. See the variable
|
|
241 `nxml-section-element-name-regexp' for more details on how to
|
|
242 customize which elements are recognized as sections and headings."
|
|
243 (interactive)
|
|
244 (nxml-transform-subtree-outline '((nil . t))))
|
|
245
|
|
246 (defun nxml-show-subheadings ()
|
|
247 "Show the subheadings at all levels of the section containing point.
|
|
248 The visibility of the text content at all levels in the section is not
|
|
249 changed. The section containing point is the innermost section that
|
|
250 contains the character following point. See the variable
|
|
251 `nxml-section-element-name-regexp' for more details on how to
|
|
252 customize which elements are recognized as sections and headings."
|
|
253 (interactive)
|
|
254 (nxml-transform-subtree-outline '((hide-children . t))))
|
|
255
|
|
256 (defun nxml-hide-other ()
|
|
257 "Hide text content other than that directly in the section containing point.
|
|
258 Hide headings other than those of ancestors of that section and their
|
|
259 immediate subheadings. The section containing point is the innermost
|
|
260 section that contains the character following point. See the variable
|
|
261 `nxml-section-element-name-regexp' for more details on how to
|
|
262 customize which elements are recognized as sections and headings."
|
|
263 (interactive)
|
|
264 (let ((nxml-outline-state-transform-exceptions nil))
|
|
265 (save-excursion
|
|
266 (while (and (condition-case err
|
|
267 (nxml-back-to-section-start)
|
|
268 (nxml-outline-error (nxml-report-outline-error
|
|
269 "Couldn't find containing section: %s"
|
|
270 err)))
|
|
271 (progn
|
|
272 (when (and nxml-outline-state-transform-exceptions
|
|
273 (null (nxml-get-outline-state (point))))
|
|
274 (nxml-set-outline-state (point) t))
|
|
275 (setq nxml-outline-state-transform-exceptions
|
|
276 (cons (point)
|
|
277 nxml-outline-state-transform-exceptions))
|
|
278 (< nxml-prolog-end (point))))
|
|
279 (goto-char (1- (point)))))
|
|
280 (nxml-transform-buffer-outline '((nil . hide-children)
|
|
281 (t . hide-children)))))
|
|
282
|
|
283 ;; These variables are dynamically bound. They are use to pass information to
|
|
284 ;; nxml-section-tag-transform-outline-state.
|
|
285
|
|
286 (defvar nxml-outline-state-transform-exceptions nil)
|
|
287 (defvar nxml-target-section-pos nil)
|
|
288 (defvar nxml-depth-in-target-section nil)
|
|
289 (defvar nxml-outline-state-transform-alist nil)
|
|
290
|
|
291 (defun nxml-transform-buffer-outline (alist)
|
|
292 (let ((nxml-target-section-pos nil)
|
|
293 (nxml-depth-in-target-section 0)
|
|
294 (nxml-outline-state-transform-alist alist)
|
|
295 (nxml-outline-display-section-tag-function
|
|
296 'nxml-section-tag-transform-outline-state))
|
|
297 (nxml-refresh-outline))
|
|
298 (nxml-outline-adjust-point))
|
|
299
|
|
300 (defun nxml-transform-subtree-outline (alist)
|
|
301 (let ((nxml-target-section-pos (nxml-section-start-position))
|
|
302 (nxml-depth-in-target-section nil)
|
|
303 (nxml-outline-state-transform-alist alist)
|
|
304 (nxml-outline-display-section-tag-function
|
|
305 'nxml-section-tag-transform-outline-state))
|
|
306 (nxml-refresh-outline))
|
|
307 (nxml-outline-adjust-point))
|
|
308
|
|
309 (defun nxml-outline-pre-adjust-point ()
|
|
310 (cond ((and (< (point-min) (point))
|
|
311 (get-char-property (1- (point)) 'invisible)
|
|
312 (not (get-char-property (point) 'invisible))
|
|
313 (let ((str (or (get-char-property (point) 'before-string)
|
|
314 (get-char-property (point) 'display))))
|
|
315 (and (stringp str)
|
|
316 (>= (length str) 3)
|
|
317 (string= (substring str 0 3) "..."))))
|
|
318 ;; The ellipsis is a display property on a visible character
|
|
319 ;; following an invisible region. The position of the event
|
|
320 ;; will be the position before that character. We want to
|
|
321 ;; move point to the other side of the invisible region, i.e.
|
|
322 ;; following the last visible character before that invisible
|
|
323 ;; region.
|
|
324 (goto-char (previous-single-char-property-change (1- (point))
|
|
325 'invisible)))
|
|
326 ((and (< (point) (point-max))
|
|
327 (get-char-property (point) 'display)
|
|
328 (get-char-property (1+ (point)) 'invisible))
|
|
329 (goto-char (next-single-char-property-change (1+ (point))
|
|
330 'invisible)))
|
|
331 ((and (< (point) (point-max))
|
|
332 (get-char-property (point) 'invisible))
|
|
333 (goto-char (next-single-char-property-change (point)
|
|
334 'invisible)))))
|
|
335
|
|
336 (defun nxml-outline-adjust-point ()
|
|
337 "Adjust point after showing or hiding elements."
|
|
338 (when (and (get-char-property (point) 'invisible)
|
|
339 (< (point-min) (point))
|
|
340 (get-char-property (1- (point)) 'invisible))
|
|
341 (goto-char (previous-single-char-property-change (point)
|
|
342 'invisible
|
|
343 nil
|
|
344 nxml-prolog-end))))
|
|
345
|
|
346 (defun nxml-transform-outline-state (section-start-pos)
|
|
347 (let* ((old-state
|
|
348 (nxml-get-outline-state section-start-pos))
|
|
349 (change (assq old-state
|
|
350 nxml-outline-state-transform-alist)))
|
|
351 (when change
|
|
352 (nxml-set-outline-state section-start-pos
|
|
353 (cdr change)))))
|
|
354
|
|
355 (defun nxml-section-tag-transform-outline-state (startp
|
|
356 section-start-pos
|
|
357 &optional
|
|
358 heading-start-pos)
|
|
359 (if (not startp)
|
|
360 (setq nxml-depth-in-target-section
|
|
361 (and nxml-depth-in-target-section
|
|
362 (> nxml-depth-in-target-section 0)
|
|
363 (1- nxml-depth-in-target-section)))
|
|
364 (cond (nxml-depth-in-target-section
|
|
365 (setq nxml-depth-in-target-section
|
|
366 (1+ nxml-depth-in-target-section)))
|
|
367 ((= section-start-pos nxml-target-section-pos)
|
|
368 (setq nxml-depth-in-target-section 0)))
|
|
369 (when (and nxml-depth-in-target-section
|
|
370 (not (member section-start-pos
|
|
371 nxml-outline-state-transform-exceptions)))
|
|
372 (nxml-transform-outline-state section-start-pos))))
|
|
373
|
|
374 (defun nxml-get-outline-state (pos)
|
|
375 (get-text-property pos 'nxml-outline-state))
|
|
376
|
|
377 (defun nxml-set-outline-state (pos state)
|
|
378 (nxml-with-unmodifying-text-property-changes
|
|
379 (if state
|
|
380 (put-text-property pos (1+ pos) 'nxml-outline-state state)
|
|
381 (remove-text-properties pos (1+ pos) '(nxml-outline-state nil)))))
|
|
382
|
|
383 ;;; Mouse interface
|
|
384
|
|
385 (defun nxml-mouse-show-direct-text-content (event)
|
|
386 "Do the same as \\[nxml-show-direct-text-content] from a mouse click."
|
|
387 (interactive "e")
|
|
388 (and (nxml-mouse-set-point event)
|
|
389 (nxml-show-direct-text-content)))
|
|
390
|
|
391 (defun nxml-mouse-hide-direct-text-content (event)
|
|
392 "Do the same as \\[nxml-hide-direct-text-content] from a mouse click."
|
|
393 (interactive "e")
|
|
394 (and (nxml-mouse-set-point event)
|
|
395 (nxml-hide-direct-text-content)))
|
|
396
|
|
397 (defun nxml-mouse-hide-subheadings (event)
|
|
398 "Do the same as \\[nxml-hide-subheadings] from a mouse click."
|
|
399 (interactive "e")
|
|
400 (and (nxml-mouse-set-point event)
|
|
401 (nxml-hide-subheadings)))
|
|
402
|
|
403 (defun nxml-mouse-show-direct-subheadings (event)
|
|
404 "Do the same as \\[nxml-show-direct-subheadings] from a mouse click."
|
|
405 (interactive "e")
|
|
406 (and (nxml-mouse-set-point event)
|
|
407 (nxml-show-direct-subheadings)))
|
|
408
|
|
409 (defun nxml-mouse-set-point (event)
|
|
410 (mouse-set-point event)
|
|
411 (and nxml-prolog-end t))
|
|
412
|
|
413 ;; Display
|
|
414
|
86540
|
415 (defsubst nxml-token-start-tag-p ()
|
|
416 (or (eq xmltok-type 'start-tag)
|
|
417 (eq xmltok-type 'partial-start-tag)))
|
|
418
|
|
419 (defsubst nxml-token-end-tag-p ()
|
|
420 (or (eq xmltok-type 'end-tag)
|
|
421 (eq xmltok-type 'partial-end-tag)))
|
|
422
|
86361
|
423 (defun nxml-refresh-outline ()
|
|
424 "Refresh the outline to correspond to the current XML element structure."
|
|
425 (interactive)
|
|
426 (save-excursion
|
|
427 (goto-char (point-min))
|
|
428 (kill-local-variable 'line-move-ignore-invisible)
|
|
429 (make-local-variable 'line-move-ignore-invisible)
|
|
430 (condition-case err
|
|
431 (nxml-outline-display-rest nil nil nil)
|
|
432 (nxml-outline-error
|
|
433 (nxml-report-outline-error "Cannot display outline: %s" err)))))
|
|
434
|
|
435 (defvar nxml-outline-display-section-tag-function nil)
|
|
436
|
|
437 (defun nxml-outline-display-rest (outline-state start-tag-indent tag-qnames)
|
|
438 "Display up to and including the end of the current element.
|
|
439 OUTLINE-STATE can be nil, t, hide-children. START-TAG-INDENT is the
|
|
440 indent of the start-tag of the current element, or nil if no
|
|
441 containing element has a non-nil OUTLINE-STATE. TAG-QNAMES is a list
|
|
442 of the qnames of the open elements. Point is after the title content.
|
|
443 Leave point after the closing end-tag Return t if we had a
|
|
444 non-transparent child section."
|
|
445 (let ((last-pos (point))
|
|
446 (transparent-depth 0)
|
|
447 ;; don't want ellipsis before root element
|
|
448 (had-children (not tag-qnames)))
|
|
449 (while
|
|
450 (cond ((not (nxml-section-tag-forward))
|
|
451 (if (null tag-qnames)
|
|
452 nil
|
|
453 (nxml-outline-error "missing end-tag %s"
|
|
454 (car tag-qnames))))
|
|
455 ;; section end-tag
|
|
456 ((nxml-token-end-tag-p)
|
|
457 (when nxml-outline-display-section-tag-function
|
|
458 (funcall nxml-outline-display-section-tag-function
|
|
459 nil
|
|
460 xmltok-start))
|
|
461 (let ((qname (xmltok-end-tag-qname)))
|
|
462 (unless tag-qnames
|
|
463 (nxml-outline-error "extra end-tag %s" qname))
|
|
464 (unless (string= (car tag-qnames) qname)
|
|
465 (nxml-outline-error "mismatched end-tag; expected %s, got %s"
|
|
466 (car tag-qnames)
|
|
467 qname)))
|
|
468 (cond ((> transparent-depth 0)
|
|
469 (setq transparent-depth (1- transparent-depth))
|
|
470 (setq tag-qnames (cdr tag-qnames))
|
|
471 t)
|
|
472 ((not outline-state)
|
|
473 (nxml-outline-set-overlay nil last-pos (point))
|
|
474 nil)
|
|
475 ((or (not had-children)
|
|
476 (eq outline-state 'hide-children))
|
|
477 (nxml-outline-display-single-line-end-tag last-pos)
|
|
478 nil)
|
|
479 (t
|
|
480 (nxml-outline-display-multi-line-end-tag last-pos
|
|
481 start-tag-indent)
|
|
482 nil)))
|
|
483 ;; section start-tag
|
|
484 (t
|
|
485 (let* ((qname (xmltok-start-tag-qname))
|
|
486 (section-start-pos xmltok-start)
|
|
487 (heading-start-pos
|
|
488 (and (or nxml-outline-display-section-tag-function
|
|
489 (not (eq outline-state 'had-children))
|
|
490 (not had-children))
|
|
491 (nxml-token-starts-line-p)
|
|
492 (nxml-heading-start-position))))
|
|
493 (when nxml-outline-display-section-tag-function
|
|
494 (funcall nxml-outline-display-section-tag-function
|
|
495 t
|
|
496 section-start-pos
|
|
497 heading-start-pos))
|
|
498 (setq tag-qnames (cons qname tag-qnames))
|
|
499 (if (or (not heading-start-pos)
|
|
500 (and (eq outline-state 'hide-children)
|
|
501 (setq had-children t)))
|
|
502 (setq transparent-depth (1+ transparent-depth))
|
|
503 (nxml-display-section last-pos
|
|
504 section-start-pos
|
|
505 heading-start-pos
|
|
506 start-tag-indent
|
|
507 outline-state
|
|
508 had-children
|
|
509 tag-qnames)
|
|
510 (setq had-children t)
|
|
511 (setq tag-qnames (cdr tag-qnames))
|
|
512 (setq last-pos (point))))
|
|
513 t)))
|
|
514 had-children))
|
|
515
|
|
516 (defconst nxml-highlighted-less-than
|
|
517 (propertize "<" 'face 'nxml-tag-delimiter-face))
|
|
518
|
|
519 (defconst nxml-highlighted-greater-than
|
|
520 (propertize ">" 'face 'nxml-tag-delimiter-face))
|
|
521
|
|
522 (defconst nxml-highlighted-colon
|
|
523 (propertize ":" 'face 'nxml-element-colon-face))
|
|
524
|
|
525 (defconst nxml-highlighted-slash
|
|
526 (propertize "/" 'face 'nxml-tag-slash-face))
|
|
527
|
|
528 (defconst nxml-highlighted-ellipsis
|
|
529 (propertize "..." 'face 'nxml-outline-ellipsis-face))
|
|
530
|
|
531 (defconst nxml-highlighted-empty-end-tag
|
|
532 (concat nxml-highlighted-ellipsis
|
|
533 nxml-highlighted-less-than
|
|
534 nxml-highlighted-slash
|
|
535 nxml-highlighted-greater-than))
|
|
536
|
|
537 (defconst nxml-highlighted-inactive-minus
|
|
538 (propertize "-" 'face 'nxml-outline-indicator-face))
|
|
539
|
|
540 (defconst nxml-highlighted-active-minus
|
|
541 (propertize "-" 'face 'nxml-outline-active-indicator-face))
|
|
542
|
|
543 (defconst nxml-highlighted-active-plus
|
|
544 (propertize "+" 'face 'nxml-outline-active-indicator-face))
|
|
545
|
|
546 (defun nxml-display-section (last-pos
|
|
547 section-start-pos
|
|
548 heading-start-pos
|
|
549 parent-indent
|
|
550 parent-outline-state
|
|
551 had-children
|
|
552 tag-qnames)
|
|
553 (let* ((section-start-pos-bol
|
|
554 (save-excursion
|
|
555 (goto-char section-start-pos)
|
|
556 (skip-chars-backward " \t")
|
|
557 (point)))
|
|
558 (outline-state (nxml-get-outline-state section-start-pos))
|
|
559 (newline-before-section-start-category
|
|
560 (cond ((and (not had-children) parent-outline-state)
|
|
561 'nxml-outline-display-ellipsis)
|
|
562 (outline-state 'nxml-outline-display-show)
|
|
563 (t nil))))
|
|
564 (nxml-outline-set-overlay (and parent-outline-state
|
|
565 'nxml-outline-display-hide)
|
|
566 last-pos
|
|
567 (1- section-start-pos-bol)
|
|
568 nil
|
|
569 t)
|
|
570 (if outline-state
|
|
571 (let* ((indent (if parent-indent
|
|
572 (+ parent-indent nxml-outline-child-indent)
|
|
573 (save-excursion
|
|
574 (goto-char section-start-pos)
|
|
575 (current-column))))
|
|
576 start-tag-overlay)
|
|
577 (nxml-outline-set-overlay newline-before-section-start-category
|
|
578 (1- section-start-pos-bol)
|
|
579 section-start-pos-bol
|
|
580 t)
|
|
581 (nxml-outline-set-overlay 'nxml-outline-display-hide
|
|
582 section-start-pos-bol
|
|
583 section-start-pos)
|
|
584 (setq start-tag-overlay
|
|
585 (nxml-outline-set-overlay 'nxml-outline-display-show
|
|
586 section-start-pos
|
|
587 (1+ section-start-pos)
|
|
588 t))
|
|
589 ;; line motion commands don't work right if start-tag-overlay
|
|
590 ;; covers multiple lines
|
|
591 (nxml-outline-set-overlay 'nxml-outline-display-hide
|
|
592 (1+ section-start-pos)
|
|
593 heading-start-pos)
|
|
594 (goto-char heading-start-pos)
|
|
595 (nxml-end-of-heading)
|
|
596 (nxml-outline-set-overlay 'nxml-outline-display-heading
|
|
597 heading-start-pos
|
|
598 (point))
|
|
599 (let* ((had-children
|
|
600 (nxml-outline-display-rest outline-state
|
|
601 indent
|
|
602 tag-qnames)))
|
|
603 (overlay-put start-tag-overlay
|
|
604 'display
|
|
605 (concat
|
|
606 ;; indent
|
|
607 (make-string indent ?\ )
|
|
608 ;; <
|
|
609 nxml-highlighted-less-than
|
|
610 ;; + or - indicator
|
|
611 (cond ((not had-children)
|
|
612 nxml-highlighted-inactive-minus)
|
|
613 ((eq outline-state 'hide-children)
|
|
614 (overlay-put start-tag-overlay
|
|
615 'category
|
|
616 'nxml-outline-display-hiding-tag)
|
|
617 nxml-highlighted-active-plus)
|
|
618 (t
|
|
619 (overlay-put start-tag-overlay
|
|
620 'category
|
|
621 'nxml-outline-display-showing-tag)
|
|
622 nxml-highlighted-active-minus))
|
|
623 ;; qname
|
|
624 (nxml-highlighted-qname (car tag-qnames))
|
|
625 ;; >
|
|
626 nxml-highlighted-greater-than))))
|
|
627 ;; outline-state nil
|
|
628 (goto-char heading-start-pos)
|
|
629 (nxml-end-of-heading)
|
|
630 (nxml-outline-set-overlay newline-before-section-start-category
|
|
631 (1- section-start-pos-bol)
|
|
632 (point)
|
|
633 t)
|
|
634 (nxml-outline-display-rest outline-state
|
|
635 (and parent-indent
|
|
636 (+ parent-indent
|
|
637 nxml-outline-child-indent))
|
|
638 tag-qnames))))
|
|
639
|
|
640 (defun nxml-highlighted-qname (qname)
|
|
641 (let ((colon (string-match ":" qname)))
|
|
642 (if colon
|
|
643 (concat (propertize (substring qname 0 colon)
|
|
644 'face
|
|
645 'nxml-element-prefix-face)
|
|
646 nxml-highlighted-colon
|
|
647 (propertize (substring qname (1+ colon))
|
|
648 'face
|
|
649 'nxml-element-local-name-face))
|
|
650 (propertize qname
|
|
651 'face
|
|
652 'nxml-element-local-name-face))))
|
|
653
|
|
654 (defun nxml-outline-display-single-line-end-tag (last-pos)
|
|
655 (nxml-outline-set-overlay 'nxml-outline-display-hide
|
|
656 last-pos
|
|
657 xmltok-start
|
|
658 nil
|
|
659 t)
|
|
660 (overlay-put (nxml-outline-set-overlay 'nxml-outline-display-show
|
|
661 xmltok-start
|
|
662 (point)
|
|
663 t)
|
|
664 'display
|
|
665 nxml-highlighted-empty-end-tag))
|
|
666
|
|
667 (defun nxml-outline-display-multi-line-end-tag (last-pos start-tag-indent)
|
|
668 (let ((indentp (save-excursion
|
|
669 (goto-char last-pos)
|
|
670 (skip-chars-forward " \t")
|
|
671 (and (eq (char-after) ?\n)
|
|
672 (progn
|
|
673 (goto-char (1+ (point)))
|
|
674 (nxml-outline-set-overlay nil last-pos (point))
|
|
675 (setq last-pos (point))
|
|
676 (goto-char xmltok-start)
|
|
677 (beginning-of-line)
|
|
678 t))))
|
|
679 end-tag-overlay)
|
|
680 (nxml-outline-set-overlay 'nxml-outline-display-hide
|
|
681 last-pos
|
|
682 xmltok-start
|
|
683 nil
|
|
684 t)
|
|
685 (setq end-tag-overlay
|
|
686 (nxml-outline-set-overlay 'nxml-outline-display-showing-tag
|
|
687 xmltok-start
|
|
688 (point)
|
|
689 t))
|
|
690 (overlay-put end-tag-overlay
|
|
691 'display
|
|
692 (concat (if indentp
|
|
693 (make-string start-tag-indent ?\ )
|
|
694 "")
|
|
695 nxml-highlighted-less-than
|
|
696 nxml-highlighted-slash
|
|
697 nxml-highlighted-active-minus
|
|
698 (nxml-highlighted-qname (xmltok-end-tag-qname))
|
|
699 nxml-highlighted-greater-than))))
|
|
700
|
|
701 (defvar nxml-outline-show-map
|
|
702 (let ((map (make-sparse-keymap)))
|
|
703 (define-key map "\C-m" 'nxml-show-direct-text-content)
|
|
704 (define-key map [mouse-2] 'nxml-mouse-show-direct-text-content)
|
|
705 map))
|
|
706
|
|
707 (defvar nxml-outline-show-help "mouse-2: show")
|
|
708
|
|
709 (put 'nxml-outline-display-show 'nxml-outline-display t)
|
|
710 (put 'nxml-outline-display-show 'evaporate t)
|
|
711 (put 'nxml-outline-display-show 'keymap nxml-outline-show-map)
|
|
712 (put 'nxml-outline-display-show 'help-echo nxml-outline-show-help)
|
|
713
|
|
714 (put 'nxml-outline-display-hide 'nxml-outline-display t)
|
|
715 (put 'nxml-outline-display-hide 'evaporate t)
|
|
716 (put 'nxml-outline-display-hide 'invisible t)
|
|
717 (put 'nxml-outline-display-hide 'keymap nxml-outline-show-map)
|
|
718 (put 'nxml-outline-display-hide 'help-echo nxml-outline-show-help)
|
|
719
|
|
720 (put 'nxml-outline-display-ellipsis 'nxml-outline-display t)
|
|
721 (put 'nxml-outline-display-ellipsis 'evaporate t)
|
|
722 (put 'nxml-outline-display-ellipsis 'keymap nxml-outline-show-map)
|
|
723 (put 'nxml-outline-display-ellipsis 'help-echo nxml-outline-show-help)
|
|
724 (put 'nxml-outline-display-ellipsis 'before-string nxml-highlighted-ellipsis)
|
|
725
|
|
726 (put 'nxml-outline-display-heading 'keymap nxml-outline-show-map)
|
|
727 (put 'nxml-outline-display-heading 'help-echo nxml-outline-show-help)
|
|
728 (put 'nxml-outline-display-heading 'nxml-outline-display t)
|
|
729 (put 'nxml-outline-display-heading 'evaporate t)
|
|
730 (put 'nxml-outline-display-heading 'face 'nxml-heading-face)
|
|
731
|
|
732 (defvar nxml-outline-hiding-tag-map
|
|
733 (let ((map (make-sparse-keymap)))
|
|
734 (define-key map [mouse-1] 'nxml-mouse-show-direct-subheadings)
|
|
735 (define-key map [mouse-2] 'nxml-mouse-show-direct-text-content)
|
|
736 (define-key map "\C-m" 'nxml-show-direct-text-content)
|
|
737 map))
|
|
738
|
|
739 (defvar nxml-outline-hiding-tag-help
|
|
740 "mouse-1: show subheadings, mouse-2: show text content")
|
|
741
|
|
742 (put 'nxml-outline-display-hiding-tag 'nxml-outline-display t)
|
|
743 (put 'nxml-outline-display-hiding-tag 'evaporate t)
|
|
744 (put 'nxml-outline-display-hiding-tag 'keymap nxml-outline-hiding-tag-map)
|
|
745 (put 'nxml-outline-display-hiding-tag 'help-echo nxml-outline-hiding-tag-help)
|
|
746
|
|
747 (defvar nxml-outline-showing-tag-map
|
|
748 (let ((map (make-sparse-keymap)))
|
|
749 (define-key map [mouse-1] 'nxml-mouse-hide-subheadings)
|
|
750 (define-key map [mouse-2] 'nxml-mouse-show-direct-text-content)
|
|
751 (define-key map "\C-m" 'nxml-show-direct-text-content)
|
|
752 map))
|
|
753
|
|
754 (defvar nxml-outline-showing-tag-help
|
|
755 "mouse-1: hide subheadings, mouse-2: show text content")
|
|
756
|
|
757 (put 'nxml-outline-display-showing-tag 'nxml-outline-display t)
|
|
758 (put 'nxml-outline-display-showing-tag 'evaporate t)
|
|
759 (put 'nxml-outline-display-showing-tag 'keymap nxml-outline-showing-tag-map)
|
|
760 (put 'nxml-outline-display-showing-tag
|
|
761 'help-echo
|
|
762 nxml-outline-showing-tag-help)
|
|
763
|
|
764 (defun nxml-outline-set-overlay (category
|
|
765 start
|
|
766 end
|
|
767 &optional
|
|
768 front-advance
|
|
769 rear-advance)
|
|
770 "Replace any nxml-outline-display overlays between START and END.
|
|
771 Overlays are removed if they overlay the region between START and END,
|
|
772 and have a non-nil nxml-outline-display property (typically via their
|
|
773 category). If CATEGORY is non-nil, they will be replaced with a new overlay
|
|
774 with that category from START to END. If CATEGORY is nil, no new
|
|
775 overlay will be created."
|
|
776 (when (< start end)
|
|
777 (let ((overlays (overlays-in start end))
|
|
778 overlay)
|
|
779 (while overlays
|
|
780 (setq overlay (car overlays))
|
|
781 (setq overlays (cdr overlays))
|
|
782 (when (overlay-get overlay 'nxml-outline-display)
|
|
783 (delete-overlay overlay))))
|
|
784 (and category
|
|
785 (let ((overlay (make-overlay start
|
|
786 end
|
|
787 nil
|
|
788 front-advance
|
|
789 rear-advance)))
|
|
790 (overlay-put overlay 'category category)
|
|
791 (setq line-move-ignore-invisible t)
|
|
792 overlay))))
|
|
793
|
|
794 (defun nxml-end-of-heading ()
|
|
795 "Move from the start of the content of the heading to the end.
|
|
796 Do not move past the end of the line."
|
|
797 (let ((pos (condition-case err
|
|
798 (and (nxml-scan-element-forward (point) t)
|
|
799 xmltok-start)
|
|
800 nil)))
|
|
801 (end-of-line)
|
|
802 (skip-chars-backward " \t")
|
|
803 (cond ((not pos)
|
|
804 (setq pos (nxml-token-before))
|
|
805 (when (eq xmltok-type 'end-tag)
|
|
806 (goto-char pos)))
|
|
807 ((< pos (point))
|
|
808 (goto-char pos)))
|
|
809 (skip-chars-backward " \t")
|
|
810 (point)))
|
|
811
|
|
812 ;;; Navigating section structure
|
|
813
|
|
814 (defun nxml-token-starts-line-p ()
|
|
815 (save-excursion
|
|
816 (goto-char xmltok-start)
|
|
817 (skip-chars-backward " \t")
|
|
818 (bolp)))
|
|
819
|
|
820 (defvar nxml-cached-section-tag-regexp nil)
|
|
821 (defvar nxml-cached-section-element-name-regexp nil)
|
|
822
|
|
823 (defsubst nxml-make-section-tag-regexp ()
|
|
824 (if (eq nxml-cached-section-element-name-regexp
|
|
825 nxml-section-element-name-regexp)
|
|
826 nxml-cached-section-tag-regexp
|
|
827 (nxml-make-section-tag-regexp-1)))
|
|
828
|
|
829 (defun nxml-make-section-tag-regexp-1 ()
|
|
830 (setq nxml-cached-section-element-name-regexp nil)
|
|
831 (setq nxml-cached-section-tag-regexp
|
|
832 (concat "</?\\("
|
|
833 "\\(" xmltok-ncname-regexp ":\\)?"
|
|
834 nxml-section-element-name-regexp
|
|
835 "\\)[ \t\r\n>]"))
|
|
836 (setq nxml-cached-section-element-name-regexp
|
|
837 nxml-section-element-name-regexp)
|
|
838 nxml-cached-section-tag-regexp)
|
|
839
|
|
840 (defun nxml-section-tag-forward ()
|
|
841 "Move forward past the first tag that is a section start- or end-tag.
|
|
842 Return xmltok-type for tag.
|
|
843 If no tag found, return nil and move to the end of the buffer."
|
|
844 (let ((case-fold-search nil)
|
|
845 (tag-regexp (nxml-make-section-tag-regexp))
|
|
846 match-end)
|
|
847 (when (< (point) nxml-prolog-end)
|
|
848 (goto-char nxml-prolog-end))
|
|
849 (while (cond ((not (re-search-forward tag-regexp nil 'move))
|
|
850 (setq xmltok-type nil)
|
|
851 nil)
|
|
852 ((progn
|
|
853 (goto-char (match-beginning 0))
|
|
854 (setq match-end (match-end 0))
|
|
855 (nxml-ensure-scan-up-to-date)
|
|
856 (let ((end (nxml-inside-end (point))))
|
|
857 (when end
|
|
858 (goto-char end)
|
|
859 t))))
|
|
860 ((progn
|
|
861 (xmltok-forward)
|
|
862 (and (memq xmltok-type '(start-tag
|
|
863 partial-start-tag
|
|
864 end-tag
|
|
865 partial-end-tag))
|
|
866 ;; just in case wildcard matched non-name chars
|
|
867 (= xmltok-name-end (1- match-end))))
|
|
868 nil)
|
|
869 (t))))
|
|
870 xmltok-type)
|
|
871
|
|
872 (defun nxml-section-tag-backward ()
|
|
873 "Move backward to the end of a tag that is a section start- or end-tag.
|
|
874 The position of the end of the tag must be <= point
|
|
875 Point is at the end of the tag. `xmltok-start' is the start."
|
|
876 (let ((case-fold-search nil)
|
|
877 (start (point))
|
|
878 (tag-regexp (nxml-make-section-tag-regexp))
|
|
879 match-end)
|
|
880 (if (< (point) nxml-prolog-end)
|
|
881 (progn
|
|
882 (goto-char (point-min))
|
|
883 nil)
|
|
884 (while (cond ((not (re-search-backward tag-regexp
|
|
885 nxml-prolog-end
|
|
886 'move))
|
|
887 (setq xmltok-type nil)
|
|
888 (goto-char (point-min))
|
|
889 nil)
|
|
890 ((progn
|
|
891 (goto-char (match-beginning 0))
|
|
892 (setq match-end (match-end 0))
|
|
893 (nxml-ensure-scan-up-to-date)
|
|
894 (let ((pos (nxml-inside-start (point))))
|
|
895 (when pos
|
|
896 (goto-char (1- pos))
|
|
897 t))))
|
|
898 ((progn
|
|
899 (xmltok-forward)
|
|
900 (and (<= (point) start)
|
|
901 (memq xmltok-type '(start-tag
|
|
902 partial-start-tag
|
|
903 end-tag
|
|
904 partial-end-tag))
|
|
905 ;; just in case wildcard matched non-name chars
|
|
906 (= xmltok-name-end (1- match-end))))
|
|
907 nil)
|
|
908 (t (goto-char xmltok-start)
|
|
909 t)))
|
|
910 xmltok-type)))
|
|
911
|
|
912 (defun nxml-section-start-position ()
|
|
913 "Return the position of the start of the section containing point.
|
|
914 Signal an error on failure."
|
|
915 (condition-case err
|
|
916 (save-excursion (if (nxml-back-to-section-start)
|
|
917 (point)
|
|
918 (error "Not in section")))
|
|
919 (nxml-outline-error
|
|
920 (nxml-report-outline-error "Couldn't determine containing section: %s"
|
|
921 err))))
|
|
922
|
|
923 (defun nxml-back-to-section-start (&optional invisible-ok)
|
|
924 "Try to move back to the start of the section containing point.
|
|
925 The start of the section must be <= point.
|
|
926 Only visible sections are included unless INVISIBLE-OK is non-nil.
|
|
927 If found, return t. Otherwise move to point-min and return nil.
|
|
928 If unbalanced section tags are found, signal an `nxml-outline-error'."
|
|
929 (when (or (nxml-after-section-start-tag)
|
|
930 (nxml-section-tag-backward))
|
|
931 (let (open-tags found)
|
|
932 (while (let (section-start-pos)
|
|
933 (setq section-start-pos xmltok-start)
|
|
934 (if (nxml-token-end-tag-p)
|
|
935 (setq open-tags (cons (xmltok-end-tag-qname)
|
|
936 open-tags))
|
|
937 (if (not open-tags)
|
|
938 (when (and (nxml-token-starts-line-p)
|
|
939 (or invisible-ok
|
|
940 (not (get-char-property section-start-pos
|
|
941 'invisible)))
|
|
942 (nxml-heading-start-position))
|
|
943 (setq found t))
|
|
944 (let ((qname (xmltok-start-tag-qname)))
|
|
945 (unless (string= (car open-tags) qname)
|
|
946 (nxml-outline-error "mismatched end-tag"))
|
|
947 (setq open-tags (cdr open-tags)))))
|
|
948 (goto-char section-start-pos)
|
|
949 (and (not found)
|
|
950 (nxml-section-tag-backward))))
|
|
951 found)))
|
|
952
|
|
953 (defun nxml-after-section-start-tag ()
|
|
954 "If the character after point is in a section start-tag, move after it.
|
|
955 Return the token type. Otherwise return nil.
|
|
956 Set up variables like `xmltok-forward'."
|
|
957 (let ((pos (nxml-token-after))
|
|
958 (case-fold-search nil))
|
|
959 (when (and (memq xmltok-type '(start-tag partial-start-tag))
|
|
960 (save-excursion
|
|
961 (goto-char xmltok-start)
|
|
962 (looking-at (nxml-make-section-tag-regexp))))
|
|
963 (goto-char pos)
|
|
964 xmltok-type)))
|
|
965
|
|
966 (defun nxml-heading-start-position ()
|
|
967 "Return the position of the start of the content of a heading element.
|
|
968 Adjust the position to be after initial leading whitespace.
|
|
969 Return nil if no heading element is found. Requires point to be
|
|
970 immediately after the section's start-tag."
|
|
971 (let ((depth 0)
|
|
972 (heading-regexp (concat "\\`\\("
|
|
973 nxml-heading-element-name-regexp
|
|
974 "\\)\\'"))
|
|
975
|
|
976 (section-regexp (concat "\\`\\("
|
|
977 nxml-section-element-name-regexp
|
|
978 "\\)\\'"))
|
|
979 (start (point))
|
|
980 found)
|
|
981 (save-excursion
|
|
982 (while (and (xmltok-forward)
|
|
983 (cond ((memq xmltok-type '(end-tag partial-end-tag))
|
|
984 (and (not (string-match section-regexp
|
|
985 (xmltok-end-tag-local-name)))
|
|
986 (> depth 0)
|
|
987 (setq depth (1- depth))))
|
|
988 ;; XXX Not sure whether this is a good idea
|
|
989 ;;((eq xmltok-type 'empty-element)
|
|
990 ;; nil)
|
|
991 ((not (memq xmltok-type
|
|
992 '(start-tag partial-start-tag)))
|
|
993 t)
|
|
994 ((string-match section-regexp
|
|
995 (xmltok-start-tag-local-name))
|
|
996 nil)
|
|
997 ((string-match heading-regexp
|
|
998 (xmltok-start-tag-local-name))
|
|
999 (skip-chars-forward " \t\r\n")
|
|
1000 (setq found (point))
|
|
1001 nil)
|
|
1002 (t
|
|
1003 (setq depth (1+ depth))
|
|
1004 t))
|
|
1005 (<= (- (point) start) nxml-heading-scan-distance))))
|
|
1006 found))
|
|
1007
|
|
1008 ;;; Error handling
|
|
1009
|
|
1010 (defun nxml-report-outline-error (msg err)
|
|
1011 (error msg (apply 'format (cdr err))))
|
|
1012
|
|
1013 (defun nxml-outline-error (&rest args)
|
|
1014 (signal 'nxml-outline-error args))
|
|
1015
|
|
1016 (put 'nxml-outline-error
|
|
1017 'error-conditions
|
|
1018 '(error nxml-error nxml-outline-error))
|
|
1019
|
|
1020 (put 'nxml-outline-error
|
|
1021 'error-message
|
|
1022 "Cannot create outline of buffer that is not well-formed")
|
|
1023
|
|
1024 ;;; Debugging
|
|
1025
|
|
1026 (defun nxml-debug-overlays ()
|
|
1027 (interactive)
|
|
1028 (let ((overlays (nreverse (overlays-in (point-min) (point-max))))
|
|
1029 overlay)
|
|
1030 (while overlays
|
|
1031 (setq overlay (car overlays))
|
|
1032 (setq overlays (cdr overlays))
|
|
1033 (when (overlay-get overlay 'nxml-outline-display)
|
|
1034 (message "overlay %s: %s...%s (%s)"
|
|
1035 (overlay-get overlay 'category)
|
|
1036 (overlay-start overlay)
|
|
1037 (overlay-end overlay)
|
|
1038 (overlay-get overlay 'display))))))
|
|
1039
|
|
1040 (provide 'nxml-outln)
|
|
1041
|
86379
|
1042 ;; arch-tag: 1f1b7454-e573-4cd7-a505-d9dc64eef828
|
86361
|
1043 ;;; nxml-outln.el ends here
|