unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
From: Marcin Borkowski <mbork@mbork.pl>
To: Help Gnu Emacs mailing list <help-gnu-emacs@gnu.org>
Subject: A strange issue with buffer-undo-list
Date: Tue, 23 Feb 2021 06:19:43 +0100	[thread overview]
Message-ID: <87o8gbqs28.fsf@mbork.pl> (raw)

Hi all,

I was writing a command to move the current line past the next one (for
educational purposes), and I encountered a strange issue.

Here is my function:

--8<---------------cut here---------------start------------->8---
(defun move-line-down (count)
  "Move the current line down."
  (interactive "p")
  (let ((position-in-line (current-column)))
    (line-move 1)
    (transpose-lines count)
    (line-move -1)
    (move-to-column position-in-line)))
--8<---------------cut here---------------end--------------->8---

(It is definitely far from optimal, and I know that - the next version
will get rid of `transpose-lines' dependency and will just delete the
line below and recreate it above within a `save-excursion', which will
render the `position-in-line' stuff unnecessary.  But never mind this.)

So, my problem is that if I say M-x move-line-down, everything works,
but after undoing that change, the point lands at the bol of the next
line instead if where it had been at the beginning.  (I suppose this is
because only the `(transpose-lines count)' is effectively undone, so
`(line-move 1)` is not undone - that makes sense.)

So, I changed the code to this:

--8<---------------cut here---------------start------------->8---
(defun move-line-down (count)
  "Move the current line down."
  (interactive "p")
  (let ((position-in-line (current-column)))
    (push (point) buffer-undo-list)
    (line-move 1)
    (transpose-lines count)
    (line-move -1)
    (move-to-column position-in-line)))
--8<---------------cut here---------------end--------------->8---

which triggers an error.

Now, I did (of course) M-x toggle-debug-on-error, and so I learned about
"change groups".  I haven't heard about them before, so I consulted the
docs, and they seem cool (much like transactions in databases).  But
I have questions.

1. Why did my code confuse the change group mechanism?

2. How do I use `undo-amalgamate-change-group'?  The manual does not
provide any examples, and I only found one occurrence in the Emacs
source, and frankly, it didn't help a lot.  (Well, once I know the
answer to my next question, this will most probably be easy.)

3. Also, I am not even sure how the change group mechanism is supposed
to be used.  The docs tell me to use `unwind-protect', but this:

--8<---------------cut here---------------start------------->8---
(defun move-line-down (count)
  "Move the current line down."
  (interactive "p")
  (let ((position-in-line (current-column))
	(change-group (prepare-change-group)))
    (unwind-protect
	(progn
	  (activate-change-group change-group)
	  (line-move 1)
	  (transpose-lines count)
	  (line-move -1)
	  (move-to-column position-in-line)
	  (accept-change-group change-group))
      (cancel-change-group change-group))))
--8<---------------cut here---------------end--------------->8---

of course doesn't work, since both `accept-change-group' and
`cancel-change-group' are evaluated.  Is there a way to get the "state"
of the change group to only cancel it if it was not finished?

Anyway, it seems that this whole machinery is an overkill for the
purpose of just moving a line down - but as I said, I want to learn and
teach here, so this is kind of intentionally a toy example.

TIA,

-- 
Marcin Borkowski
http://mbork.pl



             reply	other threads:[~2021-02-23  5:19 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-23  5:19 Marcin Borkowski [this message]
2021-02-24  0:43 ` A strange issue with buffer-undo-list Michael Heerdegen
2021-02-25  5:16   ` Marcin Borkowski
2021-02-25  5:28     ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-02-25 14:19       ` Stefan Monnier
2021-02-25 15:58         ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-03-08 21:43       ` Marcin Borkowski
2021-02-26  0:53     ` Michael Heerdegen
2021-03-08 21:42       ` Marcin Borkowski
2021-03-09  0:32         ` Michael Heerdegen
2021-03-09 21:22           ` Marcin Borkowski
2021-02-24  2:11 ` Michael Heerdegen
2021-02-24  3:33 ` Michael Heerdegen
2021-02-24  4:49   ` Stefan Monnier

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

  List information: https://www.gnu.org/software/emacs/

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

  git send-email \
    --in-reply-to=87o8gbqs28.fsf@mbork.pl \
    --to=mbork@mbork.pl \
    --cc=help-gnu-emacs@gnu.org \
    /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.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).