Mirroring location in file in two opened buffers side by side

末鹿安然 提交于 2020-02-02 11:04:19

问题


I am trying to find a package/function in emacs where it would have both files opened side by side to be at same line location mirroring the movement of whichever buffer is moving. Meaning, for two buffers opened side by side, moving in one of the buffers (page up/down, moving cursor.,..etc) would have the same movements in the other buffer.

More specifically, when opening a buffer (and while activating this mode) the opened buffer should already be at the line position of the one that is already opened in the other buffer window.


回答1:


You could try scroll-all-mode. This switches on parallel scrolling of all windows of one frame.

Scrolling with the mouse and scroll bar do not work for me. But all scrolling with keys (such as Pg-Down, Pg-Down and cursor movements) works fine.

EDIT: You could also try the following code. It works only for a frame with exactly two windows not counting the minibuffer. You have to open the files at first and make sure that they are shown in two windows side-by-side. Then define the master window by activating sync-window-mode for it. Make sure that line-wrapping is off for both windows.

EDIT: Fixed a problem (sometimes one had to press buttons twice to sync). Solution: Also hook to window-scroll-functions. At post-command-hook the right window-start position is not known since redisplay did not run yet. The fist point where the future window-start is known is at 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)

Next, a version that synchronizes lines instead of character positions.

If you select some lines in the master buffer this also marks the corresponding lines in the slave buffer. The highlighting keeps permanent until you select another region in the master buffer. It even survives deactivation of sync-window-mode in the master buffer. You get ride of the highlighting by

M-x sync-window-cleanup

in the slave buffer.

(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)


来源:https://stackoverflow.com/questions/19987071/mirroring-location-in-file-in-two-opened-buffers-side-by-side

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!