What it is
pfuture.el offers a set of simple functions wrapping Emacs’ existing process creation functionality.
It attaches the output of a process to the process itself - turning it into a “future” and making it
conveniently easy to pass around to other functions, wait for it to complete and access its output.
In other words what this package offers is an asynchronous version of
without the need to deal with process creation and filter functions.
How to use it
pfuture-new (cmd &rest cmd-args)Create a new future process for command CMD and arguments CMD-ARGS. This will return a process object with one additional ~’result~ property which can be read via
(process-get process 'result)or alternatively with
Note that CMD-ARGS must be a sequence of strings, such that this is wrong: (pfuture-new “git status”) this is right: (pfuture-new “git” “status”)
pfuture-await (process &key (timeout 1) (just-this-one t))Block until PROCESS has produced output and return it.
Will accept the following optional keyword arguments:
TIMEOUT: The timeout in seconds to wait for the process. May be a float to specify fractional number of seconds. In case of a timeout nil will be returned.
JUST-THIS-ONE: When t only read from the process of FUTURE and no other. For details see documentation of
pfuture-await-to-finish (process)Keep reading the output of PROCESS until it is done. Same as
pfuture-await, but will keep reading (and blocking) so long as the process is alive.
If the process never quits this method will block forever. Use with caution!”
pfuture-result (process)Return the output of PROCESS.
Also with callbacks
If your use-case prevents you from keeping the process around for later use and you instead prefer a
simple way to launch a process and run a callback once it’s finished you can use
Given this artificially slow_status.sh bash script
sleep 3 && git status
despite running the script twice the following code will execute within 3 seconds on account of being asynchronous:
(let ((start (float-time)) (future1 (pfuture-new "bash" "slow_status.sh")) (future2 (pfuture-new "bash" "slow_status.sh")) (future3 (pfuture-new "echo" "Foo" "Bar"))) (pfuture-await future1 :timeout 4 :just-this-one nil) (pfuture-await future2 :timeout 4 :just-this-one nil) (message "%s finished after %s seconds" (pfuture-result future3) (round (- (float-time) start))))
The many arguments
pfuture-callback are extensively documented in its docstring. The following
code provides an example of using it to run a callback based on the output of a git process.
(defun success-callback (process status output) (message "Success!") (message "Process: %s" process) (message "Status: %s" status) (message "Output: %s" output)) (defun error-callback (process status output) (message "Error!") (message "Process: %s" process) (message "Status: %s" status) (message "Output: %s" output)) (pfuture-callback ["git" "status" "--porcelain" "--ignored" "."] :directory "~/Documents/git/pfuture" :name "Pfuture Example" :connection-type 'pipe :on-success #'success-callback :on-error #'error-callback :on-status-change (message "Debug status change: %s" status))