内容提要
作者使用 rg.el 时希望搜索结果不仅显示匹配行,还能显示该行所属的函数。为此他修改 which-function 并 hack rg.el:通过 compilation-message 获取文件、行、列,调用 exec/lsp-which-function 打开对应文件并定位取得函数名,再用 overlay 在匹配行前显示缩短的函数名;exec/rg-hint-all 遍历结果行批量添加提示,并在 rg-mode-hook 中注册。
延伸解读
实现思路:从编译消息提取位置信息
作者利用 rg.el 搜索结果行携带的 compilation-message 属性,从中解析出文件、行号和列号,再调用自定义函数 exec/lsp-which-function 打开对应文件并定位,通过 which-function 获取函数名。这避免了手动跳转,但依赖 rg.el 内部使用的编译消息结构,若 rg.el 更新可能失效。
显示方式:overlay 前置缩短函数名
获取函数名后,作者用 shorten-string 将超过30字符的名称截断为前15和后14字符加省略号,再通过 overlay 的 before-string 在匹配行行首显示,并设置 evaporate 属性使其在编辑时自动消失。这样既保持界面整洁,又避免干扰原有文本。
批量处理与性能权衡
exec/rg-hint-all 遍历结果缓冲区,逐行添加提示,但限制最多处理300行,且每10行调用 sit-for 短暂停顿,防止界面卡顿。该函数注册在 compilation-finish-functions 上,搜索完成后自动执行。这种设计在结果较多时会牺牲部分提示完整性来换取响应速度。
缓冲区管理:复用与清理
exec/lsp-which-function 会记录上次打开的文件缓冲区,若文件切换则关闭旧缓冲区(除非它原本已存在),避免频繁打开文件导致缓冲区堆积。但该逻辑使用全局变量,在多项目或并发搜索时可能产生干扰,需留意缓冲区状态。
Q&A
如何在 Emacs 的 rg.el 搜索结果中显示每个匹配行所属的函数名?
通过修改 which-function 并 hack rg.el 实现:利用 compilation-message 获取文件、行、列,调用 exec/lsp-which-function 打开对应文件并定位取得函数名,然后用 overlay 在匹配行前显示缩短的函数名。
exec/lsp-which-function 函数的作用是什么?
它根据给定的文件、行、列打开对应文件并定位,然后调用 which-function 获取该位置的函数名。
如何批量给 rg 搜索结果的所有行添加函数名提示?
使用 exec/rg-hint-all 函数,它遍历结果行(最多300行),对每一行调用 exec/rg-hack 添加提示,并每处理10行暂停0.01秒以保持响应。
怎样让 rg.el 在搜索完成后自动添加函数名提示?
将 exec/setup-rg-hint 添加到 rg-mode-hook 中,该函数会把 exec/rg-hint-all 加入 compilation-finish-functions,从而在编译(搜索)完成时自动执行。
shorten-string 函数是如何缩短过长的函数名的?
如果字符串长度超过30,则截取前15个字符和后14个字符,中间用省略号连接;否则原样返回。
在 rg 结果中显示函数名时,如何避免频繁打开文件导致性能问题?
通过变量 exec/which-function-last-buffer-name 和 exec/which-function-current-buffer-already-exist 跟踪上次打开的文件,避免重复打开同一文件,并在切换文件时关闭之前打开的文件缓冲区。