如何做到 window 和 buffer 同时固定

Hi,

我自己做了一些尝试,奈何emacs lisp水平有限,请教下如何做到将某一个window和buffer同时固定,像neotree的侧边栏里那样。

要求:

  1. 同一个frame中的其它window里delete-other-windows不会关闭它.各种split不影响它。
  2. 此固定的window里,无法switch-buffer, 无法split-window, 无法delete-other-windows

上述第2个功能无法"split-window", “delete-other-windowss” 我在neotree里源码看到是通过将先关快捷键设为空函数实现的,代码如下:

(defvar neotree-mode-map
  (let ((map (make-sparse-keymap)))
    ...
    (define-key map (kbd "C-x C-f") 'find-file-other-window)
    (define-key map (kbd "C-x 1")   'neotree-empty-fn)
    (define-key map (kbd "C-x 2")   'neotree-empty-fn)
    (define-key map (kbd "C-x 3")   'neotree-empty-fn)
    (define-key map (kbd "C-c C-f") 'find-file-other-window)
    (define-key map (kbd "C-c C-c") 'neotree-change-root)
    (define-key map (kbd "C-c c")   'neotree-dir)
    ...
    map)
  "Keymap for `neotree-mode'.")

但是我代码中没找到他是怎么用这个自定义的keymap的

无法切换buffer应该可以通过dedicated-buffer做到,但第一个不是很清楚如何实现,neotree代码里貌似有detach window(buffer)相关的部分不是很能看懂。

请指教!

谢谢!

xxx-mode-map 是和 xxx-mode 关联的,即进入 xxx-modexxx-mode-map 自动变成当前 keymap,不需要另行声明。

试试看了解下 Side Window:

https://www.gnu.org/software/emacs//draft/manual/html_node/elisp/Side-Windows.html

(display-buffer-in-side-window
 (get-buffer "*Messages*")
 '((side . left)))

我没用过 Neotree,也不太了解 Window,可能只能帮到这了。

原来如此,当初看到的时候我也怀疑是不是有什么约定的模式,感谢!

Hi,

初步看了下 display-buffer-in-side-window 是个很方便的特性,github上搜了下一般用这个通过添加display-buffer-alist将某种类型的buffer固定边栏显示,或许定制下可以实现我想要的特性,等有更多的时间我再折腾折腾。谢谢你啊!

Why set-window-dedicated-p doesn't work with certain buffers? - Emacs Stack Exchange 看到一个方法,能让某个窗口固定显示某个 buffer

(defun toggle-current-window-dedication ()
  (interactive)
  (let* ((window    (selected-window))
         (dedicated (window-dedicated-p window)))
    (set-window-dedicated-p window (not dedicated))
    (message "Window %sdedicated to %s"
             (if dedicated "no longer " "")
             (buffer-name))))

我觉得对于大部分的场景就够了,之前看过的好多专有显示区域,专有窗口的插件都太复杂,不如这个简单实用

以上只能固定住 buffer, 不能避免 window 关闭,改进版

(defun toggle-current-window-dedication-and-fix ()
  (interactive)
  (let* ((window    (selected-window))
         (dedicated-and-fixed-p (window-dedicated-p window)))
    (set-window-dedicated-p window (not dedicated-and-fixed-p))
    (set-window-parameter window 'no-delete-other-windows (not dedicated-and-fixed-p))
    (message "Window fixed and %sdedicated to %s"
             (if dedicated-and-fixed-p "no longer " "")
             (buffer-name))))

可以参考一下这段代码怎么控制 window 的行为。dired-sidebar 的 window 在打开的时候可以做到该 window 锁定该 buffer (对应的是 window 的 property dedicated),同时还能锁定该窗口的宽和高(不能被 resize)。

需要注意的是 tab-bar-mode 与 side-bar window 目前有一个不兼容的现象,当你焦点位于一个 side bar window 的时候你调用命令 ·tab-bar-new-tab· 的时候,会出现无法创建新的 tab,且你当前的 tab 会只剩下这一个 side bar window,且该 side bar window 是无法分裂的。出现这种现象以后,只能使用 tab-bar-history-back 的命令来回退到你上一个版本的窗口历史。

可以参考我这里设置的dedicated side window,应该挺契合你的需求