“实战Elisp”系列旨在讲述我使用Elisp定制Emacs的经验,抛砖引玉,还请广大Emacs同好不吝赐教——若是真的有广大Emacs用户的话,哈哈哈。
半年前我在这篇文章中展现了在Emacs中查阅笔记的效果——用emacs-request请求ElasticSearch查询关键字、基于helm如下拉菜单的方式展现查询结果的标题(即问题),最后打开浏览器查看笔记内容。稍加使用就发现一些不足之处:git
question
和answer
字段比较困难;answer
字段是以一行的形式展现的,不利于阅读。为了解决这些问题,我实现了一种新的查看笔记内容的方式。github
个人目标是:json
为此,先用被选中笔记的_id
请求ES,取回完整的JSON。接着,将_source
中的question
和answer
字段的内容拼接在一块儿(以\n
做为分隔符)。最后,在Emacs中新建一个buffer、启用org-mode、插入拼接后的内容,并设置该buffer为只读。大功告成!浏览器
完整的代码以下app
;;; 调用ElasticSearch查询笔记 (require 'request) (defun faq (query) "向ElasticSearch查询QUERY匹配的笔记" (let ((response)) (request "http://localhost:9200/faq/_search" :data (encode-coding-string (json-encode (list (cons "query" (list (cons "multi_match" (list (cons "fields" (list "answer" "question")) (cons "query" query))))))) 'utf-8) :headers '(("Content-Type" . "application/json")) :parser 'buffer-string :success (cl-function (lambda (&key data &allow-other-keys) (setq data (decode-coding-string data 'utf-8)) (setq response (json-read-from-string data)))) :sync t) response)) (defun make-faq-candidates (response) "将查询ElasticSearch的结果构造为helm能够识别的candidates格式" (let ((hits (cdr (assoc 'hits (cdr (assoc 'hits response)))))) (mapcar (lambda (doc) (let ((_source (cdr (assoc '_source doc)))) (cons (cdr (assoc 'question _source)) ;; (cdr (assoc 'answer (assoc '_source doc))) (cdr (assoc '_id doc))))) hits))) (defvar faq-query nil) (defun faq-candidates () (make-faq-candidates (faq faq-query))) ;;; 建立新的buffer并将ElasticSearch的内容展现在其中 (defun show-faq (text) ;; 建立一个buffer,显示它并选中这个窗口 (let ((buffer (get-buffer-create "*FAQ*"))) (let ((window (display-buffer buffer))) (select-window window) ;; 用新的内容覆盖原来的内容 (setq inhibit-read-only t) (org-mode) (erase-buffer) (insert text) (read-only-mode)))) (setq faq-helm-sources `((name . "FAQ at Emacs") (candidates . faq-candidates) (action . (lambda (candidate) (let (response (url (format "http://localhost:9200/faq/_doc/%s" candidate))) (message "url is %s" url) (request url :parser 'buffer-string :success (cl-function (lambda (&key data &allow-other-keys) (setq data (decode-coding-string data 'utf-8)) (setq response (json-read-from-string data)))) :sync t) ;; 从文档中提取出问题和答案,拼装成本来在.org文件中的模样 (let ((answer (cdr (assoc 'answer (assoc '_source response)))) (question (cdr (assoc 'question (assoc '_source response))))) (show-faq (concat question "\n" answer)))))))) (defun lt-ask () "交互式地从minibuffer中读取笔记的关键词并展现选项" (interactive) (let ((content (read-from-minibuffer "笔记关键词:"))) (setq faq-query content) (helm :sources '(faq-helm-sources))))
与以前版本的差别主要在于:函数
faq-helm-sources
中的action
部分多了不少内容,主要是请求ES和拼接字段;show-faq
函数用于显示问题及其答案。挺好奇各位读者朋友是怎么记笔记和看笔记的XDui
阅读原文url