0

When running scroll-up or scroll-down, it's possible emacs isn't scrolling the number of lines requested (if you hit the start/end of the buffer for eg).

Is there a convenient way to know how many lines were actually scrolled?

ideasman42
  • 8,375
  • 1
  • 28
  • 105
  • I am unaware of anything available to the user via Lisp. In case you do not find anything on point to suit your needs, you may wish to consider programmatically calculating the values. If so, then it may be helpful to quickly find the line number at position: https://emacs.stackexchange.com/questions/3821/a-faster-method-to-obtain-line-number-at-pos-in-large-buffers -- keeping in mind that it has limitations as described in comments. – lawlist Jul 16 '19 at 17:25

3 Answers3

0

Here's an attempt:

(defvar jpk/scroll-count 0
  "Signed number of lines scrolled in the last scroll-up or scroll-down.")
(make-variable-buffer-local 'jpk/scroll-count)

(defun jpk/scroll-tracking (orig &rest args)
  (let ((start (window-start))
        (error t))
    (unwind-protect
        (prog1
            (apply orig args)
          (setq error nil))
      (when error
        (setq jpk/scroll-count 0)))
    (setq jpk/scroll-count (* (signum (- (window-start) start))
                              (count-lines (window-start) start)))))

(advice-add 'scroll-up :around #'jpk/scroll-tracking)
(advice-add 'scroll-down :around #'jpk/scroll-tracking)

I used count-lines because line-number-at-pos can be slow. But count-lines implicitly takes the absolute value, hence the signum. Also I'm not sure I got the error handling exactly right.

jpkotta
  • 498
  • 2
  • 11
  • `count-lines` suffers the same problem as `line-number-at-pos`, which also uses `count-lines`. See the link in my comment underneath the original question. – lawlist Jul 16 '19 at 22:34
0
(setq max-lines (- (window-height) next-screen-context-lines))
(if (< (lines-before) max-lines) 0 max-lines)
(if (< (lines-after) max-lines) 0 max-lines)

(defun lines-before ()
  "Report number of lines on current page, and how many are before or after point."
  (interactive)
  (save-excursion
    (let
      (
        (opoint (point))
        beg
        end
        total
        before
        after)
      (forward-page)
      (beginning-of-line)
      (or (looking-at page-delimiter) (end-of-line))
      (setq end (point))
      (backward-page)
      (setq beg (point))
      (count-lines beg opoint))))

(defun lines-after ()
  "Report number of lines on current page, and how many are before or after point."
  (interactive)
  (save-excursion
    (let
      (
        (opoint (point))
        beg
        end
        total
        before
        after)
      (forward-page)
      (beginning-of-line)
      (or (looking-at page-delimiter) (end-of-line))
      (setq end (point))
      (backward-page)
      (setq beg (point))
      (count-lines opoint end))))

I took the code from count-lines-page and turned it into two functions that outputs how many lines exist above and below the position at point.

Then, it's just a matter of finding out if the scroll will take place. In the above case, I'm finding out how many lines will be scrolled if I hit scroll-down-command or scroll-up-command.

Not sure if this helps. I'm a newbie in Elisp.

ideasman42
  • 8,375
  • 1
  • 28
  • 105
aadcg
  • 1,203
  • 6
  • 13
0

I use a thing like this

(defun jump-length-test (window _window-start-after)
  (with-selected-window window
    (unless (> 0.001 (float-time (time-subtract (current-time) buffer-display-time))) ; Don't run this function after a change of buffer.
      (let* ((bottom-line-before (line-number-at-pos (window-end)))
             (bottom-line-after (line-number-at-pos (window-end nil 'update))) ; NB: ‘window-start’ doesn't take the ‘update’ argument.
             (vertical-displacement (- bottom-line-after bottom-line-before)))
        (message "Lines scrolled: %s" (abs vertical-displacement))))))

(add-hook 'window-scroll-functions #'jump-length-test)

It checks if the difference between the current-time and the buffer-display-time is under 0.001 s to avoid running when you change the buffer displayed by the window (which also triggers window-scroll-functions), and then it compares the line number of the bottom lines before and after the jump to get its length.

Arch Stanton
  • 1,525
  • 9
  • 22