Function: vc-exec-after
vc-exec-after is a byte-compiled function defined in
vc-dispatcher.el.gz.
Signature
(vc-exec-after CODE &optional OKSTATUS PROC)
Documentation
Execute CODE when PROC, or the current buffer's process, is done.
CODE should be a function of no arguments.
CODE a bare form to pass to eval is also supported for compatibility.
Optional argument OKSTATUS, if non-nil, is a non-negative integer. Run CODE only if PROC (or, if PROC is nil, the current buffer's process) exits normally (i.e. does not die to a signal) with exit status not exceeding OKSTATUS.
For backwards compatibility, passing PROC (or, if PROC is nil, the current buffer's process) as OKSTATUS means the same as OKSTATUS zero. Passing other process object is invalid.
The optional PROC argument specifies the process Emacs should wait for before executing CODE. It defaults to the current buffer's process. If PROC is nil and the current buffer has no process, just evaluate CODE. Otherwise, add CODE to the process's sentinel.
Source Code
;; Defined in /usr/src/emacs/lisp/vc/vc-dispatcher.el.gz
(defun vc-exec-after (code &optional okstatus proc)
"Execute CODE when PROC, or the current buffer's process, is done.
CODE should be a function of no arguments.
CODE a bare form to pass to `eval' is also supported for compatibility.
Optional argument OKSTATUS, if non-nil, is a non-negative integer.
Run CODE only if PROC (or, if PROC is nil, the current buffer's process)
exits normally (i.e. does not die to a signal) with exit status not
exceeding OKSTATUS.
For backwards compatibility, passing PROC (or, if PROC is nil, the
current buffer's process) as OKSTATUS means the same as OKSTATUS zero.
Passing other process object is invalid.
The optional PROC argument specifies the process Emacs should wait for
before executing CODE. It defaults to the current buffer's process.
If PROC is nil and the current buffer has no process, just evaluate
CODE. Otherwise, add CODE to the process's sentinel."
(unless proc (setq proc (get-buffer-process (current-buffer))))
;; For Emacs 29--30 it was documented that the second argument
;; (then named SUCCESS) could be any process, but the implementation
;; was broken for any process other than the current buffer's process.
(cond ((eq okstatus proc)
(setq okstatus 0))
((and okstatus (not (natnump okstatus)))
(error "Invalid OKSTATUS argument to `vc-exec-after': %S"
okstatus)))
(letrec ((eval-code
(lambda ()
(when (or (null okstatus) (null proc)
(and (eq (process-status proc) 'exit)
(>= okstatus (process-exit-status proc))))
(if (functionp code) (funcall code) (eval code t)))))
(buf (and proc (process-buffer proc)))
(fun
(lambda (proc _msg)
;; In the unlikely event of `set-buffer-process'.
(setq buf (process-buffer proc))
(cond
;; Impatient users sometime kill "slow" buffers; check
;; liveness to avoid "error in process sentinel:
;; Selecting deleted buffer".
((not (buffer-live-p buf))
(remove-function (process-sentinel proc) fun))
((memq (process-status proc) '(exit signal))
(with-current-buffer buf
(setq mode-line-process nil)
(let (vc-sentinel-movepoint
(m (process-mark proc)))
;; Normally, we want async code such as sentinels to
;; not move point.
(save-excursion
(goto-char m)
;; Each sentinel may move point and the next one
;; should be run from that new position.
;; Handling this up here, instead of requiring
;; CODE to handle it, means CODE can be written
;; for both sync and async processes.
(funcall eval-code)
(move-marker m (point)))
;; But sometimes the sentinels really want to move point.
(when vc-sentinel-movepoint
(if-let* ((win (get-buffer-window (current-buffer) 0)))
(with-selected-window win
(goto-char vc-sentinel-movepoint))
(goto-char vc-sentinel-movepoint))))))
((not (eq (process-status proc) 'run))
(remove-function (process-sentinel proc) fun)
(error "Unexpected process state"))))))
(cond
;; If there's no background process, just execute the code.
;; We used to explicitly call delete-process on exited processes,
;; but this led to timing problems causing process output to be
;; lost. Terminated processes get deleted automatically
;; anyway. -- cyd
((or (null proc) (memq (process-status proc) '(exit signal)))
(when proc
;; Nonblocking call in case we are ourselves called from a
;; process sentinel (GNU ELPA's diff-hl does this).
(accept-process-output proc 0))
(funcall eval-code))
((eq (process-status proc) 'run)
(when (buffer-live-p buf)
(with-current-buffer buf
(vc-set-mode-line-busy-indicator)))
(add-function :after (process-sentinel proc) fun))
(t (error "Unexpected process state"))))
nil)