diff options
| author | Tino Calancha | 2017-08-06 13:05:16 +0900 |
|---|---|---|
| committer | Tino Calancha | 2017-08-06 13:09:31 +0900 |
| commit | 7c3593f81724d0c7a2ee2f90797db0e705adc859 (patch) | |
| tree | 1c87dc10cc0ca3fd1cd7774bbf181eef782d1f8c | |
| parent | 9b463fa8648b7baed95a44f4317cb7402fd8bf1c (diff) | |
| download | emacs-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.el | 24 | ||||
| -rw-r--r-- | test/lisp/dired-tests.el | 46 |
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." | |||
| 1444 | The positions have the form (BUFFER-POSITION WINDOW-POSITIONS). | 1444 | The positions have the form (BUFFER-POSITION WINDOW-POSITIONS). |
| 1445 | 1445 | ||
| 1446 | BUFFER-POSITION is the point position in the current Dired buffer. | 1446 | BUFFER-POSITION is the point position in the current Dired buffer. |
| 1447 | It has the form (BUFFER DIRED-FILENAME BUFFER-POINT). | 1447 | It has the form (BUFFER DIRED-FILENAME BUFFER-LINE-NUMBER). |
| 1448 | 1448 | ||
| 1449 | WINDOW-POSITIONS are current positions in all windows displaying | 1449 | WINDOW-POSITIONS are current positions in all windows displaying |
| 1450 | this dired buffer. The window positions have the form (WINDOW | 1450 | this dired buffer. The window positions have the form (WINDOW |
| 1451 | DIRED-FILENAME WINDOW-POINT)." | 1451 | DIRED-FILENAME WINDOW-LINE-NUMBER). |
| 1452 | |||
| 1453 | We store line numbers instead of point positions because the header | ||
| 1454 | lines might change as well: when this happen the line number doesn't | ||
| 1455 | change; 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 |