2014-09-05 22 views
4

我对编程emacs了解不多,但我确实知道如何用Lispy语言编程。我有一个服务可以观看项目目录,并通过类似休息的Web界面产生结果。我想挂钩emacs到这个服务,也许使用这种方案来编写emacs的一些功能。我真的不知道从哪里开始在emacs方面。那么,什么库最适合打网络服务?如何将emacs挂接到json服务?

+2

HTTP的可能重复:// stackoverflow.com/questions/15118304/making-json-requests-within-emacs。那里的答案提到了[请求](https://github.com/tkf/emacs-request)库,我还没有用过。 – 2014-09-07 06:19:08

回答

8

Emacs对这种事情有很好的内置支持,至少在进行请求和解析响应的基础级别上。使用url-retrieveurl-retrieve-synchronously从远程服务获取数据。正如名字所暗示的,一个是一个异步调用,它接受一个回调,另一个是阻塞调用,它返回一个包含响应的缓冲区。通过在您的Elisp文件中包含(require 'url)加载它们。

url-函数记录在与Elisp其余部分分开的信息手册中,名为“URL”,但在此处未提及一些有用的功能。对于在URL中传递参数的GET请求,url-build-query-string函数对于从键和值的列表构造查询参数字符串非常有用。对于POST,PUT,DELETE和其他请求,您可能需要绑定变量url-request-dataurl-request-methodurl-request-extra-headers。他们有信息文档。

有关使用这些HTTP URL调用的最后一个令人困惑的事情是,它们将HTTP响应头留在与响应正文相同的缓冲区中,这可能不是您所期望的。处理这个问题的简单方法是在处理主体之前使用(未记录的)url-http-end-of-headers变量跳过标题,尽管我怀疑可能有更好的方法。

使用json-read函数来解析JSON响应,并绑定变量json-array-typejson-object-typejson-key-type控制JSON类型如何转换为Lisp的类型。该功能通过包含(require 'json)获得。 XML响应可以使用xml-parse-regionlibxml-xml-parse-region进行分析。后者要求Emacs与libxml支持编译,前者在Elisp中实现。

把这个在一起,以一个JSON服务的请求的骨架看起来是这样的:

(url-retrieve 
"http://example.com/api/some/request" 
(lambda (events) 
    (goto-char url-http-end-of-headers) 
    (let ((json-object-type 'plist) 
     (json-key-type 'symbol) 
     (json-array-type 'vector)) 
    (let ((result (json-read))) 
     ;; Do something with RESULT here 
     )))) 

在回调中,您可以用result像任何其他的Lisp价值的工作。 plist-get,pcasecl-destructuring-bind函数通常用于提取结果片段。使用(require 'pcase)得到pcase宏,(require 'cl-lib)得到cl-destructuring-bind

0

这是我用在rate-exchange.appspot.com查找从JSON Web服务货币汇率:

(defun my-json-get (url) 
    (interactive) 
    (progn 
    (require 'json) 
    (with-current-buffer (url-retrieve-synchronously url) 
     (goto-char (point-min)) 
     (re-search-forward "^$") 
     (json-read)))) 
(defun my-currency-exchange-rate (from to) 
    (let ((xurl (format "http://rate-exchange.appspot.com/currency?from=%s&to=%s" from to))) 
    (assoc-default 'rate (my-json-get xurl)))) 

用法示例:

(my-currency-exchange-rate "USD" "SEK")