关于display-buffer-alist

elisp

#1

有没有关于display-buffer-alist详细的文档。我想自己管理所有的popup。先是看到shackle,然后又看到doom有个popup module,但是这两个东西代码量都有点大,而且Emacs Manual我都不知道从哪开始看,好烦呀。


#2

那为何不用shackle呢


#3

我的印象中 「Buffer 怎么显示」这回事相当复杂,至少我一直就没搞懂过,这件事一直在我的 TODO 列表当中。Emacs 27 中修改了这部分的文档,添加了不少说明,相信会比目前的文档更好懂。

暂时你可以试试找找看 display-buffer-alist 的例子,试试看稍微改下能不能解决手头的需求,先不求完全弄懂怎么一回事。


#4

换了两天时间,总是摸到点头绪了,看了下面的文档,又一步步调试了doom的popup module。

基本上就是就是这种感觉:

(setq
 display-buffer-alist
 '(("^\\*[Hh]elp"                            ;正则匹配buffer name
    (display-buffer-reuse-window             ;入口函数,一个个调用直到有返回值,参数是:1.buffer 2.剩下的这些alist
     display-buffer-in-side-window)
    (side . bottom)                          ;参数alist从这里开始。这个side会被display-buffer-in-side-window使用
    (window-width . 0.5)                     ;emacs会自动把这个设置到window-parameter里
    (window-height . 0.35)                   ;同上
    (slot . 1)                               ;这个会被display-buffer-in-side-window使用,控制window位置
    (reusable-frames . visible)              ;这个参数看第三个链接的display-buffer
    (haha . whatever)                        ;当然随你放什么
    (window-parameters                       ;emacs 26及以上会自动把下面的设置到window-parameter里
     (select . t)                            ;自定义的param
     (quit . t)                              ;同上
     (popup . t)                             ;同上
     (mode-line-format . none)               ;emacs version > 25, none会隐藏mode line,nil会显示...
     (no-other-window . t)                   ;随你设置其他的window-parameter,看文档
     ))))               

doom就是写了个辅助函数,把自定义的plist结合默认参数翻译成上面的东西,比如:

(set-popup-rules!
 '(("^\\*[Hh]elp" :slot 2 :vslot -2 :size 0.35 :select t)))

还有就是doom自己写了个类似display-buffer-in-side-window的函数,多了个支持vslot的功能,看文档是能更好的控制popup的位置。

基本上就这样,我现在是和doom一样自定义入口函数,在入口函数里调用display-buffer-in-side-window啥的,并附带处理所有的自定义参数,就这样了。

白花了这么多时间,希望有帮助 …


#5

之前我shackle试了一下又没用,因为会破坏magit的显示,还提了一个issue,但是看了你的帖子突然想到它的default-rule能不能为空,设为空后果真不影响magit了。相比直接用display-buffer-alist要简单一些,一个缺点(也可能是优点)是shackle用string来match,vanilla用regex。shackle同时支持string和regex

(use-package shackle
  :demand t
  :config
  (setq shackle-default-rule nil
        shackle-rules '(("*Help*" :same t :select t :inhibit-window-quit t)
                        (flycheck-error-list-mode :other t :select t :inhibit-window-quit t)))
  (shackle-mode 1))