从 Emacs 中搜索/补全 Dash 条目

Dash 的 Alfred 插件能够补全:

52%20PM

dash-at-point.el 没这个功能,Alfred 插件包含了一个 dashAlfredWorkflow 命令行程序:

~ $ dashAlfredWorkflow 'c:puts' | xmllint --format -
<?xml version="1.0"?>
<items>
  <item uid="dash-advanced://puts/Function/file:///Users/xcy/Library/Application%20Support/Dash/DocSets/C/C.docset/Contents/Resources/Documents/en.cppreference.com/w/c/io/puts.html" arg="0" autocomplete="puts">
    <title>puts</title>
    <text type="copy">puts</text>
    <text type="largetype">puts</text>
    <subtitle mod="cmd">Open "puts" in browser</subtitle>
    <subtitle mod="alt">Copy "puts" to clipboard</subtitle>
    <subtitle>C - puts</subtitle>
    <icon>/Users/xcy/Library/Application Support/Dash/Data/Alfred/23b63e037093461f49ade2edbabf166c.png</icon>
    <quicklookurl>http://127.0.0.1:59618/Dash/pcarilmq/en.cppreference.com/w/c/io/puts.html</quicklookurl>
  </item>
  <item uid="dash-advanced://fputs/Function/file:///Users/xcy/Library/Application%20Support/Dash/DocSets/C/C.docset/Contents/Resources/Documents/en.cppreference.com/w/c/io/fputs.html" arg="1" autocomplete="fputs">
    <title>fputs</title>
    <text type="copy">fputs</text>
    <text type="largetype">fputs</text>
    <subtitle mod="cmd">Open "fputs" in browser</subtitle>
    <subtitle mod="alt">Copy "fputs" to clipboard</subtitle>
    <subtitle>C - fputs</subtitle>
    <icon>/Users/xcy/Library/Application Support/Dash/Data/Alfred/23b63e037093461f49ade2edbabf166c.png</icon>
    <quicklookurl>http://127.0.0.1:59618/Dash/pcarilmq/en.cppreference.com/w/c/io/fputs.html</quicklookurl>
  </item>
</items>

利用这个 dashAlfredWorkflow 以及 ivy,Emacs 也可以搜索/补全 Dash 的条目了:

(defun chunyang-dash ()
  (interactive)
  (require 'dom)
  (ivy-read
   "Search Dash: "
   (lambda (str)
     (or
      (ivy-more-chars)
      (with-temp-buffer
        ;; dashAlfredWorkflow 'c:puts' | xmllint --format -
        (if (zerop (call-process "dashAlfredWorkflow" nil t nil str))
            (let* ((dom (libxml-parse-xml-region (point-min) (point-max)))
                   (items (dom-by-tag dom 'item)))
              (cl-loop for item in items
                       for uid = (dom-attr item 'uid)
                       for quicklookurl = (dom-text (dom-child-by-tag item 'quicklookurl))
                       for title = (dom-text (dom-child-by-tag item 'title))
                       for subtitle = (dom-text (car (last (dom-by-tag item 'subtitle))))
                       for subtitle+face = (propertize subtitle 'face 'font-lock-comment-face)
                       collect (propertize (concat title " " subtitle+face)
                                           'uid uid
                                           'quicklookurl quicklookurl)))
          (list
           "Error: dashAlfredWorkflow fails"
           ""
           (split-string (buffer-string) "\n"))))))
   :dynamic-collection t
   :action (lambda (x)
             (call-process "open" nil nil nil (get-text-property 0 'uid x)))))

(ivy-set-actions
 'chunyang-dash
 '(("b"
    (lambda (x)
      (browse-url (get-text-property 0 'quicklookurl x)))
    "browse url")))

效果图:

8 个赞

楼主不是helm忠实用户???

赞楼主!zsbd

不过有点小问题,不知道是不是dashAlfredWorkflow的锅,问题如下:

搜索printf,我们选择C++的那条,回车打开后,Dash显示没找到,你看到左栏选中的那个条目右侧有个“2”的下三角,点一下发现,有std::printf ,点它则正常打开我们需要的条目,但默认打开dash窗口时使用的是那条不存的printf条目(因为C++并没有printf)。如果直接dash中搜索printf是没有问题的。见下面一些图

09

哦,确实有问题。我又看了那个 Alfred 插件,修改成了同样的实现(见下面的代码),现在应该不存在这个问题了。

(defun chunyang-dash ()
  (interactive)
  (require 'dom)
  (ivy-read
   "Search Dash: "
   (lambda (str)
     (or
      (ivy-more-chars)
      (with-temp-buffer
        ;; dashAlfredWorkflow 'c:puts' | xmllint --format -
        (if (zerop (call-process "dashAlfredWorkflow" nil t nil str))
            (let* ((dom (libxml-parse-xml-region (point-min) (point-max)))
                   (items (dom-by-tag dom 'item)))
              (cl-loop for item in items
                       for idx from 0
                       for uid = (dom-attr item 'uid)
                       for quicklookurl = (dom-text (dom-child-by-tag item 'quicklookurl))
                       for title = (dom-text (dom-child-by-tag item 'title))
                       for subtitle = (dom-text (car (last (dom-by-tag item 'subtitle))))
                       for subtitle+face = (propertize subtitle 'face 'font-lock-comment-face)
                       collect (propertize (concat title " " subtitle+face)
                                           'uid uid
                                           'idx idx
                                           'quicklookurl quicklookurl)))
          (list
           "Error: dashAlfredWorkflow fails"
           ""
           (split-string (buffer-string) "\n"))))))
   :dynamic-collection t
   :action (lambda (x)
             (call-process "open"
                           nil nil nil
                           "-g" (format "dash-workflow-callback://%d"
                                        (get-text-property 0 'idx x))))))
2 个赞

漂亮!没有问题了

刚刚终于搞明白怎么用 Helm 实现了,之前一直不会,不想回答你的问题 :sweat_smile:

你不懂helm,还有谁人懂helm? :joy:

3 个赞

@xuchunyang 看楼上这截图,你是ivy和helm两边都水呀,优秀!我自从转投ivy,helm已经好久没碰了,虽然配置还在

我转helm了,原因 ivy.el (ivy-read): Refactor by cireu · Pull Request #2121 · abo-abo/swiper · GitHub

主要是ivy的架构太不够健壮了。导致hack起来要搞很多adhoc的玩意

helm设计比较复杂,一直没时间好好研究一下。ivy用起来简单不少

其实就是个折中,helm脱胎于anything, 完备而健壮,但太复杂,而ivy轻量而精简,必然功能会有牺牲。

这个PR的出发点是什么呢?

好东西啊,可惜 Linux 下面是 zeal,而且没有 Alfred。期待大神 Linux 下的实现啊