GNU bug report logs - #72392
30.0.50; Wrong `next-line` behavior

Previous Next

Package: emacs;

Reported by: Stefan Monnier <monnier <at> iro.umontreal.ca>

Date: Wed, 31 Jul 2024 07:44:01 UTC

Severity: normal

Found in version 30.0.50

To reply to this bug, email your comments to 72392 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to monnier <at> iro.umontreal.ca, bug-gnu-emacs <at> gnu.org:
bug#72392; Package emacs. (Wed, 31 Jul 2024 07:44:01 GMT) Full text and rfc822 format available.

Acknowledgement sent to Stefan Monnier <monnier <at> iro.umontreal.ca>:
New bug report received and forwarded. Copy sent to monnier <at> iro.umontreal.ca, bug-gnu-emacs <at> gnu.org. (Wed, 31 Jul 2024 07:44:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: bug-gnu-emacs <at> gnu.org
Subject: 30.0.50; Wrong `next-line` behavior
Date: Wed, 31 Jul 2024 03:43:20 -0400
[Message part 1 (text/plain, inline)]
Package: Emacs
Version: 30.0.50


Here's a funny corner case I just bumped into:

- Apply the `smerge-mode.patch` below to Emacs's` master` (and
  recompile `smerge-mode.el`).
- Open the short diff file below with:

    emacs -Q --eval '(setq-default word-wrap t diff-font-lock-prettify t)' \
          .../bug-weird-next-line.diff

- In my case, when this opens there's a "word wrap" just before "This"
  and just before "\id{seg}" (on the 4th and 5th lines, resp).
  If that's not the case for you, resize your frame so that this is
  the case.

- Do `C-n` a few times.

What I see is that `C-n` jumps down to the "T" of the word-wrapped
"This" as it should, but that the next `C-n` doesn't jump to the next
(visual) line but jumps to the "s" of "This" instead.
The same kind of misbehavior occurs on the next (logical) line with
"\id{seg}".


        Stefan
[smerge-mode.patch (text/x-diff, inline)]
diff --git a/lisp/vc/smerge-mode.el b/lisp/vc/smerge-mode.el
index a16c7871ff9..05ab757f09a 100644
--- a/lisp/vc/smerge-mode.el
+++ b/lisp/vc/smerge-mode.el
@@ -1034,26 +1034,68 @@ smerge--refine-highlight-change
                                   smerge-refine-forward-function)
                                 startline)
                        (point)))
