Welcome to Emacs Deferred’s documentation!¶
Contents:
Installation¶
Installing from Melpa¶
If you have already used Melpa to install some other package then all you have to do is:
M-x package-install RET deferred RET
Installing from Marmalade¶
WRITE HERE
Installing from Git¶
If you want to contribute to deferred and concurrent you should run it directly from the Git reposiotry.
First get the repository:
$ git clone git://github.com/kiwanami/emacs-deferred.git
Then add this to your init.el:
(add-to-list 'load-path "/path/to/emacs-deferred")
(require 'deferred)
(require 'concurrent)
To build deferred and concurrent manually:
WRITE HERE
deferred.el manual¶
Sample¶
You can find following sample codes in deferred-sample.el
.
Executing eval-last-sexp
(C-x C-e), you can try those
codes.
Basic usage¶
This is a basic deferred chain. This code puts some outputs into message buffer, and then require a number from minibuffer.
Chain:
(deferred:$
(deferred:next
(lambda () (message "deferred start")))
(deferred:nextc it
(lambda ()
(message "chain 1")
1))
(deferred:nextc it
(lambda (x)
(message "chain 2 : %s" x)))
(deferred:nextc it
(lambda ()
(read-minibuffer "Input a number: ")))
(deferred:nextc it
(lambda (x)
(message "Got the number : %i" x)))
(deferred:error it
(lambda (err)
(message "Wrong input : %s" err))))
- This s-exp returns immediately.
- Asynchronous tasks start subsequently.
- The macro
deferred:$
chains deferred objects.
- The anaphoric variable :el:var:`it` holds a deferred object in the previous line.
- The next deferred task receives the value that is returned by the previous deferred one.
- Inputting a wrong value, such as alphabets, this s-exp raises an
error. The error is caught by the errorback function defined by
deferred:error
.
Timer¶
After evaluating this s-exp and waiting for 1 second, a message is shown in the minibuffer.
Timer:
(deferred:$
(deferred:wait 1000) ; 1000msec
(deferred:nextc it
(lambda (x)
(message "Timer sample! : %s msec" x))))
- The next deferred task subsequent to deferred:wait receives the actual elapse time in millisecond.
Commands and Sub-process¶
This s-exp inserts the result that is performed by the command ‘ls -la’. (This s-exp may not run in windows. Try ‘dir’ command.)
Command process:
(deferred:$
(deferred:process "ls" "-la")
(deferred:nextc it
(lambda (x) (insert x))))
- This s-exp hardly blocks Emacs because of asynchronous mechanisms.
HTTP GET : Text¶
This s-exp inserts a text from http://www.gnu.org asynchronously. (You can clear the result with undo command.)
HTTP GET:
(require 'url)
(deferred:$
(deferred:url-retrieve "http://www.gnu.org")
(deferred:nextc it
(lambda (buf)
(insert (with-current-buffer buf (buffer-string)))
(kill-buffer buf))))
HTTP Get : Image¶
This s-exp inserts an image from google asynchronously.
Get an image:
(deferred:$
(deferred:url-retrieve "http://www.google.co.jp/intl/en_com/images/srpr/logo1w.png")
(deferred:nextc it
(lambda (buf)
(insert-image
(create-image
(let ((data (with-current-buffer buf (buffer-string))))
(substring data (+ (string-match "\n\n" data) 2)))
'png t))
(kill-buffer buf))))
Parallel¶
This s-exp retrieves two images from google concurrently and wait for the both results. Then, the file sizes of the images are inserted the current buffer.
Parallel deferred:
(deferred:$
(deferred:parallel
(lambda ()
(deferred:url-retrieve "http://www.google.co.jp/intl/en_com/images/srpr/logo1w.png"))
(lambda ()
(deferred:url-retrieve "http://www.google.co.jp/images/srpr/nav_logo14.png")))
(deferred:nextc it
(lambda (buffers)
(loop for i in buffers
do
(insert
(format
"size: %s\n"
(with-current-buffer i (length (buffer-string)))))
(kill-buffer i)))))
- The function ‘deferred:parallel’ runs asynchronous tasks concurrently.
- The function wait for all results, regardless normal or abnormal. Then, the subsequent tasks are executed.
- The next task receives a list of the results.
- The order of the results is corresponding to one of the argument.
- Giving an alist of tasks as the argument, the results alist is returned.
Deferred Combination : try-catch-finally¶
This s-exp executes following tasks:
- Getting an image by wget command,
- Resizing the image by convert command in ImageMagick,
- Insert the re-sized image into the current buffer. You can construct the control structure of deferred tasks, like try-catch-finally in Java.
Get an image by wget and resize by ImageMagick:
(deferred:$
;; try
(deferred:$
(deferred:process "wget" "-O" "a.jpg" "http://www.gnu.org/software/emacs/tour/images/splash.png")
(deferred:nextc it
(lambda () (deferred:process "convert" "a.jpg" "-resize" "100x100" "jpg:b.jpg")))
(deferred:nextc it
(lambda ()
(clear-image-cache)
(insert-image (create-image (expand-file-name "b.jpg") 'jpeg nil)))))
;; catch
(deferred:error it ;
(lambda (err)
(insert "Can not get a image! : " err)))
;; finally
(deferred:nextc it
(lambda ()
(deferred:parallel
(lambda () (delete-file "a.jpg"))
(lambda () (delete-file "b.jpg")))))
(deferred:nextc it
(lambda (x) (message ">> %s" x))))
- In this case, the deferred tasks are statically connected.
Here is an another sample code for try-catch-finally blocks. This is simpler than above code because of the ‘deferred:try’ macro. (Note: They bring the same results practically, but are not perfectly identical. The ‘finally’ task may not be called because of asynchrony.)
Try-catch-finally:
(deferred:$
(deferred:try
(deferred:$
(deferred:process "wget" "-O" "a.jpg" "http://www.gnu.org/software/emacs/tour/images/splash.png")
(deferred:nextc it
(lambda () (deferred:process "convert" "a.jpg" "-resize" "100x100" "jpg:b.jpg")))
(deferred:nextc it
(lambda ()
(clear-image-cache)
(insert-image (create-image (expand-file-name "b.jpg") 'jpeg nil)))))
:catch
(lambda (err) (insert "Can not get a image! : " err))
:finally
(lambda ()
(delete-file "a.jpg")
(delete-file "b.jpg")))
(deferred:nextc it
(lambda (x) (message ">> %s" x))))
Timeout¶
Although a long time command is executed (3 second sleeping), the task is canceled by timeout for 1 second.
The function ‘deferred:earlier’ also runs asynchronous tasks concurrently, however, the next deferred task receives the first result. The other results and tasks will be canceled.
Timeout Process:
(deferred:$
(deferred:earlier
(deferred:process "sh" "-c" "sleep 3 | echo 'hello!'")
(deferred:$
(deferred:wait 1000) ; timeout msec
(deferred:nextc it (lambda () "canceled!"))))
(deferred:nextc it
(lambda (x) (insert x))))
- Changing longer timeout for ‘deferred:wait’, the next task receives a result of the command.
- When a task finishes abnormally, the task is ignored.
- When all tasks finishes abnormally, the next task receives nil.
- The functions ‘deferred:parallel’ and ‘deferred:earlier’ may be corresponding to ‘and’ and ‘or’, respectively.
Here is an another sample code for timeout, employing ‘deferred:timeout’ macro.
Timeout macro:
(deferred:$
(deferred:timeout
1000 "canceled!"
(deferred:process "sh" "-c" "sleep 3 | echo 'hello!'"))
(deferred:nextc it
(lambda (x) (insert x))))
Loop and Animation¶
This s-exp plays an animation at the cursor position for few seconds. Then, you can move cursor freely, because the animation does not block Emacs.
Returning a deferred object in the deferred tasks, the returned task is executed before the next deferred one that is statically connected on the source code. (In this case, the interrupt task is dynamically connected.)
Employing a recursive structure of deferred tasks, you can construct a deferred loop. It may seem the multi-thread in Emacs Lisp.
Loop and animation:
(lexical-let ((count 0) (anm "-/|\\-")
(end 50) (pos (point))
(wait-time 50))
(deferred:$
(deferred:next
(lambda (x) (message "Animation started.")))
(deferred:nextc it
(deferred:lambda (x)
(save-excursion
(when (< 0 count)
(goto-char pos) (delete-char 1))
(insert (char-to-string
(aref anm (% count (length anm))))))
(if (> end (incf count)) ; return nil to stop this loop
(deferred:nextc (deferred:wait wait-time) self)))) ; return the deferred
(deferred:nextc it
(lambda (x)
(save-excursion
(goto-char pos) (delete-char 1))
(message "Animation finished.")))))
- ‘deferred:lambda’ is an anaphoric macro in which ‘self’ refers itself. It is convenient to construct a recursive structure.
Wrapping asynchronous function¶
Let’s say you have an asynchronous function which takes a callback. For example, dbus.el, xml-rpc.el and websocket.el has such kind of asynchronous APIs. To use such libraries with deferred.el, you can make an unregistered deferred object using deferred:new and then start the deferred callback queue using deferred:callback-post in the callback given to the asynchronous function. If the asynchronous function supports “errorback”, you can use deferred:errorback-post to pass the error information to the following callback queue.
In the following example, run-at-time is used as an example for the asynchronous function. Deferred.el already has deferred:wait for this purpose so that you don’t need the following code if you want to use run-at-time.
(deferred:$
(deferred:next
(lambda ()
(message "1")
1))
(deferred:nextc it
(lambda (x)
(lexical-let ((d (deferred:new #'identity)))
(run-at-time 0 nil (lambda (x)
;; Start the following callback queue now.
(deferred:callback-post d x))
x)
;; Return the unregistered (not yet started) callback
;; queue, so that the following queue will wait until it
;; is started.
d)))
;; You can connect deferred callback queues
(deferred:nextc it
(lambda (x)
(message "%s" (1+ x)))))
concurrent.el manual¶
WRITE HERE
deferred.el API¶
Basic functions¶
-
Function
deferred:next
&optional callback arg¶ Create a deferred object and schedule executing. :Arguments: CALLBACK a function with zero or one argument :Return: a deferred object This function is a short cut of following code:: (deferred:callback-post (deferred:new callback)).
-
Function
deferred:nextc
d callback¶ Create a deferred object with OK callback and connect it to the given deferred object. :Arguments: D a deferred object CALLBACK a function with zero or one argument :Return: a deferred object Return a deferred object that wrap the given callback function. Then, connect the created deferred object with the given deferred object.
-
Function
deferred:error
d callback¶ Create a deferred object with ERRORBACK and connect it to the given deferred object D. :Arguments: D a deferred object ERRORBACK a function with zero or one argument :Return: a deferred object Return a deferred object that wraps the given function as an ERRORBACK. Then, connect the created deferred object with the given deferred object. The given ERRORBACK function catches the error occurred in the previous task. If this function does not throw an error, the subsequent callback functions are executed.
-
Function
deferred:cancel
d¶ Cancel all callbacks and deferred chain in the deferred object.
-
Function
deferred:watch
d callback¶ Create a deferred object with watch task and connect it to the given deferred object. The watch task CALLBACK can not affect deferred chains with return values. This function is used in following purposes, simulation of try-finally block in asynchronous tasks, progress monitoring of tasks.
-
Function
deferred:wait
msec¶ Return a deferred object scheduled at MSEC millisecond later.
-
Function
deferred:$
&rest elements¶ Anaphoric function chain macro for deferred chains.
Utility functions¶
-
Function
deferred:loop
times-or-list func¶ Return a iteration deferred object.
-
Function
deferred:parallel
&rest args¶ Return a deferred object that calls given deferred objects or functions in parallel and wait for all callbacks. The following deferred task will be called with an array of the return values. ARGS can be a list or an alist of deferred objects or functions.
-
Function
deferred:earlier
&rest args¶ Return a deferred object that calls given deferred objects or functions in parallel and wait for the first callback. The following deferred task will be called with the first return value. ARGS can be a list or an alist of deferred objects or functions.
Wrapper functions¶
-
Function
deferred:call
f &rest args¶ Call the given function asynchronously.
-
Function
deferred:apply
f &optional args¶ Call the given function asynchronously.
-
Function
deferred:process
command &rest args¶ A deferred wrapper of
`start-process'
. Return a deferred object. The process name and buffer name of the argument of the`start-process'
are generated by this function automatically. The next deferred object receives stdout string from the command process.
-
Function
deferred:process-shell
command &rest args¶ A deferred wrapper of
`start-process-shell-command'
. Return a deferred object. The process name and buffer name of the argument of the`start-process-shell-command'
are generated by this function automatically. The next deferred object receives stdout string from the command process.
-
Function
deferred:process-buffer
command &rest args¶ A deferred wrapper of
`start-process'
. Return a deferred object. The process name and buffer name of the argument of the`start-process'
are generated by this function automatically. The next deferred object receives stdout buffer from the command process.
-
Function
deferred:process-shell-buffer
command &rest args¶ A deferred wrapper of
`start-process-shell-command'
. Return a deferred object. The process name and buffer name of the argument of the`start-process-shell-command'
are generated by this function automatically. The next deferred object receives stdout buffer from the command process.
-
Function
deferred:wait-idle
msec¶ Return a deferred object which will run when Emacs has been idle for MSEC millisecond.
-
Function
deferred:url-retrieve
¶
-
Function
deferred:url-get
¶
-
Function
deferred:url-post
¶
Primitive functions¶
-
Function
deferred:new
&optional callback¶ Create a deferred object.
-
Function
deferred:succeed
&optional arg¶ Create a synchronous deferred object.
-
Function
deferred:fail
&optional arg¶ Create a synchronous deferred object.
-
Function
deferred:callback
d &optional arg¶ Start deferred chain with a callback message.
-
Function
deferred:callback-post
d &optional arg¶ Add the deferred object to the execution queue.
-
Function
deferred:errorback
d &optional arg¶ Start deferred chain with an errorback message.
-
Function
deferred:errorback-post
d &optional arg¶ Add the deferred object to the execution queue.
Utility Macros¶
-
Function
deferred:try
d &key catch finally¶ Try-catch-finally macro. This macro simulates the try-catch-finally block asynchronously. CATCH and FINALLY can be nil. Because of asynchrony, this macro does not ensure that the task FINALLY should be called.
-
Function
deferred:timeout
timeout-msec timeout-form d¶ Time out macro on a deferred task D. If the deferred task D does not complete within TIMEOUT-MSEC, this macro cancels the deferred task and return the TIMEOUT-FORM.
-
Function
deferred:processc
d command &rest args¶ Process chain of
`deferred:process'
.
-
Function
deferred:process-bufferc
d command &rest args¶ Process chain of
`deferred:process-buffer'
.
-
Function
deferred:process-shellc
d command &rest args¶ Process chain of
`deferred:process'
.
-
Function
deferred:process-shell-bufferc
d command &rest args¶ Process chain of
`deferred:process-buffer'
.
concurrent.el API¶
Generator¶
-
Function
cc:generator
callback &rest body¶ Create a generator object. If BODY has
`yield'
symbols, it means calling callback function CALLBACK.
Semaphore¶
-
Function
cc:semaphore-create
permits-num¶ Return a semaphore object with PERMITS-NUM permissions.
-
Function
cc:semaphore-acquire
semaphore¶ Acquire an execution permission and return deferred object to chain. If this semaphore object has permissions, the subsequent deferred task is executed immediately. If this semaphore object has no permissions, the subsequent deferred task is blocked. After the permission is returned, the task is executed.
-
Function
cc:semaphore-release
semaphore¶ Release an execution permission. The programmer is responsible to return the permissions.
-
Function
cc:semaphore-with
semaphore body-func &optional error-func¶ Execute the task BODY-FUNC asynchronously with the semaphore block.
-
Function
cc:semaphore-release-all
semaphore¶ Release all permissions for resetting the semaphore object. If the semaphore object has some blocked tasks, this function return a list of the tasks and clear the list of the blocked tasks in the semaphore object.
-
Function
cc:semaphore-interrupt-all
semaphore¶ Clear the list of the blocked tasks in the semaphore and return a deferred object to chain. This function is used for the interruption cases.
Signal¶
-
Function
cc:signal-channel
&optional name parent-channel¶ Create a channel. NAME is a channel name for debug. PARENT-CHANNEL is an upstream channel. The observers of this channel can receive the upstream signals. In the case of using the function
`cc:signal-send'
, the observers of the upstream channel can not receive the signals of this channel. The function`cc:signal-send-global'
can send a signal to the upstream channels from the downstream channels.
-
Function
cc:signal-connect
channel event-sym &optional callback¶ Append an observer for EVENT-SYM of CHANNEL and return a deferred object. If EVENT-SYM is
`t'
, the observer receives all signals of the channel. If CALLBACK function is given, the deferred object executes the CALLBACK function asynchronously. One can connect subsequent tasks to the returned deferred object.
-
Function
cc:signal-send
channel event-sym &rest args¶ Send a signal to CHANNEL. If ARGS values are given, observers can get the values by following code: (lambda (event) (destructuring-bind (event-sym (args)) event ... )).
-
Function
cc:signal-send-global
channel event-sym &rest args¶ Send a signal to the most upstream channel.
-
Function
cc:signal-disconnect
channel deferred¶ Remove the observer object DEFERRED from CHANNEL and return the removed deferred object.
-
Function
cc:signal-disconnect-all
channel¶ Remove all observers.
Dataflow¶
-
Function
cc:dataflow-environment
&optional parent-env test-func channel¶ Create a dataflow environment. PARENT-ENV is the default environment. If this environment doesn't have the entry A and the parent one has the entry A, this environment can return the entry A. One can override the entry, setting another entry A to this environment. TEST-FUNC is a test function that compares the entry keys. The default function is
`equal'
. CHANNEL is a channel object that sends signals of variable events. Observers can receive following signals: ``get-first`` the fist referrer is waiting for binding ``get-waiting`` another referrer is waiting for binding ``set`` a value is bound ``get`` returned a bound value ``clear`` cleared one entry ``clear-all`` cleared all entries
-
Function
cc:dataflow-get
df key¶ Return a deferred object that can refer the value which is indicated by KEY. If DF has the entry that bound value, the subsequent deferred task is executed immediately. If not, the task is deferred till a value is bound.
-
Function
cc:dataflow-get-sync
df key¶ Return the value which is indicated by KEY synchronously. If the environment DF doesn't have an entry of KEY, this function returns nil.
-
Function
cc:dataflow-set
df key value¶ Bind the VALUE to KEY in the environment DF. If DF already has the bound entry of KEY, this function throws an error signal. VALUE can be nil as a value.
-
Function
cc:dataflow-clear
df key¶ Clear the entry which is indicated by KEY. This function does nothing for the waiting deferred objects.
-
Function
cc:dataflow-get-avalable-pairs
df¶ Return an available key-value alist in the environment DF and the parent ones.
-
Function
cc:dataflow-get-waiting-keys
df¶ Return a list of keys which have waiting deferred objects in the environment DF and the parent ones.
-
Function
cc:dataflow-clear-all
df¶ Clear all entries in the environment DF. This function does nothing for the waiting deferred objects.
-
Function
cc:dataflow-connect
df event-sym &optional callback¶ Append an observer for EVENT-SYM of the channel of DF and return a deferred object. See the docstring of
`cc:dataflow-environment'
for details.
Resources for deferred.el/concurrent.el development¶
How to build document¶
Document of deferred.el and concurrent.el are build using Sphinx and sphinxcontrib-emacs. It is available via read the docs.
To build document, you need to install Sphinx and sphinxcontrib-emacs, for example, using pip install:
cd PATH/TO/emacs-deferred
pip install Sphinx
pip install -r doc/requirements.txt
Then, goto doc/
directory and build document:
cd doc/
make html
You have html document in doc/build/html/
.
If autodocument does not fetch updated docstrings from *.el
files,
use make clean html
instead.