aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTino Calancha2017-08-06 13:05:16 +0900
committerTino Calancha2017-08-06 13:09:31 +0900
commit7c3593f81724d0c7a2ee2f90797db0e705adc859 (patch)
tree1c87dc10cc0ca3fd1cd7774bbf181eef782d1f8c
parent9b463fa8648b7baed95a44f4317cb7402fd8bf1c (diff)
downloademacs-7c3593f81724d0c7a2ee2f90797db0e705adc859.tar.gz
emacs-7c3593f81724d0c7a2ee2f90797db0e705adc859.zip
dired-revert: save line numbers instead of positions
Positions might change if the length of one dired header line changes; this happen, for instance, if we add new files. Instead, line numbers are invariant under shrinks/enlargements of the file header. https://lists.gnu.org/archive/html/emacs-devel/2017-07/msg01092.html * lisp/dired.el (dired-save-positions): Save the line numbers at point. (dired-restore-positions): Use forward-line to restore the original position (Bug#27968). * test/lisp/dired-tests.el (dired-test-bug27968): Add test.
-rw-r--r--lisp/dired.el24
-rw-r--r--test/lisp/dired-tests.el46
2 files changed, 61 insertions, 9 deletions
diff --git a/lisp/dired.el b/lisp/dired.el
index 24759c6c9bd..d04bd6fe037 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -1444,18 +1444,22 @@ ARG and NOCONFIRM, passed from `revert-buffer', are ignored."
1444The positions have the form (BUFFER-POSITION WINDOW-POSITIONS). 1444The positions have the form (BUFFER-POSITION WINDOW-POSITIONS).
1445 1445
1446BUFFER-POSITION is the point position in the current Dired buffer. 1446BUFFER-POSITION is the point position in the current Dired buffer.
1447It has the form (BUFFER DIRED-FILENAME BUFFER-POINT). 1447It has the form (BUFFER DIRED-FILENAME BUFFER-LINE-NUMBER).
1448 1448
1449WINDOW-POSITIONS are current positions in all windows displaying 1449WINDOW-POSITIONS are current positions in all windows displaying
1450this dired buffer. The window positions have the form (WINDOW 1450this dired buffer. The window positions have the form (WINDOW
1451DIRED-FILENAME WINDOW-POINT)." 1451DIRED-FILENAME WINDOW-LINE-NUMBER).
1452
1453We store line numbers instead of point positions because the header
1454lines might change as well: when this happen the line number doesn't
1455change; the point does."
1452 (list 1456 (list
1453 (list (current-buffer) (dired-get-filename nil t) (point)) 1457 (list (current-buffer) (dired-get-filename nil t) (line-number-at-pos))
1454 (mapcar (lambda (w) 1458 (mapcar (lambda (w)
1455 (list w 1459 (with-selected-window w
1456 (with-selected-window w 1460 (list w
1457 (dired-get-filename nil t)) 1461 (dired-get-filename nil t)
1458 (window-point w))) 1462 (line-number-at-pos (window-point w)))))
1459 (get-buffer-window-list nil 0 t)))) 1463 (get-buffer-window-list nil 0 t))))
1460 1464
1461(defun dired-restore-positions (positions) 1465(defun dired-restore-positions (positions)
@@ -1464,7 +1468,8 @@ DIRED-FILENAME WINDOW-POINT)."
1464 (buffer (nth 0 buf-file-pos))) 1468 (buffer (nth 0 buf-file-pos)))
1465 (unless (and (nth 1 buf-file-pos) 1469 (unless (and (nth 1 buf-file-pos)
1466 (dired-goto-file (nth 1 buf-file-pos))) 1470 (dired-goto-file (nth 1 buf-file-pos)))
1467 (goto-char (nth 2 buf-file-pos)) 1471 (goto-char (point-min))
1472 (forward-line (1- (nth 2 buf-file-pos)))
1468 (dired-move-to-filename)) 1473 (dired-move-to-filename))
1469 (dolist (win-file-pos (nth 1 positions)) 1474 (dolist (win-file-pos (nth 1 positions))
1470 ;; Ensure that window still displays the original buffer. 1475 ;; Ensure that window still displays the original buffer.
@@ -1472,7 +1477,8 @@ DIRED-FILENAME WINDOW-POINT)."
1472 (with-selected-window (nth 0 win-file-pos) 1477 (with-selected-window (nth 0 win-file-pos)
1473 (unless (and (nth 1 win-file-pos) 1478 (unless (and (nth 1 win-file-pos)
1474 (dired-goto-file (nth 1 win-file-pos))) 1479 (dired-goto-file (nth 1 win-file-pos)))
1475 (goto-char (nth 2 win-file-pos)) 1480 (goto-char (point-min))
1481 (forward-line (1- (nth 2 win-file-pos)))
1476 (dired-move-to-filename))))))) 1482 (dired-move-to-filename)))))))
1477 1483
1478(defun dired-remember-marks (beg end) 1484(defun dired-remember-marks (beg end)
diff --git a/test/lisp/dired-tests.el b/test/lisp/dired-tests.el
index b14bbc63609..105a79f0014 100644
--- a/test/lisp/dired-tests.el
+++ b/test/lisp/dired-tests.el
@@ -308,5 +308,51 @@
308 (should (eq 2 (current-column)))) 308 (should (eq 2 (current-column))))
309 (dired-hide-details-mode orig)))) 309 (dired-hide-details-mode orig))))
310 310
311(ert-deftest dired-test-bug27968 ()
312 "Test for http://debbugs.gnu.org/27968 ."
313 (let* ((top-dir (make-temp-file "top-dir" t))
314 (subdir (expand-file-name "subdir" top-dir))
315 (header-len-fn (lambda ()
316 (save-excursion
317 (goto-char 1)
318 (forward-line 1)
319 (- (point-at-eol) (point)))))
320 orig-len len diff pos line-nb)
321 (make-directory subdir 'parents)
322 (unwind-protect
323 (with-current-buffer (dired-noselect subdir)
324 (setq orig-len (funcall header-len-fn)
325 pos (point)
326 line-nb (line-number-at-pos))
327 ;; Bug arises when the header line changes its length; this may
328 ;; happen if the used space has changed: for instance, with the
329 ;; creation of additional files.
330 (make-directory "subdir" t)
331 (dired-revert)
332 ;; Change the header line.
333 (save-excursion
334 (goto-char 1)
335 (forward-line 1)
336 (let ((inhibit-read-only t))
337 (delete-region (point) (point-at-eol))
338 (insert " test-bug27968")))
339 (setq len (funcall header-len-fn)
340 diff (- len orig-len))
341 (should-not (zerop diff)) ; Header length has changed.
342 ;; If diff > 0, then the point moves back.
343 ;; If diff < 0, then the point moves forward.
344 ;; If diff = 0, then the point doesn't move.
345 ;; Sometimes this point movement causes
346 ;; line-nb != (line-number-at-pos pos), so that we get
347 ;; an unexpected file at point if we store buffer points.
348 ;; Note that the line number before/after revert
349 ;; doesn't change.
350 (should (= line-nb
351 (line-number-at-pos)
352 (line-number-at-pos (+ pos diff))))
353 ;; After revert, the point must be in 'subdir' line.
354 (should (equal "subdir" (dired-get-filename 'local t))))
355 (delete-directory top-dir t))))
356
311(provide 'dired-tests) 357(provide 'dired-tests)
312;; dired-tests.el ends here 358;; dired-tests.el ends here