aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2001-10-25 02:26:41 +0000
committerStefan Monnier2001-10-25 02:26:41 +0000
commita13fe4c517214b3adc34f0412c6efccf9db8094b (patch)
treed33add677afeb810dcc40db2bf6144fb24999cc3
parentf66bd220114db0773ec5d094e7112f728775a7b6 (diff)
downloademacs-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.el122
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.
1233Execution is delayed if `delay-mode-hooks' is non-nil.
1234Major 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'.
1246Only 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.
1227The syntax table of the current buffer is saved, BODY is evaluated, and the 1254The 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.
1684This 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.
1733Text clones are chunks of text that are automatically kept identical:
1734changes done to one of the clones will be immediately propagated to the other.
1735
1736The buffer's content at point is assumed to be already identical to
1737the one between START and END.
1738If SYNTAX is provided it's a regexp that describes the possible text of
1739the clones; the clone will be shrunk or killed if necessary to ensure that
1740its text matches the regexp.
1741If SPREADP is non-nil it indicates that text inserted before/after the
1742clone 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