我正在尝试在 emacs 中找到一个包/函数,它可以将两个文件并排打开以位于同一行位置,以反映正在移动的缓冲区的移动。这意味着,对于并排打开的两个缓冲区,在其中一个缓冲区中移动(向上/向下翻页、移动光标等)将在另一个缓冲区中具有相同的移动。
更具体地说,当打开一个缓冲区时(并且在激活此模式时),打开的缓冲区应该已经位于另一个缓冲区窗口中已经打开的缓冲区的行位置。
你可以试试scroll-all-mode
。这将打开一帧的所有窗口的并行滚动。
用鼠标和滚动条滚动对我不起作用。但是所有使用键滚动(例如Pg-Down,Pg-Down和光标移动)都可以正常工作。
编辑:您也可以尝试以下代码。它仅适用于恰好有两个窗口的帧,不包括迷你缓冲区。您必须首先打开文件并确保它们并排显示在两个窗口中。然后通过激活它来定义主窗口sync-window-mode
。确保两个窗口的换行都关闭。
编辑:修复了一个问题(有时必须按两次按钮才能同步)。解决方案:也挂钩到window-scroll-functions
. 在post-command-hook
正确的window-start
位置是未知的,因为redisplay
还没有运行。知道未来的第一点window-start
是在window-scroll-functions
。
(defun sync-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 (point))
(start (or display-start (window-start)))
(vscroll (window-vscroll)))
(other-window 1)
(goto-char (min (max p (point-min)) (point-max)))
(set-window-start (selected-window) start)
(set-window-vscroll (selected-window) vscroll)
(other-window 1)
)))
(define-minor-mode sync-window-mode
"Synchronized view of two buffers in two side-by-side windows."
:group 'windows
:lighter " ⇕"
(if sync-window-mode
(progn
(add-hook 'post-command-hook 'sync-window-wrapper 'append t)
(add-to-list 'window-scroll-functions 'sync-window-wrapper)
(sync-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'."
(with-selected-window (or window (selected-window))
(when sync-window-mode
(sync-window display-start))))
(provide 'sync-window)
接下来是一个同步行而不是字符位置的版本。
如果您选择主缓冲区中的某些行,这也会标记从缓冲区中的相应行。在您选择主缓冲区中的另一个区域之前,突出显示将保持不变。sync-window-mode
它甚至可以在主缓冲区中的停用中幸存下来。您可以通过以下方式获得突出显示
M-x sync-window-cleanup
在从缓冲区中。
(defface sync-window-face ;; originally copied from font-lock-function-name-face
'((((class color) (min-colors 88) (background light)) (:foreground "Yellow" :background "Blue1"))
(((class color) (min-colors 88) (background dark)) (:foreground "Red" :background "LightSkyBlue"))
(((class color) (min-colors 16) (background light)) (:foreground "Blue" :background "Yellow"))
(((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue" :background "Yellow"))
(((class color) (min-colors 8)) (:foreground "blue" :bold t))
(t (:bold t)))
"Face used to highlight regions in `sync-window-mode' slaves."
:group 'sync-window)
(defvar sync-window-overlay nil
"Overlay for current master region in `sync-window-mode' slaves.")
(make-variable-buffer-local 'sync-window-overlay)
(defun sync-window-cleanup ()
"Clean up after `sync-window-mode'."
(interactive)
(if (overlayp sync-window-overlay)
(progn
(delete-overlay sync-window-overlay)
(setq sync-window-overlay nil))
(remove-overlays (point-min) (point-max) 'sync-window-slave t)))
(defvar sync-window-master-hook nil
"Hooks to be run by `sync-window' in the master window ")
(defun sync-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))
breg ereg)
(when (use-region-p)
(setq breg (line-number-at-pos (region-beginning))
ereg (line-number-at-pos (if (looking-back "\n") (1- (region-end)) (region-end)))))
(run-hooks 'sync-window-master-hook)
(other-window 1)
(goto-char (point-min))
(when breg
(sync-window-cleanup)
(overlay-put (setq sync-window-overlay (make-overlay (line-beginning-position breg) (line-end-position ereg))) 'face 'sync-window-face)
(overlay-put sync-window-overlay 'sync-window-slave t))
(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))
)))
(defvar sync-window-mode-hook nil
"Hooks to be run at start of `sync-window-mode'.")
(define-minor-mode sync-window-mode
"Synchronized view of two buffers in two side-by-side windows."
:group 'windows
:lighter " ⇕"
(if sync-window-mode
(progn
(add-hook 'post-command-hook 'sync-window-wrapper 'append t)
(add-to-list 'window-scroll-functions 'sync-window-wrapper)
(run-hooks 'sync-window-mode-hook)
(sync-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'."
(with-selected-window (or window (selected-window))
(when sync-window-mode
(sync-window display-start))))
(provide 'sync-window)