emacs - 并排镜像两个打开的缓冲区中文件中的位置

标签 emacs elisp

我试图在 emacs 中找到一个包/函数,它可以并排打开两个文件,使其位于同一行位置,以反射(reflect)正在移动的缓冲区的移动。 这意味着,对于并排打开的两个缓冲区,在其中一个缓冲区中移动(向上/向下翻页、移动光标等)将在另一个缓冲区中进行相同的移动。

更具体地说,当打开一个缓冲区(并激活此模式)时,打开的缓冲区应该已经在另一个缓冲区窗口中已经打开的缓冲区的行位置。

最佳答案

你可以试试scroll-all-mode。这将打开一帧所有窗口的平行滚动。

用鼠标和滚动条滚动对我不起作用。但是所有使用键的滚动(例如 Pg-DownPg-Down 和光标移动)都可以正常工作。

编辑: 您也可以尝试以下代码。它只适用于恰好有两个窗口的帧,不包括迷你缓冲区。您必须首先打开文件并确保它们并排显示在两个窗口中。然后通过激活 sync-window-mode 来定义主窗口。确保两个窗口都关闭换行。

编辑:修复了一个问题(有时必须按两次按钮才能同步)。 解决方案:同时 Hook 到 window-scroll-functions。在 post-command-hook 处,正确的 window-start 位置未知,因为 redisplay 尚未运行。已知 future 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 同步窗口清理

在从缓冲区中。

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

关于emacs - 并排镜像两个打开的缓冲区中文件中的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19987071/

相关文章:

Emacs/ESS - 非常缓慢地通过 iESS 缓冲区

emacs - 使用 Emacs 以组织模式启动

emacs - 保留 Emacs 中的窗口布局

Emacs-lisp : prettify-symbols-mode for LaTeX

emacs - 在 Emacs bibtex-mode 中重新定义段落开头和段落分隔

emacs - 为什么 add-hook 允许 `hook' 无效?

emacs - 在 emacs23 状态栏中显示 CPU 负载

emacs - 如何为不同的主要模式使用相同的文件扩展名

loops - emacs 覆盖在循环中创建时自动合并

email - Gnus for Emacs 中的新邮件通知