diff options
| author | Stefan Monnier | 2001-10-25 02:26:41 +0000 |
|---|---|---|
| committer | Stefan Monnier | 2001-10-25 02:26:41 +0000 |
| commit | a13fe4c517214b3adc34f0412c6efccf9db8094b (patch) | |
| tree | d33add677afeb810dcc40db2bf6144fb24999cc3 | |
| parent | f66bd220114db0773ec5d094e7112f728775a7b6 (diff) | |
| download | emacs-a13fe4c517214b3adc34f0412c6efccf9db8094b.tar.gz emacs-a13fe4c517214b3adc34f0412c6efccf9db8094b.zip | |
(delay-mode-hooks, delayed-mode-hooks, run-mode-hooks): New vars and functions.
(text-clone-maintain, text-clone-create): New functions.
| -rw-r--r-- | lisp/subr.el | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/lisp/subr.el b/lisp/subr.el index 204aa62a2d2..ff9d9e57824 100644 --- a/lisp/subr.el +++ b/lisp/subr.el | |||
| @@ -1222,6 +1222,33 @@ in BODY." | |||
| 1222 | (combine-after-change-execute))) | 1222 | (combine-after-change-execute))) |
| 1223 | 1223 | ||
| 1224 | 1224 | ||
| 1225 | (defvar delay-mode-hooks nil | ||
| 1226 | "If non-nil, `run-mode-hooks' should delay running the hooks.") | ||
| 1227 | (defvar delayed-mode-hooks nil | ||
| 1228 | "List of delayed mode hooks waiting to be run.") | ||
| 1229 | (make-variable-buffer-local 'delayed-mode-hooks) | ||
| 1230 | |||
| 1231 | (defun run-mode-hooks (&rest hooks) | ||
| 1232 | "Run mode hooks `delayed-mode-hooks' and HOOKS, or delay HOOKS. | ||
| 1233 | Execution is delayed if `delay-mode-hooks' is non-nil. | ||
| 1234 | Major mode functions should use this." | ||
| 1235 | (if delay-mode-hooks | ||
| 1236 | ;; Delaying case. | ||
| 1237 | (dolist (hook hooks) | ||
| 1238 | (push hook delayed-mode-hooks)) | ||
| 1239 | ;; Normal case, just run the hook as before plus any delayed hooks. | ||
| 1240 | (setq hooks (nconc (nreverse delayed-mode-hooks) hooks)) | ||
| 1241 | (setq delayed-mode-hooks nil) | ||
| 1242 | (apply 'run-hooks hooks))) | ||
| 1243 | |||
| 1244 | (defmacro delay-mode-hooks (&rest body) | ||
| 1245 | "Execute BODY, but delay any `run-mode-hooks'. | ||
| 1246 | Only affects hooks run in the current buffer." | ||
| 1247 | `(progn | ||
| 1248 | (make-local-variable 'delay-mode-hooks) | ||
| 1249 | (let ((delay-mode-hooks t)) | ||
| 1250 | ,@body))) | ||
| 1251 | |||
| 1225 | (defmacro with-syntax-table (table &rest body) | 1252 | (defmacro with-syntax-table (table &rest body) |
| 1226 | "Evaluate BODY with syntax table of current buffer set to a copy of TABLE. | 1253 | "Evaluate BODY with syntax table of current buffer set to a copy of TABLE. |
| 1227 | The syntax table of the current buffer is saved, BODY is evaluated, and the | 1254 | The syntax table of the current buffer is saved, BODY is evaluated, and the |
| @@ -1650,4 +1677,99 @@ specification for `play-sound'." | |||
| 1650 | (push 'sound sound) | 1677 | (push 'sound sound) |
| 1651 | (play-sound sound)))) | 1678 | (play-sound sound)))) |
| 1652 | 1679 | ||
| 1680 | ;; Clones ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 1681 | |||
| 1682 | (defun text-clone-maintain (ol1 after beg end &optional len) | ||
| 1683 | "Propagate the changes made under the overlay OL1 to the other clones. | ||
| 1684 | This is used on the `modification-hooks' property of text clones." | ||
| 1685 | (when (and after (not undo-in-progress) (overlay-start ol1)) | ||
| 1686 | (let ((margin (if (overlay-get ol1 'text-clone-spreadp) 1 0))) | ||
| 1687 | (setq beg (max beg (+ (overlay-start ol1) margin))) | ||
| 1688 | (setq end (min end (- (overlay-end ol1) margin))) | ||
| 1689 | (when (<= beg end) | ||
| 1690 | (save-excursion | ||
| 1691 | (when (overlay-get ol1 'text-clone-syntax) | ||
| 1692 | ;; Check content of the clone's text. | ||
| 1693 | (let ((cbeg (+ (overlay-start ol1) margin)) | ||
| 1694 | (cend (- (overlay-end ol1) margin))) | ||
| 1695 | (goto-char cbeg) | ||
| 1696 | (save-match-data | ||
| 1697 | (if (not (re-search-forward | ||
| 1698 | (overlay-get ol1 'text-clone-syntax) cend t)) | ||
| 1699 | ;; Mark the overlay for deletion. | ||
| 1700 | (overlay-put ol1 'text-clones nil) | ||
| 1701 | (when (< (match-end 0) cend) | ||
| 1702 | ;; Shrink the clone at its end. | ||
| 1703 | (setq end (min end (match-end 0))) | ||
| 1704 | (move-overlay ol1 (overlay-start ol1) | ||
| 1705 | (+ (match-end 0) margin))) | ||
| 1706 | (when (> (match-beginning 0) cbeg) | ||
| 1707 | ;; Shrink the clone at its beginning. | ||
| 1708 | (setq beg (max (match-beginning 0) beg)) | ||
| 1709 | (move-overlay ol1 (- (match-beginning 0) margin) | ||
| 1710 | (overlay-end ol1))))))) | ||
| 1711 | ;; Now go ahead and update the clones. | ||
| 1712 | (let ((head (- beg (overlay-start ol1))) | ||
| 1713 | (tail (- (overlay-end ol1) end)) | ||
| 1714 | (str (buffer-substring beg end)) | ||
| 1715 | (nothing-left t) | ||
| 1716 | (inhibit-modification-hooks t)) | ||
| 1717 | (dolist (ol2 (overlay-get ol1 'text-clones)) | ||
| 1718 | (let ((oe (overlay-end ol2))) | ||
| 1719 | (unless (or (eq ol1 ol2) (null oe)) | ||
| 1720 | (setq nothing-left nil) | ||
| 1721 | (let ((mod-beg (+ (overlay-start ol2) head))) | ||
| 1722 | ;;(overlay-put ol2 'modification-hooks nil) | ||
| 1723 | (goto-char (- (overlay-end ol2) tail)) | ||
| 1724 | (unless (> mod-beg (point)) | ||
| 1725 | (save-excursion (insert str)) | ||
| 1726 | (delete-region mod-beg (point))) | ||
| 1727 | ;;(overlay-put ol2 'modification-hooks '(text-clone-maintain)) | ||
| 1728 | )))) | ||
| 1729 | (if nothing-left (delete-overlay ol1)))))))) | ||
| 1730 | |||
| 1731 | (defun text-clone-create (start end &optional spreadp syntax) | ||
| 1732 | "Create a text clone of START...END at point. | ||
| 1733 | Text clones are chunks of text that are automatically kept identical: | ||
| 1734 | changes done to one of the clones will be immediately propagated to the other. | ||
| 1735 | |||
| 1736 | The buffer's content at point is assumed to be already identical to | ||
| 1737 | the one between START and END. | ||
| 1738 | If SYNTAX is provided it's a regexp that describes the possible text of | ||
| 1739 | the clones; the clone will be shrunk or killed if necessary to ensure that | ||
| 1740 | its text matches the regexp. | ||
| 1741 | If SPREADP is non-nil it indicates that text inserted before/after the | ||
| 1742 | clone should be incorporated in the clone." | ||
| 1743 | ;; To deal with SPREADP we can either use an overlay with `nil t' along | ||
| 1744 | ;; with insert-(behind|in-front-of)-hooks or use a slightly larger overlay | ||
| 1745 | ;; (with a one-char margin at each end) with `t nil'. | ||
| 1746 | ;; We opted for a larger overlay because it behaves better in the case | ||
| 1747 | ;; where the clone is reduced to the empty string (we want the overlay to | ||
| 1748 | ;; stay when the clone's content is the empty string and we want to use | ||
| 1749 | ;; `evaporate' to make sure those overlays get deleted when needed). | ||
| 1750 | ;; | ||
| 1751 | (let* ((pt-end (+ (point) (- end start))) | ||
| 1752 | (start-margin (if (or (not spreadp) (bobp) (<= start (point-min))) | ||
| 1753 | 0 1)) | ||
| 1754 | (end-margin (if (or (not spreadp) | ||
| 1755 | (>= pt-end (point-max)) | ||
| 1756 | (>= start (point-max))) | ||
| 1757 | 0 1)) | ||
| 1758 | (ol1 (make-overlay (- start start-margin) (+ end end-margin) nil t)) | ||
| 1759 | (ol2 (make-overlay (- (point) start-margin) (+ pt-end end-margin) nil t)) | ||
| 1760 | (dups (list ol1 ol2))) | ||
| 1761 | (overlay-put ol1 'modification-hooks '(text-clone-maintain)) | ||
| 1762 | (when spreadp (overlay-put ol1 'text-clone-spreadp t)) | ||
| 1763 | (when syntax (overlay-put ol1 'text-clone-syntax syntax)) | ||
| 1764 | ;;(overlay-put ol1 'face 'underline) | ||
| 1765 | (overlay-put ol1 'evaporate t) | ||
| 1766 | (overlay-put ol1 'text-clones dups) | ||
| 1767 | ;; | ||
| 1768 | (overlay-put ol2 'modification-hooks '(text-clone-maintain)) | ||
| 1769 | (when spreadp (overlay-put ol2 'text-clone-spreadp t)) | ||
| 1770 | (when syntax (overlay-put ol2 'text-clone-syntax syntax)) | ||
| 1771 | ;;(overlay-put ol2 'face 'underline) | ||
| 1772 | (overlay-put ol2 'evaporate t) | ||
| 1773 | (overlay-put ol2 'text-clones dups))) | ||
| 1774 | |||
| 1653 | ;;; subr.el ends here | 1775 | ;;; subr.el ends here |