Mercurial > hg > xemacs-beta
comparison lisp/psgml/psgml.el @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | ac2d302a0011 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
1 ;;; psgml.el --- SGML-editing mode with parsing support | |
2 ;; $Id: psgml.el,v 1.1.1.1 1996/12/18 03:35:23 steve Exp $ | |
3 | |
4 ;; Copyright (C) 1993, 1994, 1995 Lennart Staflin | |
5 ;; Copyright (C) 1992 Free Software Foundation, Inc. | |
6 | |
7 ;; Author: Lennart Staflin <lenst@lysator.liu.se> | |
8 ;; James Clark <jjc@clark.com> | |
9 | |
10 ;; | |
11 ;; This program is free software; you can redistribute it and/or | |
12 ;; modify it under the terms of the GNU General Public License | |
13 ;; as published by the Free Software Foundation; either version 2 | |
14 ;; of the License, or (at your option) any later version. | |
15 ;; | |
16 ;; This program is distributed in the hope that it will be useful, | |
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 ;; GNU General Public License for more details. | |
20 ;; | |
21 ;; You should have received a copy of the GNU General Public License | |
22 ;; along with this program; if not, write to the Free Software | |
23 ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
24 | |
25 | |
26 ;;; Commentary: | |
27 | |
28 ;; Major mode for editing the SGML document-markup language. | |
29 | |
30 ;; Send bugs to lenst@lysator.liu.se | |
31 | |
32 ;; WHAT IT CAN DO | |
33 | |
34 ;; - Identify structural errors (but it is not a validator) | |
35 ;; - Menus for inserting tags with only the contextually valid tags | |
36 ;; - Edit attribute values in separate window with information about types | |
37 ;; and defaults | |
38 ;; - Hide attributes | |
39 ;; - Fold elements | |
40 ;; - Indent according to element nesting depth | |
41 ;; - Show context | |
42 ;; - Structure editing: move and kill by element | |
43 ;; - Find next data context | |
44 | |
45 ;; LIMITATIONS | |
46 | |
47 ;; - only accepts the referece concrete syntax, though it does allow | |
48 ;; unlimited lengths on names | |
49 | |
50 | |
51 ;;; Code: | |
52 | |
53 (defconst psgml-version "1.0a9" | |
54 "Version of psgml package.") | |
55 | |
56 (defconst psgml-maintainer-address "lenst@lysator.liu.se") | |
57 | |
58 (require 'cl) | |
59 | |
60 (defvar sgml-debug nil) | |
61 | |
62 (defmacro sgml-debug (&rest x) | |
63 (list 'if 'sgml-debug (cons 'sgml-log-message x))) | |
64 | |
65 | |
66 ;;;; Variables | |
67 | |
68 (defvar sgml-mode-abbrev-table nil | |
69 "Abbrev table in use in sgml-mode.") | |
70 (define-abbrev-table 'sgml-mode-abbrev-table ()) | |
71 | |
72 (defvar sgml-mode-syntax-table nil | |
73 "Syntax table used in sgml mode.") | |
74 | |
75 (if sgml-mode-syntax-table | |
76 () | |
77 (setq sgml-mode-syntax-table (make-syntax-table)) | |
78 (modify-syntax-entry ?< "(>" sgml-mode-syntax-table) | |
79 (modify-syntax-entry ?> ")<" sgml-mode-syntax-table) | |
80 (modify-syntax-entry ?\" ". " sgml-mode-syntax-table) | |
81 (modify-syntax-entry ?\\ ". " sgml-mode-syntax-table) | |
82 (modify-syntax-entry ?' "w " sgml-mode-syntax-table)) | |
83 | |
84 (defvar sgml-running-xemacs | |
85 (not (not (string-match "Lucid\\|XEmacs" emacs-version)))) | |
86 | |
87 ;;; User settable options: | |
88 | |
89 (defvar sgml-insert-missing-element-comment t | |
90 "*If true, and sgml-auto-insert-required-elements also true, | |
91 `sgml-insert-element' will insert a comment if there is an element required | |
92 but there is more than one to choose from." ) | |
93 | |
94 (defvar sgml-insert-end-tag-on-new-line nil | |
95 "*If true, `sgml-insert-element' will put the end-tag on a new line | |
96 after the start-tag. Useful on slow terminals if you find the end-tag after | |
97 the cursor irritating." ) | |
98 | |
99 (defvar sgml-doctype nil | |
100 "*If set, this should be the name of a file that contains the doctype | |
101 declaration to use. | |
102 Setting this variable automatically makes it local to the current buffer.") | |
103 (put 'sgml-doctype 'sgml-type 'string) | |
104 (make-variable-buffer-local 'sgml-doctype) | |
105 | |
106 (defvar sgml-system-identifiers-are-preferred nil | |
107 "*If nil, PSGML will look up external entities by searching the catalogs | |
108 in `sgml-local-catalogs' and `sgml-catalog-files' and only if the | |
109 entity is not found in the catalogs will a given system identifer be | |
110 used. If the variable is non-nil and a system identifer is given, the | |
111 system identifier will be used for the entity. If no system identifier | |
112 is given the catalogs will searched.") | |
113 | |
114 (defvar sgml-range-indicator-max-length 9 | |
115 "*Maximum number of characters used from the first and last entry | |
116 of a submenu to indicate the range of that menu.") | |
117 | |
118 (defvar sgml-default-doctype-name nil | |
119 "*Document type name to use if no document type declaration is present.") | |
120 (put 'sgml-default-doctype-name 'sgml-type 'string-or-nil) | |
121 | |
122 (defvar sgml-markup-faces '((start-tag . bold) | |
123 (end-tag . bold) | |
124 (comment . italic) | |
125 (pi . bold) | |
126 (sgml . bold) | |
127 (doctype . bold) | |
128 (entity . bold-italic) | |
129 (shortref . bold)) | |
130 "*List of markup to face mappings. | |
131 Element are of the form (MARKUP-TYPE . FACE). | |
132 Possible values for MARKUP-TYPE is: | |
133 comment - comment declaration | |
134 doctype - doctype declaration | |
135 end-tag | |
136 ignored - ignored marked section | |
137 ms-end - marked section start, if not ignored | |
138 ms-start- marked section end, if not ignored | |
139 pi - processing instruction | |
140 sgml - SGML declaration | |
141 start-tag | |
142 entity - general entity reference | |
143 shortref- short reference") | |
144 | |
145 (defvar sgml-buggy-subst-char-in-region | |
146 (or (not (boundp 'emacs-minor-version)) | |
147 (not (natnump emacs-minor-version)) | |
148 (< emacs-minor-version 23)) | |
149 "*If non-nil, work around a bug in subst-char-in-region. | |
150 The bug sets the buffer modified. If this is set, folding commands | |
151 will be slower.") | |
152 | |
153 (defvar sgml-set-face nil | |
154 "*If non-nil, psgml will set the face of parsed markup.") | |
155 (put 'sgml-set-face 'sgml-desc "Set face of parsed markup") | |
156 | |
157 (defvar sgml-live-element-indicator nil | |
158 "*If non-nil, indicate current element in mode line.") | |
159 | |
160 (defvar sgml-auto-activate-dtd nil | |
161 "*If non-nil, loading a sgml-file will automatically try to activate its DTD. | |
162 Activation means either to parse the document type declaration or to | |
163 load a previously saved parsed DTD. The name of the activated DTD | |
164 will be shown in the mode line.") | |
165 (put 'sgml-auto-activate-dtd 'sgml-desc "Auto Activate DTD") | |
166 | |
167 (defvar sgml-offer-save t | |
168 "*If non-nil, ask about saving modified buffers before \\[sgml-validate] is run.") | |
169 | |
170 (defvar sgml-parent-document nil | |
171 "* Used when the current file is part of a bigger document. | |
172 | |
173 The variable describes how the current file's content fit into the element | |
174 hierarchy. The variable should have the form | |
175 | |
176 (PARENT-FILE CONTEXT-ELEMENT* TOP-ELEMENT (HAS-SEEN-ELEMENT*)?) | |
177 | |
178 PARENT-FILE is a string, the name of the file contatining the | |
179 document entity. | |
180 CONTEXT-ELEMENT is a string, that is the name of an element type. | |
181 It can occur 0 or more times and is used to set up | |
182 exceptions and short reference map. Good candidates | |
183 for these elements are the elements open when the | |
184 entity pointing to the current file is used. | |
185 TOP-ELEMENT is a string that is the name of the element type | |
186 of the top level element in the current file. The file | |
187 should contain one instance of this element, unless | |
188 the last \(lisp) element of sgml-parent-document is a | |
189 list. If it is a list, the top level of the file | |
190 should follow the content model of top-element. | |
191 HAS-SEEN-ELEMENT is a string that is the name of an element type. This | |
192 element is satisfied in the content model of top-element. | |
193 | |
194 Setting this variable automatically makes it local to the current buffer.") | |
195 (make-variable-buffer-local 'sgml-parent-document) | |
196 (put 'sgml-parent-document 'sgml-type 'list) | |
197 | |
198 (defvar sgml-tag-region-if-active t ;; wing change | |
199 "*If non-nil, the Tags menu will tag a region if the region is | |
200 considered active by Emacs. If nil, region must be active and | |
201 transient-mark-mode/zmacs-regions must be on for the region to be tagged.") | |
202 | |
203 (defvar sgml-normalize-trims t | |
204 "*If non-nil, sgml-normalize will trim off white space from end of element | |
205 when adding end tag.") | |
206 | |
207 (defvar sgml-omittag t | |
208 "*Set to non-nil, if you use OMITTAG YES. | |
209 | |
210 Setting this variable automatically makes it local to the current buffer.") | |
211 | |
212 (make-variable-buffer-local 'sgml-omittag) | |
213 (put 'sgml-omittag 'sgml-desc "OMITTAG") | |
214 | |
215 (defvar sgml-shorttag t | |
216 "*Set to non-nil, if you use SHORTTAG YES. | |
217 | |
218 Setting this variable automatically makes it local to the current buffer.") | |
219 | |
220 (make-variable-buffer-local 'sgml-shorttag) | |
221 (put 'sgml-shorttag 'sgml-desc "SHORTTAG") | |
222 | |
223 (defvar sgml-minimize-attributes nil | |
224 "*Determines minimization of attributes inserted by edit-attributes. | |
225 Actually two things are done | |
226 1. If non-nil, omit attribute name, if attribute value is from a token group. | |
227 2. If 'max, omit attributes with default value. | |
228 | |
229 Setting this variable automatically makes it local to the current buffer.") | |
230 | |
231 (make-variable-buffer-local 'sgml-minimize-attributes) | |
232 (put 'sgml-minimize-attributes 'sgml-type | |
233 '(("No" . nil) ("Yes" . t) ("Max" . max))) | |
234 | |
235 (defvar sgml-always-quote-attributes t | |
236 "*If non-nil, quote all attribute values inserted after finishing edit attributes. | |
237 Setting this variable automatically makes it local to the current buffer.") | |
238 | |
239 (make-variable-buffer-local 'sgml-always-quote-attributes) | |
240 | |
241 (defvar sgml-auto-insert-required-elements t | |
242 "*If non-nil, automatically insert required elements in the content | |
243 of an inserted element.") | |
244 | |
245 (defvar sgml-balanced-tag-edit t | |
246 "*If non-nil, always insert start-end tag pairs.") | |
247 | |
248 (defvar sgml-omittag-transparent (not sgml-balanced-tag-edit) | |
249 "*If non-nil, will show legal tags inside elements with omittable start tags | |
250 and legal tags beyond omittable end tags.") | |
251 | |
252 (defvar sgml-leave-point-after-insert nil | |
253 "*If non-nil, the point will remain after inserted tag(s). | |
254 If nil, the point will be placed before the inserted tag(s).") | |
255 | |
256 (defvar sgml-warn-about-undefined-elements t | |
257 "*If non-nil, print a warning when a tag for an undefined element is found.") | |
258 | |
259 (defvar sgml-warn-about-undefined-entities t | |
260 "*If non-nil, print a warning when an undefined entity is found.") | |
261 | |
262 (defvar sgml-ignore-undefined-elements nil | |
263 "*If non-nil, recover from an undefined element by ignoring the tag. | |
264 If nil, recover from an undefined element by assuming it can occur any | |
265 where and has content model ANY.") | |
266 | |
267 (defvar sgml-recompile-out-of-date-cdtd 'ask | |
268 "*If non-nil, out of date compiled DTDs will be automatically recompiled. | |
269 If the value is `ask', PSGML will ask before recompiling. A `nil' | |
270 value will cause PSGML to silently load an out of date compiled DTD. | |
271 A DTD that referes to undefined external entities is always out of | |
272 date, thus in such case it can be useful to set this variable to | |
273 `nil'.") | |
274 (put 'sgml-recompile-out-of-date-cdtd 'sgml-type '(("No" . nil) | |
275 ("Yes" . t) | |
276 ("Ask" . ask))) | |
277 | |
278 (defvar sgml-indent-step 2 | |
279 "*How much to increment indent for every element level. | |
280 If nil, no indentation. | |
281 Setting this variable automatically makes it local to the current buffer.") | |
282 (make-variable-buffer-local 'sgml-indent-step) | |
283 (put 'sgml-indent-step 'sgml-type '(("None" . nil) 0 1 2 3 4 5 6 7 8)) | |
284 | |
285 (defvar sgml-indent-data nil | |
286 "*If non-nil, indent in data/mixed context also. | |
287 Setting this variable automatically makes it local to the current buffer.") | |
288 (make-variable-buffer-local 'sgml-indent-data) | |
289 | |
290 (defvar sgml-inhibit-indent-tags nil | |
291 "*List of tags within which indentation is inhibited. | |
292 The tags should be given as strings.") | |
293 | |
294 (defvar sgml-data-directory (expand-file-name "sgml" data-directory) | |
295 "*Directory for pre-supplied data files (DTD's and such). | |
296 Set this before loading psgml.") | |
297 | |
298 (defvar sgml-system-path nil | |
299 "*List of directories used to look for system identifiers. | |
300 The directory listed in `sgml-data-directory' is always searched in | |
301 addition to the directories listed here.") | |
302 (put 'sgml-system-path 'sgml-type 'list) | |
303 | |
304 (defun sgml-parse-colon-path (cd-path) | |
305 "Explode a colon-separated list of paths into a string list." | |
306 (let (cd-prefix cd-list (cd-start 0) cd-colon) | |
307 (setq cd-path (concat cd-path ":")) | |
308 (while (setq cd-colon (string-match ":" cd-path cd-start)) | |
309 (setq cd-list | |
310 (nconc cd-list | |
311 (list (if (= cd-start cd-colon) | |
312 nil | |
313 (substitute-in-file-name | |
314 (substring cd-path cd-start cd-colon)))))) | |
315 (setq cd-start (+ cd-colon 1))) | |
316 cd-list)) | |
317 | |
318 (defvar sgml-public-map (sgml-parse-colon-path | |
319 (or (getenv "SGML_PATH") | |
320 (concat "%S:" (directory-file-name | |
321 sgml-data-directory) | |
322 "%o/%c/%d"))) | |
323 | |
324 "*Mapping from public identifiers to file names. | |
325 This is a list of possible file names. To find the file for a public | |
326 identifier the elements of the list are used one at the time from the | |
327 beginning. If the element is a string a file name is constructed from | |
328 the string by substitution of the whole public identifier for %P, | |
329 owner for %O, public text class for %C, and public text description | |
330 for %D. The text class will be converted to lower case and the owner | |
331 and description will be transliterated according to the variable | |
332 sgml-public-transliterations. If the file exists it will be the file | |
333 used for the public identifier. An element can also be a dotted pair | |
334 (regexp . filename), the filename is a string treated as above, but | |
335 only if the regular expression, regexp, matches the public | |
336 identifier.") | |
337 (put 'sgml-public-map 'sgml-type 'list) | |
338 | |
339 (defvar sgml-local-catalogs nil | |
340 "*A list of SGML entity catalogs to be searched first when parsing the buffer. | |
341 This is used in addtion to `sgml-catalog-files', and `sgml-public-map'. | |
342 This variable is automatically local to the buffer.") | |
343 (make-variable-buffer-local 'sgml-local-catalogs) | |
344 (put 'sgml-local-catalogs 'sgml-type 'list) | |
345 | |
346 (defvar sgml-catalog-files (sgml-parse-colon-path | |
347 (or (getenv "SGML_CATALOG_FILES") | |
348 (concat "CATALOG:" | |
349 (expand-file-name | |
350 "CATALOG" | |
351 sgml-data-directory)))) | |
352 "*List of catalog entry files. | |
353 The files are in the format defined in the SGML Open Draft Technical | |
354 Resolution on Entity Management.") | |
355 (put 'sgml-catalog-files 'sgml-type 'list) | |
356 | |
357 (defvar sgml-ecat-files (list | |
358 "ECAT" | |
359 "~/sgml/ECAT" | |
360 (expand-file-name "ECAT" sgml-data-directory)) | |
361 "*List of catalog files for PSGML.") | |
362 (put 'sgml-ecat-files 'sgml-type 'list) | |
363 | |
364 (defvar sgml-local-ecat-files nil | |
365 "*List of local catalog files for PSGML. | |
366 Automatically becomes buffer local if set.") | |
367 | |
368 (make-variable-buffer-local 'sgml-local-ecat-files) | |
369 (put 'sgml-local-ecat-files 'sgml-type 'list) | |
370 | |
371 (defvar sgml-public-transliterations '((? . ?_) (?/ . ?%)) | |
372 "*Transliteration for characters that should be avoided in file names. | |
373 This is a list of dotted pairs (FROM . TO); where FROM is the the | |
374 character to be translated to TO. This is used when parts of a public | |
375 identifier are used to construct a file name.") | |
376 | |
377 (defvar sgml-default-dtd-file nil | |
378 "*This is the default file name for saved DTD. | |
379 This is set by sgml-mode from the buffer file name. | |
380 Can be changed in the Local variables section of the file.") | |
381 (put 'sgml-default-dtd-file 'sgml-type 'string) | |
382 (put 'sgml-default-dtd-file 'sgml-desc "Default (saved) DTD File") | |
383 | |
384 (defvar sgml-exposed-tags '() | |
385 "*The list of tag names that remain visible, despite \\[sgml-hide-tags]. | |
386 Each name is a lowercase string, and start-tags and end-tags must be | |
387 listed individually. | |
388 | |
389 `sgml-exposed-tags' is local to each buffer in which it has been set; | |
390 use `setq-default' to set it to a value that is shared among buffers.") | |
391 (make-variable-buffer-local 'sgml-exposed-tags) | |
392 (put 'sgml-exposed-tags 'sgml-type 'list) | |
393 | |
394 | |
395 (defvar sgml-custom-markup nil | |
396 "*Menu entries to be added to the Markup menu. | |
397 The value should be a list of lists of two strings. The first is a | |
398 string is the menu line and the second string is the text inserted | |
399 when the menu item is chosen. The second string can contain a \\r | |
400 where the cursor should be left. Also if a selection is made | |
401 according the same rules as for the Tags menu, the selection is | |
402 replaced with the second string and \\r is replaced with the | |
403 selection. | |
404 | |
405 Example: | |
406 | |
407 ((\"Version1\" \"<![%Version1[\\r]]>\") | |
408 (\"New page\" \"<?NewPage>\")) | |
409 ") | |
410 | |
411 (defvar sgml-custom-dtd nil | |
412 "Menu entries to be added to the DTD menu. | |
413 The value should be a list of entrys to be added to the DTD menu. | |
414 Every entry should be a list. The first element of the entry is a string | |
415 used as the menu entry. The second element is a string containing a | |
416 doctype declaration (this can be nil if no doctype). The rest of the | |
417 list should be a list of variables and values. For backward | |
418 compatibility a singel string instead of a variable is assigned to | |
419 sgml-default-dtd-file. All variables are made buffer local and are also | |
420 added to the buffers local variables list. | |
421 | |
422 Example: | |
423 ((\"HTML\" nil | |
424 sgml-default-dtd-file \"~/sgml/html.ced\" | |
425 sgml-omittag nil sgml-shorttag nil) | |
426 (\"HTML+\" \"<!doctype htmlplus system 'htmlplus.dtd'>\" | |
427 \"~/sgml/htmlplus.ced\" | |
428 sgml-omittag t sgml-shorttag nil) | |
429 (\"DOCBOOK\" \"<!doctype docbook system 'docbook.dtd'>\" | |
430 \"~/sgml/docbook.ced\" | |
431 sgml-omittag nil sgml-shorttag t))) | |
432 ") | |
433 | |
434 | |
435 ;;; Faces used in edit attribute buffer: | |
436 (put 'sgml-default 'face 'underline) ; Face for #DEFAULT | |
437 (put 'sgml-fixed 'face 'underline) ; Face of #FIXED "..." | |
438 | |
439 | |
440 ;;; sgmls is a free SGML parser available from | |
441 ;;; ftp.uu.net:pub/text-processing/sgml | |
442 ;;; Its error messages can be parsed by next-error. | |
443 ;;; The -s option suppresses output. | |
444 | |
445 (defvar sgml-validate-command "sgmls -s %s %s" | |
446 "*The shell command to validate an SGML document. | |
447 | |
448 This is a `format' control string that by default should contain two | |
449 `%s' conversion specifications: the first will be replaced by the | |
450 value of `sgml-declaration' \(or the empty string, if nil\); the | |
451 second will be replaced by the current buffer's file name \(or the | |
452 empty string, if nil\). | |
453 | |
454 If `sgml-validate-files' is non-nil, the format string should contain | |
455 one `%s' conversion specification for each element of its result. | |
456 | |
457 If sgml-validate-command is a list, then every element should be a | |
458 string. The strings will be tried in order and %-sequences in the | |
459 string will be replaced according to the list below, if the string contains | |
460 %-sequences with no replacement value the next string will be tried. | |
461 | |
462 %b means the visited file of the current buffer | |
463 %s means the SGML declaration specified in the sgml-declaration variable | |
464 %d means the file containing the DOCTYPE declaration, if not in the buffer | |
465 ") | |
466 | |
467 (defvar sgml-validate-files nil | |
468 "If non-nil, a function of no arguments that returns a list of file names. | |
469 These file names will serve as the arguments to the `sgml-validate-command' | |
470 format control string instead of the defaults.") | |
471 | |
472 (defvar sgml-validate-error-regexps | |
473 '(("\\(error\\|warning\\) at \\([^,]+\\), line \\([0-9]+\\)" 2 3) | |
474 ("^\\(.+\\):\\([0-9]+\\):\\([0-9]+\\):E: " 1 2 3)) | |
475 "Alist of regexps to recognize error messages from `sgml-validate'. | |
476 See `compilation-error-regexp-alist'.") | |
477 | |
478 (defvar sgml-declaration nil | |
479 "*If non-nil, this is the name of the SGML declaration file.") | |
480 (put 'sgml-declaration 'sgml-type 'string) | |
481 | |
482 (defvar sgml-mode-hook nil | |
483 "A hook or list of hooks to be run when entering sgml-mode") | |
484 | |
485 (defconst sgml-file-options | |
486 '( | |
487 sgml-omittag | |
488 sgml-shorttag | |
489 sgml-minimize-attributes | |
490 sgml-always-quote-attributes | |
491 sgml-indent-step | |
492 sgml-indent-data | |
493 sgml-doctype | |
494 sgml-parent-document | |
495 sgml-default-dtd-file | |
496 sgml-exposed-tags | |
497 sgml-local-catalogs | |
498 sgml-local-ecat-files | |
499 ) | |
500 "Options for the current file, can be saved or set from menu." | |
501 ) | |
502 | |
503 (defconst sgml-user-options | |
504 '( | |
505 sgml-set-face | |
506 sgml-live-element-indicator | |
507 sgml-auto-activate-dtd | |
508 sgml-offer-save | |
509 sgml-tag-region-if-active | |
510 sgml-normalize-trims | |
511 sgml-auto-insert-required-elements | |
512 sgml-balanced-tag-edit | |
513 sgml-omittag-transparent | |
514 sgml-leave-point-after-insert | |
515 sgml-warn-about-undefined-elements | |
516 sgml-warn-about-undefined-entities | |
517 sgml-ignore-undefined-elements | |
518 sgml-recompile-out-of-date-cdtd | |
519 sgml-default-doctype-name | |
520 sgml-declaration | |
521 sgml-validate-command | |
522 sgml-markup-faces | |
523 sgml-system-identifiers-are-preferred | |
524 sgml-system-path | |
525 sgml-public-map | |
526 sgml-catalog-files | |
527 sgml-ecat-files | |
528 ) | |
529 "User options that can be saved or set from menu." | |
530 ) | |
531 | |
532 ;;; Internal variables | |
533 | |
534 (defvar sgml-validate-command-history nil | |
535 "The minibuffer history list for `sgml-validate''s COMMAND argument.") | |
536 | |
537 (defvar sgml-mode-map nil "Keymap for SGML mode") | |
538 | |
539 (defvar sgml-active-dtd-indicator nil | |
540 "Displayed in the mode line") | |
541 | |
542 | |
543 ;;;; User options handling | |
544 | |
545 (defun sgml-variable-description (var) | |
546 (or (get var 'sgml-desc) | |
547 (let ((desc (symbol-name var))) | |
548 (if (string= "sgml-" (substring desc 0 5)) | |
549 (setq desc (substring desc 5))) | |
550 (loop for c across-ref desc | |
551 do (if (eq c ?-) (setf c ? ))) | |
552 (capitalize desc)))) | |
553 | |
554 (defun sgml-variable-type (var) | |
555 (or (get var 'sgml-type) | |
556 (if (memq (symbol-value var) '(t nil)) | |
557 'toggle))) | |
558 | |
559 (defun sgml-set-local-variable (var val) | |
560 "Set the value of variable VAR to VAL in buffer and local variables list." | |
561 (set (make-local-variable var) val) | |
562 (save-excursion | |
563 (let ((prefix "") | |
564 (suffix "") | |
565 (case-fold-search t)) | |
566 (goto-char (max (point-min) (- (point-max) 3000))) | |
567 (cond ((search-forward "Local Variables:" nil t) | |
568 (setq suffix (buffer-substring (point) | |
569 (save-excursion (end-of-line 1) | |
570 (point)))) | |
571 (setq prefix | |
572 (buffer-substring (save-excursion (beginning-of-line 1) | |
573 (point)) | |
574 (match-beginning 0)))) | |
575 (t | |
576 (goto-char (point-max)) | |
577 (unless (bolp) | |
578 (insert ?\n)) | |
579 (insert | |
580 "<!-- Keep this comment at the end of the file\n" | |
581 "Local variables:\n" | |
582 "mode: sgml\n" | |
583 "End:\n" | |
584 "-->\n") | |
585 (forward-line -3))) | |
586 (let* ((endpos (save-excursion | |
587 (search-forward (format "\n%send:" prefix)))) | |
588 (varpos (search-forward (format "\n%s%s:" prefix var) endpos t))) | |
589 (cond (varpos | |
590 (delete-region (point) | |
591 (save-excursion (end-of-line 1) | |
592 (point))) | |
593 (insert (format "%S" val) suffix)) | |
594 (t | |
595 (goto-char endpos) | |
596 (beginning-of-line 1) | |
597 (insert prefix (format "%s:%S" var val) suffix ?\n))))))) | |
598 | |
599 (defun sgml-valid-option (var) | |
600 (let ((type (sgml-variable-type var)) | |
601 (val (symbol-value var))) | |
602 (cond ((eq 'string type) | |
603 (stringp val)) | |
604 ((eq 'list-or-string type) | |
605 (or (stringp val) | |
606 (consp val))) | |
607 (t | |
608 t)))) | |
609 | |
610 (defun sgml-save-options () | |
611 "Save user options for sgml-mode that have buffer local values." | |
612 (interactive) | |
613 (let ((l sgml-file-options)) | |
614 (loop for var in sgml-file-options do | |
615 (when (sgml-valid-option var) | |
616 (sgml-set-local-variable var (symbol-value var)))))) | |
617 | |
618 | |
619 ;;;; Run hook with args | |
620 | |
621 (unless (fboundp 'run-hook-with-args) | |
622 (defun run-hook-with-args (hook &rest args) | |
623 "Run HOOK with the specified arguments ARGS. | |
624 HOOK should be a symbol, a hook variable. If HOOK has a non-nil | |
625 value, that value may be a function or a list of functions to be | |
626 called to run the hook. If the value is a function, it is called with | |
627 the given arguments and its return value is returned. If it is a list | |
628 of functions, those functions are called, in order, | |
629 with the given arguments ARGS. | |
630 It is best not to depend on the value return by `run-hook-with-args', | |
631 as that may change." | |
632 (and (boundp hook) | |
633 (symbol-value hook) | |
634 (let ((value (symbol-value hook))) | |
635 (if (and (listp value) (not (eq (car value) 'lambda))) | |
636 (mapcar '(lambda (foo) (apply foo args)) | |
637 value) | |
638 (apply value args)))))) | |
639 | |
640 | |
641 | |
642 | |
643 ;;;; SGML mode: template functions | |
644 | |
645 (defun sgml-markup (entry text) | |
646 (cons entry | |
647 (` (lambda () | |
648 (interactive) | |
649 (sgml-insert-markup (, text)))))) | |
650 | |
651 (defun sgml-insert-markup (text) | |
652 (let ((end (sgml-mouse-region)) | |
653 before after | |
654 old-text) | |
655 (when end | |
656 (setq old-text (buffer-substring (point) end)) | |
657 (delete-region (point) end)) | |
658 (setq before (point)) | |
659 (if (stringp text) | |
660 (insert text) | |
661 (eval text)) | |
662 (setq after (point)) | |
663 (goto-char before) | |
664 (when (search-forward "\r" after t) | |
665 (delete-char -1)) | |
666 (when old-text (insert old-text)))) | |
667 | |
668 (defun sgml-mouse-region () | |
669 (let (start end) | |
670 (cond | |
671 (sgml-running-xemacs | |
672 (cond | |
673 ((null (mark-marker)) nil) | |
674 (t (setq start (region-beginning) | |
675 end (region-end))))) | |
676 ((and transient-mark-mode | |
677 mark-active) | |
678 (setq start (region-beginning) | |
679 end (region-end))) | |
680 ((and mouse-secondary-overlay | |
681 (eq (current-buffer) | |
682 (overlay-buffer mouse-secondary-overlay))) | |
683 (setq start (overlay-start mouse-secondary-overlay) | |
684 end (overlay-end mouse-secondary-overlay)) | |
685 (delete-overlay mouse-secondary-overlay))) | |
686 (when start | |
687 (goto-char start)) | |
688 end)) | |
689 | |
690 | |
691 ;;;; SGML mode: indentation | |
692 | |
693 (defun sgml-indent-or-tab () | |
694 "Indent line in proper way for current major mode." | |
695 (interactive) | |
696 (if (null sgml-indent-step) | |
697 (insert-tab) | |
698 (funcall indent-line-function))) | |
699 | |
700 ;;;; Bug reporting | |
701 | |
702 (eval-and-compile | |
703 (autoload 'reporter-submit-bug-report "reporter")) | |
704 | |
705 (defun sgml-submit-bug-report () | |
706 "Submit via mail a bug report on PSGML." | |
707 (interactive) | |
708 (and (y-or-n-p "Do you really want to submit a report on PSGML? ") | |
709 (reporter-submit-bug-report | |
710 psgml-maintainer-address | |
711 (concat "psgml.el " psgml-version) | |
712 (list | |
713 'sgml-always-quote-attributes | |
714 'sgml-auto-activate-dtd | |
715 'sgml-auto-insert-required-elements | |
716 'sgml-balanced-tag-edit | |
717 'sgml-catalog-files | |
718 'sgml-declaration | |
719 'sgml-doctype | |
720 'sgml-ecat-files | |
721 'sgml-indent-data | |
722 'sgml-indent-step | |
723 'sgml-leave-point-after-insert | |
724 'sgml-live-element-indicator | |
725 'sgml-local-catalogs | |
726 'sgml-local-ecat-files | |
727 'sgml-markup-faces | |
728 'sgml-minimize-attributes | |
729 'sgml-normalize-trims | |
730 'sgml-omittag | |
731 'sgml-omittag-transparent | |
732 'sgml-parent-document | |
733 'sgml-public-map | |
734 'sgml-set-face | |
735 'sgml-shorttag | |
736 'sgml-tag-region-if-active | |
737 )))) | |
738 | |
739 | |
740 ;;;; SGML mode: keys and menus | |
741 | |
742 (if sgml-mode-map | |
743 () | |
744 (setq sgml-mode-map (make-sparse-keymap))) | |
745 | |
746 ;;; Key commands | |
747 | |
748 (define-key sgml-mode-map "\t" 'sgml-indent-or-tab) | |
749 ;(define-key sgml-mode-map "<" 'sgml-insert-tag) | |
750 (define-key sgml-mode-map ">" 'sgml-close-angle) | |
751 (define-key sgml-mode-map "/" 'sgml-slash) | |
752 (define-key sgml-mode-map "\C-c#" 'sgml-make-character-reference) | |
753 (define-key sgml-mode-map "\C-c-" 'sgml-untag-element) | |
754 (define-key sgml-mode-map "\C-c+" 'sgml-insert-attribute) | |
755 (define-key sgml-mode-map "\C-c/" 'sgml-insert-end-tag) | |
756 (define-key sgml-mode-map "\C-c<" 'sgml-insert-tag) | |
757 (define-key sgml-mode-map "\C-c=" 'sgml-change-element-name) | |
758 (define-key sgml-mode-map "\C-c\C-a" 'sgml-edit-attributes) | |
759 (define-key sgml-mode-map "\C-c\C-c" 'sgml-show-context) | |
760 (define-key sgml-mode-map "\C-c\C-d" 'sgml-next-data-field) | |
761 (define-key sgml-mode-map "\C-c\C-e" 'sgml-insert-element) | |
762 (define-key sgml-mode-map "\C-c\C-k" 'sgml-kill-markup) | |
763 (define-key sgml-mode-map "\C-c\C-l" 'sgml-show-or-clear-log) | |
764 (define-key sgml-mode-map "\C-c\C-n" 'sgml-up-element) | |
765 (define-key sgml-mode-map "\C-c\C-o" 'sgml-next-trouble-spot) | |
766 (define-key sgml-mode-map "\C-c\C-p" 'sgml-parse-prolog) | |
767 (define-key sgml-mode-map "\C-c\C-q" 'sgml-fill-element) | |
768 (define-key sgml-mode-map "\C-c\C-r" 'sgml-tag-region) | |
769 (define-key sgml-mode-map "\C-c\C-s" 'sgml-unfold-line) | |
770 (define-key sgml-mode-map "\C-c\C-t" 'sgml-list-valid-tags) | |
771 (define-key sgml-mode-map "\C-c\C-v" 'sgml-validate) | |
772 (define-key sgml-mode-map "\C-c\C-w" 'sgml-what-element) | |
773 (define-key sgml-mode-map "\C-c\C-z" 'sgml-trim-and-leave-element) | |
774 (define-key sgml-mode-map "\C-c\C-f\C-e" 'sgml-fold-element) | |
775 (define-key sgml-mode-map "\C-c\C-f\C-r" 'sgml-fold-region) | |
776 (define-key sgml-mode-map "\C-c\C-f\C-s" 'sgml-fold-subelement) | |
777 (define-key sgml-mode-map "\C-c\C-f\C-x" 'sgml-expand-element) | |
778 (define-key sgml-mode-map "\C-c\r" 'sgml-split-element) | |
779 (define-key sgml-mode-map "\C-c\C-u\C-e" 'sgml-unfold-element) | |
780 (define-key sgml-mode-map "\C-c\C-u\C-a" 'sgml-unfold-all) | |
781 (define-key sgml-mode-map "\C-c\C-u\C-l" 'sgml-unfold-line) | |
782 (define-key sgml-mode-map "\C-c\C-u\C-d" 'sgml-custom-dtd) | |
783 (define-key sgml-mode-map "\C-c\C-u\C-m" 'sgml-custom-markup) | |
784 | |
785 (define-key sgml-mode-map "\e\C-a" 'sgml-beginning-of-element) | |
786 (define-key sgml-mode-map "\e\C-e" 'sgml-end-of-element) | |
787 (define-key sgml-mode-map "\e\C-f" 'sgml-forward-element) | |
788 (define-key sgml-mode-map "\e\C-b" 'sgml-backward-element) | |
789 (define-key sgml-mode-map "\e\C-d" 'sgml-down-element) | |
790 (define-key sgml-mode-map "\e\C-u" 'sgml-backward-up-element) | |
791 (define-key sgml-mode-map "\e\C-k" 'sgml-kill-element) | |
792 (define-key sgml-mode-map "\e\C-@" 'sgml-mark-element) | |
793 ;;(define-key sgml-mode-map [?\M-\C-\ ] 'sgml-mark-element) | |
794 (define-key sgml-mode-map "\e\C-h" 'sgml-mark-current-element) | |
795 (define-key sgml-mode-map "\e\C-t" 'sgml-transpose-element) | |
796 (define-key sgml-mode-map "\M-\t" 'sgml-complete) | |
797 | |
798 ;;; Menu bar | |
799 | |
800 (eval-when-compile | |
801 (autoload 'sgml-build-custom-menus "psgml-other")) ; Avoid compiler warnings | |
802 | |
803 ;; load menu file at the end | |
804 | |
805 ;;;; Post command hook | |
806 | |
807 (defvar sgml-auto-activate-dtd-tried nil) | |
808 (make-variable-buffer-local 'sgml-auto-activate-dtd-tried) | |
809 | |
810 (defvar sgml-buffer-parse-state nil | |
811 "If the buffers DTD has been activated this contains the parser state. | |
812 The parser state has been created with `sgml-make-pstate' and contains | |
813 the information about the DTD and the parse tree. This parse state is | |
814 actually only the state that persists between commands.") | |
815 (make-variable-buffer-local 'sgml-buffer-parse-state) | |
816 | |
817 (eval-and-compile ; Interface to psgml-parse | |
818 (loop for fun in '(sgml-need-dtd sgml-update-display sgml-subst-expand | |
819 sgml-declaration) | |
820 do (autoload fun "psgml-parse"))) | |
821 | |
822 | |
823 (defun sgml-command-post () | |
824 (when (eq major-mode 'sgml-mode) | |
825 (when (and (null sgml-buffer-parse-state) | |
826 sgml-auto-activate-dtd | |
827 (null sgml-auto-activate-dtd-tried) | |
828 (not (zerop (buffer-size))) | |
829 (looking-at ".*<")) | |
830 (setq sgml-auto-activate-dtd-tried t) | |
831 (sgml-need-dtd)) | |
832 (when sgml-buffer-parse-state | |
833 (sgml-update-display)))) | |
834 | |
835 | |
836 ;;;; SGML mode: major mode definition | |
837 | |
838 ;;; This section is mostly from sgml-mode by James Clark. | |
839 | |
840 ;;;###autoload | |
841 (defun sgml-mode () | |
842 "Major mode for editing SGML.\\<sgml-mode-map> | |
843 Makes > display the matching <. Makes / display matching /. | |
844 Use \\[sgml-validate] to validate your document with an SGML parser. | |
845 | |
846 You can find information with: | |
847 \\[sgml-show-context] Show the nesting of elements at cursor position. | |
848 \\[sgml-list-valid-tags] Show the tags valid at cursor position. | |
849 | |
850 Insert tags with completion of contextually valid tags with \\[sgml-insert-tag]. | |
851 End the current element with \\[sgml-insert-end-tag]. Insert an element (i.e. | |
852 both start and end tag) with \\[sgml-insert-element]. Or tag a region with | |
853 \\[sgml-tag-region]. | |
854 | |
855 To tag a region with the mouse, use transient mark mode or secondary selection. | |
856 | |
857 Structure editing: | |
858 \\[sgml-backward-element] Moves backwards over the previous element. | |
859 \\[sgml-forward-element] Moves forward over the nex element. | |
860 \\[sgml-down-element] Move forward and down one level in the element structure. | |
861 \\[sgml-backward-up-element] Move backward out of this element level. | |
862 \\[sgml-beginning-of-element] Move to after the start tag of the current element. | |
863 \\[sgml-end-of-element] Move to before the end tag of the current element. | |
864 \\[sgml-kill-element] Kill the element following the cursor. | |
865 | |
866 Finding interesting positions | |
867 \\[sgml-next-data-field] Move forward to next point where data is allowed. | |
868 \\[sgml-next-trouble-spot] Move forward to next point where something is | |
869 amiss with the structure. | |
870 | |
871 Folding and unfolding | |
872 \\[sgml-fold-element] Fold the lines comprising the current element, leaving | |
873 the first line visible. | |
874 \\[sgml-fold-subelement] Fold the elements in the content of the current element. | |
875 Leaving the first line of every element visible. | |
876 \\[sgml-unfold-line] Show hidden lines in current line. | |
877 | |
878 User options: | |
879 | |
880 sgml-omittag Set this to reflect OMITTAG in the SGML declaration. | |
881 sgml-shortag Set this to reflect SHORTTAG in the SGML declaration. | |
882 sgml-auto-insert-required-elements If non-nil, automatically insert required | |
883 elements in the content of an inserted element. | |
884 sgml-balanced-tag-edit If non-nil, always insert start-end tag pairs. | |
885 sgml-omittag-transparent If non-nil, will show legal tags inside elements | |
886 with omitable start tags and legal tags beyond omitable end tags. | |
887 sgml-leave-point-after-insert If non-nil, the point will remain after | |
888 inserted tag(s). | |
889 sgml-warn-about-undefined-elements If non-nil, print a warning when a tag | |
890 for a undefined element is found. | |
891 sgml-max-menu-size Max number of entries in Tags and Entities menus before | |
892 they are split into several panes. | |
893 sgml-always-quote-attributes If non-nil, quote all attribute values | |
894 inserted after finishing edit attributes. | |
895 sgml-minimize-attributes Determines minimization of attributes inserted by | |
896 edit-attributes. | |
897 sgml-normalize-trims If non-nil, sgml-normalize will trim off white space | |
898 from end of element when adding end tag. | |
899 sgml-indent-step How much to increament indent for every element level. | |
900 sgml-indent-data If non-nil, indent in data/mixed context also. | |
901 sgml-set-face If non-nil, psgml will set the face of parsed markup. | |
902 sgml-markup-faces The faces used when the above variable is non-nil. | |
903 sgml-system-path List of directorys used to look for system identifiers. | |
904 sgml-public-map Mapping from public identifiers to file names. | |
905 sgml-offer-save If non-nil, ask about saving modified buffers before | |
906 \\[sgml-validate] is run. | |
907 | |
908 All bindings: | |
909 \\{sgml-mode-map} | |
910 " | |
911 (interactive) | |
912 (kill-all-local-variables) | |
913 (setq local-abbrev-table sgml-mode-abbrev-table) | |
914 (use-local-map sgml-mode-map) | |
915 (setq mode-name "SGML") | |
916 (setq major-mode 'sgml-mode) | |
917 | |
918 ;; A start or end tag by itself on a line separates a paragraph. | |
919 ;; This is desirable because SGML discards a newline that appears | |
920 ;; immediately after a start tag or immediately before an end tag. | |
921 | |
922 (set (make-local-variable 'paragraph-separate) | |
923 "^[ \t\n]*$\\|\ | |
924 ^[ \t]*</?\\([A-Za-z]\\([-.A-Za-z0-9= \t\n]\\|\ | |
925 \"[^\"]*\"\\|'[^']*'\\)*\\)?>$") | |
926 (set (make-local-variable 'paragraph-start) | |
927 paragraph-separate) | |
928 | |
929 (set-syntax-table text-mode-syntax-table) | |
930 (make-local-variable 'comment-start) | |
931 (setq comment-start "<!-- ") | |
932 (make-local-variable 'comment-end) | |
933 (setq comment-end " -->") | |
934 (make-local-variable 'comment-indent-function) | |
935 (setq comment-indent-function 'sgml-comment-indent) | |
936 (make-local-variable 'comment-start-skip) | |
937 ;; This will allow existing comments within declarations to be | |
938 ;; recognized. [Does not work well with auto-fill, Lst/940205] | |
939 ;;(setq comment-start-skip "--[ \t]*") | |
940 (setq comment-start-skip "<!--[ \t]*") | |
941 ;; Added for psgml: | |
942 (make-local-variable 'indent-line-function) | |
943 (setq indent-line-function 'sgml-indent-line) | |
944 (make-local-variable 'mode-line-format) | |
945 ;; wing change: use `subst' rather than duplicating the whole | |
946 ;; mode-line-format. XEmacs 19.14 changes the default mode-line-format. | |
947 (setq mode-line-format | |
948 (subst '("" mode-name sgml-active-dtd-indicator) 'mode-name | |
949 mode-line-format)) | |
950 (make-local-variable 'sgml-default-dtd-file) | |
951 (when (setq sgml-default-dtd-file (sgml-default-dtd-file)) | |
952 (unless (file-exists-p sgml-default-dtd-file) | |
953 (setq sgml-default-dtd-file nil))) | |
954 (add-hook 'post-command-hook 'sgml-command-post 'append) | |
955 (run-hooks 'text-mode-hook 'sgml-mode-hook) | |
956 (sgml-build-custom-menus)) | |
957 | |
958 (defun sgml-default-dtd-file () | |
959 (and (buffer-file-name) | |
960 (let ((base (file-name-nondirectory (buffer-file-name)))) | |
961 (concat | |
962 (cond ((string-match "\\.[^.]+$" base) | |
963 (substring base 0 (match-beginning 0))) | |
964 (t | |
965 base)) | |
966 ".ced")))) | |
967 | |
968 (defun sgml-comment-indent () | |
969 (if (and (looking-at "--") | |
970 (not (and (eq (char-after (1- (point))) ?!) | |
971 (eq (char-after (- (point) 2)) ?<)))) | |
972 (progn | |
973 (skip-chars-backward " \t") | |
974 (max comment-column (1+ (current-column)))) | |
975 0)) | |
976 | |
977 (defconst sgml-start-tag-regex | |
978 "<[A-Za-z]\\([-.A-Za-z0-9= \n\t]\\|\"[^\"]*\"\\|'[^']*'\\)*" | |
979 "Regular expression that matches a non-empty start tag. | |
980 Any terminating > or / is not matched.") | |
981 | |
982 (defvar sgml-mode-markup-syntax-table nil | |
983 "Syntax table used for scanning SGML markup.") | |
984 | |
985 (if sgml-mode-markup-syntax-table | |
986 () | |
987 (setq sgml-mode-markup-syntax-table (make-syntax-table)) | |
988 (modify-syntax-entry ?< "(>" sgml-mode-markup-syntax-table) | |
989 (modify-syntax-entry ?> ")<" sgml-mode-markup-syntax-table) | |
990 (modify-syntax-entry ?- "_ 1234" sgml-mode-markup-syntax-table) | |
991 (modify-syntax-entry ?\' "\"" sgml-mode-markup-syntax-table)) | |
992 | |
993 (defconst sgml-angle-distance 4000 | |
994 "*If non-nil, is the maximum distance to search for matching <.") | |
995 | |
996 (defun sgml-close-angle (arg) | |
997 "Insert > and display matching <." | |
998 (interactive "p") | |
999 (insert-char ?> arg) | |
1000 (if (> arg 0) | |
1001 (let ((oldpos (point)) | |
1002 (blinkpos)) | |
1003 (save-excursion | |
1004 (save-restriction | |
1005 (if sgml-angle-distance | |
1006 (narrow-to-region (max (point-min) | |
1007 (- (point) sgml-angle-distance)) | |
1008 oldpos)) | |
1009 ;; See if it's the end of a marked section. | |
1010 (and (> (- (point) (point-min)) 3) | |
1011 (eq (char-after (- (point) 2)) ?\]) | |
1012 (eq (char-after (- (point) 3)) ?\]) | |
1013 (re-search-backward "<!\\[\\(-?[A-Za-z0-9. \t\n&;]\\|\ | |
1014 --\\([^-]\\|-[^-]\\)*--\\)*\\[" | |
1015 (point-min) | |
1016 t) | |
1017 (let ((msspos (point))) | |
1018 (if (and (search-forward "]]>" oldpos t) | |
1019 (eq (point) oldpos)) | |
1020 (setq blinkpos msspos)))) | |
1021 ;; This handles cases where the > ends one of the following: | |
1022 ;; markup declaration starting with <! (possibly including a | |
1023 ;; declaration subset); start tag; end tag; SGML declaration. | |
1024 (if blinkpos | |
1025 () | |
1026 (goto-char oldpos) | |
1027 (condition-case () | |
1028 (let ((oldtable (syntax-table)) | |
1029 (parse-sexp-ignore-comments t)) | |
1030 (unwind-protect | |
1031 (progn | |
1032 (set-syntax-table sgml-mode-markup-syntax-table) | |
1033 (setq blinkpos (scan-sexps oldpos -1))) | |
1034 (set-syntax-table oldtable))) | |
1035 (error nil)) | |
1036 (and blinkpos | |
1037 (goto-char blinkpos) | |
1038 (or | |
1039 ;; Check that it's a valid delimiter in context. | |
1040 (not (looking-at | |
1041 "<\\(\\?\\|/?[A-Za-z>]\\|!\\([[A-Za-z]\\|--\\)\\)")) | |
1042 ;; Check that it's not a net-enabling start tag | |
1043 ;; nor an unclosed start-tag. | |
1044 (looking-at (concat sgml-start-tag-regex "[/<]")) | |
1045 ;; Nor an unclosed end-tag. | |
1046 (looking-at "</[A-Za-z][-.A-Za-z0-9]*[ \t]*<")) | |
1047 (setq blinkpos nil))) | |
1048 (if blinkpos | |
1049 () | |
1050 ;; See if it's the end of a processing instruction. | |
1051 (goto-char oldpos) | |
1052 (if (search-backward "<?" (point-min) t) | |
1053 (let ((pipos (point))) | |
1054 (if (and (search-forward ">" oldpos t) | |
1055 (eq (point) oldpos)) | |
1056 (setq blinkpos pipos)))))) | |
1057 (if blinkpos | |
1058 (progn | |
1059 (goto-char blinkpos) | |
1060 (if (pos-visible-in-window-p) | |
1061 (sit-for 1) | |
1062 (message "Matches %s" | |
1063 (buffer-substring blinkpos | |
1064 (progn (end-of-line) | |
1065 (point))))))))))) | |
1066 | |
1067 ;;; I doubt that null end tags are used much for large elements, | |
1068 ;;; so use a small distance here. | |
1069 (defconst sgml-slash-distance 1000 | |
1070 "*If non-nil, is the maximum distance to search for matching /.") | |
1071 | |
1072 (defun sgml-slash (arg) | |
1073 "Insert / and display any previous matching /. | |
1074 Two /s are treated as matching if the first / ends a net-enabling | |
1075 start tag, and the second / is the corresponding null end tag." | |
1076 (interactive "p") | |
1077 (insert-char ?/ arg) | |
1078 (if (> arg 0) | |
1079 (let ((oldpos (point)) | |
1080 (blinkpos) | |
1081 (level 0)) | |
1082 (save-excursion | |
1083 (save-restriction | |
1084 (if sgml-slash-distance | |
1085 (narrow-to-region (max (point-min) | |
1086 (- (point) sgml-slash-distance)) | |
1087 oldpos)) | |
1088 (if (and (re-search-backward sgml-start-tag-regex (point-min) t) | |
1089 (eq (match-end 0) (1- oldpos))) | |
1090 () | |
1091 (goto-char (1- oldpos)) | |
1092 (while (and (not blinkpos) | |
1093 (search-backward "/" (point-min) t)) | |
1094 (let ((tagend (save-excursion | |
1095 (if (re-search-backward sgml-start-tag-regex | |
1096 (point-min) t) | |
1097 (match-end 0) | |
1098 nil)))) | |
1099 (if (eq tagend (point)) | |
1100 (if (eq level 0) | |
1101 (setq blinkpos (point)) | |
1102 (setq level (1- level))) | |
1103 (setq level (1+ level))))))) | |
1104 (if blinkpos | |
1105 (progn | |
1106 (goto-char blinkpos) | |
1107 (if (pos-visible-in-window-p) | |
1108 (sit-for 1) | |
1109 (message "Matches %s" | |
1110 (buffer-substring (progn | |
1111 (beginning-of-line) | |
1112 (point)) | |
1113 (1+ blinkpos)))))))))) | |
1114 | |
1115 (eval-and-compile | |
1116 (autoload 'compile-internal "compile" "")) | |
1117 | |
1118 (defun sgml-default-validate-command () | |
1119 (cond | |
1120 ((consp sgml-validate-command) | |
1121 (let ((validate-subst | |
1122 (list | |
1123 (cons ?b (and (buffer-file-name) | |
1124 (file-name-nondirectory (buffer-file-name)))) | |
1125 (cons ?s (sgml-declaration)) | |
1126 (cons ?v sgml-declaration) | |
1127 (cons ?d sgml-doctype)))) | |
1128 (loop for template in sgml-validate-command | |
1129 thereis | |
1130 (sgml-subst-expand template validate-subst)))) | |
1131 (t | |
1132 (apply 'format sgml-validate-command | |
1133 (if sgml-validate-files | |
1134 (funcall sgml-validate-files) | |
1135 (list (or sgml-declaration "") | |
1136 (let ((name (buffer-file-name))) | |
1137 (if name | |
1138 (file-name-nondirectory name) | |
1139 "")))))))) | |
1140 | |
1141 (defun sgml-validate (command) | |
1142 "Validate an SGML document. | |
1143 Runs COMMAND, a shell command, in a separate process asynchronously | |
1144 with output going to the buffer *compilation*. | |
1145 You can then use the command \\[next-error] to find the next error message | |
1146 and move to the line in the SGML document that caused it." | |
1147 (interactive | |
1148 (list (read-from-minibuffer "Validate command: " | |
1149 (sgml-default-validate-command) | |
1150 nil nil 'sgml-validate-command-history))) | |
1151 (if sgml-offer-save | |
1152 (save-some-buffers nil nil)) | |
1153 (compile-internal command "No more errors" "SGML validation" | |
1154 nil | |
1155 sgml-validate-error-regexps)) | |
1156 | |
1157 | |
1158 | |
1159 ;;;; Autoloads and hooks | |
1160 | |
1161 (autoload 'sgml-doctype-insert "psgml-edit" | |
1162 nil | |
1163 nil nil) | |
1164 (autoload 'sgml-indent-line "psgml-edit" nil) | |
1165 | |
1166 ;;; Generated by sgml-build-autoloads | |
1167 | |
1168 (autoload 'sgml-load-dtd "psgml-parse" "Load a saved DTD from FILE." t) | |
1169 (autoload 'sgml-show-or-clear-log "psgml-parse" "Show the *SGML LOG* buffer if it is not showing, or clear and | |
1170 remove it if it is showing." t) | |
1171 (autoload 'sgml-parse-prolog "psgml-parse" "Parse the document prolog to learn the DTD." t) | |
1172 (autoload 'sgml-beginning-of-element "psgml-edit" "Move to after the start-tag of the current element. | |
1173 If the start-tag is implied, move to the start of the element." t) | |
1174 (autoload 'sgml-end-of-element "psgml-edit" "Move to before the end-tag of the current element." t) | |
1175 (autoload 'sgml-backward-up-element "psgml-edit" "Move backward out of this element level. | |
1176 That is move to before the start-tag or where a start-tag is implied." t) | |
1177 (autoload 'sgml-up-element "psgml-edit" "Move forward out of this element level. | |
1178 That is move to after the end-tag or where an end-tag is implied." t) | |
1179 (autoload 'sgml-forward-element "psgml-edit" "Move forward over next element." t) | |
1180 (autoload 'sgml-backward-element "psgml-edit" "Move backward over previous element at this level. | |
1181 With implied tags this is ambigous." t) | |
1182 (autoload 'sgml-down-element "psgml-edit" "Move forward and down one level in the element structure." t) | |
1183 (autoload 'sgml-kill-element "psgml-edit" "Kill the element following the cursor." t) | |
1184 (autoload 'sgml-transpose-element "psgml-edit" "Interchange element before point with element after point, leave point after." t) | |
1185 (autoload 'sgml-mark-element "psgml-edit" "Set mark after next element." t) | |
1186 (autoload 'sgml-mark-current-element "psgml-edit" "Set mark at end of current element, and leave point before current element." t) | |
1187 (autoload 'sgml-change-element-name "psgml-edit" "Replace the name of the current element with a new name. | |
1188 Eventual attributes of the current element will be translated if | |
1189 possible." t) | |
1190 (autoload 'sgml-untag-element "psgml-edit" "Remove tags from current element." t) | |
1191 (autoload 'sgml-kill-markup "psgml-edit" "Kill next tag, markup declaration or process instruction." t) | |
1192 (autoload 'sgml-fold-region "psgml-edit" "Hide (or if prefixarg unhide) region. | |
1193 If called from a program first two arguments are start and end of | |
1194 region. And optional third argument true unhides." t) | |
1195 (autoload 'sgml-fold-element "psgml-edit" "Fold the lines comprising the current element, leaving the first line visible. | |
1196 This uses the selective display feature." t) | |
1197 (autoload 'sgml-fold-subelement "psgml-edit" "Fold all elements current elements content, leaving the first lines visible. | |
1198 This uses the selective display feature." t) | |
1199 (autoload 'sgml-unfold-line "psgml-edit" "Show hidden lines in current line." t) | |
1200 (autoload 'sgml-unfold-element "psgml-edit" "Show all hidden lines in current element." t) | |
1201 (autoload 'sgml-expand-element "psgml-edit" "As sgml-fold-subelement, but unfold first." t) | |
1202 (autoload 'sgml-unfold-all "psgml-edit" "Show all hidden lines in buffer." t) | |
1203 (autoload 'sgml-next-data-field "psgml-edit" "Move forward to next point where data is allowed." t) | |
1204 (autoload 'sgml-next-trouble-spot "psgml-edit" "Move forward to next point where something is amiss with the structure." t) | |
1205 (autoload 'sgml-list-valid-tags "psgml-edit" "Display a list of the contextually valid tags." t) | |
1206 (autoload 'sgml-show-context "psgml-edit" "Display where the cursor is in the element hierarchy." t) | |
1207 (autoload 'sgml-what-element "psgml-edit" "Display what element is under the cursor." t) | |
1208 (autoload 'sgml-insert-tag "psgml-edit" "Insert a tag, reading tag name in minibuffer with completion. | |
1209 If the variable sgml-balanced-tag-edit is t, also inserts the | |
1210 corresponding end tag. If sgml-leave-point-after-insert is t, the point | |
1211 is left after the inserted tag(s), unless the element has som required | |
1212 content. If sgml-leave-point-after-insert is nil the point is left | |
1213 after the first tag inserted." t) | |
1214 (autoload 'sgml-insert-element "psgml-edit" "Reads element name from minibuffer and inserts start and end tags." t) | |
1215 (autoload 'sgml-tag-region "psgml-edit" "Reads element name from minibuffer and inserts start and end tags." t) | |
1216 (autoload 'sgml-insert-end-tag "psgml-edit" "Insert end-tag for the current open element." t) | |
1217 (autoload 'sgml-insert-attribute "psgml-edit" "Read attribute name and value from minibuffer and insert attribute spec." t) | |
1218 (autoload 'sgml-split-element "psgml-edit" "Split the current element at point. | |
1219 If repeated, the containing element will be split before the beginning | |
1220 of then current element." t) | |
1221 (autoload 'sgml-custom-dtd "psgml-edit" "Insert a DTD declaration from the sgml-custom-dtd alist." t) | |
1222 (autoload 'sgml-custom-markup "psgml-edit" "Insert markup from the sgml-custom-markup alist." t) | |
1223 (autoload 'sgml-tags-menu "psgml-edit" "Pop up a menu with valid tags and insert the choosen tag. | |
1224 If the variable sgml-balanced-tag-edit is t, also inserts the | |
1225 corresponding end tag. If sgml-leave-point-after-insert is t, the point | |
1226 is left after the inserted tag(s), unless the element has som required | |
1227 content. If sgml-leave-point-after-insert is nil the point is left | |
1228 after the first tag inserted." t) | |
1229 (autoload 'sgml-element-menu "psgml-edit" "Pop up a menu with valid elements and insert choice. | |
1230 If sgml-leave-point-after-insert is nil the point is left after the first | |
1231 tag inserted." t) | |
1232 (autoload 'sgml-start-tag-menu "psgml-edit" "Pop up a menu with valid start-tags and insert choice." t) | |
1233 (autoload 'sgml-end-tag-menu "psgml-edit" "Pop up a menu with valid end-tags and insert choice." t) | |
1234 (autoload 'sgml-tag-region-menu "psgml-edit" "Pop up a menu with valid elements and tag current region with the choice." t) | |
1235 (autoload 'sgml-entities-menu "psgml-edit" nil t) | |
1236 (autoload 'sgml-attrib-menu "psgml-edit" "Pop up a menu of the attributes of the current element | |
1237 \(or the element whith start-tag before point)." t) | |
1238 (autoload 'sgml-fill-element "psgml-edit" "Fill bigest enclosing element with mixed content. | |
1239 If current element has pure element content, recursively fill the | |
1240 subelements." t) | |
1241 (autoload 'sgml-edit-attributes "psgml-edit" "Edit attributes of current element. | |
1242 Editing is done in a separate window." t) | |
1243 (autoload 'sgml-edit-attrib-finish "psgml-edit" "Finish editing and insert attribute values in original buffer." t) | |
1244 (autoload 'sgml-edit-attrib-default "psgml-edit" "Set current attribute value to default." t) | |
1245 (autoload 'sgml-edit-attrib-clear "psgml-edit" "Kill the value of current attribute." t) | |
1246 (autoload 'sgml-edit-attrib-field-start "psgml-edit" "Go to the start of the attribute value field." t) | |
1247 (autoload 'sgml-edit-attrib-field-end "psgml-edit" "Go to the end of the attribute value field." t) | |
1248 (autoload 'sgml-edit-attrib-next "psgml-edit" "Move to next attribute value." t) | |
1249 (autoload 'sgml-hide-tags "psgml-edit" "Hide all tags in buffer." t) | |
1250 (autoload 'sgml-show-tags "psgml-edit" "Show hidden tags in buffer." t) | |
1251 (autoload 'sgml-hide-attributes "psgml-edit" "Hide all attribute specifications in the buffer." t) | |
1252 (autoload 'sgml-show-attributes "psgml-edit" "Show all attribute specifications in the buffer." t) | |
1253 (autoload 'sgml-expand-all-shortrefs "psgml-edit" "Expand all short references in the buffer. | |
1254 Short references to text entities are expanded to the replacement text | |
1255 of the entity other short references are expanded into general entity | |
1256 references. If argument, TO-ENTITY, is non-nil, or if called | |
1257 interactive with numeric prefix argument, all short references are | |
1258 replaced by generaly entity references." t) | |
1259 (autoload 'sgml-normalize "psgml-edit" "Normalize buffer by filling in omitted tags and expanding empty tags. | |
1260 Argument TO-ENTITY controls how short references are expanded as with | |
1261 `sgml-expand-all-shortrefs'. An optional argument ELEMENT can be the | |
1262 element to normalize insted of the whole buffer, if used no short | |
1263 references will be expanded." t) | |
1264 (autoload 'sgml-normalize-element "psgml-edit" nil t) | |
1265 (autoload 'sgml-make-character-reference "psgml-edit" "Convert character after point into a character reference. | |
1266 If called with a numeric argument, convert a character reference back | |
1267 to a normal character. If called from a program, set optional | |
1268 argument INVERT to non-nil." t) | |
1269 (autoload 'sgml-expand-entity-reference "psgml-edit" "Insert the text of the entity referenced at point." t) | |
1270 (autoload 'sgml-complete "psgml-edit" "Complete the word/tag/entity before point. | |
1271 If it is a tag (starts with < or </) complete with valid tags. | |
1272 If it is an entity (starts with &) complete with declared entities. | |
1273 If it is a markup declaration (starts with <!) complete with markup | |
1274 declaration names. | |
1275 If it is something else complete with ispell-complete-word." t) | |
1276 (autoload 'sgml-file-options-menu "psgml-edit" nil t) | |
1277 (autoload 'sgml-user-options-menu "psgml-edit" nil t) | |
1278 (autoload 'sgml-save-dtd "psgml-dtd" "Save the parsed dtd on FILE." t) | |
1279 (autoload 'sgml-list-elements "psgml-info" "List the elements and their attributes in the current DTD." t) | |
1280 (autoload 'sgml-list-attributes "psgml-info" "List the attributes and in which elements they occur." t) | |
1281 (autoload 'sgml-list-terminals "psgml-info" "List the elements that can have data in their content." t) | |
1282 (autoload 'sgml-list-content-elements "psgml-info" "List all element types and the element types that can occur in its content." t) | |
1283 (autoload 'sgml-list-occur-in-elements "psgml-info" "List all element types and where it can occur." t) | |
1284 (autoload 'sgml-describe-entity "psgml-info" "Describe the properties of an entity as declared in the current DTD." t) | |
1285 (autoload 'sgml-describe-element-type "psgml-info" "Describe the properties of an element type as declared in the current DTD." t) | |
1286 (autoload 'sgml-general-dtd-info "psgml-info" "Display information about the current DTD." t) | |
1287 (autoload 'sgml-charent-to-display-char "psgml-charent" "Replace character entities with their display character equivalents" t) | |
1288 (autoload 'sgml-display-char-to-charent "psgml-charent" "Replace displayable characters with their character entity equivalents" t) | |
1289 | |
1290 | |
1291 ;;;; Last provisions | |
1292 (provide 'psgml) | |
1293 (provide 'sgml-mode) | |
1294 | |
1295 (cond | |
1296 (sgml-running-xemacs | |
1297 (require 'psgml-xemacs) | |
1298 (add-hook 'sgml-mode-hook 'sgml-install-xemacs-menus)) | |
1299 (t | |
1300 (require 'psgml-other))) | |
1301 | |
1302 ;;; psgml.el ends HERE |