Reputation: 2027
I have this code that is "partially" working. I am trying to sync two windows, so regardless which window you are in the other will sync and start moving accordingly. The inconsistency I am seeing are around page boundaries; if you move the cursor in one window all the way down till you scroll one more into the next page then directly go up again one line you will notice that both windows will go out of sync. I tried debugging this with no luck. Not sure what is causing this weird behavior.
Here is the code:
(defun Xsync-window (&optional display-start)
"Synchronize point position other window in current frame.
Only works if there are exactly two windows in the active wrame not counting the minibuffer."
(interactive)
(when (= (count-windows 'noMiniBuf) 2)
(let ((p (line-number-at-pos))
(start (line-number-at-pos (or display-start (window-start))))
(vscroll (window-vscroll)))
(other-window 1)
(goto-char (point-min))
(setq start (line-beginning-position start))
(forward-line (1- p))
(set-window-start (selected-window) start)
(set-window-vscroll (selected-window) vscroll)
(other-window 1)
(unless display-start
(redisplay t))
)))
(define-minor-mode sync-window-mode
"Synchronized view of two buffers in two side-by-side windows."
:group 'windows
:lighter " ⇕"
(unless (boundp 'sync-window-mode-active)
(setq sync-window-mode-active nil))
(if sync-window-mode
(progn
(add-hook 'post-command-hook 'sync-window-wrapper 'append t)
(add-to-list 'window-scroll-functions 'sync-window-wrapper)
(Xsync-window)
)
(remove-hook 'post-command-hook 'sync-window-wrapper t)
(setq window-scroll-functions (remove 'sync-window-wrapper window-scroll-functions))
))
(defun sync-window-wrapper (&optional window display-start)
"This wrapper makes sure that `sync-window' is fired from `post-command-hook'
only when the buffer of the active window is in `sync-window-mode'."
(unless sync-window-mode-active
(setq sync-window-mode-active t)
(with-selected-window (or window (selected-window))
(when sync-window-mode
(Xsync-window display-start)))
(setq sync-window-mode-active nil))
)
(defun sync-window-dual ()
"Toggle synchronized view of two buffers in two side-by-side windows simultaneously."
(interactive)
(if (not (= (count-windows 'noMiniBuf) 2))
(error "restricted to two windows")
(let ((mode (if sync-window-mode 0 1)))
(sync-window-mode mode)
(with-selected-window (selected-window)
(other-window 1)
(sync-window-mode mode)))))
Upvotes: 1
Views: 336
Reputation: 26134
When the cursor ends up outside a window, Emacs will reposition the window. However, this occurs after the post-command-hook
is called.
If you call (sit-for 0)
in your post-command-hook
, the window will be redisplayed, and you get the new value for window-start
etc.
Upvotes: 1