Skip to content
No description or website provided.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


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 shell-command-to-string 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 (pfuture-result process).

    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 accept-process-output.

  • 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 pfuture-callback.

Practical examples

Future version

Given this artificially 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" ""))
      (future2 (pfuture-new "bash" ""))
      (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))))

Callback version

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
  (message "Debug status change: %s" status))
You can’t perform that action at this time.