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
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
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.