From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Marcin Borkowski Newsgroups: gmane.emacs.help Subject: A strange issue with buffer-undo-list Date: Tue, 23 Feb 2021 06:19:43 +0100 Message-ID: <87o8gbqs28.fsf@mbork.pl> Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="39748"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: mu4e 1.1.0; emacs 28.0.50 To: Help Gnu Emacs mailing list Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane-mx.org@gnu.org Tue Feb 23 06:20:43 2021 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lEQ7l-000ACi-Uv for geh-help-gnu-emacs@m.gmane-mx.org; Tue, 23 Feb 2021 06:20:41 +0100 Original-Received: from localhost ([::1]:45890 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lEQ7k-0005mx-Vt for geh-help-gnu-emacs@m.gmane-mx.org; Tue, 23 Feb 2021 00:20:41 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:49200) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lEQ7C-0005mk-Sb for help-gnu-emacs@gnu.org; Tue, 23 Feb 2021 00:20:06 -0500 Original-Received: from mail.mojserwer.eu ([195.110.48.8]:60256) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lEQ7A-0007CG-CF for help-gnu-emacs@gnu.org; Tue, 23 Feb 2021 00:20:06 -0500 Original-Received: from localhost (localhost [127.0.0.1]) by mail.mojserwer.eu (Postfix) with ESMTP id 009F3E6870 for ; Tue, 23 Feb 2021 06:19:53 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at mail.mojserwer.eu Original-Received: from mail.mojserwer.eu ([127.0.0.1]) by localhost (mail.mojserwer.eu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 2VPKG1u44RLq for ; Tue, 23 Feb 2021 06:19:49 +0100 (CET) Original-Received: from localhost (178235147125.dynamic-3-poz-k-0-1-0.vectranet.pl [178.235.147.125]) by mail.mojserwer.eu (Postfix) with ESMTPSA id D4166E683A for ; Tue, 23 Feb 2021 06:19:48 +0100 (CET) Received-SPF: pass client-ip=195.110.48.8; envelope-from=mbork@mbork.pl; helo=mail.mojserwer.eu X-Spam_score_int: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "help-gnu-emacs" Xref: news.gmane.io gmane.emacs.help:128208 Archived-At: 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