21

I am in the early stages of writing an Emacs major mode for browsing and contributing to sites on the Stack Exchange network, in much the same way as dired and list-packages works, with a few inspirations from magit and org-mode.

The problem is, of course, I have no idea how I would interface Emacs with the SE API (v2.1) in the first place. I've never done anything that involves a network connection within Elisp, although I'm comfortable with the language itself (and have taken more than a few looks at package.el).

I've never worked with JSON, although I'm in the middle of W3C's tutorial on it.

A simple 'hello world' would suffice, possibly along the lines of

(execute-json-query "/info")

The W3C tutorial doesn't seem to go over requests, either. I'll have to do my own research on that.
I really don't have any idea what I'm doing; I've only just started feverishly working on this yesterday afternoon.

Sean Allred
  • 3,558
  • 3
  • 32
  • 71

3 Answers3

27

The problem with other answers is that Stack Exchange API is GZIP'd and url.el shipped with Emacs does not automatically decompress it.

Take a look at my request.el library which supports automatic decompression (to be honest, I just added the support). Here is an example to fetch the most active question in stackoverflow:

(request
 "https://api.stackexchange.com/2.1/questions"
 :params '((order . "desc")
           (sort . "activity")
           (site . "stackoverflow"))
 :parser 'json-read
 :success (function*
           (lambda (&key data &allow-other-keys)
             (let* ((item (elt (assoc-default 'items data) 0))
                    (title (assoc-default 'title item))
                    (tags (assoc-default 'tags item)))
               (message "%s %S" title tags)))))

request.el is well documented, comes with executable examples and is well tested.

tkf
  • 2,990
  • 18
  • 32
  • This is awesome. I actually looked at this package *while researching the package* but was lost for it. Unfortunately, running your example as-is produces an error which I must host on https://gist.github.com/vermiculus/5050463. – Sean Allred Feb 27 '13 at 18:46
  • As I mentioned, I just added the gzip support. Check `request-version` and if it's not 0.2.0alpha1, you need to update it. – tkf Feb 27 '13 at 18:55
  • Also, you need curl if you need automatic decompression. – tkf Feb 27 '13 at 18:56
  • Doesn't melpa just refer to the blob in its package listings? That's where I installed yours from. – Sean Allred Feb 27 '13 at 19:02
  • 1
    It takes some time to be packaged by melpa. Checkout https://twitter.com/melpa_emacs – tkf Feb 27 '13 at 19:11
  • 1
    This request.el library looks awesome. Thanks tkf. – Randy Morris Feb 27 '13 at 19:29
  • @tkf, I'm having a lot of trouble getting this set up. Now it just won't connect, it seems. Head on over to the [Emacs](http://chat.stackoverflow.com/rooms/25252/emacs) room I set up? I feel like this doesn't belong in the comments. – Sean Allred Feb 27 '13 at 21:40
  • Actually, I may jave just found the problem. Hold on... **Got it.** – Sean Allred Feb 27 '13 at 21:50
  • @tkf, could you explain a bit more about what you are doing with `:success`? I understand from the documentation that it specifies a function to be called upon success, but its use isn't terribly well-documented (but almost learn-by-example). Is there some reason one has to specify `&allow-other-keys`? – Sean Allred Mar 03 '13 at 20:01
  • The reason why you need `&allow-other-keys` is in the document http://tkf.github.com/emacs-request/manual.html#request. If you don't know what `&allow-other-keys` does, read CL's document `M-: (info "(cl) Argument Lists") ERT`. – tkf Mar 03 '13 at 23:27
  • @tkf What if one just wanted to simply return the (parsed) object on success? – Sean Allred Apr 08 '13 at 14:47
  • You mean you want blocking call? You can use `:sync t` if you want. See the manual for more info. – tkf Apr 08 '13 at 17:20
  • Ah! assoc-default was what I've been hunting down. Thanks for this answer – Joe Heyming Aug 24 '15 at 20:11
  • Does not seem to work on Windows. I get just `REQUEST [error] Error (error) while connecting to https://api.stackexchange.com/2.1/questions.` – ceving Dec 06 '15 at 15:39
  • Reqeust.el is a slick package, but if you're using authentication you have to fall back to uri.el – Ashton Honnecke Sep 01 '17 at 21:36
11

Take a look at REST Client on GitHub - a tool to manually explore and test HTTP REST webservices.

David J. Liszewski
  • 10,959
  • 6
  • 44
  • 57
  • 1
    This is really cool. This might end up being the marked answer if there are no others, but *especially* if you provide an example of an elisp expression (using `restclient` if necessary) that will resolve to the returned string. – Sean Allred Feb 27 '13 at 18:22
8

This may not be the best way of doing things but it seems to work for me.

(defun fetch-json (url)
   (with-current-buffer (url-retrieve-synchronously url)
     ; there's probably a better way of stripping the headers
     (search-forward "\n\n")
     (delete-region (point-min) (point))
     (buffer-string)))

Then calling this function with a url will return the content of the response, in this case, json. I've used the reddit api as an example because I'm not sure how the Stack Exchange api works.

 (fetch-json "http://reddit.com/r/emacs.json")

There is pretty much no error checking included here, if the url returns no data then this will blow up.

Randy Morris
  • 39,631
  • 8
  • 69
  • 76