【问题标题】:Sync two windows of emacs together同步两个emacs窗口
【发布时间】:2014-02-27 22:15:29
【问题描述】:

我的 dotmacs 文件中有一个 sn-p 代码,它可以并排同步两个打开的缓冲区(感谢 Tobias),在主缓冲区中滚动将导致从属缓冲区相应地移动匹配相同的“行”光标在。

我一直在尝试修改代码,让一个缓冲区在获得焦点时充当主缓冲区,而另一个缓冲区则充当跟随者。基本上,无论滚动哪个缓冲区,我都希望两者同步。

不幸的是,由于主从同步的紧密程度,在两个缓冲区上应用 (Xsync-window) 失败。

代码如下:

(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 " ⇕"
  (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'."
  (with-selected-window (or window (selected-window))
    (when sync-window-mode
      (Xsync-window display-start)
      )))

【问题讨论】:

    标签: emacs elisp


    【解决方案1】:

    这应该可以解决问题:

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

    这基本上通过sync-window-mode-active来保护Xsync-windows是否已经在工作。

    您还可以同时在两个窗口中切换模式:

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

    【讨论】:

    • 优秀。工作得很好。关于第二个功能“sync-window-dual”,我认为让文件在执行命令时的任何位置同步而不是从两个文件的顶部开始会更有利。有时您想比较两个文件中两个不同部分“行号”的代码。因此,无论行号如何,都让它们同步会很棒。这会是一个可能的变化吗?
    • 您是否已经考虑过使用ediff,可能与narrow-to-region一起使用?
    • 我现在正在研究 ediff。感谢您的建议。
    • 对于临时比较,compare-windows 非常方便。您绝对应该将其绑定到一个键(我使用C-M-=);然后只需移动到每个窗口中的相关起点,并根据需要重复compare-windows 多次以消除差异。
    • theldoria,您的解决方案一直运行良好,但我开始注意到一些奇怪之处。如果您使用 sync-window-dual 同步两个缓冲区并将光标移动到一个缓冲区中“页面”的最末端,再向下移动一行将导致缓冲区不同步,另一行向下移动将导致它们重新同步。在处理 Blame 时,两个窗口之间的任何不同步都会导致有关谁更改了源代码的错误信息。你愿意研究一下这个问题吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多