-           (end (progn (funcall (if smerge-refine-weight-hack
-                                    #'forward-char
-                                  smerge-refine-forward-function)
-                          (if match-num2
-                              (- (string-to-number match-num2)
-                                 startline)
-                            1))
-                       (point))))
-      (when smerge-refine-ignore-whitespace
-        (skip-chars-backward " \t\n" beg) (setq end (point))
-        (goto-char beg)
-        (skip-chars-forward " \t\n" end)  (setq beg (point)))
-      (when (> end beg)
+           (end (if (eq t match-num2) beg
+                  (funcall (if smerge-refine-weight-hack
+                               #'forward-char
+                             smerge-refine-forward-function)
+                           (if match-num2
+                               (- (string-to-number match-num2)
+                                  startline)
+                             1))
+                  (point))))
+      (when (eq t match-num2)
+        ;; FIXME: No idea where this off-by-one comes from!
+        (setq beg (1+ beg))
+        (setq end (1+ end))
+        (goto-char end))
+      (when (and smerge-refine-ignore-whitespace
+                 (< beg end))
+        (let* ((newend (progn (skip-chars-backward " \t\n" beg) (point)))
+               (newbeg (progn (goto-char beg)
+                              (skip-chars-forward " \t\n" newend) (point))))
+          (unless (eq newend newbeg)
+            (setq end newend)
+            (setq beg newbeg))))
+      (cond
+       ((> end beg)
         (let ((ol (make-overlay
                    beg end nil
                    ;; Make them tend to shrink rather than spread when editing.
                    'front-advance nil)))
+          (overlay-put ol 'smerge--debug (list match-num1 match-num2 startline))
           (overlay-put ol 'evaporate t)
           (dolist (x props) (overlay-put ol (car x) (cdr x)))
-          ol)))))
+          ol))
+       ((= end beg)
+        (setq end (if (< beg (point-max))
+                      (1+ beg)
+                    (cl-assert (< (point-min) (point-max)))
+                    (setq beg (1- (point-max)))
+                    (point-max)))
+        (let ((ol (make-overlay
+                   beg end nil
+                   ;; Make them tend to shrink rather than spread when editing.
+                   'front-advance nil)))
+          (overlay-put ol 'smerge--debug (list match-num1 match-num2 startline))
+          (overlay-put ol 'evaporate t)
+          ;; Some of the properties need to go to `ol' and others
+          ;; need to go to the string :-(
+          ;; FIXME: I've seen lines in `diff-mode' where the half-space ends up
+          ;; placed at the beginning of the next line rather than the
+          ;; end of the current line, as in:
+          ;;
+          ;;     -foo bar
+          ;;     + foo bar b
+          ;;      ^
+          (overlay-put ol 'before-string
+                       (propertize
+                        " " 'face (cdr (assq 'face props))
+                        'display '(space :width 0.5)))
+          (dolist (x props)
+            (unless (eq (car-safe x) 'face)
+              (overlay-put ol (car x) (cdr x))))
+          ol))
+       (t (error "Smerge WOW! %S" (list beg end match-num2)))))))
 
 ;;;###autoload
 (defun smerge-refine-regions (beg1 end1 beg2 end2 props-c &optional preproc props-r props-a)
@@ -1114,20 +1156,18 @@ smerge-refine-regions
                     (m2 (match-string 2))
                     (m4 (match-string 4))
                     (m5 (match-string 5)))
-                (when (memq op '(?d ?c))
-                  (setq last1
-                        (smerge--refine-highlight-change
-			 beg1 m1 m2
-			 ;; Try to use props-c only for changed chars,
-			 ;; fallback to props-r for changed/removed chars,
-			 ;; but if props-r is nil then fallback to props-c.
-			 (or (and (eq op '?c) props-c) props-r props-c))))
-                (when (memq op '(?a ?c))
-                  (setq last2
-                        (smerge--refine-highlight-change
-			 beg2 m4 m5
-			 ;; Same logic as for removed chars above.
-			 (or (and (eq op '?c) props-c) props-a props-c)))))
+                (setq last1
+                      (smerge--refine-highlight-change
+		       beg1 m1 (if (eq op ?a) t m2)
+		       ;; Try to use props-c only for changed chars,
+		       ;; fallback to props-r for changed/removed chars,
+		       ;; but if props-r is nil then fallback to props-c.
+		       (or (and (eq op '?c) props-c) props-r props-c)))
+                (setq last2
+                      (smerge--refine-highlight-change
+		       beg2 m4 (if (eq op ?d) t m5)
+		       ;; Same logic as for removed chars above.
+		       (or (and (eq op '?c) props-c) props-a props-c))))
               (forward-line 1)                            ;Skip hunk header.
               (and (re-search-forward "^[0-9]" nil 'move) ;Skip hunk body.
                    (goto-char (match-beginning 0))))
[bug-weird-next-line.diff (text/x-diff, inline)]
@@ -2004,7 +2538,8 @@
 
 equivalent to a function out of the interval. Its defining characteristic is
-that the output of such a function has to agree at both endpoints of $\bI$. This
-is enforced by the elimination principle of the $\bI$ that ensures that \id{seg}
+that the output of such a function has to agree at both endpoints of $\bI$.
+This is enforced by the elimination principle of the $\bI$ that ensures that
+\id{seg} is respected.
 
 \begin{minted}[escapeinside=@@,mathescape=true]{agda}
     type I

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#72392; Package emacs. (Fri, 02 Aug 2024 06:58:01 GMT) Full text and rfc822 format available.

Message #8 received at 72392 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: 72392 <at> debbugs.gnu.org, monnier <at> iro.umontreal.ca
Subject: Re: bug#72392: 30.0.50; Wrong `next-line` behavior
Date: Fri, 02 Aug 2024 09:57:25 +0300
> Cc: monnier <at> iro.umontreal.ca
> Date: Wed, 31 Jul 2024 03:43:20 -0400
> From:  Stefan Monnier via "Bug reports for GNU Emacs,
>  the Swiss army knife of text editors" <bug-gnu-emacs <at> gnu.org>
> 
> - Apply the `smerge-mode.patch` below to Emacs's` master` (and
>   recompile `smerge-mode.el`).
> - Open the short diff file below with:
> 
>     emacs -Q --eval '(setq-default word-wrap t diff-font-lock-prettify t)' \
>           .../bug-weird-next-line.diff
> 
> - In my case, when this opens there's a "word wrap" just before "This"
>   and just before "\id{seg}" (on the 4th and 5th lines, resp).
>   If that's not the case for you, resize your frame so that this is
>   the case.
> 
> - Do `C-n` a few times.

Any hope of a simpler recipe, which would not require patching Emacs?
Cannot you just post the contents of the problematic buffer and the
non-default settings to use to reproduce the problem?

The bug is probably somewhere in vertical-motion or in line-move and
its subroutines, but a simpler recipe will make the investigation less
painful.

TIA




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#72392; Package emacs. (Sat, 24 Aug 2024 08:24:02 GMT) Full text and rfc822 format available.

Message #11 received at 72392 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: monnier <at> iro.umontreal.ca
Cc: 72392 <at> debbugs.gnu.org
Subject: Re: bug#72392: 30.0.50; Wrong `next-line` behavior
Date: Sat, 24 Aug 2024 11:22:08 +0300
Ping! A simple test case could go a long way towards a solution.

> Cc: 72392 <at> debbugs.gnu.org, monnier <at> iro.umontreal.ca
> Date: Fri, 02 Aug 2024 09:57:25 +0300
> From: Eli Zaretskii <eliz <at> gnu.org>
> 
> > Cc: monnier <at> iro.umontreal.ca
> > Date: Wed, 31 Jul 2024 03:43:20 -0400
> > From:  Stefan Monnier via "Bug reports for GNU Emacs,
> >  the Swiss army knife of text editors" <bug-gnu-emacs <at> gnu.org>
> > 
> > - Apply the `smerge-mode.patch` below to Emacs's` master` (and
> >   recompile `smerge-mode.el`).
> > - Open the short diff file below with:
> > 
> >     emacs -Q --eval '(setq-default word-wrap t diff-font-lock-prettify t)' \
> >           .../bug-weird-next-line.diff
> > 
> > - In my case, when this opens there's a "word wrap" just before "This"
> >   and just before "\id{seg}" (on the 4th and 5th lines, resp).
> >   If that's not the case for you, resize your frame so that this is
> >   the case.
> > 
> > - Do `C-n` a few times.
> 
> Any hope of a simpler recipe, which would not require patching Emacs?
> Cannot you just post the contents of the problematic buffer and the
> non-default settings to use to reproduce the problem?
> 
> The bug is probably somewhere in vertical-motion or in line-move and
> its subroutines, but a simpler recipe will make the investigation less
> painful.
> 
> TIA
> 
> 
> 
> 




This bug report was last modified 293 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.