diff options
| author | Michael Olson | 2008-06-06 16:14:49 +0000 |
|---|---|---|
| committer | Michael Olson | 2008-06-06 16:14:49 +0000 |
| commit | e8ec402f1b86a1ed2c61bbc7de27aaefa2adb496 (patch) | |
| tree | 5f38efb237d6a61a93748ebee3028643e2fb49b9 | |
| parent | 0a3a94b3d28f55ceb4d443da17c00c9bda83eb4a (diff) | |
| download | emacs-e8ec402f1b86a1ed2c61bbc7de27aaefa2adb496.tar.gz emacs-e8ec402f1b86a1ed2c61bbc7de27aaefa2adb496.zip | |
nXML: Use font lock
| -rw-r--r-- | lisp/nxml/nxml-mode.el | 312 | ||||
| -rw-r--r-- | lisp/nxml/nxml-rap.el | 24 | ||||
| -rw-r--r-- | lisp/nxml/nxml-util.el | 40 |
3 files changed, 217 insertions, 159 deletions
diff --git a/lisp/nxml/nxml-mode.el b/lisp/nxml/nxml-mode.el index b1c6194cfa3..cb13d588c04 100644 --- a/lisp/nxml/nxml-mode.el +++ b/lisp/nxml/nxml-mode.el | |||
| @@ -24,11 +24,6 @@ | |||
| 24 | 24 | ||
| 25 | ;; See nxml-rap.el for description of parsing strategy. | 25 | ;; See nxml-rap.el for description of parsing strategy. |
| 26 | 26 | ||
| 27 | ;; The font locking here is independent of font-lock.el. We want to | ||
| 28 | ;; do more sophisticated handling of changes and we want to use the | ||
| 29 | ;; same xmltok rather than regexps for parsing so that we parse | ||
| 30 | ;; consistently and correctly. | ||
| 31 | |||
| 32 | ;;; Code: | 27 | ;;; Code: |
| 33 | 28 | ||
| 34 | (when (featurep 'mucs) | 29 | (when (featurep 'mucs) |
| @@ -56,11 +51,6 @@ | |||
| 56 | :group 'nxml | 51 | :group 'nxml |
| 57 | :group 'font-lock-faces) | 52 | :group 'font-lock-faces) |
| 58 | 53 | ||
| 59 | (defcustom nxml-syntax-highlight-flag t | ||
| 60 | "*Non-nil means nxml-mode should perform syntax highlighting." | ||
| 61 | :group 'nxml | ||
| 62 | :type 'boolean) | ||
| 63 | |||
| 64 | (defcustom nxml-char-ref-display-glyph-flag t | 54 | (defcustom nxml-char-ref-display-glyph-flag t |
| 65 | "*Non-nil means display glyph following character reference. | 55 | "*Non-nil means display glyph following character reference. |
| 66 | The glyph is displayed in face `nxml-glyph'. The hook | 56 | The glyph is displayed in face `nxml-glyph'. The hook |
| @@ -100,8 +90,6 @@ attribute on the previous line." | |||
| 100 | :group 'nxml | 90 | :group 'nxml |
| 101 | :type 'integer) | 91 | :type 'integer) |
| 102 | 92 | ||
| 103 | (defvar nxml-fontify-chunk-size 500) | ||
| 104 | |||
| 105 | (defcustom nxml-bind-meta-tab-to-complete-flag (not window-system) | 93 | (defcustom nxml-bind-meta-tab-to-complete-flag (not window-system) |
| 106 | "*Non-nil means bind M-TAB in `nxml-mode-map' to `nxml-complete'. | 94 | "*Non-nil means bind M-TAB in `nxml-mode-map' to `nxml-complete'. |
| 107 | C-return will be bound to `nxml-complete' in any case. | 95 | C-return will be bound to `nxml-complete' in any case. |
| @@ -432,19 +420,13 @@ reference.") | |||
| 432 | map) | 420 | map) |
| 433 | "Keymap for nxml-mode.") | 421 | "Keymap for nxml-mode.") |
| 434 | 422 | ||
| 423 | (defvar nxml-font-lock-keywords | ||
| 424 | '(nxml-fontify-matcher) | ||
| 425 | "Default font lock keywords for nxml-mode.") | ||
| 426 | |||
| 435 | (defsubst nxml-set-face (start end face) | 427 | (defsubst nxml-set-face (start end face) |
| 436 | (when (and face (< start end)) | 428 | (when (and face (< start end)) |
| 437 | (put-text-property start end 'face face))) | 429 | (font-lock-append-text-property start end 'face face))) |
| 438 | |||
| 439 | (defun nxml-clear-face (start end) | ||
| 440 | (remove-text-properties start end '(face nil)) | ||
| 441 | (nxml-clear-char-ref-extra-display start end)) | ||
| 442 | |||
| 443 | (defsubst nxml-set-fontified (start end) | ||
| 444 | (put-text-property start end 'fontified t)) | ||
| 445 | |||
| 446 | (defsubst nxml-clear-fontified (start end) | ||
| 447 | (remove-text-properties start end '(fontified nil))) | ||
| 448 | 430 | ||
| 449 | ;;;###autoload | 431 | ;;;###autoload |
| 450 | (defun nxml-mode () | 432 | (defun nxml-mode () |
| @@ -453,9 +435,6 @@ reference.") | |||
| 453 | ;; not mnemonic. | 435 | ;; not mnemonic. |
| 454 | "Major mode for editing XML. | 436 | "Major mode for editing XML. |
| 455 | 437 | ||
| 456 | Syntax highlighting is performed unless the variable | ||
| 457 | `nxml-syntax-highlight-flag' is nil. | ||
| 458 | |||
| 459 | \\[nxml-finish-element] finishes the current element by inserting an end-tag. | 438 | \\[nxml-finish-element] finishes the current element by inserting an end-tag. |
| 460 | C-c C-i closes a start-tag with `>' and then inserts a balancing end-tag | 439 | C-c C-i closes a start-tag with `>' and then inserts a balancing end-tag |
| 461 | leaving point between the start-tag and end-tag. | 440 | leaving point between the start-tag and end-tag. |
| @@ -540,13 +519,9 @@ Many aspects this mode can be customized using | |||
| 540 | (nxml-clear-dependent-regions (point-min) (point-max)) | 519 | (nxml-clear-dependent-regions (point-min) (point-max)) |
| 541 | (setq nxml-scan-end (copy-marker (point-min) nil)) | 520 | (setq nxml-scan-end (copy-marker (point-min) nil)) |
| 542 | (nxml-with-unmodifying-text-property-changes | 521 | (nxml-with-unmodifying-text-property-changes |
| 543 | (when nxml-syntax-highlight-flag | 522 | (nxml-clear-inside (point-min) (point-max)) |
| 544 | (nxml-clear-fontified (point-min) (point-max))) | ||
| 545 | (nxml-clear-inside (point-min) (point-max)) | ||
| 546 | (nxml-with-invisible-motion | 523 | (nxml-with-invisible-motion |
| 547 | (nxml-scan-prolog))))) | 524 | (nxml-scan-prolog))))) |
| 548 | (when nxml-syntax-highlight-flag | ||
| 549 | (add-hook 'fontification-functions 'nxml-fontify nil t)) | ||
| 550 | (add-hook 'after-change-functions 'nxml-after-change nil t) | 525 | (add-hook 'after-change-functions 'nxml-after-change nil t) |
| 551 | (add-hook 'change-major-mode-hook 'nxml-cleanup nil t) | 526 | (add-hook 'change-major-mode-hook 'nxml-cleanup nil t) |
| 552 | 527 | ||
| @@ -561,6 +536,19 @@ Many aspects this mode can be customized using | |||
| 561 | (setq buffer-file-coding-system nxml-default-buffer-file-coding-system)) | 536 | (setq buffer-file-coding-system nxml-default-buffer-file-coding-system)) |
| 562 | (when nxml-auto-insert-xml-declaration-flag | 537 | (when nxml-auto-insert-xml-declaration-flag |
| 563 | (nxml-insert-xml-declaration))) | 538 | (nxml-insert-xml-declaration))) |
| 539 | |||
| 540 | (setq font-lock-defaults | ||
| 541 | '(nxml-font-lock-keywords | ||
| 542 | t ; keywords-only; we highlight comments and strings here | ||
| 543 | nil ; font-lock-keywords-case-fold-search. XML is case sensitive | ||
| 544 | nil ; no special syntax table | ||
| 545 | nil ; no automatic syntactic fontification | ||
| 546 | (font-lock-extend-after-change-region-function | ||
| 547 | . nxml-extend-after-change-region) | ||
| 548 | (font-lock-extend-region-functions . (nxml-extend-region)) | ||
| 549 | (jit-lock-contextually . t) | ||
| 550 | (font-lock-unfontify-region-function . nxml-unfontify-region))) | ||
| 551 | |||
| 564 | (rng-nxml-mode-init) | 552 | (rng-nxml-mode-init) |
| 565 | (nxml-enable-unicode-char-name-sets) | 553 | (nxml-enable-unicode-char-name-sets) |
| 566 | (run-hooks 'nxml-mode-hook)) | 554 | (run-hooks 'nxml-mode-hook)) |
| @@ -591,84 +579,73 @@ Many aspects this mode can be customized using | |||
| 591 | (save-restriction | 579 | (save-restriction |
| 592 | (widen) | 580 | (widen) |
| 593 | (nxml-with-unmodifying-text-property-changes | 581 | (nxml-with-unmodifying-text-property-changes |
| 594 | (nxml-clear-face (point-min) (point-max)) | ||
| 595 | (nxml-set-fontified (point-min) (point-max)) | ||
| 596 | (nxml-clear-inside (point-min) (point-max)))))) | 582 | (nxml-clear-inside (point-min) (point-max)))))) |
| 597 | 583 | ||
| 598 | ;;; Change management | 584 | ;;; Change management |
| 599 | 585 | ||
| 586 | (defun nxml-debug-region (start end) | ||
| 587 | (interactive "r") | ||
| 588 | (let ((font-lock-beg start) | ||
| 589 | (font-lock-end end)) | ||
| 590 | (nxml-extend-region) | ||
| 591 | (goto-char font-lock-beg) | ||
| 592 | (set-mark font-lock-end))) | ||
| 593 | |||
| 600 | (defun nxml-after-change (start end pre-change-length) | 594 | (defun nxml-after-change (start end pre-change-length) |
| 601 | ;; Work around bug in insert-file-contents. | 595 | ; In font-lock mode, nxml-after-change1 is called via |
| 602 | (when (> end (1+ (buffer-size))) | 596 | ; nxml-extend-after-change-region instead so that the updated |
| 603 | (setq start 1) | 597 | ; book-keeping information is available for fontification. |
| 604 | (setq end (1+ (buffer-size)))) | 598 | (unless (or font-lock-mode nxml-degraded) |
| 605 | (unless nxml-degraded | 599 | (nxml-with-degradation-on-error 'nxml-after-change |
| 606 | (condition-case err | 600 | (save-excursion |
| 607 | (save-excursion | 601 | (save-restriction |
| 608 | (save-restriction | 602 | (widen) |
| 609 | (widen) | 603 | (save-match-data |
| 610 | (save-match-data | 604 | (nxml-with-invisible-motion |
| 611 | (nxml-with-invisible-motion | 605 | (nxml-with-unmodifying-text-property-changes |
| 612 | (nxml-with-unmodifying-text-property-changes | 606 | (nxml-after-change1 |
| 613 | (nxml-after-change1 start end pre-change-length)))))) | 607 | start end pre-change-length))))))))) |
| 614 | (error | ||
| 615 | (nxml-degrade 'nxml-after-change err))))) | ||
| 616 | 608 | ||
| 617 | (defun nxml-after-change1 (start end pre-change-length) | 609 | (defun nxml-after-change1 (start end pre-change-length) |
| 618 | (setq nxml-last-fontify-end nil) | 610 | "After-change bookkeeping. Returns a cons cell containing a |
| 611 | possibly-enlarged change region. You must call | ||
| 612 | nxml-extend-region on this expanded region to obtain the full | ||
| 613 | extent of the area needing refontification. | ||
| 614 | |||
| 615 | For bookkeeping, call this function even when fontification is | ||
| 616 | disabled." | ||
| 619 | (let ((pre-change-end (+ start pre-change-length))) | 617 | (let ((pre-change-end (+ start pre-change-length))) |
| 620 | (setq start | 618 | (setq start |
| 621 | (nxml-adjust-start-for-dependent-regions start | 619 | (nxml-adjust-start-for-dependent-regions start |
| 622 | end | 620 | end |
| 623 | pre-change-length)) | 621 | pre-change-length)) |
| 622 | ;; If the prolog might have changed, rescan the prolog | ||
| 624 | (when (<= start | 623 | (when (<= start |
| 625 | ;; Add 2 so as to include the < and following char | 624 | ;; Add 2 so as to include the < and following char that |
| 626 | ;; that start the instance, since changing these | 625 | ;; start the instance (document element), since changing |
| 627 | ;; can change where the prolog ends. | 626 | ;; these can change where the prolog ends. |
| 628 | (+ nxml-prolog-end 2)) | 627 | (+ nxml-prolog-end 2)) |
| 629 | ;; end must be extended to at least the end of the old prolog | 628 | ;; end must be extended to at least the end of the old prolog in |
| 629 | ;; case the new prolog is shorter | ||
| 630 | (when (< pre-change-end nxml-prolog-end) | 630 | (when (< pre-change-end nxml-prolog-end) |
| 631 | (setq end | 631 | (setq end |
| 632 | ;; don't let end get out of range even if pre-change-length | 632 | ;; don't let end get out of range even if pre-change-length |
| 633 | ;; is bogus | 633 | ;; is bogus |
| 634 | (min (point-max) | 634 | (min (point-max) |
| 635 | (+ end (- nxml-prolog-end pre-change-end))))) | 635 | (+ end (- nxml-prolog-end pre-change-end))))) |
| 636 | (nxml-scan-prolog))) | 636 | (nxml-scan-prolog) |
| 637 | (cond ((<= end nxml-prolog-end) | 637 | (setq start (point-min)))) |
| 638 | (setq end nxml-prolog-end) | 638 | |
| 639 | (goto-char start) | 639 | (when (> end nxml-prolog-end) |
| 640 | ;; This is so that Emacs redisplay works | 640 | (goto-char start) |
| 641 | (setq start (line-beginning-position))) | 641 | (nxml-move-tag-backwards (point-min)) |
| 642 | ((and (<= start nxml-scan-end) | 642 | (setq start (point)) |
| 643 | (> start (point-min)) | 643 | (setq end (max (nxml-scan-after-change start end) |
| 644 | (nxml-get-inside (1- start))) | 644 | end))) |
| 645 | ;; The closing delimiter might have been removed. | 645 | |
| 646 | ;; So we may need to redisplay from the beginning | 646 | (nxml-debug-change "nxml-after-change1" start end) |
| 647 | ;; of the token. | 647 | (cons start end)) |
| 648 | (goto-char (1- start)) | 648 | |
| 649 | (nxml-move-outside-backwards) | ||
| 650 | ;; This is so that Emacs redisplay works | ||
| 651 | (setq start (line-beginning-position)) | ||
| 652 | (setq end (max (nxml-scan-after-change (point) end) | ||
| 653 | end))) | ||
| 654 | (t | ||
| 655 | (goto-char start) | ||
| 656 | ;; This is both for redisplay and to move back | ||
| 657 | ;; past any incomplete opening delimiters | ||
| 658 | (setq start (line-beginning-position)) | ||
| 659 | (setq end (max (nxml-scan-after-change start end) | ||
| 660 | end)))) | ||
| 661 | (when nxml-syntax-highlight-flag | ||
| 662 | (when (>= start end) | ||
| 663 | ;; Must clear at least one char so as to trigger redisplay. | ||
| 664 | (cond ((< start (point-max)) | ||
| 665 | (setq end (1+ start))) | ||
| 666 | (t | ||
| 667 | (setq end (point-max)) | ||
| 668 | (goto-char end) | ||
| 669 | (setq start (line-beginning-position))))) | ||
| 670 | (nxml-clear-fontified start end))) | ||
| 671 | |||
| 672 | ;;; Encodings | 649 | ;;; Encodings |
| 673 | 650 | ||
| 674 | (defun nxml-insert-xml-declaration () | 651 | (defun nxml-insert-xml-declaration () |
| @@ -854,51 +831,98 @@ The XML declaration will declare an encoding depending on the buffer's | |||
| 854 | 831 | ||
| 855 | ;;; Fontification | 832 | ;;; Fontification |
| 856 | 833 | ||
| 857 | (defun nxml-fontify (start) | 834 | (defun nxml-unfontify-region (start end) |
| 858 | (condition-case err | 835 | (font-lock-default-unfontify-region start end) |
| 859 | (save-excursion | 836 | (nxml-clear-char-ref-extra-display start end)) |
| 860 | (save-restriction | 837 | |
| 861 | (widen) | 838 | (defvar font-lock-beg) (defvar font-lock-end) |
| 862 | (save-match-data | 839 | (defun nxml-extend-region () |
| 863 | (nxml-with-invisible-motion | 840 | "Extend the region to hold the minimum area we can fontify with nXML. |
| 864 | (nxml-with-unmodifying-text-property-changes | 841 | Called with font-lock-beg and font-lock-end dynamically bound." |
| 865 | (if (or nxml-degraded | 842 | (let ((start font-lock-beg) |
| 866 | ;; just in case we get called in the wrong buffer | 843 | (end font-lock-end)) |
| 867 | (not nxml-prolog-end)) | 844 | |
| 868 | (nxml-set-fontified start (point-max)) | 845 | (nxml-debug-change "nxml-extend-region(input)" start end) |
| 869 | (nxml-fontify1 start))))))) | 846 | |
| 870 | (error | 847 | (when (< start nxml-prolog-end) |
| 871 | (nxml-degrade 'nxml-fontify err)))) | 848 | (setq start (point-min))) |
| 872 | 849 | ||
| 873 | (defun nxml-fontify1 (start) | 850 | (cond ((<= end nxml-prolog-end) |
| 874 | (cond ((< start nxml-prolog-end) | 851 | (setq end nxml-prolog-end)) |
| 875 | (nxml-fontify-prolog) | 852 | |
| 876 | (nxml-set-fontified (point-min) | 853 | (t |
| 877 | nxml-prolog-end)) | 854 | (goto-char start) |
| 878 | (t | 855 | ;; some font-lock backends (like Emacs 22 jit-lock) snap |
| 879 | (goto-char start) | 856 | ;; the region to the beginning of the line no matter what |
| 880 | (when (not (eq nxml-last-fontify-end start)) | 857 | ;; we say here. To mitigate the resulting excess |
| 881 | (when (not (equal (char-after) ?\<)) | 858 | ;; fontification, ignore leading whitespace. |
| 882 | (search-backward "<" nxml-prolog-end t)) | 859 | (skip-syntax-forward " ") |
| 883 | (nxml-ensure-scan-up-to-date) | 860 | |
| 884 | (nxml-move-outside-backwards)) | 861 | ;; find the beginning of the previous tag |
| 885 | (let ((start (point))) | 862 | (when (not (equal (char-after) ?\<)) |
| 886 | (nxml-do-fontify (min (point-max) | 863 | (search-backward "<" nxml-prolog-end t)) |
| 887 | (+ start nxml-fontify-chunk-size))) | 864 | (nxml-ensure-scan-up-to-date) |
| 888 | (setq nxml-last-fontify-end (point)) | 865 | (nxml-move-outside-backwards) |
| 889 | (nxml-set-fontified start nxml-last-fontify-end))))) | 866 | (setq start (point)) |
| 890 | 867 | ||
| 891 | (defun nxml-fontify-buffer () | 868 | (while (< (point) end) |
| 892 | (interactive) | 869 | (nxml-tokenize-forward)) |
| 893 | (save-excursion | 870 | |
| 894 | (save-restriction | 871 | (setq end (point)))) |
| 895 | (widen) | 872 | |
| 896 | (nxml-with-invisible-motion | 873 | (when (or (< start font-lock-beg) |
| 897 | (goto-char (point-min)) | 874 | (> end font-lock-end)) |
| 898 | (nxml-with-unmodifying-text-property-changes | 875 | (setq font-lock-beg start |
| 899 | (nxml-fontify-prolog) | 876 | font-lock-end end) |
| 900 | (goto-char nxml-prolog-end) | 877 | (nxml-debug-change "nxml-extend-region" start end) |
| 901 | (nxml-do-fontify)))))) | 878 | t))) |
| 879 | |||
| 880 | (defun nxml-extend-after-change-region (start end pre-change-length) | ||
| 881 | (unless nxml-degraded | ||
| 882 | (setq nxml-last-fontify-end nil) | ||
| 883 | |||
| 884 | (nxml-with-degradation-on-error 'nxml-extend-after-change-region | ||
| 885 | (save-excursion | ||
| 886 | (save-restriction | ||
| 887 | (widen) | ||
| 888 | (save-match-data | ||
| 889 | (nxml-with-invisible-motion | ||
| 890 | (nxml-with-unmodifying-text-property-changes | ||
| 891 | (nxml-extend-after-change-region1 | ||
| 892 | start end pre-change-length))))))))) | ||
| 893 | |||
| 894 | (defun nxml-extend-after-change-region1 (start end pre-change-length) | ||
| 895 | (let* ((region (nxml-after-change1 start end pre-change-length)) | ||
| 896 | (font-lock-beg (car region)) | ||
| 897 | (font-lock-end (cdr region))) | ||
| 898 | |||
| 899 | (nxml-extend-region) | ||
| 900 | (cons font-lock-beg font-lock-end))) | ||
| 901 | |||
| 902 | (defun nxml-fontify-matcher (bound) | ||
| 903 | "Called as font-lock keyword matcher." | ||
| 904 | |||
| 905 | (unless nxml-degraded | ||
| 906 | (nxml-debug-change "nxml-fontify-matcher" (point) bound) | ||
| 907 | |||
| 908 | (when (< (point) nxml-prolog-end) | ||
| 909 | ;; prolog needs to be fontified in one go, and | ||
| 910 | ;; nxml-extend-region makes sure we start at BOB. | ||
| 911 | (assert (bobp)) | ||
| 912 | (nxml-fontify-prolog) | ||
| 913 | (goto-char nxml-prolog-end)) | ||
| 914 | |||
| 915 | (let (xmltok-dependent-regions | ||
| 916 | xmltok-errors) | ||
| 917 | (while (and (nxml-tokenize-forward) | ||
| 918 | (<= (point) bound)) ; intervals are open-ended | ||
| 919 | (nxml-apply-fontify-rule))) | ||
| 920 | |||
| 921 | (setq nxml-last-fontify-end (point))) | ||
| 922 | |||
| 923 | ;; Since we did the fontification internally, tell font-lock to not | ||
| 924 | ;; do anything itself. | ||
| 925 | nil) | ||
| 902 | 926 | ||
| 903 | (defun nxml-fontify-prolog () | 927 | (defun nxml-fontify-prolog () |
| 904 | "Fontify the prolog. | 928 | "Fontify the prolog. |
| @@ -906,7 +930,6 @@ The buffer is assumed to be prepared for fontification. | |||
| 906 | This does not set the fontified property, but it does clear | 930 | This does not set the fontified property, but it does clear |
| 907 | faces appropriately." | 931 | faces appropriately." |
| 908 | (let ((regions nxml-prolog-regions)) | 932 | (let ((regions nxml-prolog-regions)) |
| 909 | (nxml-clear-face (point-min) nxml-prolog-end) | ||
| 910 | (while regions | 933 | (while regions |
| 911 | (let ((region (car regions))) | 934 | (let ((region (car regions))) |
| 912 | (nxml-apply-fontify-rule (aref region 0) | 935 | (nxml-apply-fontify-rule (aref region 0) |
| @@ -914,17 +937,6 @@ faces appropriately." | |||
| 914 | (aref region 2))) | 937 | (aref region 2))) |
| 915 | (setq regions (cdr regions))))) | 938 | (setq regions (cdr regions))))) |
| 916 | 939 | ||
| 917 | (defun nxml-do-fontify (&optional bound) | ||
| 918 | "Fontify at least as far as bound. | ||
| 919 | Leave point after last fontified position." | ||
| 920 | (unless bound (setq bound (point-max))) | ||
| 921 | (let (xmltok-dependent-regions | ||
| 922 | xmltok-errors) | ||
| 923 | (while (and (< (point) bound) | ||
| 924 | (nxml-tokenize-forward)) | ||
| 925 | (nxml-clear-face xmltok-start (point)) | ||
| 926 | (nxml-apply-fontify-rule)))) | ||
| 927 | |||
| 928 | ;; Vectors identify a substring of the token to be highlighted in some face. | 940 | ;; Vectors identify a substring of the token to be highlighted in some face. |
| 929 | 941 | ||
| 930 | ;; Token types returned by xmltok-forward. | 942 | ;; Token types returned by xmltok-forward. |
| @@ -2574,13 +2586,7 @@ With a prefix argument, inserts the character directly." | |||
| 2574 | (> (prefix-numeric-value arg) 0)))) | 2586 | (> (prefix-numeric-value arg) 0)))) |
| 2575 | (when (not (eq new nxml-char-ref-extra-display)) | 2587 | (when (not (eq new nxml-char-ref-extra-display)) |
| 2576 | (setq nxml-char-ref-extra-display new) | 2588 | (setq nxml-char-ref-extra-display new) |
| 2577 | (save-excursion | 2589 | (font-lock-fontify-buffer)))) |
| 2578 | (save-restriction | ||
| 2579 | (widen) | ||
| 2580 | (if nxml-char-ref-extra-display | ||
| 2581 | (nxml-with-unmodifying-text-property-changes | ||
| 2582 | (nxml-clear-fontified (point-min) (point-max))) | ||
| 2583 | (nxml-clear-char-ref-extra-display (point-min) (point-max)))))))) | ||
| 2584 | 2590 | ||
| 2585 | (put 'nxml-char-ref 'evaporate t) | 2591 | (put 'nxml-char-ref 'evaporate t) |
| 2586 | 2592 | ||
diff --git a/lisp/nxml/nxml-rap.el b/lisp/nxml/nxml-rap.el index 47ef53bbcbe..7d6078f1119 100644 --- a/lisp/nxml/nxml-rap.el +++ b/lisp/nxml/nxml-rap.el | |||
| @@ -110,9 +110,11 @@ There must be no nxml-inside properties after nxml-scan-end.") | |||
| 110 | (get-text-property pos 'nxml-inside)) | 110 | (get-text-property pos 'nxml-inside)) |
| 111 | 111 | ||
| 112 | (defsubst nxml-clear-inside (start end) | 112 | (defsubst nxml-clear-inside (start end) |
| 113 | (nxml-debug-clear-inside start end) | ||
| 113 | (remove-text-properties start end '(nxml-inside nil))) | 114 | (remove-text-properties start end '(nxml-inside nil))) |
| 114 | 115 | ||
| 115 | (defsubst nxml-set-inside (start end type) | 116 | (defsubst nxml-set-inside (start end type) |
| 117 | (nxml-debug-set-inside start end) | ||
| 116 | (put-text-property start end 'nxml-inside type)) | 118 | (put-text-property start end 'nxml-inside type)) |
| 117 | 119 | ||
| 118 | (defun nxml-inside-end (pos) | 120 | (defun nxml-inside-end (pos) |
| @@ -137,12 +139,10 @@ Return nil if the character at POS is not inside." | |||
| 137 | "Restore `nxml-scan-end' invariants after a change. | 139 | "Restore `nxml-scan-end' invariants after a change. |
| 138 | The change happened between START and END. | 140 | The change happened between START and END. |
| 139 | Return position after which lexical state is unchanged. | 141 | Return position after which lexical state is unchanged. |
| 140 | END must be > nxml-prolog-end." | 142 | END must be > nxml-prolog-end. START must be outside |
| 143 | any 'inside' regions and at the beginning of a token." | ||
| 141 | (if (>= start nxml-scan-end) | 144 | (if (>= start nxml-scan-end) |
| 142 | nxml-scan-end | 145 | nxml-scan-end |
| 143 | (goto-char start) | ||
| 144 | (nxml-move-outside-backwards) | ||
| 145 | (setq start (point)) | ||
| 146 | (let ((inside-remove-start start) | 146 | (let ((inside-remove-start start) |
| 147 | xmltok-errors | 147 | xmltok-errors |
| 148 | xmltok-dependent-regions) | 148 | xmltok-dependent-regions) |
| @@ -214,7 +214,7 @@ END must be > nxml-prolog-end." | |||
| 214 | (setq adjusted-start ostart))))) | 214 | (setq adjusted-start ostart))))) |
| 215 | (setq overlays (cdr overlays))) | 215 | (setq overlays (cdr overlays))) |
| 216 | adjusted-start)) | 216 | adjusted-start)) |
| 217 | 217 | ||
| 218 | (defun nxml-mark-parse-dependent-regions () | 218 | (defun nxml-mark-parse-dependent-regions () |
| 219 | (while xmltok-dependent-regions | 219 | (while xmltok-dependent-regions |
| 220 | (apply 'nxml-mark-parse-dependent-region | 220 | (apply 'nxml-mark-parse-dependent-region |
| @@ -300,6 +300,20 @@ Sets variables like `nxml-token-after'." | |||
| 300 | (set-marker nxml-scan-end (point))) | 300 | (set-marker nxml-scan-end (point))) |
| 301 | xmltok-type)) | 301 | xmltok-type)) |
| 302 | 302 | ||
| 303 | (defun nxml-move-tag-backwards (bound) | ||
| 304 | "Move point backwards outside any 'inside' regions or tags, up | ||
| 305 | to nxml-prolog-end. Point will either be at bound or a '<' | ||
| 306 | character starting a tag outside any 'inside' regions. Ignores | ||
| 307 | dependent regions. As a precondition, point must be >= bound." | ||
| 308 | (nxml-move-outside-backwards) | ||
| 309 | (when (not (equal (char-after) ?<)) | ||
| 310 | (if (search-backward "<" bound t) | ||
| 311 | (progn | ||
| 312 | (nxml-move-outside-backwards) | ||
| 313 | (when (not (equal (char-after) ?<)) | ||
| 314 | (search-backward "<" bound t))) | ||
| 315 | (goto-char bound)))) | ||
| 316 | |||
| 303 | (defun nxml-move-outside-backwards () | 317 | (defun nxml-move-outside-backwards () |
| 304 | "Move point to first character of the containing special thing. | 318 | "Move point to first character of the containing special thing. |
| 305 | Leave point unmoved if it is not inside anything special." | 319 | Leave point unmoved if it is not inside anything special." |
diff --git a/lisp/nxml/nxml-util.el b/lisp/nxml/nxml-util.el index 3aab1ee6b8c..2e90dfc32dc 100644 --- a/lisp/nxml/nxml-util.el +++ b/lisp/nxml/nxml-util.el | |||
| @@ -24,6 +24,35 @@ | |||
| 24 | 24 | ||
| 25 | ;;; Code: | 25 | ;;; Code: |
| 26 | 26 | ||
| 27 | (defconst nxml-debug nil | ||
| 28 | "enable nxml debugging. effective only at compile time") | ||
| 29 | |||
| 30 | (eval-when-compile | ||
| 31 | (require 'cl)) | ||
| 32 | |||
| 33 | (defsubst nxml-debug (format &rest args) | ||
| 34 | (when nxml-debug | ||
| 35 | (apply #'message format args))) | ||
| 36 | |||
| 37 | (defmacro nxml-debug-change (name start end) | ||
| 38 | (when nxml-debug | ||
| 39 | `(nxml-debug "%s: %S" ,name | ||
| 40 | (buffer-substring-no-properties ,start ,end)))) | ||
| 41 | |||
| 42 | (defmacro nxml-debug-set-inside (start end) | ||
| 43 | (when nxml-debug | ||
| 44 | `(let ((overlay (make-overlay ,start ,end))) | ||
| 45 | (overlay-put overlay 'face '(:background "red")) | ||
| 46 | (overlay-put overlay 'nxml-inside-debug t) | ||
| 47 | (nxml-debug-change "nxml-set-inside" ,start ,end)))) | ||
| 48 | |||
| 49 | (defmacro nxml-debug-clear-inside (start end) | ||
| 50 | (when nxml-debug | ||
| 51 | `(loop for overlay in (overlays-in ,start ,end) | ||
| 52 | if (overlay-get overlay 'nxml-inside-debug) | ||
| 53 | do (delete-overlay overlay) | ||
| 54 | finally (nxml-debug-change "nxml-clear-inside" ,start ,end)))) | ||
| 55 | |||
| 27 | (defun nxml-make-namespace (str) | 56 | (defun nxml-make-namespace (str) |
| 28 | "Return a symbol for the namespace URI STR. | 57 | "Return a symbol for the namespace URI STR. |
| 29 | STR must be a string. If STR is the empty string, return nil. | 58 | STR must be a string. If STR is the empty string, return nil. |
| @@ -37,12 +66,21 @@ Otherwise, return the symbol whose name is STR prefixed with a colon." | |||
| 37 | This is the inverse of `nxml-make-namespace'." | 66 | This is the inverse of `nxml-make-namespace'." |
| 38 | (and ns (substring (symbol-name ns) 1))) | 67 | (and ns (substring (symbol-name ns) 1))) |
| 39 | 68 | ||
| 40 | (defconst nxml-xml-namespace-uri | 69 | (defconst nxml-xml-namespace-uri |
| 41 | (nxml-make-namespace "http://www.w3.org/XML/1998/namespace")) | 70 | (nxml-make-namespace "http://www.w3.org/XML/1998/namespace")) |
| 42 | 71 | ||
| 43 | (defconst nxml-xmlns-namespace-uri | 72 | (defconst nxml-xmlns-namespace-uri |
| 44 | (nxml-make-namespace "http://www.w3.org/2000/xmlns/")) | 73 | (nxml-make-namespace "http://www.w3.org/2000/xmlns/")) |
| 45 | 74 | ||
| 75 | (defmacro nxml-with-degradation-on-error (context &rest body) | ||
| 76 | (if (not nxml-debug) | ||
| 77 | (let ((error-symbol (make-symbol "err"))) | ||
| 78 | `(condition-case ,error-symbol | ||
| 79 | (progn ,@body) | ||
| 80 | (error | ||
| 81 | (nxml-degrade ,context ,error-symbol)))) | ||
| 82 | `(progn ,@body))) | ||
| 83 | |||
| 46 | (defmacro nxml-with-unmodifying-text-property-changes (&rest body) | 84 | (defmacro nxml-with-unmodifying-text-property-changes (&rest body) |
| 47 | "Evaluate BODY without any text property changes modifying the buffer. | 85 | "Evaluate BODY without any text property changes modifying the buffer. |
| 48 | Any text properties changes happen as usual but the changes are not treated as | 86 | Any text properties changes happen as usual but the changes are not treated as |