![有没有办法控制 Emacs 在哪个窗口中打开新缓冲区?](https://linux22.com/image/1359636/%E6%9C%89%E6%B2%A1%E6%9C%89%E5%8A%9E%E6%B3%95%E6%8E%A7%E5%88%B6%20Emacs%20%E5%9C%A8%E5%93%AA%E4%B8%AA%E7%AA%97%E5%8F%A3%E4%B8%AD%E6%89%93%E5%BC%80%E6%96%B0%E7%BC%93%E5%86%B2%E5%8C%BA%EF%BC%9F.png)
我将 sr-speedbar 与 emacs 结合使用,并且我经常将框架拆分为 2-3 个不同的窗口,每当我在 sr-speedbar 中单击文件时,它总是在最下方的窗口中打开新缓冲区。我试图将最右下角的窗口保持为相对较小的 ansi-term,而 emacs 一直坚持在较小的 term 窗口中打开新缓冲区,而不是在我想用于编辑缓冲区的更大的区域中打开新缓冲区。
有没有什么方法可以配置缓冲区创建逻辑,使其优先选择较高的窗口而不是较低的窗口?
我已经尝试过将我最低的窗口标记为受保护,但这只会让 emacs 将其分成两个不合理的小部分。然后我尝试启用 window-size-fixed,它并没有让 emacs 打开该窗口上方的缓冲区,而是给了我一个错误,提示窗口太小而无法拆分。我想这很好,它停止破坏我最低的窗口,但它却阻止我打开新的缓冲区,这很愚蠢。
理想情况下,我希望能够强制 emacs 选择最右上角的窗口来显示新创建的缓冲区,而不是尝试分割最右下角的窗口。
答案1
我假设您使用的是 Emacs 24;我没有在任何早期版本中测试过这个答案,也不知道专用窗口的概念是什么时候添加到 Emacs 中的。我看到过关于其使用的提及,日期是 2011 年,所以我假设 Emacs 23(至少)也具有此功能。
您可以通过以下方式阻止 Emacs 在给定窗口中打开新缓冲区将窗口专用于其缓冲区。
在最简单的情况下,您可以通过选择要专用的窗口,确保它当前显示要专用的缓冲区,然后执行 来执行此操作M-: (set-window-dedicated-p (selected-window) t)
。这将防止 Emacs 在决定在哪个窗口中显示缓冲区时考虑经过修改的窗口。要删除专用,请评估相同的表达式,将第二个参数替换为nil
。
您可以通过将缓冲区局部变量 window-size-fixed 设置为非零值来阻止 Emacs 尝试拆分显示给定缓冲区的窗口。
在最简单的情况下,您可以通过选择窗口并执行 来做到这一点M-: (setq window-size-fixed t)
。要仅修复显示缓冲区的窗口的高度或宽度,请计算相同的表达式,传递'height
或'width
作为第二个参数;要删除限制,请用 替换第二个参数nil
。
一般情况下,我发现你的问题很有趣,想出解决办法,您可以将其放入加载路径,(require)
并使用:
;;; dedicate-windows-manually.el --- Manually (un)dedicate windows
;; Copyright (C) 2013 Aaron Miller
;; <[email protected]>
;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 2 of
;; the License, or (at your option) any later version.
;; This program is distributed in the hope that it will be
;; useful, but WITHOUT ANY WARRANTY; without even the implied
;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
;; PURPOSE. See the GNU General Public License for more details.
;; You should have received a copy of the GNU General Public
;; License along with this program; if not, write to the Free
;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
;; MA 02111-1307 USA
;;; Commentary:
;; Introduction
;; ============
;; The functions here defined allow you to manually dedicate and
;; undedicate windows, that is, prevent `set-window-buffer' from
;; considering them when selecting a window in which to display a
;; given buffer.
;; Windows dedicated in this fashion will also be protected from
;; splitting by setting `window-size-fixed'.
;; Installation
;; ============
;; Place this file in your load path; then, place the following
;; command somewhere in your initialization file:
;; (require 'dedicate-windows-manually)
;; Now you can use M-x dedicate-window to dedicate the selected window
;; to its currently displayed buffer, M-x undedicate-window to release
;; a dedication so applied, and M-x dedicate-window-toggle to switch
;; between the states.
;; These functions will operate only on manually dedicated or
;; undedicated windows; that is, M-x dedicate-window will not dedicate
;; a window which is already dedicated (i.e. "(window-dedicated-p
;; window) -> t", and M-x undedicate-window will not undedicate a
;; window which was not dedicated by way of M-x dedicate-window.
;; If you find yourself frequently doing M-x dedicate-window-toggle,
;; you might wish to place something like this in your init file:
;; (global-set-key (kbd "C-x 4 C-d") 'dedicate-window-toggle)
;; Bugs:
;; * Changing the lighter string while you have windows dedicated is
;; probably not a good idea.
;; * I should certainly find a better way to change the mode line.
;;; Code:
(defcustom dedicated-window-lighter-string " [D]"
"A string, propertized with `dedicated-window-lighter-face', prepended
to the mode line of manually dedicated windows.")
(defvar dedicated-windows-by-hand nil
"A list of windows known to have been manually dedicated. Windows not
in this list will not be undedicated by `undedicate-window'.")
(defun dedicate-window-was-by-hand-p (window)
(let ((result nil))
(loop for w in dedicated-windows-by-hand
collect (if (eq w window) (setq result t)))
result))
(defun dedicate-window (&optional window flag)
"Dedicate a window to its buffer, and prevent it from being split.
Optional argument WINDOW, if non-nil, should specify a window. Otherwise,
or when called interactively, the currently selected window is used.
Optional argument FLAG, if non-nil, will be passed verbatim to
`set-window-dedicated-p'."
(interactive nil)
(if (eq nil window) (setq window (selected-window)))
(if (eq nil flag) (setq flag t))
(if (window-dedicated-p window)
(message "Window is already dedicated.")
(progn
(add-to-list 'dedicated-windows-by-hand window)
(setq mode-line-format
(append `(,dedicated-window-lighter-string) mode-line-format))
(setq window-size-fixed t)
(set-window-dedicated-p window flag))))
(defun undedicate-window (&optional window)
"Un-dedicate a window from its buffer.
Optional argument WINDOW, if non-nil, should specify a window listed in
`dedicated-windows-by-hand'. Otherwise, or when called interactively,
the currently selected window is used.
If WINDOW is not in `dedicated-windows-by-hand', a complaint will be
issued and nothing will be done."
(interactive nil)
(if (eq nil window) (setq window (selected-window)))
(if (not (window-dedicated-p window))
(message "Window is not dedicated.")
(if (not (dedicate-window-was-by-hand-p window))
(message "Window is not dedicated by hand.")
(progn
(setq dedicated-windows-by-hand
(remove window dedicated-windows-by-hand))
(setq mode-line-format
(remove dedicated-window-lighter-string mode-line-format))
(setq window-size-fixed nil)
(set-window-dedicated-p window nil)))))
(defun dedicate-window-toggle (&optional window)
"Toggle a window's manual buffer dedication state.
Optional argument WINDOW, if non-nil, should specify a window. Otherwise,
or when called interactively, the value of `selected-window' is used."
(interactive nil)
(if (eq nil window) (setq window (selected-window)))
(if (window-dedicated-p window)
(undedicate-window window)
(dedicate-window window)))
(provide 'dedicate-windows-manually)
;;; dedicate-windows-manually.el ends here
答案2
在最近的 Emacs 版本中,display-buffer-alist
添加了选项。它提供了对缓冲区显示、使用的窗口等的细粒度控制。但是,由于它允许您执行如此多的操作,因此它也相当复杂且难以描述。请参阅文档:C-h v display-buffer-alist
。
答案3
我还可以推荐投入的模式。