aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard M. Stallman2002-02-06 15:20:36 +0000
committerRichard M. Stallman2002-02-06 15:20:36 +0000
commit69cae2d4bf5ef048ae933a49e64258d4a7b4fc99 (patch)
tree6152098dc946cb12a63c0606409944a6a1a0283d
parentdc7d755295030e86ee294f74809c87483ef521e8 (diff)
downloademacs-69cae2d4bf5ef048ae933a49e64258d4a7b4fc99.tar.gz
emacs-69cae2d4bf5ef048ae933a49e64258d4a7b4fc99.zip
(atomic-change-group, prepare-change-group, activate-change-group)
(accept-change-group, cancel-change-group): New functions. (add-minor-mode): Include the mode's lighter string in the minor mode menu item name.
-rw-r--r--lisp/subr.el122
1 files changed, 113 insertions, 9 deletions
diff --git a/lisp/subr.el b/lisp/subr.el
index 4b33973afd4..302ec022311 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -996,6 +996,104 @@ Optional DEFAULT is a default password to use instead of empty input."
996 (message nil) 996 (message nil)
997 (or pass default "")))) 997 (or pass default ""))))
998 998
999(defmacro atomic-change-group (&rest body)
1000 "Perform BODY as an atomic change group.
1001This means that if BODY exits abnormally,
1002all of its changes to the current buffer are undone.
1003This works regadless of whether undo is enabled in the buffer.
1004
1005This mechanism is transparent to ordinary use of undo;
1006if undo is enabled in the buffer and BODY succeeds, the
1007user can undo the change normally."
1008 (let ((handle (make-symbol "--change-group-handle--"))
1009 (success (make-symbol "--change-group-success--")))
1010 `(let ((,handle (prepare-change-group))
1011 (,success nil))
1012 (unwind-protect
1013 (progn
1014 ;; This is inside the unwind-protect because
1015 ;; it enables undo if that was disabled; we need
1016 ;; to make sure that it gets disabled again.
1017 (activate-change-group ,handle)
1018 ,@body
1019 (setq ,success t))
1020 ;; Either of these functions will disable undo
1021 ;; if it was disabled before.
1022 (if ,success
1023 (accept-change-group ,handle)
1024 (cancel-change-group ,handle))))))
1025
1026(defun prepare-change-group (&optional buffer)
1027 "Return a handle for the current buffer's state, for a change group.
1028If you specify BUFFER, make a handle for BUFFER's state instead.
1029
1030Pass the handle to `activate-change-group' afterward to initiate
1031the actual changes of the change group.
1032
1033To finish the change group, call either `accept-change-group' or
1034`cancel-change-group' passing the same handle as argument. Call
1035`accept-change-group' to accept the changes in the group as final;
1036call `cancel-change-group' to undo them all. You should use
1037`unwind-protect' to make sure the group is always finished. The call
1038to `activate-change-group' should be inside the `unwind-protect'.
1039Once you finish the group, don't use the handle again--don't try to
1040finish the same group twice. For a simple example of correct use, see
1041the source code of `atomic-change-group'.
1042
1043The handle records only the specified buffer. To make a multibuffer
1044change group, call this function once for each buffer you want to
1045cover, then use `nconc' to combine the returned values, like this:
1046
1047 (nconc (prepare-change-group buffer-1)
1048 (prepare-change-group buffer-2))
1049
1050You can then activate that multibuffer change group with a single
1051call to `activate-change-group' and finish it with a single call
1052to `accept-change-group' or `cancel-change-group'."
1053
1054 (list (cons (current-buffer) buffer-undo-list)))
1055
1056(defun activate-change-group (handle)
1057 "Activate a change group made with `prepare-change-group' (which see)."
1058 (dolist (elt handle)
1059 (with-current-buffer (car elt)
1060 (if (eq buffer-undo-list t)
1061 (setq buffer-undo-list nil)))))
1062
1063(defun accept-change-group (handle)
1064 "Finish a change group made with `prepare-change-group' (which see).
1065This finishes the change group by accepting its changes as final."
1066 (dolist (elt handle)
1067 (with-current-buffer (car elt)
1068 (if (eq elt t)
1069 (setq buffer-undo-list t)))))
1070
1071(defun cancel-change-group (handle)
1072 "Finish a change group made with `prepare-change-group' (which see).
1073This finishes the change group by reverting all of its changes."
1074 (dolist (elt handle)
1075 (with-current-buffer (car elt)
1076 (setq elt (cdr elt))
1077 (let ((old-car
1078 (if (consp elt) (car elt)))
1079 (old-cdr
1080 (if (consp elt) (cdr elt))))
1081 ;; Temporarily truncate the undo log at ELT.
1082 (when (consp elt)
1083 (setcar elt nil) (setcdr elt nil))
1084 (unless (eq last-command 'undo) (undo-start))
1085 ;; Make sure there's no confusion.
1086 (when (and (consp elt) (not (eq elt (last pending-undo-list))))
1087 (error "Undoing to some unrelated state"))
1088 ;; Undo it all.
1089 (while pending-undo-list (undo-more 1))
1090 ;; Reset the modified cons cell ELT to its original content.
1091 (when (consp elt)
1092 (setcar elt old-car)
1093 (setcdr elt old-cdr))
1094 ;; Revert the undo info to what it was when we grabbed the state.
1095 (setq buffer-undo-list elt)))))
1096
999(defun force-mode-line-update (&optional all) 1097(defun force-mode-line-update (&optional all)
1000 "Force the mode-line of the current buffer to be redisplayed. 1098 "Force the mode-line of the current buffer to be redisplayed.
1001With optional non-nil ALL, force redisplay of all mode-lines." 1099With optional non-nil ALL, force redisplay of all mode-lines."
@@ -1707,15 +1805,6 @@ If TOGGLE has a non-nil `:included' property, an entry for the mode is
1707included in the mode-line minor mode menu. 1805included in the mode-line minor mode menu.
1708If TOGGLE has a `:menu-tag', that is used for the menu item's label." 1806If TOGGLE has a `:menu-tag', that is used for the menu item's label."
1709 (unless toggle-fun (setq toggle-fun toggle)) 1807 (unless toggle-fun (setq toggle-fun toggle))
1710 ;; Add the toggle to the minor-modes menu if requested.
1711 (when (get toggle :included)
1712 (define-key mode-line-mode-menu
1713 (vector toggle)
1714 (list 'menu-item
1715 (or (get toggle :menu-tag)
1716 (if (stringp name) name (symbol-name toggle)))
1717 toggle-fun
1718 :button (cons :toggle toggle))))
1719 ;; Add the name to the minor-mode-alist. 1808 ;; Add the name to the minor-mode-alist.
1720 (when name 1809 (when name
1721 (let ((existing (assq toggle minor-mode-alist))) 1810 (let ((existing (assq toggle minor-mode-alist)))
@@ -1737,6 +1826,21 @@ If TOGGLE has a `:menu-tag', that is used for the menu item's label."
1737 (nconc found (list (list toggle name)) rest)) 1826 (nconc found (list (list toggle name)) rest))
1738 (setq minor-mode-alist (cons (list toggle name) 1827 (setq minor-mode-alist (cons (list toggle name)
1739 minor-mode-alist))))))) 1828 minor-mode-alist)))))))
1829 ;; Add the toggle to the minor-modes menu if requested.
1830 (when (get toggle :included)
1831 (define-key mode-line-mode-menu
1832 (vector toggle)
1833 (list 'menu-item
1834 (concat
1835 (or (get toggle :menu-tag)
1836 (if (stringp name) name (symbol-name toggle)))
1837 (let ((mode-name (if (stringp name) name
1838 (if (symbolp name) (symbol-value name)))))
1839 (if mode-name
1840 (concat " (" mode-name ")"))))
1841 toggle-fun
1842 :button (cons :toggle toggle))))
1843
1740 ;; Add the map to the minor-mode-map-alist. 1844 ;; Add the map to the minor-mode-map-alist.
1741 (when keymap 1845 (when keymap
1742 (let ((existing (assq toggle minor-mode-map-alist))) 1846 (let ((existing (assq toggle minor-mode-map-alist)))