Spite is a REPL for interacting with web services inside Emacs.
Launch spite with M-x spite
.
spite> (spite/req-url "https://api.github.com/repos/codahale/metrics") ((network_count . 394) (default_branch . "master") (master_branch . "master") (watchers . 1654) (open_issues . 13) (forks . 394) (open_issues_count . 13) (mirror_url) (forks_count . 394) (has_wiki . :json-false) (has_downloads . t) (has_issues . t) (language . "Java") (watchers_count . 1654) (size . 15715) (homepage . "http://github.com/codahale/metrics") (svn_url . "https://github.com/codahale/metrics") (clone_url . "https://github.com/codahale/metrics.git") (ssh_url . "git@github.com:codahale/metrics.git") (git_url . "git://github.com/codahale/metrics.git") (pushed_at . "2013-07-23T22:19:30Z") (updated_at . "2013-08-07T15:25:50Z") (created_at . "2010-02-26T19:44:42Z") (labels_url . "https://api.github.com/repos/codahale/metrics/labels{/name}") (notifications_url . "https://api.github.com/repos/codahale/metrics/notifications{?since,all,participating}") (milestones_url . "https://api.github.com/repos/codahale/metrics/milestones{/number}") (pulls_url . "https://api.github.com/repos/codahale/metrics/pulls{/number}") (issues_url . "https://api.github.com/repos/codahale/metrics/issues{/number}") (downloads_url . "https://api.github.com/repos/codahale/metrics/downloads") (archive_url . "https://api.github.com/repos/codahale/metrics/{archive_format}{/ref}") (merges_url . "https://api.github.com/repos/codahale/metrics/merges") (compare_url . "https://api.github.com/repos/codahale/metrics/compare/{base}...{head}") (contents_url . "https://api.github.com/repos/codahale/metrics/contents/{+path}") (issue_comment_url . "https://api.github.com/repos/codahale/metrics/issues/comments/{number}") (comments_url . "https://api.github.com/repos/codahale/metrics/comments{/number}") (git_commits_url . "https://api.github.com/repos/codahale/metrics/git/commits{/sha}") (commits_url . "https://api.github.com/repos/codahale/metrics/commits{/sha}") (subscription_url . "https://api.github.com/repos/codahale/metrics/subscription") (subscribers_url . "https://api.github.com/repos/codahale/metrics/subscribers") (contributors_url . "https://api.github.com/repos/codahale/metrics/contributors") (stargazers_url . "https://api.github.com/repos/codahale/metrics/stargazers") (languages_url . "https://api.github.com/repos/codahale/metrics/languages") (statuses_url . "https://api.github.com/repos/codahale/metrics/statuses/{sha}") (trees_url . "https://api.github.com/repos/codahale/metrics/git/trees{/sha}") (git_refs_url . "https://api.github.com/repos/codahale/metrics/git/refs{/sha}") (git_tags_url . "https://api.github.com/repos/codahale/metrics/git/tags{/sha}") (blobs_url . "https://api.github.com/repos/codahale/metrics/git/blobs{/sha}") (tags_url . "https://api.github.com/repos/codahale/metrics/tags") (branches_url . "https://api.github.com/repos/codahale/metrics/branches{/branch}") (assignees_url . "https://api.github.com/repos/codahale/metrics/assignees{/user}") (events_url . "https://api.github.com/repos/codahale/metrics/events") (issue_events_url . "https://api.github.com/repos/codahale/metrics/issues/events{/number}") (hooks_url . "https://api.github.com/repos/codahale/metrics/hooks") (teams_url . "https://api.github.com/repos/codahale/metrics/teams") (collaborators_url . "https://api.github.com/repos/codahale/metrics/collaborators{/collaborator}") (keys_url . "https://api.github.com/repos/codahale/metrics/keys{/key_id}") (forks_url . "https://api.github.com/repos/codahale/metrics/forks") (url . "https://api.github.com/repos/codahale/metrics") (fork . :json-false) (description . "Capturing JVM- and application-level metrics. So you know what's going on.") (html_url . "https://github.com/codahale/metrics") (private . :json-false) (owner (type . "User") (received_events_url . "https://api.github.com/users/codahale/received_events") (events_url . "https://api.github.com/users/codahale/events{/privacy}") (repos_url . "https://api.github.com/users/codahale/repos") (organizations_url . "https://api.github.com/users/codahale/orgs") (subscriptions_url . "https://api.github.com/users/codahale/subscriptions") (starred_url . "https://api.github.com/users/codahale/starred{/owner}{/repo}") (gists_url . "https://api.github.com/users/codahale/gists{/gist_id}") (following_url . "https://api.github.com/users/codahale/following{/other_user}") (followers_url . "https://api.github.com/users/codahale/followers") (html_url . "https://github.com/codahale") (url . "https://api.github.com/users/codahale") (gravatar_id . "87206f3bf53d403e16ec023c56e904c5") (avatar_url . "https://secure.gravatar.com/avatar/87206f3bf53d403e16ec023c56e904c5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png") (id . 207) (login . "codahale")) (full_name . "codahale/metrics") (name . "metrics") (id . 537800)) spite>
The spite-make-url
function is the main way to build a request
URL. Once built, you can use spite/req-url
to fetch and display
it.
The value of spite-base-url
(which is buffer-local) is prepended
to all output, making it easy to have multiple Spite instances
targeting different APIs.
The first argument is a format string for building the URL, and the rest of the arguments are the values to substitute into it:
(let ((user "ieure"))
(spite-make-url "users/%s" user))
;; -> "users/ieure"
Quoted symbols and keywords are turned into strings. Normal symbols work the way you’d expect.
If you want to include query-string arguments, you may include an alist of them as the last argument:
(let ((user "ieure"))
(spite-make-url "users" `((username ,user) (status active))))
;; -> "users?username=ieure&status=active"
The convenience function spite/req
accepts the same arguments as
spite-make-url
, and sends the result to spite/req-url
.
Spite tries to read the response into a native elisp structure. It includes support for JSON and XML. If you request an image, it will be displayed inline in the Spite buffer.
New readers can be added in spite-response-readers
, which is an
alist of (pred-fun . reader-fun)
. The predicate function is
evaluated in the HTTP response buffer, and if it returns a truthy
value, reader=fun
is called. This function is also evaluated in
the context of the HTTP response buffer, and must return the forms
to be displayed.
The parsed structures are then pretty-printed with spite-pp
and
inserted with spite-insert
. You may need to hack these to
support exotic types.
If you want a custom Spite tailored to a specific API, you can use
defspite
and write a few helper functions:
(defspite github "https://api.github.com/")
(defun github/repo (org repo)
(spite/req "repos/%s/%s" org repo))
Then, you can launch it with M-x github
, and do:
github> (github/repo 'codahale 'metrics)
A fuller example can be found in github-api.el.
- Support for OAuth would be nice.
- Hook into nspace.el so you can prefix all your helper functions but avoid typing it.
- Paren insertion if the forms lack them.