From 82d5cffeca77974676f2e8b161f00accd914af71 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Fri, 25 May 2012 20:57:48 +0200 Subject: [PATCH] Add ein-query.el --- ein-query.el | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 ein-query.el diff --git a/ein-query.el b/ein-query.el new file mode 100644 index 0000000..ce02823 --- /dev/null +++ b/ein-query.el @@ -0,0 +1,132 @@ +;;; ein-query.el --- jQuery like interface on to of url-retrieve + +;; Copyright (C) 2012- Takafumi Arakaki + +;; Author: Takafumi Arakaki + +;; This file is NOT part of GNU Emacs. + +;; ein-query.el is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; ein-query.el is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with ein-query.el. If not, see . + +;;; Commentary: + +;; + +;;; Code: + +(eval-when-compile (require 'cl)) +(require 'url) + +(require 'ein-utils) +(require 'ein-log) + +(defun ein:safe-funcall-packed (packed &rest args) + (when packed + (ein:log-ignore-errors (apply #'ein:funcall-packed packed args)))) + +(defun* ein:query-ajax (url &rest settings + &key + (cache t) + (type "GET") + (data nil) + (headers nil) + (success nil) + (error nil) + (timeout nil) + (status-code nil)) + "Mimic `$.ajax'. + +:CACHE (nil/t) : append time-stamp to URL so the URL is always loaded. +:TYPE (string) : sets `url-request-method' +:DATA (string) : sets `url-request-data' +:HEADERS (alist) : sets `url-request-extra-headers' +:SUCCESS (cons) : called on success +:ERROR (cons) : called on error +:TIMEOUT (number) : timeout in millisecond +:STATUS-CODE (alist) : map status code (int) to callback (cons) + +* Callback functions + +All callbacks must be given as `cons' where car is a FUNCTION and +cdr is its first ARGUMENT. It is analogous of `$.proxy'. Call +signature is like this: + \(FUNCTION ARGUMENT [other callback specific arguments]) + +The second note is that the callback FUNCTION must be defined +using `defun*' with `&key' and `&allow-other-keys' to ignore +missing/extra arguments as some callback (namely :ERROR) changes +arguments to be passed, depending on situation. + +Finally, note that callback FUNCTION is executed on the process +buffer, meaning that response data is on the current buffer when +the FUNCTION is called. There is no `:data' argument for +FUNCTION so it must be fetched from the buffer. + +* :ERROR callback + +:SYMBOL-STATUS (`error'/`timeout') : analogous of `textStatus' +:STATUS (list) : see `url-retrieve' + +The :SUCCESS callback also takes the :STATUS argument. + +* See also: http://api.jquery.com/jQuery.ajax/" + (unless cache + (setq url (ein:url-no-cache url))) + (let* ((url-request-extra-headers headers) + (url-request-method type) + (url-request-data data) + (buffer (url-retrieve url #'ein:query-ajax-callback settings))) + (when timeout + (run-at-time (/ timeout 1000.0) nil + #'ein:query-ajax-timeout-callback + (cons buffer settings))) + buffer)) + +(defun* ein:query-ajax-callback (status &key + (headers nil) + (success nil) + (error nil) + (timeout nil) + (status-code nil) + &allow-other-keys) + (declare (special url-http-response-status + url-http-method)) + (unwind-protect + (progn + (ein:log 'debug "EIN:QUERY-AJAX-CALLBACK") + (ein:log 'debug "status = %S" status) + (ein:log 'debug "url-http-response-status = %s" + url-http-response-status) + (ein:log 'debug "(buffer-string) =\n%s" (buffer-string)) + + (apply #'ein:safe-funcall-packed + (if (plist-get status :error) + (list error :symbol-status 'error :status status) + (list success :status status))) + (ein:aif (assq url-http-response-status status-code) + (ein:safe-funcall-packed (cdr it)))) + (kill-buffer))) + +(defun* ein:query-ajax-timeout-callback (buffer &key + (error nil) + &allow-other-keys) + (with-current-buffer buffer + (ein:safe-funcall-packed error :symbol-status 'timeout)) + (let ((proc (process-buffer buffer))) + (kill-process proc) + (kill-buffer buffer))) + +(provide 'ein-query) + +;;; ein-query.el ends here