Skip to content

Commit 12da4f0

Browse files
committed
Better handle slow completion functions.
This change sets a very long timeout for custom completion, as completion functions can take an arbitrarily long time to run. Bash commands that are not custom completions still have the current, short timeout, to better deal with unresponsive bash processes. Additionally, the completion table function now caches any error, to avoid failed calls being retried when next time the function is called.
1 parent 377969f commit 12da4f0

File tree

1 file changed

+26
-4
lines changed

1 file changed

+26
-4
lines changed

bash-completion.el

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,15 @@ ignored."
187187
:type '(float)
188188
:group 'bash-completion)
189189

190+
(defcustom bash-completion-command-timeout 30
191+
"Number of seconds to wait for an answer from programmable
192+
completion functions.
193+
194+
Programmable completion functions might take an arbitrary long
195+
time to run, so this should be long."
196+
:type '(float)
197+
:group 'bash-completion)
198+
190199
(defcustom bash-completion-message-delay 0.4
191200
"Time to wait before displaying a message while waiting for results.
192201
@@ -851,8 +860,13 @@ COMP_CWORD) and calls compgen.
851860
852861
The result is a list of candidates, which might be empty."
853862
(let* ((buffer (bash-completion--get-buffer process))
863+
(cmd-timeout (if (eq 'custom (bash-completion--type comp))
864+
bash-completion-command-timeout
865+
bash-completion-process-timeout))
854866
(completion-status))
855-
(setq completion-status (bash-completion-send (bash-completion-generate-line comp) process))
867+
(setq completion-status (bash-completion-send
868+
(bash-completion-generate-line comp)
869+
process cmd-timeout))
856870
(when (eq 124 completion-status)
857871
;; Special 'retry-completion' exit status, typically returned by
858872
;; functions bound by complete -D. Presumably, the function has
@@ -861,7 +875,9 @@ The result is a list of candidates, which might be empty."
861875
(bash-completion-send "complete -p" process)
862876
(process-put process 'complete-p (bash-completion-build-alist buffer))
863877
(bash-completion--customize comp process 'nodefault)
864-
(setq completion-status (bash-completion-send (bash-completion-generate-line comp) process)))
878+
(setq completion-status (bash-completion-send
879+
(bash-completion-generate-line comp)
880+
process cmd-timeout)))
865881
(when (eq 0 completion-status)
866882
(bash-completion-extract-candidates comp buffer))))
867883

@@ -1541,7 +1557,8 @@ The result is a function that works like one built by
15411557
`completion-table-with-cache' with the difference that the
15421558
completions, built by `bash-completion-comm' are not filtered
15431559
using the current Emacs completion style."
1544-
(let ((last-result)
1560+
(let ((last-result nil)
1561+
(last-error nil)
15451562
(calling-buffer (current-buffer))
15461563
(dir default-directory)
15471564
(use-separate-process bash-completion-use-separate-processes)
@@ -1550,13 +1567,18 @@ using the current Emacs completion style."
15501567
(if (or (eq (car-safe action) 'boundaries)
15511568
(eq action 'metadata))
15521569
nil
1570+
(when last-error (signal (car last-error) (cdr last-error)))
15531571
(let ((result
15541572
(or last-result
15551573
(let ((bash-completion-use-separate-processes use-separate-process)
15561574
(bash-completion-nospace nospace)
15571575
(default-directory dir))
15581576
(with-current-buffer calling-buffer
1559-
(bash-completion-comm comp process))))))
1577+
(condition-case err
1578+
(bash-completion-comm comp process)
1579+
(error
1580+
(setq last-error err)
1581+
(signal (car err) (cdr err)))))))))
15601582
(setq last-result result)
15611583
(let ((filtered-result (if predicate (mapcar predicate result) result))
15621584
(completion-ignore-case (process-get process 'completion-ignore-case)))

0 commit comments

Comments
 (0)