all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: martin rudalics <rudalics@gmx.at>
To: Stefan Monnier <monnier@iro.umontreal.ca>
Cc: emacs-devel@gnu.org
Subject: Re: undo weirdness with insert-file-contents
Date: Fri, 07 Mar 2008 10:33:13 +0100	[thread overview]
Message-ID: <47D10BD9.9050001@gmx.at> (raw)
In-Reply-To: <jwvzltfjzgt.fsf-monnier+emacs@gnu.org>

[-- Attachment #1: Type: text/plain, Size: 964 bytes --]

 > Good, point so we just turn off undo during the dance and then insert
 > the single undo-element (this is only valid for non-REPLACE, of course).

Hopefully for VISIT as well - we should not record deletions when
handling the VISIT&REPLACE case.  I see only three cases here:

(1) undo-list was t => leave it alone.

(2) nochange => restore undo-list to previous value.

(3) otherwise => reset undo-list to nil.

I also added a nochange arm for the non-decoding case - please have a
look.  BTW nochange makes an incompatible change to `revert-buffer': You
can no longer use `revert-buffer' to get rid of the undo list.  I think
this should be documented somehow.  Finally, we should document that
REPLACE doesn't handle differences in text properties and tell users to
write their own `revert-buffer-insert-file-contents-function' to handle
them.

martin, who still considers the non-VISIT&REPLACE case obscure and
cannot see any "example" in `smerge-resolve'.

[-- Attachment #2: fileio.patch --]
[-- Type: text/plain, Size: 6265 bytes --]

*** fileio.c	Wed Feb 27 07:49:02 2008
--- fileio.c	Fri Mar  7 10:16:10 2008
***************
*** 3721,3727 ****
    register int unprocessed;
    int count = SPECPDL_INDEX ();
    struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
!   Lisp_Object handler, val, insval, orig_filename, old_undo;
    Lisp_Object p;
    int total = 0;
    int not_regular = 0;
--- 3721,3727 ----
    register int unprocessed;
    int count = SPECPDL_INDEX ();
    struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
!   Lisp_Object handler, val, insval, orig_filename, old_undo_list;
    Lisp_Object p;
    int total = 0;
    int not_regular = 0;
***************
*** 3734,3739 ****
--- 3734,3740 ----
    int read_quit = 0;
    Lisp_Object old_Vdeactivate_mark = Vdeactivate_mark;
    int we_locked_file = 0;
+   int buffer_was_unmodified;
  
    if (current_buffer->base_buffer && ! NILP (visit))
      error ("Cannot do file visiting in an indirect buffer");
***************
*** 3744,3752 ****
    val = Qnil;
    p = Qnil;
    orig_filename = Qnil;
!   old_undo = Qnil;
  
!   GCPRO5 (filename, val, p, orig_filename, old_undo);
  
    CHECK_STRING (filename);
    filename = Fexpand_file_name (filename, Qnil);
--- 3745,3754 ----
    val = Qnil;
    p = Qnil;
    orig_filename = Qnil;
!   old_undo_list = Qnil;
!   buffer_was_unmodified = MODIFF <= SAVE_MODIFF;
  
!   GCPRO5 (filename, val, p, orig_filename, old_undo_list);
  
    CHECK_STRING (filename);
    filename = Fexpand_file_name (filename, Qnil);
***************
*** 3984,3989 ****
--- 3986,3999 ----
        set_coding_system = 1;
      }
  
+   /* Don't record undo information when visiting or not replacing; we
+      restore the undo list manually after the format decode step.  */
+   if (! NILP (visit) || NILP (replace))
+     {
+       old_undo_list = current_buffer->undo_list;
+       current_buffer->undo_list = Qt;
+     }
+ 
    /* If requested, replace the accessible part of the buffer
       with the file contents.  Avoid replacing text at the
       beginning or end of the buffer that matches the file contents;
***************
*** 4067,4074 ****
  	{
  	  emacs_close (fd);
  	  specpdl_ptr--;
! 	  /* Truncate the buffer to the size of the file.  */
! 	  del_range_1 (same_at_start, same_at_end, 0, 0);
  	  goto handled;
  	}
        immediate_quit = 1;
--- 4077,4088 ----
  	{
  	  emacs_close (fd);
  	  specpdl_ptr--;
! 	  if (same_at_start == same_at_end)
! 	    nochange = 1;
! 	  else
! 	    /* Truncate the buffer to the size of the file.  */
! 	    del_range_1 (same_at_start, same_at_end, 0, 0);
! 	  inserted = 0;
  	  goto handled;
  	}
        immediate_quit = 1;
