--- Begin Message ---
Subject: |
org-mode causes undo boundaries to be lost |
Date: |
Sun, 24 Jun 2012 23:27:55 +0200 |
User-agent: |
Mutt/1.5.21 (2010-09-15) |
Steps to reproduce, starting from "emacs -Q":
1. C-x C-f test.org
2. M-x org-mode
3. M-: (add-hook 'post-command-hook
(lambda () (message "%s" buffer-undo-list)) nil t)
4. type "a"
5. C-<SPC> C-<SPC>
6. type "bc"
Expected behaviour:
contents of `buffer-undo-list' after step 6. should be
((2 . 4) nil (1 . 2) (t . -1))
Actual behaviour:
contents of `buffer-undo-list' after step 6. are
((2 . 4) (1 . 2) (t . -1))
For some unknown reason, org-mode is causing the undo boundary between
the (2 . 4) and (1 . 2) entries to be removed from `buffer-undo-list'.
If we try the same thing under another major mode (e.g. replace
step 2 with "M-x text-mode"), then `buffer-undo-list' does contain the
undo boundary, as expected.
Step 3 is there to monitor what's going on. The same results are obtained
if that step is omitted. However, with the post-command-hook enabled, you
can see that the undo boundary is still there after typing "b" in
step 6, but gets deleted after typing "c".
This might look like a minor bug, but it can have severe
consequences. E.g. when using undo-tree-mode in org-mode, the corrupted
`buffer-undo-list' contents cause undo-tree-mode to discard the entire
undo history.
Toby
In GNU Emacs 24.1.50.2 (i686-pc-linux-gnu, GTK+ Version 2.24.10)
of 2012-06-20 on c3po
Windowing system distributor `The X.Org Foundation', version 11.0.11104000
Configured using:
`configure '--prefix=/usr' '--host=i686-pc-linux-gnu'
'--mandir=/usr/share/man' '--infodir=/usr/share/info'
'--datadir=/usr/share' '--sysconfdir=/etc' '--localstatedir=/var/lib'
'--disable-dependency-tracking' '--program-suffix=-emacs-24-vcs'
'--infodir=/usr/share/info/emacs-24-vcs'
'--enable-locallisppath=/etc/emacs:/usr/share/emacs/site-lisp'
'--with-crt-dir=/usr/lib/gcc/i686-pc-linux-gnu/4.5.3/../../../../lib'
'--with-gameuser=games' '--without-compress-info' '--without-hesiod'
'--without-kerberos' '--without-kerberos5' '--with-gpm' '--with-dbus'
'--without-gnutls' '--without-xml2' '--without-selinux'
'--without-wide-int' '--without-sound' '--with-x' '--without-ns'
'--without-gconf' '--without-gsettings' '--with-toolkit-scroll-bars'
'--without-gif' '--without-jpeg' '--with-png' '--with-rsvg'
'--without-tiff' '--with-xpm' '--without-imagemagick' '--with-xft'
'--without-libotf' '--without-m17n-flt' '--with-x-toolkit=gtk'
'EBZR_BRANCH=trunk' 'EBZR_REVNO=108667' '--build=i686-pc-linux-gnu'
'build_alias=i686-pc-linux-gnu' 'host_alias=i686-pc-linux-gnu'
'CFLAGS=-march=prescott -O2 -pipe -O2' 'LDFLAGS=-Wl,-O1
-Wl,--as-needed' 'CPPFLAGS=''
Important settings:
value of $LANG: en_GB.utf-8
locale-coding-system: utf-8-unix
default enable-multibyte-characters: t
--
Dr T. S. Cubitt
Mathematics and Quantum Information group
Department of Mathematics
Complutense University
Madrid, Spain
email: address@hidden
web: www.dr-qubit.org
--- End Message ---
--- Begin Message ---
Subject: |
Re: [O] bug#11774: bug#11774: org-mode causes undo boundaries to be lost |
Date: |
Wed, 18 Jul 2012 09:21:42 -0400 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/24.1.50 (gnu/linux) |
>>> self-insert-command. Even just turning that magic 20 number into a
>>> variable would help.
>> Providing it as a variable would be very easy, indeed.
> Maybe the user should be able to set undo boundaries and
> have them work after self-insert-command? Dunno, I'm
> not familiar with internals enough to opine.
I installed the patch below which makes self-insert-command more careful
to only remove undo boundaries that were auto-added.
So (add-hook 'post-self-insert-hook #'undo-boundary 'append) should give you
pretty much the behavior you were looking for.
Stefan
=== modified file 'src/ChangeLog'
--- src/ChangeLog 2012-07-18 05:44:36 +0000
+++ src/ChangeLog 2012-07-18 13:17:22 +0000
@@ -1,3 +1,10 @@
+2012-07-18 Stefan Monnier <address@hidden>
+
+ * lisp.h (last_undo_boundary): Declare new var.
+ * keyboard.c (command_loop_1): Set it.
+ * cmds.c (Fself_insert_command): Use it to only remove boundaries that
+ were auto-added by the command loop (bug#11774).
+
2012-07-18 Dmitry Antipov <address@hidden>
Return more descriptive data from Fgarbage_collect.
=== modified file 'src/cmds.c'
--- src/cmds.c 2012-06-16 12:24:15 +0000
+++ src/cmds.c 2012-07-18 13:08:43 +0000
@@ -296,7 +296,10 @@
if (remove_boundary
&& CONSP (BVAR (current_buffer, undo_list))
- && NILP (XCAR (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. */
BVAR (current_buffer, undo_list) = XCDR (BVAR (current_buffer, undo_list));
=== modified file 'src/keyboard.c'
--- src/keyboard.c 2012-07-12 03:45:46 +0000
+++ src/keyboard.c 2012-07-18 13:13:31 +0000
@@ -1318,6 +1318,9 @@
}
#endif
+/* The last boundary auto-added to buffer-undo-list. */
+Lisp_Object last_undo_boundary;
+
/* FIXME: This is wrong rather than test window-system, we should call
a new set-selection, which will then dispatch to x-set-selection, or
tty-set-selection, or w32-set-selection, ... */
@@ -1565,7 +1568,13 @@
#endif
if (NILP (KVAR (current_kboard, Vprefix_arg))) /* FIXME: Why?
--Stef */
+ {
+ Lisp_Object undo = BVAR (current_buffer, undo_list);
Fundo_boundary ();
+ last_undo_boundary
+ = (EQ (undo, BVAR (current_buffer, undo_list))
+ ? Qnil : BVAR (current_buffer, undo_list));
+ }
Fcommand_execute (Vthis_command, Qnil, Qnil, Qnil);
#ifdef HAVE_WINDOW_SYSTEM
=== modified file 'src/lisp.h'
--- src/lisp.h 2012-07-18 05:44:36 +0000
+++ src/lisp.h 2012-07-18 13:05:33 +0000
@@ -2921,7 +2921,7 @@
extern void syms_of_search (void);
extern void clear_regexp_cache (void);
-/* Defined in minibuf.c */
+/* Defined in minibuf.c. */
extern Lisp_Object Qcompletion_ignore_case;
extern Lisp_Object Vminibuffer_list;
@@ -2930,25 +2930,25 @@
extern void init_minibuf_once (void);
extern void syms_of_minibuf (void);
-/* Defined in callint.c */
+/* Defined in callint.c. */
extern Lisp_Object Qminus, Qplus;
extern Lisp_Object Qwhen;
extern Lisp_Object Qcall_interactively, Qmouse_leave_buffer_hook;
extern void syms_of_callint (void);
-/* Defined in casefiddle.c */
+/* Defined in casefiddle.c. */
extern Lisp_Object Qidentity;
extern void syms_of_casefiddle (void);
extern void keys_of_casefiddle (void);
-/* Defined in casetab.c */
+/* Defined in casetab.c. */
extern void init_casetab_once (void);
extern void syms_of_casetab (void);
-/* Defined in keyboard.c */
+/* Defined in keyboard.c. */
extern Lisp_Object echo_message_buffer;
extern struct kboard *echo_kboard;
@@ -2956,6 +2956,7 @@
extern Lisp_Object Qdisabled, QCfilter;
extern Lisp_Object Qup, Qdown, Qbottom;
extern Lisp_Object Qtop;
+extern Lisp_Object last_undo_boundary;
extern int input_pending;
extern Lisp_Object menu_bar_items (Lisp_Object);
extern Lisp_Object tool_bar_items (Lisp_Object, int *);
@@ -2976,13 +2977,13 @@
extern void syms_of_keyboard (void);
extern void keys_of_keyboard (void);
-/* Defined in indent.c */
+/* Defined in indent.c. */
extern ptrdiff_t current_column (void);
extern void invalidate_current_column (void);
extern int indented_beyond_p (ptrdiff_t, ptrdiff_t, EMACS_INT);
extern void syms_of_indent (void);
-/* Defined in frame.c */
+/* Defined in frame.c. */
extern Lisp_Object Qonly;
extern Lisp_Object Qvisible;
extern void store_frame_param (struct frame *, Lisp_Object, Lisp_Object);
@@ -2995,7 +2996,7 @@
extern void frames_discard_buffer (Lisp_Object);
extern void syms_of_frame (void);
-/* Defined in emacs.c */
+/* Defined in emacs.c. */
extern char **initial_argv;
extern int initial_argc;
#if defined (HAVE_X_WINDOWS) || defined (HAVE_NS)
--- End Message ---