首页
归档
友情链接
关于
Search
1
在wsl2中安装archlinux
295 阅读
2
从零开始配置 vim(15)——状态栏配置
173 阅读
3
nvim番外之将配置的插件管理器更新为lazy
162 阅读
4
2018总结与2019规划
150 阅读
5
PDF标准详解(五)——图形状态
126 阅读
软件与环境配置
读书笔记
编程
Thinking
FIRE
菜谱
翻译
登录
Search
标签搜索
c++
c
emacs
学习笔记
elisp
windows
文本操作术
编辑器
NeoVim
Vim
win32
读书笔记
VimScript
linux
文本编辑器
投资理财
Java
反汇编
OLEDB
数据库编程
Masimaro
累计撰写
452
篇文章
累计收到
33
条评论
首页
栏目
软件与环境配置
读书笔记
编程
Thinking
FIRE
菜谱
翻译
页面
归档
友情链接
关于
搜索到
2
篇与
的结果
2026-08-31
《elisp 每日一练》——Window 锁定与专属窗口
我们想象这样一个场景,假设你精心布局了当前的编程窗口,左边是文件树、右边一个大窗口区域是代码编辑区域,右侧有一个小的显示当前类和函数定义的缩率图,下面有输出的日志。但是你运行某个命令弹出了 *Help* 或者 *Compile* 占用了你的某个窗口,本来对整个项目可以一览无余的,现在不得不重新关掉这个新显示的窗口。整个场景想想就糟心。我们有没有办法固定这些布局,新弹出的窗口不要破话它。Emacs一般是只有你想不到,没有它办不到的。背景知识上述场景的解决办法是通过 专属窗口(Dedicated Window) 与 窗口参数(Window Parameters),我们可以给特定 Window 加上“锁”,强制 Emacs 将新 Buffer 弹出到指定位置,保护主窗口不被侵占。各位读者可能有这样的疑问,我们前面介绍了 display-buffer 和 pop-to-buffer 已经解决了新显示的buffer乱弹窗导致布局混乱的问题,为什么又有一个 deddicated window 和 window parameters 这类解决方案呢?其实它们是不同的机制,侧重于从不同方面解决。display-buffer 和 pop-to-buffer 讲究的是这次应该将buffer放在哪。它侧重于将一个内容显示在窗口的某个位置,如果这个位置有了窗口,则重用这个窗口。Dedicated Window 和 Window Parameters 解决的是“这个窗口本身有什么规则”例如我们上面那个布局,display-buffer 和 pop-to-buffer 虽然可以靠算法精确的控制它显示的区域,但是无法保证我们主要的代码区域永远属于显示代码的buffer,设置专有窗口之后,这个窗口就专门用来显示这个buffer的内容。每个窗口都有一个 dedicated 的标志位,当设置这个标志之后,Emacs会尽量避免在本窗口中显示其他内容,例如 switch-buffer、pop-to-buffer、display-buffer 会尽量避免在对应窗口中显示新内容。我们可以通过 set-window-dedicated-p 将一个窗口设置为专属窗口,它接受两个参数:WINDOW 表示设置哪个窗口flag 为 t 时设置专属窗口,为 nil 解除该设置通过 window-dedicated-p 函数可以查看窗口的专属状态。但是仅仅设置 dedicated 标签并不意味着可以精细的管理窗口。我们可以通过设置窗口参数来更细致的控制窗口。Emacs对每个窗口都维护着一个参数的 alist 列表,可以控制窗口的一些行为。窗口参数实际是一推窗口的标签,有些标签Emacs自己就可以利用来改变窗口行为,我们也可以自定这些标签,然后在我们的程序中通过这些标签控制窗口行为和显示。也就是说窗口参数给我们扩展窗口带来了极大的便利设置窗口属性可以使用 set-window-parameter 设置属性,通过 window-parameters 获取对应的属性练习我们来实现一个小例子,来体会一下该如何使用窗口自定义参数改变窗口行为。我们实现一个通过自定义参数 this-window-height 和 this-window-width 参数来修改光标所在窗口大小的函数我们先封装一些获取和设置窗口大小的基本函数(defun my/set-window-height(height) (let ((window (selected-window))) (set-window-parameter window 'this-window-height height) (window-resize window (- height (window-total-height window))))) (defun my/set-window-width(width) (let ((window (selected-window))) (set-window-parameter window 'this-window-width width) (window-resize window (- width (window-total-width window)) t))) (defun my/get-window-height() (window-height (selected-window))) (defun my/get-window-width() (window-width (selected-window)))然后提供一个根据当前参数中存储的大小数据来更新窗口实际大小的函数(defun my/update-window-size() (let* ((params (window-parameters (selected-window))) (height (cdr (assq 'this-window-height params))) (width (cdr (assq 'this-window-width params)))) (if (not) (setq height (my/get-window-height))) (if (not width) (setq width (my/get-window-width))) (my/set-window-height height) (my/set-window-width width)))最终我们在此基础上封装一套修改大小的函数:(defun my/width_zoomin() (interactive) (let* ((params (window-parameters (selected-window))) (width (cdr (assq 'this-window-width params)))) (if (not width) (setq width (my/get-window-width))) (setq width (- 10 width)) (my/set-window-width width))) (defun my/width_zoomout() (interactive) (let* ((params (window-parameters (selected-window))) (width (cdr (assq 'this-window-width params)))) (if (not width) (setq width (my/get-window-width))) (setq width (+ 10 width)) (my/set-window-width width))) (defun my/height_zoomin() (interactive) (let* ((params (window-parameters (selected-window))) (height (cdr (assq 'this-window-height params)))) (if (not height) (setq height (my/get-window-height))) (setq height (- 5 height)) (my/set-window-height height))) (defun my/height_zoomout() (interactive) (let* ((params (window-parameters (selected-window))) (height (cdr (assq 'this-window-height params)))) (if (not height) (setq height (my/get-window-height))) (setq height (+ 5 height)) (my/set-window-height height)))小结本节我们介绍了专属窗口和窗口属性。本节有关的函数有:set-window-dedicated-pwindow-dedicated-pset-window-parameterwindow-parameter
2026年08月31日
7 阅读
0 评论
0 点赞
2026-08-30
《elisp 每日一练》——Window 树与布局状态恢复
前面的文章中,我们介绍了可以通过 split-window 来创建窗口,也介绍了通过 walk-windows 遍历窗口并且通过 overlay 机制实现了一个简单、直观的快速跳转窗口的功能。今天我们来深入了解背后的原理背景知识各位读者如果观察过Emacs执行 split-window 的效果,应该会发现它只会将当前窗口的区域进行划分,将当前窗口区域分为两个部分。这样我们很容易想到一个树的结构,光标所在的位置是树的一个叶子节点,在新建窗口时将该叶子节点作为新的根节点,在下方创建两个新的叶子节点。其实Emacs底层正是这样做的。我们可以通过 window-tree 来获取当前frame下窗口布局的树结构。我们用一个简单的例子来描述一下返回的具体结构, 假设我们有如下一个窗口布局+------------+-------------+ | | Window | | Window | B | | A +-------------+ | | Window | | | C | +------------+-------------+我们调用 window-tree 得到的结果可能是这样的( (nil (0 3 84 38) #<window 3 on *scratch*> (t (42 3 84 38) #<window 8 on *scratch*> #<window 10 on *scratch*>)) #<window 4 on *Minibuf-0*>)从整体上看它分为两个大的部分,第一个部分是一个复杂的结构,而第二个部分是一个window对象,它实际上是 mini-buffer 的窗口。我们再来看看前面一个大的结构。我们将它转换成一个树状结构├── (nil (0 3 84 38) │ ├── #<window 3 on *scratch*> │ └── (t (42 3 84 38) │ ├── #<window 8 on *scratch*> │ ├── #<window 10 on *scratch*> └── #<window 4 on *Minibuf-0*>通过这个我们发现,一个根节点实际是当前区域的分割方式和区域的大小,第一个参数为 nil 表示它是水平分割,而 t 表示垂直分割。各位读者请注意,这里的水平和数值的理解,这里并不是在窗口上按水平或者竖直方向画一条线将窗口进行划分,而是表示将新窗口按照水平或者竖直方向进行排列。所以上述结构真正含义其实是:先通过 nil 将窗口区域划分为水平方向的两个窗口,也就是左右两个其中一个为window3将右边区域一分为二,通过 t 表明它应该是竖直方向的两个窗口,也就是在中间水平位置画一条线进行区分在过去如果想要保存和恢复这个窗口布局,我们需要通过 window-tree 函数保存当前的树结构,恢复时解析每个节点并且调用 split-window 重新根据节点进行。但是从Emacs 24.1 之后提供了两个函数,可以方便的进行保存和后续的恢复: window-state-get 和 window-state-put(window-state-get &optional WINDOW WRITABLE)它可以返回指定窗口的布局状态,默认就是root 窗口,也就是当前frame 的主视图区域。我们可以在关闭时通过 window-state-get 获取root 的布局信息,保存到一个文件中,再下一次启动Emacs 时通过window-state-put 进行恢复窗口。如果我们只是临时性的保存和恢复当前窗口布局,可以使用 current-window-configuration 和 set-window-configuration 。它们的作用与前面介绍的 save-excursion、save-restriction 和 with-current-buffer 类似,如果包含临时性的窗口操作,为了让用户没有察觉或者不改变当前窗口布局,可以使用练习好了,我们来实现一个保存和恢复窗口布局的例子,因为我们还没有接触过Emacs文件的操作,所以这里简单的实现一个在Emacs启动期间执行保存和恢复的功能,后续学习了如何读取和保存文件之后我们可以继续完善因为不涉及到持久化的保存,所以我们可以简单的使用 current-window-configuration 和 set-window-configuration 函数。(defvar current-window-state nil) (defun my/save-current-window-state() (interactive) (setq current-window-state (current-window-configuration))) (defun my/restore-current-window-state() (interactive) (set-window-configuration current-window-state))我们的练习比较简单,如果读者觉得难度不过瘾,可以考虑通过保存和遍历 window-tree 的方式实现这个功能小结本篇我们介绍的函数有:window-treecurrent-window-configuration 和 set-window-configurationget-window-state 和 put-window-state
2026年08月30日
7 阅读
0 评论
0 点赞