10

Q: is there a way to set different scroll margins at the top and bottom of a window?

The variable scroll-margin (defined in the C source code) sets how many lines of text that Emacs displays, at a minimum, at the top and bottom of a window:

Number of lines of margin at the top and bottom of a window. Recenter the window whenever point gets within this many lines of the top or bottom of the window.

I'd like to use scroll-margin for the bottom of the window, but don't want it at the top (e.g., a positive value at the bottom, but 0 at the top). Is there a way to do so?

Dan
  • 32,584
  • 6
  • 98
  • 168
  • I don't know the answer, but in all likelihood `scroll-margin` is not the right tool for the job. You may need some function to put on `post-command-hook` to determine whether to scroll the window. – Harald Hanche-Olsen Jan 19 '15 at 15:29
  • To follow up on my previous comment, finding out how many lines are visible around point seems highly nontrivial, considering wrapped lines, hidden text and the like. I suspect the necessary information is easily available only inside the display code. You could try submitting a feature request to allow (for example) a cons `(top . bottom)` for `scroll-margin`. – Harald Hanche-Olsen Jan 19 '15 at 17:25
  • You might be interested in playing with the `window-scroll-functions` hook (which takes two arguments) and putting a `recenter` command into a function attached to that hook and then use a setting of `(setq scroll-conservatively 101)` -- in essence, you define when recentering occurs and turn off the built-in auto-scroll. Something like `(when (and (>= (point) (window-end nil t)) (not (pos-visible-in-window-p (point) (get-buffer-window (current-buffer) (selected-frame))))) (recenter))` – lawlist Jan 19 '15 at 18:41
  • @lawlist: thanks for the suggestion, but the end of the docstring reads "Warning: Do not use this feature to alter the way the window is scrolled. It is not designed for that, and such use probably won't work." – Dan Jan 19 '15 at 19:17
  • Interesting question, I am wondering why there is no comments/vote on the answer provided by PythonNut. – Name Jul 19 '15 at 07:36

2 Answers2

1

The following works for me:

(defun my-define-scroll-margins (&rest _args)
  (interactive)
  (with-demoted-errors
    (let ((computed-margin
            (if (> (cdr (nth 6 (posn-at-point)))
                  (/ (window-body-height) 2)) 5 0)))
      (setq
        scroll-margin computed-margin
        smooth-scroll-margin computed-margin))))

(add-hook 'post-command-hook #'my-define-scroll-margins)

Note that this is theoretically inefficient, but performance on my lame computer seems unaffected.

PythonNut
  • 10,243
  • 2
  • 29
  • 75
0

Edit: Oh hey heads up. I just realized that this wasn't exactly answer to the original question. I just arrived her via search looking for a way to calculate the scroll-margin based on window height. Hope it's useful to somebody though.

Thanks to @PythonNut, I was able to take their answer to this question and improve it closer to my preferences.

Just change the minimum-window-height and percent-margin variables to your preferences, and stick this in your config.

If you're using Doom Emacs like me, it can go into your config.el file.

(defun my/define-scroll-margins ()
  "Set the scroll margins dynamically based on the current window height."
  (let ((minimum-window-height 14))
    (let ((percent-margin 0.1))
      (setq scroll-margin
            (if (<= (window-body-height) minimum-window-height)
                0
              (floor (* (window-body-height) (* percent-margin 2))))))))
(add-hook 'window-configuration-change-hook #'my/define-scroll-margins)

Ryan Hart
  • 3
  • 2