comparison lisp/subr.el @ 43126:6f39ff1c6d8f

(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.
author Richard M. Stallman <rms@gnu.org>
date Wed, 06 Feb 2002 15:20:36 +0000
parents b722504d0ba4
children 2c6477a9d9d5
comparison
equal deleted inserted replaced
43125:49ff3106980b 43126:6f39ff1c6d8f
994 (and (arrayp pass) (fillarray pass ?\0)) 994 (and (arrayp pass) (fillarray pass ?\0))
995 (setq pass new-pass)))))) 995 (setq pass new-pass))))))
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.
1001 This means that if BODY exits abnormally,
1002 all of its changes to the current buffer are undone.
1003 This works regadless of whether undo is enabled in the buffer.
1004
1005 This mechanism is transparent to ordinary use of undo;
1006 if undo is enabled in the buffer and BODY succeeds, the
1007 user 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.
1028 If you specify BUFFER, make a handle for BUFFER's state instead.
1029
1030 Pass the handle to `activate-change-group' afterward to initiate
1031 the actual changes of the change group.
1032
1033 To 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;
1036 call `cancel-change-group' to undo them all. You should use
1037 `unwind-protect' to make sure the group is always finished. The call
1038 to `activate-change-group' should be inside the `unwind-protect'.
1039 Once you finish the group, don't use the handle again--don't try to
1040 finish the same group twice. For a simple example of correct use, see
1041 the source code of `atomic-change-group'.
1042
1043 The handle records only the specified buffer. To make a multibuffer
1044 change group, call this function once for each buffer you want to
1045 cover, 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
1050 You can then activate that multibuffer change group with a single
1051 call to `activate-change-group' and finish it with a single call
1052 to `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).
1065 This 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).
1073 This 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.
1001 With optional non-nil ALL, force redisplay of all mode-lines." 1099 With optional non-nil ALL, force redisplay of all mode-lines."
1002 (if all (save-excursion (set-buffer (other-buffer)))) 1100 (if all (save-excursion (set-buffer (other-buffer))))
1003 (set-buffer-modified-p (buffer-modified-p))) 1101 (set-buffer-modified-p (buffer-modified-p)))
1705 1803
1706 If TOGGLE has a non-nil `:included' property, an entry for the mode is 1804 If TOGGLE has a non-nil `:included' property, an entry for the mode is
1707 included in the mode-line minor mode menu. 1805 included in the mode-line minor mode menu.
1708 If TOGGLE has a `:menu-tag', that is used for the menu item's label." 1806 If 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)))
1722 (when (and (stringp name) (not (get-text-property 0 'local-map name))) 1811 (when (and (stringp name) (not (get-text-property 0 'local-map name)))
1723 (setq name 1812 (setq name
1735 (let ((rest (cdr found))) 1824 (let ((rest (cdr found)))
1736 (setcdr found nil) 1825 (setcdr found nil)
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)))
1743 (if existing 1847 (if existing
1744 (setcdr existing keymap) 1848 (setcdr existing keymap)