diff options
| author | Stefan Monnier | 2001-10-25 22:25:30 +0000 |
|---|---|---|
| committer | Stefan Monnier | 2001-10-25 22:25:30 +0000 |
| commit | 6436765542a0f14d8c0d65bf7616d78bc6767289 (patch) | |
| tree | 759977bf2ae62e8bf195031426ab0042d223a7f7 | |
| parent | 5cd62b8c044951d524a703cbacb8abf249ea0dd0 (diff) | |
| download | emacs-6436765542a0f14d8c0d65bf7616d78bc6767289.tar.gz emacs-6436765542a0f14d8c0d65bf7616d78bc6767289.zip | |
(sgml-font-lock-keywords-1): Ignore comments.
(sgml-font-lock-keywords-2): Use `eval'. Moved from sgml-mode-common.
(sgml-font-lock-syntactic-keywords): New var.
(sgml-mode-common): Drop the two args.
Don't make buffer-local variables that aren't used.
Don't set sgml-font-lock-keywords-2 now that it uses `eval instead.
Don't set `before-string' props from sgml-display-text.
(sgml-mode): Use define-derived-mode.
(sgml-tags-invisible): Use sgml-display-text.
(sgml-quote): New command.
(html-tag-alist): Add args for `span'.
(html-mode): Use define-derived-mode.
Set sgml-display-text and sgml-tag-face-alist.
| -rw-r--r-- | lisp/textmodes/sgml-mode.el | 127 |
1 files changed, 69 insertions, 58 deletions
diff --git a/lisp/textmodes/sgml-mode.el b/lisp/textmodes/sgml-mode.el index a97f0888b11..3642aa5c5b3 100644 --- a/lisp/textmodes/sgml-mode.el +++ b/lisp/textmodes/sgml-mode.el | |||
| @@ -234,16 +234,31 @@ Any terminating `>' or `/' is not matched.") | |||
| 234 | (defconst sgml-font-lock-keywords-1 | 234 | (defconst sgml-font-lock-keywords-1 |
| 235 | '(("<\\([!?][a-z][-.a-z0-9]*\\)" 1 font-lock-keyword-face) | 235 | '(("<\\([!?][a-z][-.a-z0-9]*\\)" 1 font-lock-keyword-face) |
| 236 | ("<\\(/?[a-z][-.a-z0-9]*\\)" 1 font-lock-function-name-face) | 236 | ("<\\(/?[a-z][-.a-z0-9]*\\)" 1 font-lock-function-name-face) |
| 237 | ("[&%][a-z][-.a-z0-9]*;?" . font-lock-variable-name-face) | 237 | ("[&%][a-z][-.a-z0-9]*;?" . font-lock-variable-name-face))) |
| 238 | ("<! *--.*-- *>" . font-lock-comment-face))) | 238 | |
| 239 | 239 | (defconst sgml-font-lock-keywords-2 | |
| 240 | (defconst sgml-font-lock-keywords-2 ()) | 240 | (append |
| 241 | sgml-font-lock-keywords-1 | ||
| 242 | '((eval | ||
| 243 | . (cons (concat "<" | ||
| 244 | (regexp-opt (mapcar 'car sgml-tag-face-alist) t) | ||
| 245 | "\\([ \t][^>]*\\)?>\\([^<]+\\)</\\1>") | ||
| 246 | '(3 (cdr (assoc (downcase (match-string 1)) | ||
| 247 | sgml-tag-face-alist)))))))) | ||
| 241 | 248 | ||
| 242 | ;; for font-lock, but must be defvar'ed after | 249 | ;; for font-lock, but must be defvar'ed after |
| 243 | ;; sgml-font-lock-keywords-1 and sgml-font-lock-keywords-2 above | 250 | ;; sgml-font-lock-keywords-1 and sgml-font-lock-keywords-2 above |
| 244 | (defvar sgml-font-lock-keywords sgml-font-lock-keywords-1 | 251 | (defvar sgml-font-lock-keywords sgml-font-lock-keywords-1 |
| 245 | "*Rules for highlighting SGML code. See also `sgml-tag-face-alist'.") | 252 | "*Rules for highlighting SGML code. See also `sgml-tag-face-alist'.") |
| 246 | 253 | ||
| 254 | (defvar sgml-font-lock-syntactic-keywords | ||
| 255 | ;; Use the `b' style of comments to avoid interference with the -- ... -- | ||
| 256 | ;; comments recognized when `sgml-specials' includes ?-. | ||
| 257 | ;; FIXME: beware of <!--> blabla <!--> !! | ||
| 258 | '(("\\(<\\)!--" (1 "< b")) | ||
| 259 | ("--[ \t\n]*\\(>\\)" (1 "> b"))) | ||
| 260 | "Syntactic keywords for `sgml-mode'.") | ||
| 261 | |||
| 247 | ;; internal | 262 | ;; internal |
| 248 | (defvar sgml-face-tag-alist () | 263 | (defvar sgml-face-tag-alist () |
| 249 | "Alist of face and tag name for facemenu.") | 264 | "Alist of face and tag name for facemenu.") |
| @@ -303,13 +318,8 @@ an optional alist of possible values." | |||
| 303 | 318 | ||
| 304 | (defvar v2) ; free for skeleton | 319 | (defvar v2) ; free for skeleton |
| 305 | 320 | ||
| 306 | (defun sgml-mode-common (sgml-tag-face-alist sgml-display-text) | 321 | (defun sgml-mode-common () |
| 307 | "Common code for setting up `sgml-mode' and derived modes. | 322 | "Common code for setting up `sgml-mode' and derived modes." |
| 308 | SGML-TAG-FACE-ALIST is used for calculating `sgml-font-lock-keywords-2'. | ||
| 309 | SGML-DISPLAY-TEXT sets up alternate text for when tags are invisible (see | ||
| 310 | varables of same name)." | ||
| 311 | (setq local-abbrev-table text-mode-abbrev-table) | ||
| 312 | (set-syntax-table sgml-mode-syntax-table) | ||
| 313 | (make-local-variable 'indent-line-function) | 323 | (make-local-variable 'indent-line-function) |
| 314 | (make-local-variable 'paragraph-start) | 324 | (make-local-variable 'paragraph-start) |
| 315 | (make-local-variable 'paragraph-separate) | 325 | (make-local-variable 'paragraph-separate) |
| @@ -318,25 +328,13 @@ varables of same name)." | |||
| 318 | (make-local-variable 'comment-start) | 328 | (make-local-variable 'comment-start) |
| 319 | (make-local-variable 'comment-end) | 329 | (make-local-variable 'comment-end) |
| 320 | (make-local-variable 'comment-indent-function) | 330 | (make-local-variable 'comment-indent-function) |
| 321 | (make-local-variable 'comment-indent-function) | ||
| 322 | (make-local-variable 'sgml-tags-invisible) | ||
| 323 | (make-local-variable 'skeleton-transformation) | 331 | (make-local-variable 'skeleton-transformation) |
| 324 | (make-local-variable 'skeleton-further-elements) | 332 | (make-local-variable 'skeleton-further-elements) |
| 325 | (make-local-variable 'skeleton-end-hook) | 333 | (make-local-variable 'skeleton-end-hook) |
| 326 | (make-local-variable 'font-lock-defaults) | 334 | (make-local-variable 'font-lock-defaults) |
| 327 | (make-local-variable 'sgml-font-lock-keywords-1) | ||
| 328 | (make-local-variable 'sgml-font-lock-keywords-2) | ||
| 329 | (make-local-variable 'facemenu-add-face-function) | 335 | (make-local-variable 'facemenu-add-face-function) |
| 330 | (make-local-variable 'facemenu-end-add-face) | 336 | (make-local-variable 'facemenu-end-add-face) |
| 331 | ;;(make-local-variable 'facemenu-remove-face-function) | 337 | ;;(make-local-variable 'facemenu-remove-face-function) |
| 332 | (and sgml-tag-face-alist | ||
| 333 | (not (assq 1 sgml-tag-face-alist)) | ||
| 334 | (nconc sgml-tag-face-alist | ||
| 335 | `((1 (,(concat "<\\(" | ||
| 336 | (mapconcat 'car sgml-tag-face-alist "\\|") | ||
| 337 | "\\)\\([ \t].+\\)?>\\(.+\\)</\\1>") | ||
| 338 | 3 (cdr (assoc (downcase (match-string 1)) | ||
| 339 | ',sgml-tag-face-alist))))))) | ||
| 340 | (setq indent-line-function 'indent-relative-maybe | 338 | (setq indent-line-function 'indent-relative-maybe |
| 341 | ;; A start or end tag by itself on a line separates a paragraph. | 339 | ;; A start or end tag by itself on a line separates a paragraph. |
| 342 | ;; This is desirable because SGML discards a newline that appears | 340 | ;; This is desirable because SGML discards a newline that appears |
| @@ -356,21 +354,17 @@ varables of same name)." | |||
| 356 | (not (or (eq v2 '\n) | 354 | (not (or (eq v2 '\n) |
| 357 | (eq (car-safe v2) '\n))) | 355 | (eq (car-safe v2) '\n))) |
| 358 | (newline-and-indent))) | 356 | (newline-and-indent))) |
| 359 | sgml-font-lock-keywords-2 (append | ||
| 360 | sgml-font-lock-keywords-1 | ||
| 361 | (cdr (assq 1 sgml-tag-face-alist))) | ||
| 362 | font-lock-defaults '((sgml-font-lock-keywords | 357 | font-lock-defaults '((sgml-font-lock-keywords |
| 363 | sgml-font-lock-keywords-1 | 358 | sgml-font-lock-keywords-1 |
| 364 | sgml-font-lock-keywords-2) | 359 | sgml-font-lock-keywords-2) |
| 365 | nil | 360 | nil t nil nil |
| 366 | t) | 361 | (font-lock-syntactic-keywords |
| 362 | . sgml-font-lock-syntactic-keywords)) | ||
| 367 | facemenu-add-face-function 'sgml-mode-facemenu-add-face-function) | 363 | facemenu-add-face-function 'sgml-mode-facemenu-add-face-function) |
| 368 | ;; This will allow existing comments within declarations to be | 364 | ;; This will allow existing comments within declarations to be |
| 369 | ;; recognized. | 365 | ;; recognized. |
| 370 | (set (make-local-variable 'comment-start-skip) "\\(?:<!\\)?--[ \t]*") | 366 | (set (make-local-variable 'comment-start-skip) "\\(?:<!\\)?--[ \t]*") |
| 371 | (set (make-local-variable 'comment-end-skip) "[ \t]*--\\([ \t\n]*>\\)?") | 367 | (set (make-local-variable 'comment-end-skip) "[ \t]*--\\([ \t\n]*>\\)?")) |
| 372 | (dolist (pair sgml-display-text) | ||
| 373 | (put (car pair) 'before-string (cdr pair)))) | ||
| 374 | 368 | ||
| 375 | 369 | ||
| 376 | (defun sgml-mode-facemenu-add-face-function (face end) | 370 | (defun sgml-mode-facemenu-add-face-function (face end) |
| @@ -383,7 +377,7 @@ varables of same name)." | |||
| 383 | 377 | ||
| 384 | 378 | ||
| 385 | ;;;###autoload | 379 | ;;;###autoload |
| 386 | (defun sgml-mode () | 380 | (define-derived-mode sgml-mode text-mode "SGML" |
| 387 | "Major mode for editing SGML documents. | 381 | "Major mode for editing SGML documents. |
| 388 | Makes > match <. Makes / blink matching /. | 382 | Makes > match <. Makes / blink matching /. |
| 389 | Keys <, &, SPC within <>, \" and ' can be electric depending on | 383 | Keys <, &, SPC within <>, \" and ' can be electric depending on |
| @@ -401,18 +395,12 @@ Use \\[sgml-validate] to validate your document with an SGML parser. | |||
| 401 | Do \\[describe-variable] sgml- SPC to see available variables. | 395 | Do \\[describe-variable] sgml- SPC to see available variables. |
| 402 | Do \\[describe-key] on the following bindings to discover what they do. | 396 | Do \\[describe-key] on the following bindings to discover what they do. |
| 403 | \\{sgml-mode-map}" | 397 | \\{sgml-mode-map}" |
| 404 | (interactive) | 398 | (sgml-mode-common) |
| 405 | (kill-all-local-variables) | ||
| 406 | (setq mode-name "SGML" | ||
| 407 | major-mode 'sgml-mode) | ||
| 408 | (sgml-mode-common sgml-tag-face-alist sgml-display-text) | ||
| 409 | ;; Set imenu-generic-expression here, rather than in sgml-mode-common, | 399 | ;; Set imenu-generic-expression here, rather than in sgml-mode-common, |
| 410 | ;; because this definition probably is not useful in HTML mode. | 400 | ;; because this definition probably is not useful in HTML mode. |
| 411 | (make-local-variable 'imenu-generic-expression) | 401 | (make-local-variable 'imenu-generic-expression) |
| 412 | (setq imenu-generic-expression | 402 | (setq imenu-generic-expression |
| 413 | "<!\\(element\\|entity\\)[ \t\n]+%?[ \t\n]*\\([A-Za-z][-A-Za-z.0-9]*\\)") | 403 | "<!\\(element\\|entity\\)[ \t\n]+%?[ \t\n]*\\([A-Za-z][-A-Za-z.0-9]*\\)")) |
| 414 | (use-local-map sgml-mode-map) | ||
| 415 | (run-hooks 'text-mode-hook 'sgml-mode-hook)) | ||
| 416 | 404 | ||
| 417 | 405 | ||
| 418 | (defun sgml-comment-indent () | 406 | (defun sgml-comment-indent () |
| @@ -747,8 +735,9 @@ With prefix argument ARG, repeat this ARG times." | |||
| 747 | (buffer-file-name nil) | 735 | (buffer-file-name nil) |
| 748 | ;; This is needed in case font lock gets called, | 736 | ;; This is needed in case font lock gets called, |
| 749 | ;; since it moves point and might call sgml-point-entered. | 737 | ;; since it moves point and might call sgml-point-entered. |
| 738 | ;; How could it get called? -stef | ||
| 750 | (inhibit-point-motion-hooks t) | 739 | (inhibit-point-motion-hooks t) |
| 751 | symbol) | 740 | string) |
| 752 | (unwind-protect | 741 | (unwind-protect |
| 753 | (save-excursion | 742 | (save-excursion |
| 754 | (goto-char (point-min)) | 743 | (goto-char (point-min)) |
| @@ -758,21 +747,22 @@ With prefix argument ARG, repeat this ARG times." | |||
| 758 | (not sgml-tags-invisible))) | 747 | (not sgml-tags-invisible))) |
| 759 | (while (re-search-forward "<\\([!/?A-Za-z][-A-Za-z0-9]*\\)" | 748 | (while (re-search-forward "<\\([!/?A-Za-z][-A-Za-z0-9]*\\)" |
| 760 | nil t) | 749 | nil t) |
| 761 | (setq symbol (intern-soft (downcase (match-string 1)))) | 750 | (setq string |
| 751 | (cdr (assq (intern-soft (downcase (match-string 1))) | ||
| 752 | sgml-display-text))) | ||
| 762 | (goto-char (match-beginning 0)) | 753 | (goto-char (match-beginning 0)) |
| 763 | (and (get symbol 'before-string) | 754 | (and (stringp string) |
| 764 | (not (overlays-at (point))) | 755 | (not (overlays-at (point))) |
| 765 | (overlay-put (make-overlay (point) | 756 | (overlay-put (make-overlay (point) |
| 766 | (match-beginning 1)) | 757 | (match-beginning 1)) |
| 767 | 'category symbol)) | 758 | 'before-string string)) |
| 768 | (put-text-property (point) | 759 | (put-text-property (point) |
| 769 | (progn (forward-list) (point)) | 760 | (progn (forward-list) (point)) |
| 770 | 'category 'sgml-tag)) | 761 | 'category 'sgml-tag)) |
| 771 | (let ((pos (point))) | 762 | (let ((pos (point-min))) |
| 772 | (while (< (setq pos (next-overlay-change pos)) (point-max)) | 763 | (while (< (setq pos (next-overlay-change pos)) (point-max)) |
| 773 | (delete-overlay (car (overlays-at pos))))) | 764 | (delete-overlay (car (overlays-at pos))))) |
| 774 | (remove-text-properties (point-min) (point-max) | 765 | (remove-text-properties (point-min) (point-max) '(category nil)))) |
| 775 | '(category sgml-tag intangible t)))) | ||
| 776 | (restore-buffer-modified-p modified)) | 766 | (restore-buffer-modified-p modified)) |
| 777 | (run-hooks 'sgml-tags-invisible-hook) | 767 | (run-hooks 'sgml-tags-invisible-hook) |
| 778 | (message ""))) | 768 | (message ""))) |
| @@ -854,6 +844,22 @@ See `sgml-tag-alist' for info about attributerules.." | |||
| 854 | (if alist | 844 | (if alist |
| 855 | (insert (skeleton-read '(completing-read "Value: " alist)))) | 845 | (insert (skeleton-read '(completing-read "Value: " alist)))) |
| 856 | (insert ?\")))) | 846 | (insert ?\")))) |
| 847 | |||
| 848 | (defun sgml-quote (start end &optional unquotep) | ||
| 849 | "Quote SGML text in region. | ||
| 850 | With prefix argument, unquote the region." | ||
| 851 | (interactive "r\np") | ||
| 852 | (if (< start end) | ||
| 853 | (goto-char start) | ||
| 854 | (goto-char end) | ||
| 855 | (setq end start)) | ||
| 856 | (if unquotep | ||
| 857 | (while (re-search-forward "&\\(amp\\|\\(l\\|\\(g\\)\\)t\\);" end t) | ||
| 858 | (replace-match (if (match-end 3) ">" (if (match-end 2) "<" "&")))) | ||
| 859 | (while (re-search-forward "[&<>]" end t) | ||
| 860 | (replace-match (cdr (assq (char-before) '((?& . "&") | ||
| 861 | (?< . "<") | ||
| 862 | (?> . ">")))))))) | ||
| 857 | 863 | ||
| 858 | 864 | ||
| 859 | ;;; HTML mode | 865 | ;;; HTML mode |
| @@ -1098,7 +1104,17 @@ This takes effect when first loading the library.") | |||
| 1098 | ("s") | 1104 | ("s") |
| 1099 | ("samp") | 1105 | ("samp") |
| 1100 | ("small") | 1106 | ("small") |
| 1101 | ("span") | 1107 | ("span" nil |
| 1108 | ("class" | ||
| 1109 | ("builtin") | ||
| 1110 | ("comment") | ||
| 1111 | ("constant") | ||
| 1112 | ("function-name") | ||
| 1113 | ("keyword") | ||
| 1114 | ("string") | ||
| 1115 | ("type") | ||
| 1116 | ("variable-name") | ||
| 1117 | ("warning"))) | ||
| 1102 | ("strong") | 1118 | ("strong") |
| 1103 | ("sub") | 1119 | ("sub") |
| 1104 | ("sup") | 1120 | ("sup") |
| @@ -1202,7 +1218,7 @@ This takes effect when first loading the library.") | |||
| 1202 | "*Value of `sgml-tag-help' for HTML mode.") | 1218 | "*Value of `sgml-tag-help' for HTML mode.") |
| 1203 | 1219 | ||
| 1204 | ;;;###autoload | 1220 | ;;;###autoload |
| 1205 | (defun html-mode () | 1221 | (define-derived-mode html-mode sgml-mode "HTML" |
| 1206 | "Major mode based on SGML mode for editing HTML documents. | 1222 | "Major mode based on SGML mode for editing HTML documents. |
| 1207 | This allows inserting skeleton constructs used in hypertext documents with | 1223 | This allows inserting skeleton constructs used in hypertext documents with |
| 1208 | completion. See below for an introduction to HTML. Use | 1224 | completion. See below for an introduction to HTML. Use |
| @@ -1238,12 +1254,8 @@ To work around that, do: | |||
| 1238 | (eval-after-load \"sgml-mode\" '(aset sgml-char-names ?' nil)) | 1254 | (eval-after-load \"sgml-mode\" '(aset sgml-char-names ?' nil)) |
| 1239 | 1255 | ||
| 1240 | \\{html-mode-map}" | 1256 | \\{html-mode-map}" |
| 1241 | (interactive) | 1257 | (set (make-local-variable 'sgml-display-text) html-display-text) |
| 1242 | (kill-all-local-variables) | 1258 | (set (make-local-variable 'sgml-tag-face-alist) html-tag-face-alist) |
| 1243 | (setq mode-name "HTML" | ||
| 1244 | major-mode 'html-mode) | ||
| 1245 | (sgml-mode-common html-tag-face-alist html-display-text) | ||
| 1246 | (use-local-map html-mode-map) | ||
| 1247 | (make-local-variable 'sgml-tag-alist) | 1259 | (make-local-variable 'sgml-tag-alist) |
| 1248 | (make-local-variable 'sgml-face-tag-alist) | 1260 | (make-local-variable 'sgml-face-tag-alist) |
| 1249 | (make-local-variable 'sgml-tag-help) | 1261 | (make-local-variable 'sgml-tag-help) |
| @@ -1254,8 +1266,7 @@ To work around that, do: | |||
| 1254 | (setq sentence-end | 1266 | (setq sentence-end |
| 1255 | (if sentence-end-double-space | 1267 | (if sentence-end-double-space |
| 1256 | "[.?!][]\"')}]*\\(<[^>]*>\\)*\\($\\| $\\|\t\\| \\)[ \t\n]*" | 1268 | "[.?!][]\"')}]*\\(<[^>]*>\\)*\\($\\| $\\|\t\\| \\)[ \t\n]*" |
| 1257 | 1269 | "[.?!][]\"')}]*\\(<[^>]*>\\)*\\($\\|[ \t]\\)[ \t\n]*")) | |
| 1258 | "[.?!][]\"')}]*\\(<[^>]*>\\)*\\($\\| \\|\t\\)[ \t\n]*")) | ||
| 1259 | (setq sgml-tag-alist html-tag-alist | 1270 | (setq sgml-tag-alist html-tag-alist |
| 1260 | sgml-face-tag-alist html-face-tag-alist | 1271 | sgml-face-tag-alist html-face-tag-alist |
| 1261 | sgml-tag-help html-tag-help | 1272 | sgml-tag-help html-tag-help |
| @@ -1267,7 +1278,7 @@ To work around that, do: | |||
| 1267 | ;; It's for the user to decide if it defeats it or not -stef | 1278 | ;; It's for the user to decide if it defeats it or not -stef |
| 1268 | ;; (make-local-variable 'imenu-sort-function) | 1279 | ;; (make-local-variable 'imenu-sort-function) |
| 1269 | ;; (setq imenu-sort-function nil) ; sorting the menu defeats the purpose | 1280 | ;; (setq imenu-sort-function nil) ; sorting the menu defeats the purpose |
| 1270 | (run-hooks 'text-mode-hook 'sgml-mode-hook 'html-mode-hook)) | 1281 | ) |
| 1271 | 1282 | ||
| 1272 | (defvar html-imenu-regexp | 1283 | (defvar html-imenu-regexp |
| 1273 | "\\s-*<h\\([1-9]\\)[^\n<>]*>\\(<[^\n<>]*>\\)*\\s-*\\([^\n<>]*\\)" | 1284 | "\\s-*<h\\([1-9]\\)[^\n<>]*>\\(<[^\n<>]*>\\)*\\s-*\\([^\n<>]*\\)" |