0

I have some code from "Writing GNU emacs extensions". It is merely a script that allows you to get back to the previous position, kinda like an undo for the buffer position:

(put 'scroll-up 'unscrollable t)
(put 'scroll-down 'unscrollable t)
(put 'scroll-left 'unscrollable t)
(put 'scroll-right 'unscrollable t)


(defvar unscroll-point (make-marker)
  "Text position for next call to 'unscroll'.")

(defvar unscroll-window-start nil
  "Window start for next call to unscroll.")

(defvar unscroll-hscroll nil
  "Hscroll for next call to 'unscroll'.")

(defadvice scroll-up (before remember-for-unscroll
                             activate compile)
  "Remember where we started from, for unscroll."
  (unscroll-maybe-remember))

(defadvice scroll-down (before remember-for-unscroll
                             activate compile)
  "Remember where we started from, for unscroll."
  (unscroll-maybe-remember))

(defun unscroll-maybe-remember ()
  (if (not (get last-command 'unscrollable))
      (progn
        (set-marker unscroll-point (point))
        (setq unscroll-window-start (window-start))
        (setq unscroll-hscroll (window-hscroll)))))

(defun unscroll ()
  (interactive)
  (goto-char unscroll-point)
  (set-window-start nil unscroll-window-start)
  (set-window-hscroll nil unscroll-hscroll))

Problem is, it does not work. When I try to use Ctrl-f and Ctrl-b* I get following error below the mode-line: wrong type argument markerp

If I change the lines using markers to use points it works.

(defvar unscroll-point nil
  "Text position for next call to 'unscroll'.")

and

(defun unscroll-maybe-remember ()
  (if (not (get last-command 'unscrollable))
      (progn
        (setq unscroll-point (point))
        (setq unscroll-window-start (window-start))
        (setq unscroll-hscroll (window-hscroll))))) ;; I know setq can take multiple arguments

I want to use markers since these are robust and are unaffected by buffer edits. How do I fix this code? The book is almost 20 years old, but all the code has worked so far. Dunno if this used to be correct, but isn't anymore.

*are these evil-commands or not? Can't remember...

Here is the debug-info:

Debugger entered--Lisp error: (wrong-type-argument markerp 8245)
  set-marker(8245 176)
  (progn (set-marker unscroll-point (point)) (setq unscroll-window-start (window-start)) (setq unscroll-hscroll (window-hscroll)))
  (if (not (get last-command (quote unscrollable))) (progn (set-marker unscroll-point (point)) (setq unscroll-window-start (window-start)) (setq unscroll-hscroll (window-hscroll))))
  unscroll-maybe-remember()
  ad-Advice-scroll-up(#<subr scroll-up> nil)
  apply(ad-Advice-scroll-up #<subr scroll-up> nil)
  scroll-up(nil)
  evil-scroll-page-down(1)
  funcall-interactively(evil-scroll-page-down 1)
  call-interactively(evil-scroll-page-down nil nil)
  command-execute(evil-scroll-page-down)
  • 1
    Could you please update your post by including a full backtrace? Do M-x toggle-debug-on-error and reproduce the error to obtain it. – wasamasa Jan 8 '15 at 15:43
  • Will do tomorrow; can't access the code from home. – The Unfun Cat Jan 8 '15 at 16:24
  • @wasamasa Added the info. To reproduce the error I just need to press C-f for evil-scroll-page-down. – The Unfun Cat Jan 9 '15 at 12:35
2

What's happening

It looks like your unscroll-point's value is a number. That's why set-marker fails on it.

Since there's nothing in your first code block that could be responsible for that, I'm guessing this is some left over state. This left over state can be caused because defvar does not change the value of a variable that's already set, it only sets the variable's value the first time. See here for why it's like that.

How to avoid it

To prevent this from happening again as you develop packages, whenever you change the value of a defvar (or defcustom), you need to reevaluate it with eval-defun (bound to C-M-x), instead of using C-x C-e, or loading the file, or eval-buffer. eval-defun is designed for developing and forces the value to be reset even on defvars.

  • Wonderful. Thanks! The error must have been that unscroll-point had been a number, but I changed the code to use a marker. For some reason unscroll-point stayed a number even though I reevaled the buffer. – The Unfun Cat Jan 9 '15 at 13:00
  • Probably because defvar does not change non-nil values... – The Unfun Cat Jan 9 '15 at 13:00
  • @TheUnfunCat Yes, that's why. Updated the answer with the explanation. – Malabarba Jan 9 '15 at 13:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.