-;;; async --- Asynchronous processing in Emacs
+;;; async.el --- Asynchronous processing in Emacs
-;; Copyright (C) 2012~2013 John Wiegley
+;; Copyright (C) 2012~2014 John Wiegley
;; Author: John Wiegley <jwiegley@gmail.com>
;; Created: 18 Jun 2012
-;; Version: 1.1
+
;; Keywords: async
;; X-URL: https://github.com/jwiegley/emacs-async
(defvar async-callback-value nil)
(defvar async-callback-value-set nil)
(defvar async-current-process nil)
+(defvar async--procvar nil)
(defun async-inject-variables
(include-regexp &optional predicate exclude-regexp)
(eval sexp)))
(defun async--insert-sexp (sexp)
- (prin1 sexp (current-buffer))
- ;; Just in case the string we're sending might contain EOF
- (encode-coding-region (point-min) (point-max) 'utf-8-unix)
- (base64-encode-region (point-min) (point-max) t)
- (goto-char (point-min)) (insert ?\")
- (goto-char (point-max)) (insert ?\" ?\n))
+ (let (print-level print-length)
+ (prin1 sexp (current-buffer))
+ ;; Just in case the string we're sending might contain EOF
+ (encode-coding-region (point-min) (point-max) 'utf-8-unix)
+ (base64-encode-region (point-min) (point-max) t)
+ (goto-char (point-min)) (insert ?\")
+ (goto-char (point-max)) (insert ?\" ?\n)))
(defun async--transmit-sexp (process sexp)
(with-temp-buffer
PROGRAM is passed PROGRAM-ARGS, calling FINISH-FUNC with the
process object when done. If FINISH-FUNC is nil, the future
object will return the process object when the program is
-finished."
+finished. Set DEFAULT-DIRECTORY to change PROGRAM's current
+working directory."
(let* ((buf (generate-new-buffer (concat "*" name "*")))
(proc (let ((process-connection-type nil))
(apply #'start-process name buf program program-args))))
proc)))
;;;###autoload
-(defmacro async-start (start-func &optional finish-func)
+(defun async-start (start-func &optional finish-func)
"Execute START-FUNC (often a lambda) in a subordinate Emacs process.
When done, the return value is passed to FINISH-FUNC. Example:
passed to FINISH-FUNC). Call `async-get' on such a future always
returns nil. It can still be useful, however, as an argument to
`async-ready' or `async-wait'."
- (require 'find-func)
- (let ((procvar (make-symbol "proc")))
- `(let* ((sexp ,start-func)
- (,procvar
- (async-start-process
- "emacs" (file-truename
- (expand-file-name invocation-name
- invocation-directory))
- ,finish-func
- "-Q" "-l" ,(symbol-file 'async-batch-invoke 'defun)
- "-batch" "-f" "async-batch-invoke"
- (if async-send-over-pipe
- "<none>"
- (with-temp-buffer
- (async--insert-sexp (list 'quote sexp))
- (buffer-string))))))
- (if async-send-over-pipe
- (async--transmit-sexp ,procvar (list 'quote sexp)))
- ,procvar)))
+ (let ((sexp start-func))
+ (setq async--procvar
+ (async-start-process
+ "emacs" (file-truename
+ (expand-file-name invocation-name
+ invocation-directory))
+ finish-func
+ "-Q" "-l"
+ ;; Using `locate-library' ensure we use the right file
+ ;; when the .elc have been deleted.
+ (locate-library "async")
+ "-batch" "-f" "async-batch-invoke"
+ (if async-send-over-pipe
+ "<none>"
+ (with-temp-buffer
+ (async--insert-sexp (list 'quote sexp))
+ (buffer-string)))))
+ (if async-send-over-pipe
+ (async--transmit-sexp async--procvar (list 'quote sexp)))
+ async--procvar))
(defmacro async-sandbox(func)
"Evaluate FUNC in a separate Emacs process, synchronously."