1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
<h3 class="section">Atomic Change Groups</h3> <p>In database terminology, an <em>atomic</em> change is an indivisible change—it can succeed entirely or it can fail entirely, but it cannot partly succeed. A Lisp program can make a series of changes to one or several buffers as an <em>atomic change group</em>, meaning that either the entire series of changes will be installed in their buffers or, in case of an error, none of them will be. </p> <p>To do this for one buffer, the one already current, simply write a call to <code>atomic-change-group</code> around the code that makes the changes, like this: </p> <div class="example"> <pre class="example">(atomic-change-group
(insert foo)
(delete-region x y))
</pre>
</div> <p>If an error (or other nonlocal exit) occurs inside the body of <code>atomic-change-group</code>, it unmakes all the changes in that buffer that were during the execution of the body. This kind of change group has no effect on any other buffers—any such changes remain. </p> <p>If you need something more sophisticated, such as to make changes in various buffers constitute one atomic group, you must directly call lower-level functions that <code>atomic-change-group</code> uses. </p> <dl> <dt id="prepare-change-group">Function: <strong>prepare-change-group</strong> <em>&optional buffer</em>
</dt> <dd><p>This function sets up a change group for buffer <var>buffer</var>, which defaults to the current buffer. It returns a handle that represents the change group. You must use this handle to activate the change group and subsequently to finish it. </p></dd>
</dl> <p>To use the change group, you must <em>activate</em> it. You must do this before making any changes in the text of <var>buffer</var>. </p> <dl> <dt id="activate-change-group">Function: <strong>activate-change-group</strong> <em>handle</em>
</dt> <dd><p>This function activates the change group that <var>handle</var> designates. </p></dd>
</dl> <p>After you activate the change group, any changes you make in that buffer become part of it. Once you have made all the desired changes in the buffer, you must <em>finish</em> the change group. There are two ways to do this: you can either accept (and finalize) all the changes, or cancel them all. </p> <dl> <dt id="accept-change-group">Function: <strong>accept-change-group</strong> <em>handle</em>
</dt> <dd><p>This function accepts all the changes in the change group specified by <var>handle</var>, making them final. </p></dd>
</dl> <dl> <dt id="cancel-change-group">Function: <strong>cancel-change-group</strong> <em>handle</em>
</dt> <dd><p>This function cancels and undoes all the changes in the change group specified by <var>handle</var>. </p></dd>
</dl> <p>You can cause some or all of the changes in a change group to be considered as a single unit for the purposes of the <code>undo</code> commands (see <a href="undo">Undo</a>) by using <code>undo-amalgamate-change-group</code>. </p> <dl> <dt id="undo-amalgamate-change-group">Function: <strong>undo-amalgamate-change-group</strong>
</dt> <dd><p>Amalgamate all the changes made in the change-group since the state identified by <var>handle</var>. This function removes all undo boundaries between undo records of changes since the state described by <var>handle</var>. Usually, <var>handle</var> is the handle returned by <code>prepare-change-group</code>, in which case all the changes since the beginning of the change-group are amalgamated into a single undo unit. </p></dd>
</dl> <p>Your code should use <code>unwind-protect</code> to make sure the group is always finished. The call to <code>activate-change-group</code> should be inside the <code>unwind-protect</code>, in case the user types <kbd>C-g</kbd> just after it runs. (This is one reason why <code>prepare-change-group</code> and <code>activate-change-group</code> are separate functions, because normally you would call <code>prepare-change-group</code> before the start of that <code>unwind-protect</code>.) Once you finish the group, don’t use the handle again—in particular, don’t try to finish the same group twice. </p> <p>To make a multibuffer change group, call <code>prepare-change-group</code> once for each buffer you want to cover, then use <code>nconc</code> to combine the returned values, like this: </p> <div class="example"> <pre class="example">(nconc (prepare-change-group buffer-1)
(prepare-change-group buffer-2))
</pre>
</div> <p>You can then activate the multibuffer change group with a single call to <code>activate-change-group</code>, and finish it with a single call to <code>accept-change-group</code> or <code>cancel-change-group</code>. </p> <p>Nested use of several change groups for the same buffer works as you would expect. Non-nested use of change groups for the same buffer will get Emacs confused, so don’t let it happen; the first change group you start for any given buffer should be the last one finished. </p><div class="_attribution">
<p class="_attribution-p">
Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc. <br>Licensed under the GNU GPL license.<br>
<a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Atomic-Changes.html" class="_attribution-link">https://www.gnu.org/software/emacs/manual/html_node/elisp/Atomic-Changes.html</a>
</p>
</div>
|