aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPhillip Lord2015-08-06 21:33:58 +0100
committerPhillip Lord2015-11-12 21:06:05 +0000
commit44dfa86b7d382b84564d68472da1448d08f48129 (patch)
tree778e2228ec90a4401b2be6cd7b258ee44a212b26 /src
parent0aec2aaccd8b745fa7214f3edd453c04a04bfba4 (diff)
downloademacs-44dfa86b7d382b84564d68472da1448d08f48129.tar.gz
emacs-44dfa86b7d382b84564d68472da1448d08f48129.zip
The heuristic that Emacs uses to add an `undo-boundary' has been
reworked, as it interacts poorly with functions on `post-command-hook' or `after-change-functions'. * lisp/simple.el: New section added. * src/cmds.c (remove_excessive_undo_boundaries): Now in lisp. (self_insert_command): Calls simple.el to amalgamate. (delete_char): Calls simple.el to amalgamate. * src/keyboard.c (last_undo_boundary): Removed. * src/undo.c (run_undoable_change): New function.
Diffstat (limited to 'src')
-rw-r--r--src/cmds.c41
-rw-r--r--src/keyboard.c17
-rw-r--r--src/lisp.h1
-rw-r--r--src/undo.c51
4 files changed, 30 insertions, 80 deletions
diff --git a/src/cmds.c b/src/cmds.c
index a975a8ed4e0..6f19a046893 100644
--- a/src/cmds.c
+++ b/src/cmds.c
@@ -220,36 +220,6 @@ to t. */)
220 return Qnil; 220 return Qnil;
221} 221}
222 222
223static int nonundocount;
224
225static void
226remove_excessive_undo_boundaries (void)
227{
228 bool remove_boundary = true;
229
230 if (!EQ (Vthis_command, KVAR (current_kboard, Vlast_command)))
231 nonundocount = 0;
232
233 if (NILP (Vexecuting_kbd_macro))
234 {
235 if (nonundocount <= 0 || nonundocount >= 20)
236 {
237 remove_boundary = false;
238 nonundocount = 0;
239 }
240 nonundocount++;
241 }
242
243 if (remove_boundary
244 && CONSP (BVAR (current_buffer, undo_list))
245 && NILP (XCAR (BVAR (current_buffer, undo_list)))
246 /* Only remove auto-added boundaries, not boundaries
247 added by explicit calls to undo-boundary. */
248 && EQ (BVAR (current_buffer, undo_list), last_undo_boundary))
249 /* Remove the undo_boundary that was just pushed. */
250 bset_undo_list (current_buffer, XCDR (BVAR (current_buffer, undo_list)));
251}
252
253DEFUN ("delete-char", Fdelete_char, Sdelete_char, 1, 2, "p\nP", 223DEFUN ("delete-char", Fdelete_char, Sdelete_char, 1, 2, "p\nP",
254 doc: /* Delete the following N characters (previous if N is negative). 224 doc: /* Delete the following N characters (previous if N is negative).
255Optional second arg KILLFLAG non-nil means kill instead (save in kill ring). 225Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).
@@ -265,7 +235,7 @@ because it respects values of `delete-active-region' and `overwrite-mode'. */)
265 CHECK_NUMBER (n); 235 CHECK_NUMBER (n);
266 236
267 if (abs (XINT (n)) < 2) 237 if (abs (XINT (n)) < 2)
268 remove_excessive_undo_boundaries (); 238 call0 (Qundo_auto__amalgamate);
269 239
270 pos = PT + XINT (n); 240 pos = PT + XINT (n);
271 if (NILP (killflag)) 241 if (NILP (killflag))
@@ -311,7 +281,7 @@ At the end, it runs `post-self-insert-hook'. */)
311 error ("Negative repetition argument %"pI"d", XFASTINT (n)); 281 error ("Negative repetition argument %"pI"d", XFASTINT (n));
312 282
313 if (XFASTINT (n) < 2) 283 if (XFASTINT (n) < 2)
314 remove_excessive_undo_boundaries (); 284 call0 (Qundo_auto__amalgamate);
315 285
316 /* Barf if the key that invoked this was not a character. */ 286 /* Barf if the key that invoked this was not a character. */
317 if (!CHARACTERP (last_command_event)) 287 if (!CHARACTERP (last_command_event))
@@ -321,7 +291,7 @@ At the end, it runs `post-self-insert-hook'. */)
321 XINT (last_command_event)); 291 XINT (last_command_event));
322 int val = internal_self_insert (character, XFASTINT (n)); 292 int val = internal_self_insert (character, XFASTINT (n));
323 if (val == 2) 293 if (val == 2)
324 nonundocount = 0; 294 Fset (Qundo_auto__this_command_amalgamating, Qnil);
325 frame_make_pointer_invisible (SELECTED_FRAME ()); 295 frame_make_pointer_invisible (SELECTED_FRAME ());
326 } 296 }
327 297
@@ -526,6 +496,10 @@ internal_self_insert (int c, EMACS_INT n)
526void 496void
527syms_of_cmds (void) 497syms_of_cmds (void)
528{ 498{
499 DEFSYM (Qundo_auto__amalgamate, "undo-auto--amalgamate");
500 DEFSYM (Qundo_auto__this_command_amalgamating,
501 "undo-auto--this-command-amalgamating");
502
529 DEFSYM (Qkill_forward_chars, "kill-forward-chars"); 503 DEFSYM (Qkill_forward_chars, "kill-forward-chars");
530 504
531 /* A possible value for a buffer's overwrite-mode variable. */ 505 /* A possible value for a buffer's overwrite-mode variable. */
@@ -555,7 +529,6 @@ keys_of_cmds (void)
555{ 529{
556 int n; 530 int n;
557 531
558 nonundocount = 0;
559 initial_define_key (global_map, Ctl ('I'), "self-insert-command"); 532 initial_define_key (global_map, Ctl ('I'), "self-insert-command");
560 for (n = 040; n < 0177; n++) 533 for (n = 040; n < 0177; n++)
561 initial_define_key (global_map, n, "self-insert-command"); 534 initial_define_key (global_map, n, "self-insert-command");
diff --git a/src/keyboard.c b/src/keyboard.c
index 5f8667586c4..1f08e1f23ed 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -1278,9 +1278,6 @@ static int read_key_sequence (Lisp_Object *, int, Lisp_Object,
1278 bool, bool, bool, bool); 1278 bool, bool, bool, bool);
1279static void adjust_point_for_property (ptrdiff_t, bool); 1279static void adjust_point_for_property (ptrdiff_t, bool);
1280 1280
1281/* The last boundary auto-added to buffer-undo-list. */
1282Lisp_Object last_undo_boundary;
1283
1284/* FIXME: This is wrong rather than test window-system, we should call 1281/* FIXME: This is wrong rather than test window-system, we should call
1285 a new set-selection, which will then dispatch to x-set-selection, or 1282 a new set-selection, which will then dispatch to x-set-selection, or
1286 tty-set-selection, or w32-set-selection, ... */ 1283 tty-set-selection, or w32-set-selection, ... */
@@ -1505,14 +1502,10 @@ command_loop_1 (void)
1505 } 1502 }
1506#endif 1503#endif
1507 1504
1508 if (NILP (KVAR (current_kboard, Vprefix_arg))) /* FIXME: Why? --Stef */ 1505 /* Ensure that we have added appropriate undo-boundaries as a
1509 { 1506 result of changes from the last command. */
1510 Lisp_Object undo = BVAR (current_buffer, undo_list); 1507 call0 (Qundo_auto__add_boundary);
1511 Fundo_boundary (); 1508
1512 last_undo_boundary
1513 = (EQ (undo, BVAR (current_buffer, undo_list))
1514 ? Qnil : BVAR (current_buffer, undo_list));
1515 }
1516 call1 (Qcommand_execute, Vthis_command); 1509 call1 (Qcommand_execute, Vthis_command);
1517 1510
1518#ifdef HAVE_WINDOW_SYSTEM 1511#ifdef HAVE_WINDOW_SYSTEM
@@ -11095,6 +11088,8 @@ syms_of_keyboard (void)
11095 DEFSYM (Qpre_command_hook, "pre-command-hook"); 11088 DEFSYM (Qpre_command_hook, "pre-command-hook");
11096 DEFSYM (Qpost_command_hook, "post-command-hook"); 11089 DEFSYM (Qpost_command_hook, "post-command-hook");
11097 11090
11091 DEFSYM (Qundo_auto__add_boundary, "undo-auto--add-boundary");
11092
11098 DEFSYM (Qdeferred_action_function, "deferred-action-function"); 11093 DEFSYM (Qdeferred_action_function, "deferred-action-function");
11099 DEFSYM (Qdelayed_warnings_hook, "delayed-warnings-hook"); 11094 DEFSYM (Qdelayed_warnings_hook, "delayed-warnings-hook");
11100 DEFSYM (Qfunction_key, "function-key"); 11095 DEFSYM (Qfunction_key, "function-key");
diff --git a/src/lisp.h b/src/lisp.h
index 02109d72174..aaf52bdd1be 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4174,7 +4174,6 @@ extern void syms_of_casetab (void);
4174extern Lisp_Object echo_message_buffer; 4174extern Lisp_Object echo_message_buffer;
4175extern struct kboard *echo_kboard; 4175extern struct kboard *echo_kboard;
4176extern void cancel_echoing (void); 4176extern void cancel_echoing (void);
4177extern Lisp_Object last_undo_boundary;
4178extern bool input_pending; 4177extern bool input_pending;
4179#ifdef HAVE_STACK_OVERFLOW_HANDLING 4178#ifdef HAVE_STACK_OVERFLOW_HANDLING
4180extern sigjmp_buf return_to_command_loop; 4179extern sigjmp_buf return_to_command_loop;
diff --git a/src/undo.c b/src/undo.c
index 750bc8afff2..364b37eeeb4 100644
--- a/src/undo.c
+++ b/src/undo.c
@@ -26,10 +26,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
26#include "commands.h" 26#include "commands.h"
27#include "window.h" 27#include "window.h"
28 28
29/* Last buffer for which undo information was recorded. */
30/* BEWARE: This is not traced by the GC, so never dereference it! */
31static struct buffer *last_undo_buffer;
32
33/* Position of point last time we inserted a boundary. */ 29/* Position of point last time we inserted a boundary. */
34static struct buffer *last_boundary_buffer; 30static struct buffer *last_boundary_buffer;
35static ptrdiff_t last_boundary_position; 31static ptrdiff_t last_boundary_position;
@@ -41,6 +37,12 @@ static ptrdiff_t last_boundary_position;
41 an undo-boundary. */ 37 an undo-boundary. */
42static Lisp_Object pending_boundary; 38static Lisp_Object pending_boundary;
43 39
40void
41run_undoable_change ()
42{
43 call0 (Qundo_auto__undoable_change);
44}
45
44/* Record point as it was at beginning of this command (if necessary) 46/* Record point as it was at beginning of this command (if necessary)
45 and prepare the undo info for recording a change. 47 and prepare the undo info for recording a change.
46 PT is the position of point that will naturally occur as a result of the 48 PT is the position of point that will naturally occur as a result of the
@@ -59,15 +61,7 @@ record_point (ptrdiff_t pt)
59 if (NILP (pending_boundary)) 61 if (NILP (pending_boundary))
60 pending_boundary = Fcons (Qnil, Qnil); 62 pending_boundary = Fcons (Qnil, Qnil);
61 63
62 if ((current_buffer != last_undo_buffer) 64 run_undoable_change ();
63 /* Don't call Fundo_boundary for the first change. Otherwise we
64 risk overwriting last_boundary_position in Fundo_boundary with
65 PT of the current buffer and as a consequence not insert an
66 undo boundary because last_boundary_position will equal pt in
67 the test at the end of the present function (Bug#731). */
68 && (MODIFF > SAVE_MODIFF))
69 Fundo_boundary ();
70 last_undo_buffer = current_buffer;
71 65
72 at_boundary = ! CONSP (BVAR (current_buffer, undo_list)) 66 at_boundary = ! CONSP (BVAR (current_buffer, undo_list))
73 || NILP (XCAR (BVAR (current_buffer, undo_list))); 67 || NILP (XCAR (BVAR (current_buffer, undo_list)));
@@ -139,9 +133,7 @@ record_marker_adjustments (ptrdiff_t from, ptrdiff_t to)
139 if (NILP (pending_boundary)) 133 if (NILP (pending_boundary))
140 pending_boundary = Fcons (Qnil, Qnil); 134 pending_boundary = Fcons (Qnil, Qnil);
141 135
142 if (current_buffer != last_undo_buffer) 136 run_undoable_change ();
143 Fundo_boundary ();
144 last_undo_buffer = current_buffer;
145 137
146 for (m = BUF_MARKERS (current_buffer); m; m = m->next) 138 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
147 { 139 {
@@ -228,10 +220,6 @@ record_first_change (void)
228 if (EQ (BVAR (current_buffer, undo_list), Qt)) 220 if (EQ (BVAR (current_buffer, undo_list), Qt))
229 return; 221 return;
230 222
231 if (current_buffer != last_undo_buffer)
232 Fundo_boundary ();
233 last_undo_buffer = current_buffer;
234
235 if (base_buffer->base_buffer) 223 if (base_buffer->base_buffer)
236 base_buffer = base_buffer->base_buffer; 224 base_buffer = base_buffer->base_buffer;
237 225
@@ -259,15 +247,10 @@ record_property_change (ptrdiff_t beg, ptrdiff_t length,
259 if (NILP (pending_boundary)) 247 if (NILP (pending_boundary))
260 pending_boundary = Fcons (Qnil, Qnil); 248 pending_boundary = Fcons (Qnil, Qnil);
261 249
262 if (buf != last_undo_buffer)
263 boundary = true;
264 last_undo_buffer = buf;
265
266 /* Switch temporarily to the buffer that was changed. */ 250 /* Switch temporarily to the buffer that was changed. */
267 current_buffer = buf; 251 set_buffer_internal (buf);
268 252
269 if (boundary) 253 run_undoable_change ();
270 Fundo_boundary ();
271 254
272 if (MODIFF <= SAVE_MODIFF) 255 if (MODIFF <= SAVE_MODIFF)
273 record_first_change (); 256 record_first_change ();
@@ -278,7 +261,8 @@ record_property_change (ptrdiff_t beg, ptrdiff_t length,
278 bset_undo_list (current_buffer, 261 bset_undo_list (current_buffer,
279 Fcons (entry, BVAR (current_buffer, undo_list))); 262 Fcons (entry, BVAR (current_buffer, undo_list)));
280 263
281 current_buffer = obuf; 264 /* Reset the buffer */
265 set_buffer_internal (obuf);
282} 266}
283 267
284DEFUN ("undo-boundary", Fundo_boundary, Sundo_boundary, 0, 0, 0, 268DEFUN ("undo-boundary", Fundo_boundary, Sundo_boundary, 0, 0, 0,
@@ -308,6 +292,8 @@ but another undo command will undo to the previous boundary. */)
308 } 292 }
309 last_boundary_position = PT; 293 last_boundary_position = PT;
310 last_boundary_buffer = current_buffer; 294 last_boundary_buffer = current_buffer;
295
296 Fset (Qundo_auto__last_boundary_cause, Qexplicit);
311 return Qnil; 297 return Qnil;
312} 298}
313 299
@@ -383,7 +369,6 @@ truncate_undo_list (struct buffer *b)
383 && !NILP (Vundo_outer_limit_function)) 369 && !NILP (Vundo_outer_limit_function))
384 { 370 {
385 Lisp_Object tem; 371 Lisp_Object tem;
386 struct buffer *temp = last_undo_buffer;
387 372
388 /* Normally the function this calls is undo-outer-limit-truncate. */ 373 /* Normally the function this calls is undo-outer-limit-truncate. */
389 tem = call1 (Vundo_outer_limit_function, make_number (size_so_far)); 374 tem = call1 (Vundo_outer_limit_function, make_number (size_so_far));
@@ -394,10 +379,6 @@ truncate_undo_list (struct buffer *b)
394 unbind_to (count, Qnil); 379 unbind_to (count, Qnil);
395 return; 380 return;
396 } 381 }
397 /* That function probably used the minibuffer, and if so, that
398 changed last_undo_buffer. Change it back so that we don't
399 force next change to make an undo boundary here. */
400 last_undo_buffer = temp;
401 } 382 }
402 383
403 if (CONSP (next)) 384 if (CONSP (next))
@@ -455,6 +436,9 @@ void
455syms_of_undo (void) 436syms_of_undo (void)
456{ 437{
457 DEFSYM (Qinhibit_read_only, "inhibit-read-only"); 438 DEFSYM (Qinhibit_read_only, "inhibit-read-only");
439 DEFSYM (Qundo_auto__undoable_change, "undo-auto--undoable-change");
440 DEFSYM (Qundo_auto__last_boundary_cause, "undo-auto--last-boundary-cause");
441 DEFSYM (Qexplicit, "explicit");
458 442
459 /* Marker for function call undo list elements. */ 443 /* Marker for function call undo list elements. */
460 DEFSYM (Qapply, "apply"); 444 DEFSYM (Qapply, "apply");
@@ -462,7 +446,6 @@ syms_of_undo (void)
462 pending_boundary = Qnil; 446 pending_boundary = Qnil;
463 staticpro (&pending_boundary); 447 staticpro (&pending_boundary);
464 448
465 last_undo_buffer = NULL;
466 last_boundary_buffer = NULL; 449 last_boundary_buffer = NULL;
467 450
468 defsubr (&Sundo_boundary); 451 defsubr (&Sundo_boundary);