aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/textmodes
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/textmodes')
-rw-r--r--lisp/textmodes/conf-mode.el531
-rw-r--r--lisp/textmodes/flyspell.el2
-rw-r--r--lisp/textmodes/sgml-mode.el117
3 files changed, 604 insertions, 46 deletions
diff --git a/lisp/textmodes/conf-mode.el b/lisp/textmodes/conf-mode.el
new file mode 100644
index 00000000000..cb692616947
--- /dev/null
+++ b/lisp/textmodes/conf-mode.el
@@ -0,0 +1,531 @@
1;;; conf-mode.el --- Simple major mode for editing conf/ini/properties files
2
3;; Copyright (C) 2004 by Daniel Pfeiffer <occitan@esperanto.org>
4;; Keywords: conf ini windows java
5
6;; This file is part of GNU Emacs.
7
8;; GNU Emacs is free software; you can redistribute it and/or modify
9;; it under the terms of the GNU General Public License as published by
10;; the Free Software Foundation; either version 2, or (at your option)
11;; any later version.
12
13;; GNU Emacs is distributed in the hope that it will be useful,
14;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16;; GNU General Public License for more details.
17
18;; You should have received a copy of the GNU General Public License
19;; along with GNU Emacs; see the file COPYING. If not, write to the
20;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21;; Boston, MA 02111-1307, USA.
22
23;;; Commentary:
24;;
25;; This mode is designed to edit many similar varieties of Conf/Ini files and
26;; Java properties. It started out from Aurélien Tisné's ini-mode.
27;; `conf-space-keywords' were inspired by Robert Fitzgerald's any-ini-mode.
28
29
30;;; Code:
31
32(require 'newcomment)
33
34;; Variables:
35
36(defgroup conf nil
37 "Configuration files."
38 :group 'data
39 :version "21.4")
40
41(defcustom conf-assignment-column 24
42 "Align assignments to this column by default with \\[conf-align-assignments].
43If this number is negative, the `=' comes before the whitespace. Use 0 to
44not align (only setting space according to `conf-assignment-space')."
45 :type 'integer
46 :group 'conf)
47
48(defcustom conf-javaprop-assignment-column 32
49 "Value for `conf-assignment-column' in Java properties buffers."
50 :type 'integer
51 :group 'conf)
52
53(defcustom conf-colon-assignment-column (- (abs conf-assignment-column))
54 "Value for `conf-assignment-column' in Java properties buffers."
55 :type 'integer
56 :group 'conf)
57
58(defcustom conf-assignment-space t
59 "Put at least one space around assignments when aligning."
60 :type 'boolean
61 :group 'conf)
62
63(defcustom conf-colon-assignment-space nil
64 "Value for `conf-assignment-space' in colon style Conf mode buffers."
65 :type 'boolean
66 :group 'conf)
67
68
69(defvar conf-mode-map
70 (let ((map (make-sparse-keymap)))
71 (define-key map "\C-c\C-u" 'conf-unix-mode)
72 (define-key map "\C-c\C-w" 'conf-windows-mode)
73 (define-key map "\C-c\C-j" 'conf-javaprop-mode)
74 (define-key map "\C-c\C-s" 'conf-space-mode)
75 (define-key map "\C-c " 'conf-space-mode)
76 (define-key map "\C-c\C-c" 'conf-colon-mode)
77 (define-key map "\C-c:" 'conf-colon-mode)
78 (define-key map "\C-c\C-x" 'conf-xdefaults-mode)
79 (define-key map "\C-c\C-q" 'conf-quote-normal)
80 (define-key map "\C-c\"" 'conf-quote-normal)
81 (define-key map "\C-c'" 'conf-quote-normal)
82 (define-key map "\C-c\C-a" 'conf-align-assignments)
83 map)
84 "Local keymap for conf-mode buffers.")
85
86(defvar conf-mode-syntax-table
87 (let ((table (make-syntax-table)))
88 (modify-syntax-entry ?= "." table)
89 (modify-syntax-entry ?_ "_" table)
90 (modify-syntax-entry ?- "_" table)
91 (modify-syntax-entry ?. "_" table)
92 (modify-syntax-entry ?\' "\"" table)
93; (modify-syntax-entry ?: "_" table)
94 (modify-syntax-entry ?\; "<" table)
95 (modify-syntax-entry ?\n ">" table)
96 (modify-syntax-entry ?\r ">" table)
97 table)
98 "Syntax table in use in Windows style conf-mode buffers.")
99
100(defvar conf-unix-mode-syntax-table
101 (let ((table (make-syntax-table conf-mode-syntax-table)))
102 (modify-syntax-entry ?\# "<" table)
103 ;; override
104 (modify-syntax-entry ?\; "." table)
105 table)
106 "Syntax table in use in Unix style conf-mode buffers.")
107
108(defvar conf-javaprop-mode-syntax-table
109 (let ((table (make-syntax-table conf-unix-mode-syntax-table)))
110 (modify-syntax-entry ?/ ". 124" table)
111 (modify-syntax-entry ?* ". 23b" table)
112 table)
113 "Syntax table in use in Java prperties buffers.")
114
115(defvar conf-xdefaults-mode-syntax-table
116 (let ((table (make-syntax-table conf-mode-syntax-table)))
117 (modify-syntax-entry ?! "<" table)
118 ;; override
119 (modify-syntax-entry ?\; "." table)
120 table)
121 "Syntax table in use in Xdefaults style conf-mode buffers.")
122
123
124(defvar conf-font-lock-keywords
125 `(;; [section] (do this first because it may look like a parameter)
126 ("^[ \t]*\\[\\(.+\\)\\]" 1 'font-lock-type-face)
127 ;; var=val or var[index]=val
128 ("^[ \t]*\\(.+?\\)\\(?:\\[\\(.*?\\)\\]\\)?[ \t]*="
129 (1 'font-lock-variable-name-face)
130 (2 'font-lock-constant-face nil t))
131 ;; section { ... } (do this last because some assign ...{...)
132 ("^[ \t]*\\([^=:\n]+?\\)[ \t\n]*{[^{}]*?$" 1 'font-lock-type-face prepend))
133 "Keywords to hilight in Conf mode")
134
135(defvar conf-javaprop-font-lock-keywords
136 '(;; var=val
137 ("^[ \t]*\\(.+?\\)\\(?:\\.\\([0-9]+\\)\\(?:\\.\\(.+?\\)\\(?:\\.\\([0-9]+\\)\\(?:\\.\\(.+?\\)\\(?:\\.\\([0-9]+\\)\\(\\..+?\\)?\\)?\\)?\\)?\\)?\\)?\\([:= \t]\\|$\\)"
138 (1 'font-lock-variable-name-face)
139 (2 'font-lock-constant-face nil t)
140 (3 'font-lock-variable-name-face nil t)
141 (4 'font-lock-constant-face nil t)
142 (5 'font-lock-variable-name-face nil t)
143 (6 'font-lock-constant-face nil t)
144 (7 'font-lock-variable-name-face nil t)))
145 "Keywords to hilight in Conf Java Properties mode")
146
147(defvar conf-space-keywords-alist
148 '(("\\`/etc/gpm/" . "key\\|name\\|foreground\\|background\\|border\\|head")
149 ("\\`/etc/magic\\'" . "[^ \t]+[ \t]+\\(?:[bl]?e?\\(?:short\\|long\\)\\|byte\\|string\\)[^ \t]*")
150 ("/mod\\(?:ules\\|probe\\)\\.conf" . "alias\\|in\\(?:clude\\|stall\\)\\|options\\|remove")
151 ("/manpath\\.config" . "MAN\\(?:DATORY_MANPATH\\|PATH_MAP\\|DB_MAP\\)")
152 ("/sensors\\.conf" . "chip\\|bus\\|label\\|compute\\|set\\|ignore")
153 ("/sane\\(\\.d\\)?/" . "option\\|device\\|port\\|usb\\|sc\\(?:si\\|anner\\)")
154 ("/resmgr\\.conf" . "class\\|add\\|allow\\|deny")
155 ("/dictionary\\.lst\\'" . "DICT\\|HYPH\\|THES")
156 ("/tuxracer/options" . "set"))
157 "File name based settings for `conf-space-keywords'.")
158
159(defvar conf-space-keywords nil
160 "Regexps for functions that may come before a space assignment.
161This allows constructs such as
162keyword var value
163This variable is best set in the file local variables, or through
164`conf-space-keywords-alist'.")
165
166(defvar conf-space-font-lock-keywords
167 `(;; [section] (do this first because it may look like a parameter)
168 ("^[ \t]*\\[\\(.+\\)\\]" 1 'font-lock-type-face)
169 ;; section { ... } (do this first because it looks like a parameter)
170 ("^[ \t]*\\(.+?\\)[ \t\n]*{[^{}]*?$" 1 'font-lock-type-face)
171 ;; var val
172 (eval if conf-space-keywords
173 (list (concat "^[ \t]*\\(" conf-space-keywords "\\)[ \t]+\\([^\000- ]+\\)")
174 '(1 'font-lock-keyword-face)
175 '(2 'font-lock-variable-name-face))
176 '("^[ \t]*\\([^\000- ]+\\)" 1 'font-lock-variable-name-face)))
177 "Keywords to hilight in Conf Space mode")
178
179(defvar conf-colon-font-lock-keywords
180 `(;; [section] (do this first because it may look like a parameter)
181 ("^[ \t]*\\[\\(.+\\)\\]" 1 'font-lock-type-face)
182 ;; var: val
183 ("^[ \t]*\\(.+?\\)[ \t]*:"
184 (1 'font-lock-variable-name-face))
185 ;; section { ... } (do this last because some assign ...{...)
186 ("^[ \t]*\\([^:\n]+\\)[ \t\n]*{[^{}]*?$" 1 'font-lock-type-face prepend))
187 "Keywords to hilight in Conf Colon mode")
188
189(defvar conf-assignment-sign ?=
190 "What sign is used for assignments.")
191
192(defvar conf-assignment-regexp ".+?\\([ \t]*=[ \t]*\\)"
193 "Regexp to recognize assignments.
194It is anchored after the first sexp on a line. There must a
195grouping for the assignment sign, including leading and trailing
196whitespace.")
197
198
199;; If anybody can figure out how to get the same effect by configuring
200;; `align', I'd be glad to hear.
201(defun conf-align-assignments (&optional arg)
202 (interactive "P")
203 (setq arg (if arg
204 (prefix-numeric-value arg)
205 conf-assignment-column))
206 (save-excursion
207 (goto-char (point-min))
208 (while (not (eobp))
209 (let ((cs (comment-beginning))) ; go before comment if within
210 (if cs (goto-char cs)))
211 (while (forward-comment 9)) ; max-int?
212 (when (and (not (eobp))
213 (looking-at conf-assignment-regexp))
214 (goto-char (match-beginning 1))
215 (delete-region (point) (match-end 1))
216 (if conf-assignment-sign
217 (if (>= arg 0)
218 (progn
219 (indent-to-column arg)
220 (or (not conf-assignment-space) (memq (char-before (point)) '(? ?\t)) (insert ? ))
221 (insert conf-assignment-sign (if (and conf-assignment-space (not (eolp))) ?\ "")))
222 (insert (if conf-assignment-space ?\ "") conf-assignment-sign)
223 (unless (eolp)
224 (indent-to-column (- arg))
225 (or (not conf-assignment-space) (memq (char-before (point)) '(? ?\t)) (insert ? ))))
226 (unless (eolp)
227 (if (>= (current-column) (abs arg))
228 (insert ? )
229 (indent-to-column (abs arg))))))
230 (forward-line))))
231
232
233(defun conf-quote-normal ()
234 "Set the syntax of \" and ' to punctuation.
235This only affects the current buffer. Some conf files use quotes
236to delimit strings, while others allow quotes as simple parts of
237the assigned value. In those files font locking will be wrong,
238and you can correct it with this command. (Some files even do
239both, i.e. quotes delimit strings, except when they are
240unbalanced, but hey...)"
241 (interactive)
242 (let ((table (copy-syntax-table (syntax-table))))
243 (modify-syntax-entry ?\" "." table)
244 (modify-syntax-entry ?\' "." table)
245 (set-syntax-table table)
246 (and (boundp 'font-lock-mode)
247 font-lock-mode
248 (font-lock-fontify-buffer))))
249
250
251(defun conf-outline-level ()
252 (let ((depth 0)
253 (pt (match-end 0)))
254 (condition-case nil
255 (while (setq pt (scan-lists pt -1 1)
256 depth (1+ depth)))
257 (scan-error depth))))
258
259
260
261;;;###autoload
262(defun conf-mode (&optional comment syntax-table name)
263 "Mode for Unix and Windows Conf files and Java properties.
264Most conf files know only three kinds of constructs: parameter
265assignments optionally grouped into sections and comments. Yet
266there is a great range of variation in the exact syntax of conf
267files. See below for various wrapper commands that set up the
268details for some of the most widespread variants.
269
270This mode sets up font locking, outline, imenu and it provides
271alignment support through `conf-align-assignments'. If strings
272come out wrong, try `conf-quote-normal'.
273
274Some files allow continuation lines, either with a backslash at
275the end of line, or by indenting the next line (further). These
276constructs cannot currently be recognized.
277
278Because of this great variety of nuances, which are often not
279even clearly specified, please don't expect it to get every file
280quite right. Patches that clearly identify some special case,
281without breaking the general ones, are welcome.
282
283If instead you start this mode with the generic `conf-mode'
284command, it will parse the buffer. It will generally well
285identify the first four cases listed below. If the buffer
286doesn't have enough contents to decide, this is identical to
287`conf-windows-mode' on Windows, elsewhere to `conf-unix-mode'. See
288also `conf-space-mode', `conf-colon-mode', `conf-javaprop-mode' and
289`conf-xdefaults-mode'.
290
291\\{conf-mode-map}"
292
293 (interactive)
294 (if (not comment)
295 (let ((unix 0) (win 0) (equal 0) (colon 0) (space 0) (jp 0))
296 (save-excursion
297 (goto-char (point-min))
298 (while (not (eobp))
299 (skip-chars-forward " \t\f")
300 (cond ((eq (char-after) ?\#) (setq unix (1+ unix)))
301 ((eq (char-after) ?\;) (setq win (1+ win)))
302 ((eq (char-after) ?\[)) ; nop
303 ((eolp)) ; nop
304 ((eq (char-after) ?})) ; nop
305 ;; recognize at most double spaces within names
306 ((looking-at "[^ \t\n=:]+\\(?: ?[^ \t\n=:]+\\)*[ \t]*[=:]")
307 (if (eq (char-before (match-end 0)) ?=)
308 (setq equal (1+ equal))
309 (setq colon (1+ colon))))
310 ((looking-at "/[/*]") (setq jp (1+ jp)))
311 ((looking-at ".*{")) ; nop
312 ((setq space (1+ space))))
313 (forward-line)))
314 (if (> jp (max unix win 3))
315 (conf-javaprop-mode)
316 (if (> colon (max equal space))
317 (conf-colon-mode)
318 (if (> space (max equal colon))
319 (conf-space-mode)
320 (if (or (> win unix)
321 (and (= win unix) (eq system-type 'windows-nt)))
322 (conf-windows-mode)
323 (conf-unix-mode))))))
324 (kill-all-local-variables)
325 (use-local-map conf-mode-map)
326
327 (setq major-mode 'conf-mode
328 mode-name name)
329 (set (make-local-variable 'comment-start) comment)
330 (set (make-local-variable 'comment-start-skip)
331 (concat comment-start "+\\s *"))
332 (set (make-local-variable 'comment-use-syntax) t)
333 (set (make-local-variable 'parse-sexp-ignore-comments) t)
334 (set (make-local-variable 'outline-regexp)
335 "[ \t]*\\(?:\\[\\|.+[ \t\n]*{\\)")
336 (set (make-local-variable 'outline-heading-end-regexp)
337 "[\n}]")
338 (set (make-local-variable 'outline-level)
339 'conf-outline-level)
340 (set-syntax-table syntax-table)
341 (setq imenu-generic-expression
342 '(("Parameters" "^[ \t]*\\(.+?\\)[ \t]*=" 1)
343 ;; [section]
344 (nil "^[ \t]*\\[[ \t]*\\(.+\\)[ \t]*\\]" 1)
345 ;; section { ... }
346 (nil "^[ \t]*\\([^=:\n]+\\)[ \t\n]*{" 1)))
347
348 (run-mode-hooks 'conf-mode-hook)))
349
350;;;###autoload
351(defun conf-unix-mode ()
352 "Conf Mode starter for Unix style Conf files.
353Comments start with `#'.
354For details see `conf-mode'. Example:
355
356# Conf mode font-locks this right on Unix and with C-c C-u
357
358\[Desktop Entry]
359 Encoding=UTF-8
360 Name=The GIMP
361 Name[ca]=El GIMP
362 Name[cs]=GIMP"
363 (interactive)
364 (conf-mode "#" conf-unix-mode-syntax-table "Conf[Unix]"))
365
366;;;###autoload
367(defun conf-windows-mode ()
368 "Conf Mode starter for Windows style Conf files.
369Comments start with `;'.
370For details see `conf-mode'. Example:
371
372; Conf mode font-locks this right on Windows and with C-c C-w
373
374\[ExtShellFolderViews]
375Default={5984FFE0-28D4-11CF-AE66-08002B2E1262}
376{5984FFE0-28D4-11CF-AE66-08002B2E1262}={5984FFE0-28D4-11CF-AE66-08002B2E1262}
377
378\[{5984FFE0-28D4-11CF-AE66-08002B2E1262}]
379PersistMoniker=file://Folder.htt"
380 (interactive)
381 (conf-mode ";" conf-mode-syntax-table "Conf[WinIni]"))
382
383;; Here are a few more or less widespread styles. There are others, so
384;; obscure, they are not covered. E.g. RFC 2614 allows both Unix and Windows
385;; comments. Or the donkey has (* Pascal comments *) -- roll your own starter
386;; if you need it.
387
388;;;###autoload
389(defun conf-javaprop-mode ()
390 "Conf Mode starter for Java properties files.
391Comments start with `#' but are also recognized with `//' or
392between `/*' and `*/'.
393For details see `conf-mode'. Example:
394
395# Conf mode font-locks this right with C-c C-j (Java properties)
396// another kind of comment
397/* yet another */
398
399name:value
400name=value
401name value
402x.1 =
403x.2.y.1.z.1 =
404x.2.y.1.z.2.zz ="
405 (interactive)
406 (conf-mode "#" conf-javaprop-mode-syntax-table "Conf[JavaProp]")
407 (set (make-local-variable 'conf-assignment-column)
408 conf-javaprop-assignment-column)
409 (set (make-local-variable 'conf-assignment-regexp)
410 ".+?\\([ \t]*[=: \t][ \t]*\\|$\\)")
411 (set (make-local-variable 'conf-font-lock-keywords)
412 conf-javaprop-font-lock-keywords)
413 (setq comment-start-skip "\\(?:#+\\|/[/*]+\\)\\s *")
414 (setq imenu-generic-expression
415 '(("Parameters" "^[ \t]*\\(.+?\\)[=: \t]" 1))))
416
417;;;###autoload
418(defun conf-space-mode (&optional keywords)
419 "Conf Mode starter for space separated conf files.
420\"Assignments\" are with ` '. Keywords before the parameters are
421recognized according to `conf-space-keywords'. Interactively
422with a prefix ARG of `0' no keywords will be recognized. With
423any other prefix arg you will be prompted for a regexp to match
424the keywords. Programmatically you can pass such a regexp as
425KEYWORDS, or any non-nil non-string for no keywords.
426
427For details see `conf-mode'. Example:
428
429# Conf mode font-locks this right with C-c C-s (space separated)
430
431image/jpeg jpeg jpg jpe
432image/png png
433image/tiff tiff tif
434
435# Or with keywords (from a recognized file name):
436class desktop
437# Standard multimedia devices
438add /dev/audio desktop
439add /dev/mixer desktop"
440 (interactive
441 (list (if current-prefix-arg
442 (if (> (prefix-numeric-value current-prefix-arg) 0)
443 (read-string "Regexp to match keywords: ")
444 t))))
445 (conf-unix-mode)
446 (setq mode-name "Conf[Space]")
447 (set (make-local-variable 'conf-assignment-sign)
448 nil)
449 (set (make-local-variable 'conf-font-lock-keywords)
450 conf-space-font-lock-keywords)
451 ;; This doesn't seem right, but the next two depend on conf-space-keywords
452 ;; being set, while after-change-major-mode-hook might set up imenu, needing
453 ;; the following result:
454 (hack-local-variables-prop-line)
455 (hack-local-variables)
456 (if keywords
457 (set (make-local-variable 'conf-space-keywords)
458 (if (stringp keywords) keywords))
459 (or conf-space-keywords
460 (not buffer-file-name)
461 (set (make-local-variable 'conf-space-keywords)
462 (assoc-default buffer-file-name conf-space-keywords-alist
463 'string-match))))
464 (set (make-local-variable 'conf-assignment-regexp)
465 (if conf-space-keywords
466 (concat "\\(?:" conf-space-keywords "\\)[ \t]+.+?\\([ \t]+\\|$\\)")
467 ".+?\\([ \t]+\\|$\\)"))
468 (setq imenu-generic-expression
469 `(,@(cdr imenu-generic-expression)
470 ("Parameters"
471 ,(if conf-space-keywords
472 (concat "^[ \t]*\\(?:" conf-space-keywords
473 "\\)[ \t]+\\([^ \t\n]+\\)\\(?:[ \t]\\|$\\)")
474 "^[ \t]*\\([^ \t\n[]+\\)\\(?:[ \t]\\|$\\)")
475 1))))
476
477;;;###autoload
478(defun conf-colon-mode (&optional comment syntax-table name)
479 "Conf Mode starter for Colon files.
480\"Assignments\" are with `:'.
481For details see `conf-mode'. Example:
482
483# Conf mode font-locks this right with C-c C-c (colon)
484
485<Multi_key> <exclam> <exclam> : \"\\241\" exclamdown
486<Multi_key> <c> <slash> : \"\\242\" cent"
487 (interactive)
488 (if comment
489 (conf-mode comment syntax-table name)
490 (conf-unix-mode)
491 (setq mode-name "Conf[Colon]"))
492 (set (make-local-variable 'conf-assignment-space)
493 conf-colon-assignment-space)
494 (set (make-local-variable 'conf-assignment-column)
495 conf-colon-assignment-column)
496 (set (make-local-variable 'conf-assignment-sign)
497 ?:)
498 (set (make-local-variable 'conf-assignment-regexp)
499 ".+?\\([ \t]*:[ \t]*\\)")
500 (set (make-local-variable 'conf-font-lock-keywords)
501 conf-colon-font-lock-keywords)
502 (setq imenu-generic-expression
503 `(("Parameters" "^[ \t]*\\(.+?\\)[ \t]*:" 1)
504 ,@(cdr imenu-generic-expression))))
505
506;;;###autoload
507(defun conf-xdefaults-mode ()
508 "Conf Mode starter for Xdefaults files.
509Comments start with `!' and \"assignments\" are with `:'.
510For details see `conf-mode'. Example:
511
512! Conf mode font-locks this right with C-c C-x (.Xdefaults)
513
514*background: gray99
515*foreground: black"
516 (interactive)
517 (conf-colon-mode "!" conf-xdefaults-mode-syntax-table "Conf[Xdefaults]"))
518
519
520;; font lock support
521(if (boundp 'font-lock-defaults-alist)
522 (add-to-list
523 'font-lock-defaults-alist
524 (cons 'conf-mode
525 (list 'conf-font-lock-keywords nil t nil nil))))
526
527
528(provide 'conf-mode)
529
530;; arch-tag: 0a3805b2-0371-4d3a-8498-8897116b2356
531;;; conf-mode.el ends here
diff --git a/lisp/textmodes/flyspell.el b/lisp/textmodes/flyspell.el
index 556369077d8..441d9972173 100644
--- a/lisp/textmodes/flyspell.el
+++ b/lisp/textmodes/flyspell.el
@@ -1281,7 +1281,7 @@ Word syntax described by `ispell-dictionary-alist' (which see)."
1281(defun flyspell-external-point-words () 1281(defun flyspell-external-point-words ()
1282 (let ((buffer flyspell-external-ispell-buffer)) 1282 (let ((buffer flyspell-external-ispell-buffer))
1283 (set-buffer buffer) 1283 (set-buffer buffer)
1284 (beginning-of-buffer) 1284 (goto-char (point-min))
1285 (let ((size (- flyspell-large-region-end flyspell-large-region-beg)) 1285 (let ((size (- flyspell-large-region-end flyspell-large-region-beg))
1286 (start flyspell-large-region-beg)) 1286 (start flyspell-large-region-beg))
1287 ;; now we are done with ispell, we have to find the word in 1287 ;; now we are done with ispell, we have to find the word in
diff --git a/lisp/textmodes/sgml-mode.el b/lisp/textmodes/sgml-mode.el
index 4ac96b2e4b0..dd606a53434 100644
--- a/lisp/textmodes/sgml-mode.el
+++ b/lisp/textmodes/sgml-mode.el
@@ -1,6 +1,7 @@
1;;; sgml-mode.el --- SGML- and HTML-editing modes 1;;; sgml-mode.el --- SGML- and HTML-editing modes
2 2
3;; Copyright (C) 1992,95,96,98,2001,2002, 2003 Free Software Foundation, Inc. 3;; Copyright (C) 1992, 1995, 1996, 1998, 2001, 2002, 2003, 2004
4;; Free Software Foundation, Inc.
4 5
5;; Author: James Clark <jjc@jclark.com> 6;; Author: James Clark <jjc@jclark.com>
6;; Maintainer: FSF 7;; Maintainer: FSF
@@ -1053,53 +1054,79 @@ You might want to turn on `auto-fill-mode' to get better results."
1053 (and (>= start (point-min)) 1054 (and (>= start (point-min))
1054 (equal str (buffer-substring-no-properties start (point)))))) 1055 (equal str (buffer-substring-no-properties start (point))))))
1055 1056
1057(defun sgml-tag-text-p (start end)
1058 "Return non-nil if text between START and END is a tag.
1059Checks among other things that the tag does not contain spurious
1060unquoted < or > chars inside, which would indicate that it
1061really isn't a tag after all."
1062 (save-excursion
1063 (with-syntax-table sgml-tag-syntax-table
1064 (let ((pps (parse-partial-sexp start end 2)))
1065 (and (= (nth 0 pps) 0))))))
1066
1056(defun sgml-parse-tag-backward (&optional limit) 1067(defun sgml-parse-tag-backward (&optional limit)
1057 "Parse an SGML tag backward, and return information about the tag. 1068 "Parse an SGML tag backward, and return information about the tag.
1058Assume that parsing starts from within a textual context. 1069Assume that parsing starts from within a textual context.
1059Leave point at the beginning of the tag." 1070Leave point at the beginning of the tag."
1060 (let (tag-type tag-start tag-end name) 1071 (catch 'found
1061 (or (re-search-backward "[<>]" limit 'move) 1072 (let (tag-type tag-start tag-end name)
1062 (error "No tag found")) 1073 (or (re-search-backward "[<>]" limit 'move)
1063 (when (eq (char-after) ?<) 1074 (error "No tag found"))
1064 ;; Oops!! Looks like we were not in a textual context after all!. 1075 (when (eq (char-after) ?<)
1065 ;; Let's try to recover. 1076 ;; Oops!! Looks like we were not in a textual context after all!.
1066 (with-syntax-table sgml-tag-syntax-table 1077 ;; Let's try to recover.
1067 (forward-sexp) 1078 (with-syntax-table sgml-tag-syntax-table
1068 (forward-char -1))) 1079 (let ((pos (point)))
1069 (setq tag-end (1+ (point))) 1080 (condition-case nil
1070 (cond 1081 (forward-sexp)
1071 ((sgml-looking-back-at "--") ; comment 1082 (scan-error
1072 (setq tag-type 'comment 1083 ;; This < seems to be just a spurious one, let's ignore it.
1073 tag-start (search-backward "<!--" nil t))) 1084 (goto-char pos)
1074 ((sgml-looking-back-at "]]") ; cdata 1085 (throw 'found (sgml-parse-tag-backward limit))))
1075 (setq tag-type 'cdata 1086 ;; Check it is really a tag, without any extra < or > inside.
1076 tag-start (re-search-backward "<!\\[[A-Z]+\\[" nil t))) 1087 (unless (sgml-tag-text-p pos (point))
1077 (t 1088 (goto-char pos)
1078 (setq tag-start 1089 (throw 'found (sgml-parse-tag-backward limit)))
1079 (with-syntax-table sgml-tag-syntax-table 1090 (forward-char -1))))
1080 (goto-char tag-end) 1091 (setq tag-end (1+ (point)))
1081 (backward-sexp) 1092 (cond
1082 (point))) 1093 ((sgml-looking-back-at "--") ; comment
1083 (goto-char (1+ tag-start)) 1094 (setq tag-type 'comment
1084 (case (char-after) 1095 tag-start (search-backward "<!--" nil t)))
1085 (?! ; declaration 1096 ((sgml-looking-back-at "]]") ; cdata
1086 (setq tag-type 'decl)) 1097 (setq tag-type 'cdata
1087 (?? ; processing-instruction 1098 tag-start (re-search-backward "<!\\[[A-Z]+\\[" nil t)))
1088 (setq tag-type 'pi)) 1099 (t
1089 (?/ ; close-tag 1100 (setq tag-start
1090 (forward-char 1) 1101 (with-syntax-table sgml-tag-syntax-table
1091 (setq tag-type 'close 1102 (goto-char tag-end)
1092 name (sgml-parse-tag-name))) 1103 (condition-case nil
1093 (?% ; JSP tags 1104 (backward-sexp)
1094 (setq tag-type 'jsp)) 1105 (scan-error
1095 (t ; open or empty tag 1106 ;; This > isn't really the end of a tag. Skip it.
1096 (setq tag-type 'open 1107 (goto-char (1- tag-end))
1097 name (sgml-parse-tag-name)) 1108 (throw 'found (sgml-parse-tag-backward limit))))
1098 (if (or (eq ?/ (char-before (- tag-end 1))) 1109 (point)))
1099 (sgml-empty-tag-p name)) 1110 (goto-char (1+ tag-start))
1100 (setq tag-type 'empty)))))) 1111 (case (char-after)
1101 (goto-char tag-start) 1112 (?! ; declaration
1102 (sgml-make-tag tag-type tag-start tag-end name))) 1113 (setq tag-type 'decl))
1114 (?? ; processing-instruction
1115 (setq tag-type 'pi))
1116 (?/ ; close-tag
1117 (forward-char 1)
1118 (setq tag-type 'close
1119 name (sgml-parse-tag-name)))
1120 (?% ; JSP tags
1121 (setq tag-type 'jsp))
1122 (t ; open or empty tag
1123 (setq tag-type 'open
1124 name (sgml-parse-tag-name))
1125 (if (or (eq ?/ (char-before (- tag-end 1)))
1126 (sgml-empty-tag-p name))
1127 (setq tag-type 'empty))))))
1128 (goto-char tag-start)
1129 (sgml-make-tag tag-type tag-start tag-end name))))
1103 1130
1104(defun sgml-get-context (&optional until) 1131(defun sgml-get-context (&optional until)
1105 "Determine the context of the current position. 1132 "Determine the context of the current position.
@@ -1966,5 +1993,5 @@ Can be used as a value for `html-mode-hook'."
1966 1993
1967(provide 'sgml-mode) 1994(provide 'sgml-mode)
1968 1995
1969;;; arch-tag: 9675da94-b7f9-4bda-ad19-73ed7b4fb401 1996;; arch-tag: 9675da94-b7f9-4bda-ad19-73ed7b4fb401
1970;;; sgml-mode.el ends here 1997;;; sgml-mode.el ends here