From 5729f459d1dbb28bc405a142860a99e1329f388a Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Mon, 13 Apr 2015 14:05:09 -0400 Subject: [PATCH] Collapse successive char deletions in the undo log * src/cmds.c (remove_excessive_undo_boundaries): New function, extracted from Fself_insert_command. (Fdelete_char, Fself_insert_command): Use it. * src/fileio.c (Fmake_symbolic_link): Rename arg to `target'. * src/keyboard.c (syms_of_keyboard): `top-level' shouldn't be special. --- etc/NEWS | 3 +++ src/cmds.c | 60 +++++++++++++++++++++++++++++--------------------- src/fileio.c | 32 +++++++++++++-------------- src/keyboard.c | 1 + 4 files changed, 55 insertions(+), 41 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 03d4ced6dd4..13cd512cb5e 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -201,6 +201,9 @@ font, and (iii) the specified window. * Editing Changes in Emacs 25.1 +** Successive single-char deletions are collapsed in the undo-log just like +successive char insertions. + ** Unicode names entered via C-x 8 RET now use substring completion by default. ** New minor mode global-eldoc-mode is enabled by default. diff --git a/src/cmds.c b/src/cmds.c index 270fc39cabc..168ce8355ed 100644 --- a/src/cmds.c +++ b/src/cmds.c @@ -213,6 +213,36 @@ to t. */) return Qnil; } +static int nonundocount; + +static void +remove_excessive_undo_boundaries (void) +{ + bool remove_boundary = true; + + if (!EQ (Vthis_command, KVAR (current_kboard, Vlast_command))) + nonundocount = 0; + + if (NILP (Vexecuting_kbd_macro)) + { + if (nonundocount <= 0 || nonundocount >= 20) + { + remove_boundary = false; + nonundocount = 0; + } + nonundocount++; + } + + if (remove_boundary + && CONSP (BVAR (current_buffer, undo_list)) + && NILP (XCAR (BVAR (current_buffer, undo_list))) + /* Only remove auto-added boundaries, not boundaries + added by explicit calls to undo-boundary. */ + && EQ (BVAR (current_buffer, undo_list), last_undo_boundary)) + /* Remove the undo_boundary that was just pushed. */ + bset_undo_list (current_buffer, XCDR (BVAR (current_buffer, undo_list))); +} + DEFUN ("delete-char", Fdelete_char, Sdelete_char, 1, 2, "p\nP", doc: /* Delete the following N characters (previous if N is negative). Optional second arg KILLFLAG non-nil means kill instead (save in kill ring). @@ -227,6 +257,9 @@ because it respects values of `delete-active-region' and `overwrite-mode'. */) CHECK_NUMBER (n); + if (abs (XINT (n)) < 2) + remove_excessive_undo_boundaries (); + pos = PT + XINT (n); if (NILP (killflag)) { @@ -252,8 +285,6 @@ because it respects values of `delete-active-region' and `overwrite-mode'. */) return Qnil; } -static int nonundocount; - /* Note that there's code in command_loop_1 which typically avoids calling this. */ DEFUN ("self-insert-command", Fself_insert_command, Sself_insert_command, 1, 1, "p", @@ -267,34 +298,13 @@ After insertion, the value of `auto-fill-function' is called if the At the end, it runs `post-self-insert-hook'. */) (Lisp_Object n) { - bool remove_boundary = 1; CHECK_NUMBER (n); if (XFASTINT (n) < 0) error ("Negative repetition argument %"pI"d", XFASTINT (n)); - if (!EQ (Vthis_command, KVAR (current_kboard, Vlast_command))) - nonundocount = 0; - - if (NILP (Vexecuting_kbd_macro) - && !EQ (minibuf_window, selected_window)) - { - if (nonundocount <= 0 || nonundocount >= 20) - { - remove_boundary = 0; - nonundocount = 0; - } - nonundocount++; - } - - if (remove_boundary - && CONSP (BVAR (current_buffer, undo_list)) - && NILP (XCAR (BVAR (current_buffer, undo_list))) - /* Only remove auto-added boundaries, not boundaries - added be explicit calls to undo-boundary. */ - && EQ (BVAR (current_buffer, undo_list), last_undo_boundary)) - /* Remove the undo_boundary that was just pushed. */ - bset_undo_list (current_buffer, XCDR (BVAR (current_buffer, undo_list))); + if (XFASTINT (n) < 2) + remove_excessive_undo_boundaries (); /* Barf if the key that invoked this was not a character. */ if (!CHARACTERP (last_command_event)) diff --git a/src/fileio.c b/src/fileio.c index a6e7fbb83d2..796f08d3c58 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -2344,62 +2344,62 @@ This is what happens in interactive use with M-x. */) DEFUN ("make-symbolic-link", Fmake_symbolic_link, Smake_symbolic_link, 2, 3, "FMake symbolic link to file: \nGMake symbolic link to file %s: \np", - doc: /* Make a symbolic link to FILENAME, named LINKNAME. + doc: /* Make a symbolic link to TARGET, named LINKNAME. Both args must be strings. Signals a `file-already-exists' error if a file LINKNAME already exists unless optional third argument OK-IF-ALREADY-EXISTS is non-nil. A number as third arg means request confirmation if LINKNAME already exists. This happens for interactive use with M-x. */) - (Lisp_Object filename, Lisp_Object linkname, Lisp_Object ok_if_already_exists) + (Lisp_Object target, Lisp_Object linkname, Lisp_Object ok_if_already_exists) { Lisp_Object handler; - Lisp_Object encoded_filename, encoded_linkname; + Lisp_Object encoded_target, encoded_linkname; struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; - GCPRO4 (filename, linkname, encoded_filename, encoded_linkname); - encoded_filename = encoded_linkname = Qnil; - CHECK_STRING (filename); + GCPRO4 (target, linkname, encoded_target, encoded_linkname); + encoded_target = encoded_linkname = Qnil; + CHECK_STRING (target); CHECK_STRING (linkname); /* If the link target has a ~, we must expand it to get a truly valid file name. Otherwise, do not expand; we want to permit links to relative file names. */ - if (SREF (filename, 0) == '~') - filename = Fexpand_file_name (filename, Qnil); + if (SREF (target, 0) == '~') + target = Fexpand_file_name (target, Qnil); if (!NILP (Ffile_directory_p (linkname))) - linkname = Fexpand_file_name (Ffile_name_nondirectory (filename), linkname); + linkname = Fexpand_file_name (Ffile_name_nondirectory (target), linkname); else linkname = Fexpand_file_name (linkname, Qnil); /* If the file name has special constructs in it, call the corresponding file handler. */ - handler = Ffind_file_name_handler (filename, Qmake_symbolic_link); + handler = Ffind_file_name_handler (target, Qmake_symbolic_link); if (!NILP (handler)) - RETURN_UNGCPRO (call4 (handler, Qmake_symbolic_link, filename, + RETURN_UNGCPRO (call4 (handler, Qmake_symbolic_link, target, linkname, ok_if_already_exists)); /* If the new link name has special constructs in it, call the corresponding file handler. */ handler = Ffind_file_name_handler (linkname, Qmake_symbolic_link); if (!NILP (handler)) - RETURN_UNGCPRO (call4 (handler, Qmake_symbolic_link, filename, + RETURN_UNGCPRO (call4 (handler, Qmake_symbolic_link, target, linkname, ok_if_already_exists)); - encoded_filename = ENCODE_FILE (filename); + encoded_target = ENCODE_FILE (target); encoded_linkname = ENCODE_FILE (linkname); if (NILP (ok_if_already_exists) || INTEGERP (ok_if_already_exists)) barf_or_query_if_file_exists (linkname, false, "make it a link", INTEGERP (ok_if_already_exists), false); - if (symlink (SSDATA (encoded_filename), SSDATA (encoded_linkname)) < 0) + if (symlink (SSDATA (encoded_target), SSDATA (encoded_linkname)) < 0) { /* If we didn't complain already, silently delete existing file. */ int symlink_errno; if (errno == EEXIST) { unlink (SSDATA (encoded_linkname)); - if (symlink (SSDATA (encoded_filename), SSDATA (encoded_linkname)) + if (symlink (SSDATA (encoded_target), SSDATA (encoded_linkname)) >= 0) { UNGCPRO; @@ -2414,7 +2414,7 @@ This happens for interactive use with M-x. */) } symlink_errno = errno; - report_file_errno ("Making symbolic link", list2 (filename, linkname), + report_file_errno ("Making symbolic link", list2 (target, linkname), symlink_errno); } UNGCPRO; diff --git a/src/keyboard.c b/src/keyboard.c index 2d047da5511..068a47c6c75 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -11492,6 +11492,7 @@ for that character after that prefix key. */); doc: /* Form to evaluate when Emacs starts up. Useful to set before you dump a modified Emacs. */); Vtop_level = Qnil; + XSYMBOL (Qtop_level)->declared_special = false; DEFVAR_KBOARD ("keyboard-translate-table", Vkeyboard_translate_table, doc: /* Translate table for local keyboard input, or nil. -- 2.39.2