***************
*** 4281,4290 ****
        if (bufpos == inserted)
  	{
  	  specpdl_ptr--;
- 	  /* Truncate the buffer to the size of the file.  */
  	  if (same_at_start == same_at_end)
  	    nochange = 1;
  	  else
  	    del_range_byte (same_at_start, same_at_end, 0);
  	  inserted = 0;
  
--- 4295,4304 ----
        if (bufpos == inserted)
  	{
  	  specpdl_ptr--;
  	  if (same_at_start == same_at_end)
  	    nochange = 1;
  	  else
+ 	    /* Truncate the buffer to the size of the file.  */
  	    del_range_byte (same_at_start, same_at_end, 0);
  	  inserted = 0;
  
***************
*** 4632,4640 ****
  
    if (!NILP (visit))
      {
-       if (!EQ (current_buffer->undo_list, Qt) && !nochange)
- 	current_buffer->undo_list = Qnil;
- 
        if (NILP (handler))
  	{
  	  current_buffer->modtime = st.st_mtime;
--- 4646,4651 ----
***************
*** 4679,4688 ****
        specbind (Qinhibit_point_motion_hooks, Qt);
        specbind (Qinhibit_modification_hooks, Qt);
  
-       /* Save old undo list and don't record undo for decoding. */
-       old_undo = current_buffer->undo_list;
-       current_buffer->undo_list = Qt;
- 
        if (NILP (replace))
  	{
  	  insval = call3 (Qformat_decode,
--- 4690,4695 ----
***************
*** 4766,4793 ****
  	  p = XCDR (p);
  	}
  
!       if (NILP (visit))
  	{
! 	  Lisp_Object lbeg, lend;
! 	  XSETINT (lbeg, PT);
! 	  XSETINT (lend, PT + inserted);
! 	  if (CONSP (old_undo))
  	    {
! 	      Lisp_Object tem = XCAR (old_undo);
! 	      if (CONSP (tem) && INTEGERP (XCAR (tem)) &&
! 		  INTEGERP (XCDR (tem)) && EQ (XCAR (tem), lbeg))
! 		/* In the non-visiting case record only the final insertion. */
! 		current_buffer->undo_list =
! 		  Fcons (Fcons (lbeg, lend), Fcdr (old_undo));
  	    }
  	}
-       else
- 	/* If undo_list was Qt before, keep it that way.
- 	   Otherwise start with an empty undo_list. */
- 	current_buffer->undo_list = EQ (old_undo, Qt) ? Qt : Qnil;
- 
        unbind_to (count, Qnil);
      }
  
    /* Call after-change hooks for the inserted text, aside from the case
       of normal visiting (not with REPLACE), which is done in a new buffer
--- 4773,4813 ----
  	  p = XCDR (p);
  	}
  
!       if (! NILP (visit))
  	{
! 	  if (! EQ (old_undo_list, Qt))
! 	    /* Reset undo list for visiting case.  */
! 	    current_buffer->undo_list =  Qnil;
! 	}
!       else if (NILP (replace) && ! EQ (old_undo_list, Qt))
! 	/* For the non-visiting, non-replacing case record the last
! 	   insertion only.  This avoids that intermediate steps get
! 	   recorded and show up during undo.  */
! 	{
! 	  current_buffer->undo_list = old_undo_list;
! 	  if (inserted > 0)
  	    {
! 	      if (buffer_was_unmodified)
! 		/* If the buffer was unmodified when this function was
! 		   called record a first buffer change (this is *not*
! 		   done by the record_insert below since the buffer is
! 		   already modified).  */
! 		record_first_change ();
! 	      record_insert (PT, inserted);
  	    }
  	}
        unbind_to (count, Qnil);
      }
+   else if (! NILP (visit))
+     {
+       if (! EQ (old_undo_list, Qt))
+ 	/* For the visiting case restore old undo list iff replacing and
+ 	   nothing changed.  Otherwise start with empty undo list.  */
+ 	current_buffer->undo_list = nochange ? old_undo_list : Qnil;
+     }
+   else if (NILP (replace))
+     /* Restore old undo list in non-visiting, non-replacing case.  */
+     current_buffer->undo_list = old_undo_list;
  
    /* Call after-change hooks for the inserted text, aside from the case
       of normal visiting (not with REPLACE), which is done in a new buffer

  reply	other threads:[~2008-03-07  9:33 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-02-28  7:46 undo weirdness with insert-file-contents Miles Bader
2008-02-28  9:56 ` martin rudalics
2008-02-28 11:01   ` Miles Bader
2008-02-28 13:12     ` martin rudalics
2008-02-28 16:52       ` Stefan Monnier
2008-02-28 19:31         ` martin rudalics
2008-02-28 20:01           ` Miles Bader
2008-02-28 22:19             ` martin rudalics
2008-02-28 21:35           ` Stefan Monnier
2008-02-28 22:21             ` martin rudalics
2008-02-28 17:45 ` Glenn Morris
2008-02-28 19:35   ` martin rudalics
2008-02-28 20:28     ` Glenn Morris
2008-02-28 22:20       ` martin rudalics
2008-02-29 22:42       ` martin rudalics
2008-03-02  5:02         ` Stefan Monnier
2008-03-02 12:44           ` martin rudalics
2008-03-02 19:07             ` Stefan Monnier
2008-03-02 22:05               ` martin rudalics
2008-03-03  2:15                 ` Stefan Monnier
2008-03-03  9:09                   ` martin rudalics
2008-03-03 21:03                     ` Stefan Monnier
2008-03-07  9:33                       ` martin rudalics [this message]
2008-03-07 22:04                         ` Stefan Monnier
2008-03-08  9:55                           ` martin rudalics
2008-03-02 22:18               ` Bill Wohler
2008-03-03  9:09                 ` martin rudalics
2008-02-29  5:50   ` Bill Wohler

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=47D10BD9.9050001@gmx.at \
    --to=rudalics@gmx.at \
    --cc=emacs-devel@gnu.org \
    --cc=monnier@iro.umontreal.ca \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.