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
next prev parent 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.