Fix Pcompletion of "tar" when using unrecognized arguments

Previously, arguments to tar like "--warning=no-timestamp" would cause
Pcompletion to hang (bug#58921).

This simplifies the logic flow by moving all the cases for "--"
arguments inside the THEN form of '(if (pcomplete-match "^--" 0)', and
for all "-" arguments inside the ELSE form.

* lisp/pcmpl-gnu.el (pcmpl-gnu--tar-long-options): New variable.
(pcomplete/tar): Properly handle completion of arguments that look
like "--ARG=", even if they're not recognized by this function.
This commit is contained in:
Jim Porter 2023-02-09 23:27:50 -08:00
parent 2e73dec15f
commit 38427494d5

View file

@ -184,6 +184,86 @@ Return the new list."
(when (and (not ,exist) (buffer-live-p ,buf)) (when (and (not ,exist) (buffer-live-p ,buf))
(kill-buffer ,buf)))))) (kill-buffer ,buf))))))
(defvar pcmpl-gnu--tar-long-options
;; FIXME: Extract this list from "tar --help".
'("--absolute-names"
"--after-date="
"--append"
"--atime-preserve"
"--backup"
"--block-number"
"--blocking-factor="
"--catenate"
"--checkpoint"
"--compare"
"--compress"
"--concatenate"
"--confirmation"
"--create"
"--delete"
"--dereference"
"--diff"
"--directory="
"--exclude="
"--exclude-from="
"--extract"
"--file="
"--files-from="
"--force-local"
"--get"
"--group="
"--gzip"
"--help"
"--ignore-failed-read"
"--ignore-zeros"
"--incremental"
"--info-script="
"--interactive"
"--keep-old-files"
"--label="
"--list"
"--listed-incremental"
"--mode="
"--modification-time"
"--multi-volume"
"--new-volume-script="
"--newer="
"--newer-mtime"
"--no-recursion"
"--null"
"--numeric-owner"
"--old-archive"
"--one-file-system"
"--owner="
"--portability"
"--posix"
"--preserve"
"--preserve-order"
"--preserve-permissions"
"--read-full-records"
"--record-size="
"--recursive-unlink"
"--remove-files"
"--rsh-command="
"--same-order"
"--same-owner"
"--same-permissions"
"--sparse"
"--starting-file="
"--suffix="
"--tape-length="
"--to-stdout"
"--totals"
"--uncompress"
"--ungzip"
"--unlink-first"
"--update"
"--use-compress-program="
"--verbose"
"--verify"
"--version"
"--volno-file="))
;;;###autoload ;;;###autoload
(defun pcomplete/tar () (defun pcomplete/tar ()
"Completion for the GNU tar utility." "Completion for the GNU tar utility."
@ -192,148 +272,53 @@ Return the new list."
(while (pcomplete-match "^-" 0) (while (pcomplete-match "^-" 0)
(setq saw-option t) (setq saw-option t)
(if (pcomplete-match "^--" 0) (if (pcomplete-match "^--" 0)
(if (pcomplete-match "^--\\([^= \t\n\f]*\\)\\'" 0) (cond
;; FIXME: Extract this list from "tar --help". ((pcomplete-match "^--\\([^= \t\n\f]*\\)\\'" 0)
(pcomplete-here* (pcomplete-here* pcmpl-gnu--tar-long-options))
'("--absolute-names" ((pcomplete-match "\\`--directory=\\(.*\\)" 0)
"--after-date=" (pcomplete-here* (pcomplete-dirs)
"--append" (pcomplete-match-string 1 0)))
"--atime-preserve" ((pcomplete-match "\\`--exclude-from=\\(.*\\)" 0)
"--backup" (pcomplete-here* (pcomplete-entries)
"--block-number" (pcomplete-match-string 1 0)))
"--blocking-factor=" ((pcomplete-match "\\`--\\(extract\\|list\\)\\'" 0)
"--catenate" (setq complete-within t))
"--checkpoint" ((pcomplete-match "\\`--file=\\(.*\\)" 0)
"--compare" (pcomplete-here* (pcomplete-dirs-or-entries
"--compress" pcmpl-gnu-tarfile-regexp)
"--concatenate" (pcomplete-match-string 1 0)))
"--confirmation" ((pcomplete-match "\\`--files-from=\\(.*\\)" 0)
"--create" (pcomplete-here* (pcomplete-entries)
"--delete" (pcomplete-match-string 1 0)))
"--dereference" ((pcomplete-match "\\`--group=\\(.*\\)" 0)
"--diff" (pcomplete-here* (pcmpl-unix-group-names)
"--directory=" (pcomplete-match-string 1 0)))
"--exclude=" ((pcomplete-match "\\`--info-script=\\(.*\\)" 0)
"--exclude-from=" (pcomplete-here* (pcomplete-entries)
"--extract" (pcomplete-match-string 1 0)))
"--file=" ((pcomplete-match "\\`--new-volume-script=\\(.*\\)" 0)
"--files-from=" (pcomplete-here* (pcomplete-entries)
"--force-local" (pcomplete-match-string 1 0)))
"--get" ((pcomplete-match "\\`--owner=\\(.*\\)" 0)
"--group=" (pcomplete-here* (pcmpl-unix-user-names)
"--gzip" (pcomplete-match-string 1 0)))
"--help" ((pcomplete-match "\\`--rsh-command=\\(.*\\)" 0)
"--ignore-failed-read" (pcomplete-here* (funcall pcomplete-command-completion-function)
"--ignore-zeros" (pcomplete-match-string 1 0)))
"--incremental" ((pcomplete-match "\\`--starting-file=\\(.*\\)" 0)
"--info-script=" (pcomplete-here* (pcomplete-entries)
"--interactive" (pcomplete-match-string 1 0)))
"--keep-old-files" ((pcomplete-match "\\`--use-compress-program=\\(.*\\)" 0)
"--label=" (pcomplete-here* (funcall pcomplete-command-completion-function)
"--list" (pcomplete-match-string 1 0)))
"--listed-incremental" ((pcomplete-match "\\`--volno-file=\\(.*\\)" 0)
"--mode=" (pcomplete-here* (pcomplete-entries)
"--modification-time" (pcomplete-match-string 1 0)))
"--multi-volume" (t
"--new-volume-script=" (pcomplete-here*)))
"--newer=" (pcomplete-opt "01234567ABCFGKLMNOPRSTUVWXZbcdfghiklmoprstuvwxz")
"--newer-mtime" (when (pcomplete-match "\\`-\\'" 0)
"--no-recursion" (pcomplete-here*))))
"--null"
"--numeric-owner"
"--old-archive"
"--one-file-system"
"--owner="
"--portability"
"--posix"
"--preserve"
"--preserve-order"
"--preserve-permissions"
"--read-full-records"
"--record-size="
"--recursive-unlink"
"--remove-files"
"--rsh-command="
"--same-order"
"--same-owner"
"--same-permissions"
"--sparse"
"--starting-file="
"--suffix="
"--tape-length="
"--to-stdout"
"--totals"
"--uncompress"
"--ungzip"
"--unlink-first"
"--update"
"--use-compress-program="
"--verbose"
"--verify"
"--version"
"--volno-file=")))
(pcomplete-opt "01234567ABCFGKLMNOPRSTUVWXZbcdfghiklmoprstuvwxz"))
(cond
((pcomplete-match "\\`-\\'" 0)
(pcomplete-here*))
((pcomplete-match "\\`--after-date=" 0)
(pcomplete-here*))
((pcomplete-match "\\`--backup=" 0)
(pcomplete-here*))
((pcomplete-match "\\`--blocking-factor=" 0)
(pcomplete-here*))
((pcomplete-match "\\`--directory=\\(.*\\)" 0)
(pcomplete-here* (pcomplete-dirs)
(pcomplete-match-string 1 0)))
((pcomplete-match "\\`--exclude-from=\\(.*\\)" 0)
(pcomplete-here* (pcomplete-entries)
(pcomplete-match-string 1 0)))
((pcomplete-match "\\`--exclude=" 0)
(pcomplete-here*))
((pcomplete-match "\\`--\\(extract\\|list\\)\\'" 0)
(setq complete-within t))
((pcomplete-match "\\`--file=\\(.*\\)" 0)
(pcomplete-here* (pcomplete-dirs-or-entries pcmpl-gnu-tarfile-regexp)
(pcomplete-match-string 1 0)))
((pcomplete-match "\\`--files-from=\\(.*\\)" 0)
(pcomplete-here* (pcomplete-entries)
(pcomplete-match-string 1 0)))
((pcomplete-match "\\`--group=\\(.*\\)" 0)
(pcomplete-here* (pcmpl-unix-group-names)
(pcomplete-match-string 1 0)))
((pcomplete-match "\\`--info-script=\\(.*\\)" 0)
(pcomplete-here* (pcomplete-entries)
(pcomplete-match-string 1 0)))
((pcomplete-match "\\`--label=" 0)
(pcomplete-here*))
((pcomplete-match "\\`--mode=" 0)
(pcomplete-here*))
((pcomplete-match "\\`--new-volume-script=\\(.*\\)" 0)
(pcomplete-here* (pcomplete-entries)
(pcomplete-match-string 1 0)))
((pcomplete-match "\\`--newer=" 0)
(pcomplete-here*))
((pcomplete-match "\\`--owner=\\(.*\\)" 0)
(pcomplete-here* (pcmpl-unix-user-names)
(pcomplete-match-string 1 0)))
((pcomplete-match "\\`--record-size=" 0)
(pcomplete-here*))
((pcomplete-match "\\`--rsh-command=\\(.*\\)" 0)
(pcomplete-here* (funcall pcomplete-command-completion-function)
(pcomplete-match-string 1 0)))
((pcomplete-match "\\`--starting-file=\\(.*\\)" 0)
(pcomplete-here* (pcomplete-entries)
(pcomplete-match-string 1 0)))
((pcomplete-match "\\`--suffix=" 0)
(pcomplete-here*))
((pcomplete-match "\\`--tape-length=" 0)
(pcomplete-here*))
((pcomplete-match "\\`--use-compress-program=\\(.*\\)" 0)
(pcomplete-here* (funcall pcomplete-command-completion-function)
(pcomplete-match-string 1 0)))
((pcomplete-match "\\`--volno-file=\\(.*\\)" 0)
(pcomplete-here* (pcomplete-entries)
(pcomplete-match-string 1 0)))))
(unless saw-option (unless saw-option
(pcomplete-here (pcomplete-here
(mapcar #'char-to-string (mapcar #'char-to-string