g reverts the Dired buffer. It invokes function
revert-buffer, which uses the function bound to variable
revert-buffer-function. In a Dired buffer, that function is
dired-revert does (e.g. using
debug-on-entry) you find that it is
dired-goto-file that scrolls the listing, to put the file where the cursor was when you hit
g in the middle of the window vertically. It does this because the last thing it does is call
search-forward, and that function does the recentering.
You can't prevent it from doing that -
search-forward is coded in C, and there's no parameter to modify this part of its behavior (and I don't know of any global variable that will do so).
But you can make the buffer/window scroll, when
dired-revert is done, that is, after
search-forward centers the cursor vertically, to put the cursor's file where you want it in the window. You can do that by advising
dired-revert with an
:after function that scrolls the window the way you want.
The function you want, to scroll the window, is
recenter. Its doc (
C-h f recenter) tells you that you can pass it a numeric arg ARG, to put "putting point on screen line
ARG relative to the selected window." And if
ARG is negative then it does so relative to the bottom of the window. So an
ARG value of
-1 puts the line you want at the bottom of the window - which is where I guess you're asking to put it.
;; Function to use at end of `dired-revert'.
(defun foo (_arg _noconfirm)
"Put cursor line at bottom of window."
;; Do `foo' at the end of `dired-revert'.
(advice-add 'dired-goto-file :after 'foo)
Of course, maybe you don't always want the current line (where the cursor is) to end up at the bottom of the window. In that case, you'll have to do something else.
You can, for example, find out where in the window, vertically, the cursor is before you hit
g, and then have a function such as
foo recenter to that vertical window position, instead of always using
-1 as the arg to
I don't think there's a function that gives you the window line, that is, the current line number relative to the window beginning. You can do that this way:
(defun window-line-at-point ()
(let ((bow (save-excursion (move-to-window-line 0) (point))))
(count-screen-lines bow (point))))
And then you can move to that window line using function
But you need to use
window-line-at-point at the outset, when
dired-revert is called, so you need to advise that function (with
:around) to get the window line, bind it to a variable, and then call
recenter to move to that window line at the end. This does that:
(defun foo (old-fn _a _b)
(let ((curr-line (window-line-at-point)))
(recenter (1- curr-line))))
(advice-add 'dired-revert :around 'foo)
(Alternatively, you could define your own revert function, and bind that to
revert-function in Dired buffers, instead of it being bound to