写 helm/ivy 函数有没有什么捷径?

想写一个 helm 或者 ivy 命令,就是用 helm 生成文件列表,就像 helm-find-file 那样的,找到文件后回车就执行 my-function。以前没有写过 helm/ivy 的函数,看了一下 wiki,但是上面的例子都不太实用。

只用过 Helm,文档 :point_right: Developing · emacs-helm/helm Wiki · GitHub

(helm :sources
      (helm-build-sync-source "helm test"
        :candidates '("foo" "bar" "baz" "aux")
        :action '(("Echo" . (lambda (candidate)
                              (message "You have picked %s" candidate))))))

:candidates 是候选项,是元素为 String 的 List,上面可以直接写出来;也可以是变量名,保存这样类型的值;也可以是函数返回这样值;

(setq some-random-words '("foo" "bar" "baz" "aux"))

:candidates '("foo" "bar" "baz" "aux")
:candidates 'some-random-words
:candidates (lambda () '("foo" "bar" "baz" "aux"))

:action 指定操作,是 Key 为函数描述和 Value 为函数的 Alist,函数的参数是你所选择的选项,也就是 :candidates 中的之一。


附上两个简单的例子,第一个是我为了举例子写的,第二个是我配置里的,偶而有用到。

(defun chunyang-find-emacs-config-files ()
  (interactive)
  (let ((default-directory "~/.emacs.d/"))
    (helm :sources
          (helm-build-sync-source "Emacs Config Files"
            :candidates
            (lambda ()
              (split-string
               (shell-command-to-string "git ls-files --full-name")
               "\n" t))
            :action (helm-make-actions
                     "Open" 'find-file
                     "View" 'view-file))
          :buffer "*helm emacs config file*")))

(defun helm-eww-bookmarks ()
  "Alternative to `eww-list-bookmarks'."
  (interactive)
  (require 'eww)
  (helm :sources
        (helm-build-sync-source "EWW Bookmarks"
          :candidates
          (lambda ()
            (cl-loop for elt in (eww-read-bookmarks)
                     collect (cons (plist-get elt :title)
                                   (plist-get elt :url))))
          :action #'eww)
        :buffer "*Helm EWW Bookmarks*"))
1 个赞

ls file这部分可以不用外部命令吗?有没有更 canonical 的方式?

上面是 git ls-files,你可以用现成的(VC,Magit,Projectile,project.el 等可能都有这样的函数),只是它们很可能用的是同样的方法(即调用一个 Git 命令)。

比如 Projectile 里面有一个

这个可以像 find-file 那样导航到任意文件夹吗?

好的,我试试

上面那个貌似只能生成静态列表,不能导航到其它文件夹?

我好像知道怎么做了: How to write helm extensions - WikEmacs

谢谢 @xuchunyang 的指点,我之前没有想过用外部命令来获得 candidate list

我又读了一下 helm-find-files 的源码,觉得我可能需要的不是写一个extension,而是 override helm-find-files 的default action,因为 helm-find-files 的实现太复杂了。

最新进展,我已经放弃 helm 转投 ivy 了,代码简单得多:slight_smile:

简直太handy了,随便把内置函数一改就得到我需要的效果,大赞 ivy!

我觉得我可能要重新考虑一下,要不要永久迁移到 ivy 了

1 个赞

我曾经尝试过一次改用ivy,但是忘记为什么没有最终转过去

同从helm转到了ivy。我觉得helm虽然界面漂亮,刚刚用的时候觉得漂亮,可用久了会发现还是ivy朴素简单好用。而且我这里用helm会卡。。。ivy就很流畅

你用的也是 spacemacs 吗?

那当然啦!我以前是vim党,不用spacemacs没其它选择

同是前vim党。 其实vim就用了两个月。然后被安利了Emacs。

用的helm,觉得ivy不够直观。虽然也觉得helm糟糟的。

虽然我也觉得 Ivy 挺好的,但是我用的时候有一些问题困扰着我。

我快速按 SPC SPC 的时候,选单会等一会才显示。但是 M-x 的时候就没有这问题。这个让强迫症情何以堪啊。如果我 SPC 和 SPC 中间顿一下,哪怕零点几秒,都会立即显示选单,但我都是 SPC SPC快速连按。因为这个原因有一段我放弃 Ivy 了。不知道有没有和我一样问题的。

BTW,我是在虚拟机上使用 GUI spacemacs 的。

你说SPC和SPC中间停顿时打开的?那个不应该是which-key吗?:joy:

已经开新主题了

写了一篇写 Helm 函数的博客,或许会帮助:

主要就是几个例子。因为我也不懂 Helm 的底层(面向对象/OOP、EIEIO 什么的),没办法自里向外解释。

2 个赞