目标:使用ivy-posframe,ivy默认使用ivy-posframe-display-at-point
,而swiper
使用ivy-posframe-display-at-window-bottom-left
。问题出在C-M-i
触发completion-at-point
用ivy补全时,非全局设置(github主页称为per-command mode),会失效。
我的配置如下:
(use-package ivy-posframe
:ensure t
:after (ivy)
:config
(setq ivy-fixed-height-minibuffer nil
;; ivy-display-function #'ivy-posframe-display-at-point
ivy-posframe-parameters
`((min-width . 90)
(min-height .,ivy-height)
(internal-border-width . 10)))
(push '(t . ivy-posframe-display-at-point) ivy-display-functions-alist)
(push '(completion-at-point . ivy-posframe-display-at-point)
ivy-display-functions-alist)
(push '(complete-symbol . ivy-posframe-display-at-point) ivy-display-functions-alist)
;; posframe doesn't work well with async sources
(push '(swiper . ivy-posframe-display-at-window-bottom-left)
ivy-display-functions-alist)
(ivy-posframe-enable))
这个设备满足了默认的ivy用...-display-at-point
,swiper用...-display-at-window-bottom-left
,这个非常满意。
如下两图所示:
但是中间的completion-at-point或者complete-symbol并没有起作用(在ivy-posframe的github主页是给了这样的设置的),而且其实是没有调用ivy-posframe的,(注意要复现这个bug,要用 C-M-i
来触发这个补全命令,不能用M-x运行,因为M-x会调用counsel-M-x,它会触发display-at-point
),如下图所示:
如果使用注释掉的那行,即全局设ivy-display-funtion
为ivy-posframe-display-at-point
,则能使得 C-M-i
正确使用ivy-posframe在光标处补全,如下图(当然这种全局设置,就会使swiper也使用…at-point补全了):
然后我试了各种组合以及顺序,都搞不定哪。
求帮助
@tumashu 求助作者,如果看到且有空,请帮忙看看
Temp override ivy-alist-setting, and run your command, you will find the proper function, need to setting
(defun ivy-alist-setting (alist &optional key)
"Return the value associated with KEY in ALIST, using `assq'.
KEY defaults to the last caller of `ivy-read'; if no entry is
found, it falls back to the key t."
(let ((s (cdr (or (let ((caller (or key (ivy-state-caller ivy-last))))
(and caller (assq caller alist)))
(assq t alist)))))
(princ s)
(princ "\n")
s
))
这个法子没法拿到正确的ivy命令那个用于complete-symbol
或者completion-at-point
,输出如下:
ivy-sort-function-buffer
ivy-recompute-index-zero
ivy-display-function-overlay
nil
ivy--regex-plus
nil
ivy-recompute-index-zero
事实上,正确使用ivy-posframe的ivy命令,都是先调用的ivy-posframe-display-at-point,如下运行find-file时:
ivy-posframe-display-at-point
nil
ivy--regex-plus
ivy-sort-function-buffer
ivy-recompute-index-zero
ivy-sort-function-buffer
ivy-recompute-index-zero
估计ivy实现这个complete-symbol用的方式很特别吧
你可以不可以试试你的配置,看你运行C-M-i
(completion-at-point
)时,是不是正确使用-display-at-point (我相信你不会使用全局display-at-point,不然swiper根本没法用,跳到眼睛都花了)?如果没问题,可不可以分享你对ivy-posframe的配置?或者复现一下这个bug?
或者,分享下你使用ivy-posframe的正确姿势?都用一种么?还是不理completion-at-point
这种老古董,反正也不会用到?
我刚才测试了以下,感觉不是补全的问题,而是 swiper 的问题
你的swiper 是绑定到快捷键的么? 还是从 M-x 调用的,如果
从 M-x 调用, 你就需要设置 M-x 的 ivy-posframe 显示方法。
谢谢!
不会啊,按我上面提供的设置,除了completion-at-point
,其他所有的ivy工具都正常,包括swiper应该右下显示(是使用快捷键)。你可以重新看下我一楼的问题描述。而如果想让completion-at-point
也用ivy-posframe,就一定要用全局设置ivy-display-function
了。
算了,估计是ivy实现complete-symbol
(or completion-at-point
),比较特殊,现有的ivy-posframe的per-command mode形式没法影响到它吧,即ivy-display-functions-alist
的设置对它不起作用。
是doom-nord-light,注意是fuxialexander的实现,官方那个也是fuxialexander贡献的,但颜色有点不同,我喜欢fu–的实现,可能是pull request滞后吧。
好吧,可能我的回答掺了别的让你迷惑了。
我刚才测试了以下,感觉不是补全的问题,而是 swiper 的问题
为什么提到swiper?我的swiper没问题,ivy-posframe不正常调用的是completion-at-point
。还是你指的是,completion-at-point中有swiper的事儿?
提到swiper我不懂,所以我上条回复才重申了一下我的问题所在(即ivy-posframe的per-command下,哪里出问题了)
你的swiper 是绑定到快捷键的么? 还是从 M-x 调用的,如果 从 M-x 调用, 你就需要设置 M-x 的 ivy-posframe 显示方法。
我的测试都是它们的快键键触发的,我知道M-x调用时,用的是M-x的ivy-posframe设置。重新说明一下,除了complete-symbol
(即completion-at-point
),其他所有ivy/counsel/swiper (我所用到的)都正确使用ivy-posframe的。
我希望我说清楚了。
@tumashu
好了,解决方案找到了,通过翻找abo-abo很久前新加这个功能时的各种issues回复。
首先一个对一楼的简单回复,目标函数应该是ivy-completion-in-region
。
以下方案任选一:
- 不清空ivy默认设定的
ivy-display-function-alist
时,设置completion-at-point
或complete-symbol
(你在ivy-posframe的readme.md里提供的)是不起作用的(C-M-i
触发ivy补全时并不使用ivy-posframe),
而应该追加对ivy-completion-in-region
进行ivy-posframe设置,如下:
(push '(ivy-completion-in-region . ivy-posframe-display-at-point)
ivy-display-functions-alist)
- 之所以push
complete-symbol
那条或全局的(push '(t . ivy-posframe-display-at-point) ivy-display-functions-alist)
不对 C-M-i
作用,是因为ivy默认在ivy-display-function-alist
中有对ivy-completion-in-region
的设置。所以,简单处理可以清理ivy-display-function-alist
,然后再添加ivy-posframe的per-command mode,这样可以避免被ivy默认设定的display形式覆盖而无法正确使用ivy-posframe:
(setq ivy-display-functions-alist nil)
(push '(t . ivy-posframe-display-at-point) ivy-display-functions-alist)
(push '(swiper . ivy-posframe-display-at-window-bottom-left)
ivy-display-functions-alist)
当然,你如果默认用的不是at-point,即(push (t . ...
用的是别的display形式,但你想C-M-i
用ivy-posframe的at-point,那你单独对ivy-completion-in-region
设置一条at-point就好了。
这里贴出来给同样有疑惑的筒子们作参考吧。
总的来说,交流不是很顺畅,算了,不过问题算是解决啦。看来我有空了还是去了解下Ivy吧,只是抄配置用用,碰到问题就麻瓜了。
2 个赞
这里说的 command, 都是指的是绑定到快捷键的命令, 我这边 C-M-i 绑定到的是 completing-at-point
我在7楼给了theme链接,是doom-nord-light.