刚刚写了个一辅助输入 nerd fonts 的扩展 nerd-fonts.el,顺便写了个 ivy-nerd-fonts
函数,提供以下功能:
由于 ivy 默认就有 i: insert
和 w: copy
两个 actio,这样菜单里就出现多余的选项。作为一名 helm 用户,我想当然就用自己的 action 覆盖了默认值。然而等我补完测试之后,发现 ivy action 操作异常:一旦通过 M-x ... M-o w
选择了 copy 操作,之后所有的 M-x ... RET
都变成了 copy。
粗略翻了一下 ivy 源代码和 issues 列表,似乎作者有意不让覆盖/重载默认 action
我现在采用的方案是:
(defun ivy-nerd-fonts ()
...
(ivy-save-action
...override-default-actions...
))
把默认 action 备份起来,函数执行完之后还原。这样所有测试用例通过了,简单试用也未发现异常。
不知有没有其它更好的做法,或者是我调查不周,ivy 其实是支持覆盖默认 action 的?
repo 的描述包含的 md 链接无法渲染,效果为: Emacs [nerd-fonts](https://github.com/ryanoasis/nerd-fonts) utilities.
1 个赞
我觉得从行为统一的角度看,作者的要求合情合理,i
w
是内置键,默认行为应该保持
一致,都是简单地插入或拷贝当前选中的候选项,这样对于 ivy 的用户遇到一个新插件时
用起来才不会 surprise 。
你这个插件实现默认按 RET
插入 nerd font
字符就够了,其它的交给 Emacs 本身就
好了,按 M-o w
并不比剪切刚插入的 nerd font
字符方便多少。
1 个赞
菜单的作用其实并不大,默认的也能用。我只是想把默认的操作在当下做一点微调(只复制/插入 icon 符号,忽略名称),并没有破坏一致性,i
w
的结果依然是可以预期的。
老铁写个 nerd fonts lib 来替换 all-the-icons 吧,最好 terminal 下也能统一使用,哈哈
2 个赞
之前有个用户给我提过issue,希望doom-modeline集成 nerd fonts,无奈工作量太大,确实没时间搞。老兄能做最好了,我有时间也可以帮帮忙。
研究过all-the-icons
和·icons-in-terminal
,都有一点缺陷。all-the-icons
需要安装多个字体文件,在模拟终端下就无法设置,除非把几种 fonts 合并起来。我尝试过,发现有冲突,得手工处理,要集成到不同字体中还不通用。icons-in-terminal
用的方法挺巧妙,把多个字体映射到private 空间。Windows 下好像有些问题,API也不完善,而且作者死活不愿意上 melpa,安装略显麻烦,影响了体验。目前好像也没有更新了。
个人觉得 nerd fonts 可能是目前最好的方案,只需要一种字体,集成了几乎所有 icons 和 symbol,GUI 和 Terminal 通杀,如果能成绝对大赞!到时我会第一时间集成进 Centuar Emacs 和 doom-modeline 中,啊哈哈~~~
Update: 浏览了下 nerd-fonts
的代码,似乎 font data 已经很全了,只需要参考all-the-icons
增加一些接口就可以了。老兄真是前进了一大步!!!只有一个疑问,不知道file type 的 icon 是否齐全。nerd fonts 中没有包含 fileicon 和 alltheicon 两个字体。不过从vim-devicons的效果看应该是有的,但我不确认。
工作量主要在于从这些字体中筛选出一套合适的 icons。我想可以优先处理高频使用的 icon,比如文件、分支等等。
cireu
9
这里的terminal是X下的terminal emulator吧,真正的terminal也能用?
真正的终端支持字体就行,不过我看很难呀。
现在远程终端很普遍。
我照着manual这样设感觉没遇到问题?
(defun ivy-yank-action (x)
(kill-new x))
(defun ivy-copy-to-buffer-action (x)
(with-ivy-window
(insert x)))
(defun myfun (x)
(insert (concat "hello->" x)))
(ivy-set-actions
t
'(
("i" ivy-copy-to-buffer-action "inserts")
("w" ivy-yank-action "yank")
("h" myfun "myfun")
))
(ivy-read "test: " (list 'a 'b))
有两个问题需要考虑:
-
(ivy-set-actions t ...)
是全局有效的,如果想做到单次有效,就要像我前面那样 (save-ivy-action ...)
。
-
ivy 如何组织 action 的,我看了一下 (ivy-read)
的实现:
1839 (let ((extra-actions (cl-delete-duplicates
1840 (append (plist-get ivy--actions-list t)
1841 (plist-get ivy--actions-list this-command)
1842 (plist-get ivy--actions-list caller))
1843 :key #'car :test #'equal)))
1844 (when extra-actions
1845 (setq action
1846 (cond ((functionp action)
1847 `(1
1848 ("o" ,action "default")
1849 ,@extra-actions))
1850 ((null action)
1851 `(1
1852 ("o" identity "default")
1853 ,@extra-actions))
1854 (t
1855 (delete-dups (append action extra-actions)))))))
通过 (ivy-set-actions ...)
添加的 action 都存放在 ivy--actions-list
,最后都汇总到上边代码l里的局部变量 extra-actions,所以它不影响最后展示的 o: default
选项。
通过 (ivy-read ... :action ...)
添加的 action(就是上边代码里的 action 变量)。如果是单个函数,就直接作为 default,如果是空则用 identity
作为 default。
所以,如果 (ivy-read ...)
不设置 action,就会产生一个啥也不干的 o: default
选项(因为是 identity)。
嗯。看起来应该是这样的,有前面的append。总是会去拿 (plist-get ivy--actions-list t)
。所以默认的全局设置还真是对每个生效。
这会看起来的话,如果真是要覆盖的话,你的那种暂存的方法是一种解法
cireu
16
let-boundivy--action-list
, quick and dirty hack
我一开始就是企图用 let
应付的,但是会有问题(具体已经不记得了),所以才专门写一个 save,并且在里边加了一些保护措施,防止 C-g
退出。不过 let 仍然在里边起作用:
先 save 再 let。