Subject: Re: bug#33458: 27.0.50; dired loses position when reverted from outside place

From: martin rudalics <[email-masked]>
Date: Tue, 04 Dec 2018 09:33:26 +0100

> If dired buffer reverted from outside it, cursor jumps to begin of the
 > buffer once this buffer becomes current again.
 >
 > How to reproduce:
 >
 > 0. emacs -Q
 >
 > 1. Open some directory, say "DIR-A" in dired.
 >
 > 2. Move cursor to subdirectory, say "DIR-B", M-: (point) ;=> e.g. 225.
 >
 > 3. Dive into subdirectory "DIR-B".
 >
 > 4. Let's check position: M-: (with-current-buffer "DIR-A" (point)) ;=> 225, so cursor in the right place.
 >
 > 5. Revert original buffer: M-: (with-current-buffer "DIR-A" (dired-revert))
 >
 > 6. Check position again: M-: (with-current-buffer "DIR-A" (point)) ;=> 225, seems right here...
 >
 > 7. Switch back from the buffer with "DIR-B" to the buffer with "DIR-A".
 >
 > 8. Position lost! M-: (point) ;=> 1, but 225 expected.
 >
 > The issue very spunky if auto-revert-mode is used.
 >
 > Can't reproduce this issue with regular buffer, so it seems dired-specific.

The attached patch should fix this problem and the other ones with
'dired' that have been cited in this context.  Please try it.

Thanks, martin
diff --git a/lisp/dired.el b/lisp/dired.el
index cbd85fe..e5dc862 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -1478,12 +1478,36 @@ dired-save-positions
                (list w
 		     (dired-get-filename nil t)
                      (line-number-at-pos (window-point w)))))
-	   (get-buffer-window-list nil 0 t))))
+	   (get-buffer-window-list nil 0 t))
+   ;; For each window that showed the current buffer before, scan its
+   ;; list of previous buffers.  For each association thus found save
+   ;; a triple <point, name, line> where 'point' is that window's
+   ;; window-point marker stored in the window's list of previous
+   ;; buffers, 'name' is the filename at the position of 'point' and
+   ;; 'line' is the line number at the position of 'point'.
+   (let ((buffer (current-buffer))
+         prevs)
+     (walk-windows
+      (lambda (window)
+        (let ((prev (assq buffer (window-prev-buffers window))))
+          (when prev
+            (with-current-buffer buffer
+              (save-excursion
+                (goto-char (nth 2 prev))
+                (setq prevs
+                      (cons
+                       (list (nth 2 prev)
+                             (dired-get-filename nil t)
+                             (line-number-at-pos (point)))
+                       prevs)))))))
+      'nomini t)
+     prevs)))
 
 (defun dired-restore-positions (positions)
   "Restore POSITIONS saved with `dired-save-positions'."
   (let* ((buf-file-pos (nth 0 positions))
-	 (buffer (nth 0 buf-file-pos)))
+	 (buffer (nth 0 buf-file-pos))
+         (prevs (nth 2 positions)))
     (unless (and (nth 1 buf-file-pos)
 		 (dired-goto-file (nth 1 buf-file-pos)))
       (goto-char (point-min))
@@ -1497,7 +1521,21 @@ dired-restore-positions
 		       (dired-goto-file (nth 1 win-file-pos)))
             (goto-char (point-min))
 	    (forward-line (1- (nth 2 win-file-pos)))
-	    (dired-move-to-filename)))))))
+	    (dired-move-to-filename)))))
+    (when prevs
+      (with-current-buffer buffer
+        (save-excursion
+          (dolist (prev prevs)
+            (let ((point (nth 0 prev)))
+              ;; Sanity check of the point marker.
+              (when (and (markerp point)
+                         (eq (marker-buffer point) buffer))
+                (unless (and (nth 0 prev)
+                             (dired-goto-file (nth 1 prev)))
+                  (goto-char (point-min))
+	          (forward-line (1- (nth 2 prev))))
+	        (dired-move-to-filename)
+                (move-marker point (point) buffer)))))))))
 
 (defun dired-remember-marks (beg end)
   "Return alist of files and their marks, from BEG to END."