@@ -329,8 +329,8 @@ Created by `bash-completion-send' and printed by
329329 stub ; parsed version of the stub
330330 open-quote ; quote open at stub end: nil, ?' or ?\""
331331 compgen-args ; compgen arguments for this command (list of strings)
332+ compopt-args ; additional compgen arguments forced with compopt
332333 wordbreaks ; value of COMP_WORDBREAKS active for this completion
333- compopt ; options forced with compopt nil or `(nospace . ,bool)
334334 )
335335
336336(defun bash-completion--type (comp )
@@ -351,14 +351,15 @@ customized, usually by `bash-completion--customize'."
351351The option can be:
352352 - set globally, by setting `bash-completion-nospace' to t
353353 - set for a customized completion, in bash, with
354- \" -o nospace\" ."
355- (let ((cell))
356- (cond
357- (bash-completion-nospace t ) ; set globally
358- ((setq cell (assq 'nospace (bash-completion--compopt comp)))
359- (cdr cell))
360- (t (bash-completion--has-compgen-option
361- (bash-completion--compgen-args comp) " nospace" )))))
354+ \" -o nospace\" .
355+ - set during completion, using compopt"
356+ (or
357+ bash-completion-nospace ; set globally
358+ (eq 'set
359+ (or (bash-completion--get-compgen-option
360+ (bash-completion--compopt-args comp) " nospace" )
361+ (bash-completion--get-compgen-option
362+ (bash-completion--compgen-args comp) " nospace" )))))
362363
363364(defun bash-completion--command (comp )
364365 " Return the current command for the completion, if there is one.
@@ -424,13 +425,9 @@ returned."
424425 (concat " function compopt {"
425426 " command compopt \" $@\" 2>/dev/null;"
426427 " local ret=$?; "
427- " if [[ $ret == 1 && \" $*\" = *\" -o nospace\" * ]]; then"
428- " _EMACS_COMPOPT='-o nospace';"
429- " return 0;"
430- " fi;"
431- " if [[ $ret == 1 && \" $*\" = *\" +o nospace\" * ]]; then"
432- " _EMACS_COMPOPT='+o nospace';"
433- " return 0;"
428+ " if [[ $ret == 1 ]]; then"
429+ " _EMACS_COMPOPT=\" $EMACS_COMPOPT $*\" ;"
430+ " return 0;"
434431 " fi;"
435432 " return $ret; "
436433 " }" )
@@ -934,8 +931,27 @@ The result is a list of candidates, which might be empty."
934931 (setq completion-status (bash-completion-send
935932 (bash-completion-generate-line comp)
936933 process cmd-timeout comp)))
937- (when (eq 0 completion-status)
938- (bash-completion-extract-candidates comp buffer))))
934+ (let ((candidates (when (eq 0 completion-status)
935+ (bash-completion-extract-candidates comp buffer)))
936+ (compopt (bash-completion--compopt-args comp)))
937+
938+ ; ; Possibly run compgen as instructed by a call to compopt
939+ ; ; inside of a function.
940+ (when (or (member " plusdir" compopt)
941+ (and (null candidates)
942+ (or (member " default" compopt)
943+ (member " bashdefault" compopt)
944+ (member " dirnames" compopt)
945+ (member " filenames" compopt))))
946+ (setf (bash-completion--compgen-args comp)
947+ (bash-completion--compopt-args comp))
948+ (when (eq 0 (bash-completion-send
949+ (bash-completion-generate-line comp)
950+ process cmd-timeout comp))
951+ (setq candidates (append candidates
952+ (bash-completion-extract-candidates
953+ comp buffer)))))
954+ candidates)))
939955
940956(defun bash-completion-extract-candidates (comp buffer )
941957 " Extract the completion candidates for COMP form BUFFER.
@@ -950,16 +966,11 @@ for directory name detection to work.
950966Post-processing includes escaping special characters, adding a /
951967to directory names, replacing STUB with UNPARSED-STUB in the
952968result. See `bash-completion-fix' for more details."
953- (let ((output) (candidates))
954- (with-current-buffer buffer
955- (let ((compopt (bash-completion--parse-side-channel-data " compopt" )))
956- (cond
957- ((string= " -o nospace" compopt)
958- (setf (bash-completion--compopt comp) '((nospace . t ))))
959- ((string= " +o nospace" compopt)
960- (setf (bash-completion--compopt comp) '((nospace . nil ))))))
961- (setq output (buffer-string )))
962- (setq candidates (delete-dups (split-string output " \n " t )))
969+ (with-current-buffer buffer
970+ (setf (bash-completion--compopt-args comp)
971+ (bash-completion--parse-side-channel-data " compopt" 'tokenize )))
972+ (let* ((output (with-current-buffer buffer (buffer-string )))
973+ (candidates (delete-dups (split-string output " \n " t ))))
963974 (if (eq 1 (length candidates))
964975 (list (bash-completion-fix (car candidates) comp t ))
965976 ; ; multiple candidates
@@ -1689,14 +1700,23 @@ characters. These are output as-is."
16891700 (file-remote-p expanded 'localname )
16901701 expanded)))
16911702
1692- (defun bash-completion--has-compgen-option (compgen-args option-name )
1693- " Check whether COMPGEN-ARGS contains -o OPTION-NAME."
1694- (let ((rest compgen-args) (found))
1695- (while (and (not found)
1696- (setq rest (cdr (member " -o" rest))))
1697- (when (string= option-name (car rest))
1698- (setq found t ))
1703+ (defun bash-completion--get-compgen-option (compgen-args option-name )
1704+ " Check whether COMPGEN-ARGS contains -o or +o OPTION-NAME.
1705+
1706+ Returns nil if the option was unspecified, \\= 'set if it was
1707+ specified with -o and \\= 'unset if it was specified with +o."
1708+ (let ((rest compgen-args)
1709+ found)
1710+ (while rest
1711+ (cond
1712+ ((and (string= " -o" (car rest))
1713+ (equal option-name (car (cdr rest))))
1714+ (setq found 'set ))
1715+ ((and (string= " +o" (car rest))
1716+ (equal option-name (car (cdr rest))))
1717+ (setq found 'unset )))
16991718 (setq rest (cdr rest)))
1719+
17001720 found))
17011721
17021722(defun bash-completion--side-channel-data (name value )
@@ -1706,7 +1726,7 @@ Parse that data from the buffer output using
17061726`bash-completion--side-channel-data' ."
17071727 (format " echo \"\e\e %s =%s \e\e\" ; " name value))
17081728
1709- (defun bash-completion--parse-side-channel-data (name )
1729+ (defun bash-completion--parse-side-channel-data (name &optional tokenize )
17101730 " Parse side-channel data NAME from the current buffer.
17111731
17121732This parses data added by `bash-completion--side-channel-data'
@@ -1720,8 +1740,16 @@ Return the parsed value, as a string or nil."
17201740 (format " \e\e %s =\\ ([^\e ]*\\ )\e\e "
17211741 (regexp-quote name))
17221742 nil 'noerror )
1723- (prog1 (match-string 1 )
1724- (delete-region (match-beginning 0 ) (1+ (match-end 0 ))))))))
1743+ (let ((result (match-string 1 ))
1744+ (start (match-beginning 0 ))
1745+ (end (1+ (match-end 0 ))))
1746+ (when tokenize
1747+ (setq result
1748+ (bash-completion-strings-from-tokens
1749+ (bash-completion-tokenize (match-beginning 1 ) (match-end 1 )))))
1750+ (delete-region start end)
1751+
1752+ result)))))
17251753
17261754(defun bash-completion--completion-table-with-cache (comp process )
17271755 " Build a dynamic completion table for COMP using PROCESS.
0 commit comments