GNU bug report logs - #16197
24.3.50; no completion on commands following "sudo" in shell and eshell

Previous Next

Package: emacs;

Reported by: Thierry Volpiatto <thierry.volpiatto <at> gmail.com>

Date: Fri, 20 Dec 2013 08:20:01 UTC

Severity: minor

Tags: fixed, patch

Found in version 24.3.50

Fixed in version 28.1

Done: Lars Ingebrigtsen <larsi <at> gnus.org>

Bug is archived. No further changes may be made.

Full log


View this message in rfc822 format

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Thierry Volpiatto <thierry.volpiatto <at> gmail.com>
Cc: 16197 <at> debbugs.gnu.org, Stefan Monnier <monnier <at> iro.umontreal.ca>
Subject: bug#16197: 24.3.50; no completion on commands following "sudo" in shell and eshell
Date: Fri, 25 Sep 2020 12:44:29 +0200
Thierry Volpiatto <thierry.volpiatto <at> gmail.com> writes:

>> Can you send it as a patch against pcmpl-unix.el to fix pcomplete/xargs
>> (and add pcomplete/sudo at the same time)?
>
> * lisp/pcml-unix.el (pcomplete/sudo): New.
> * lisp/pcomplete.el (pcomplete-command-name): Allow extracting
> command-name in more complex command lines.
> * lisp/shell.el (shell-command-completion-function): Fix it (was not
> working at all).

There was unfortunately no followup to this at the time.  I've now
respun the patch and tried to do some testing, but...  this doesn't seem
to work?

Here's how I tested:

1) Apply the patch
2) Build Emacs
3) emacs -Q
f) M-x shell
IV) sudo apt-g<TAB>

Result: "No match"

I'm not very familiar with the completion framework, and the code has
changed over the years...  Anybody?

diff --git a/lisp/pcmpl-unix.el b/lisp/pcmpl-unix.el
index 74f45b9523..0096020ab4 100644
--- a/lisp/pcmpl-unix.el
+++ b/lisp/pcmpl-unix.el
@@ -82,9 +82,13 @@ pcomplete/rm
 ;;;###autoload
 (defun pcomplete/xargs ()
   "Completion for `xargs'."
-  (pcomplete-here (funcall pcomplete-command-completion-function))
-  (funcall (or (pcomplete-find-completion-function (pcomplete-arg 1))
-	       pcomplete-default-completion-function)))
+  (let ((pcomplete-cmd-name (pcomplete-command-name)))
+    (cond ((string= "xargs" pcomplete-cmd-name)
+           (while (pcomplete-here*
+                   (funcall pcomplete-command-completion-function)
+                   (pcomplete-arg 'last) t)))
+          (t (funcall (or (pcomplete-find-completion-function (pcomplete-arg 1))
+                          pcomplete-default-completion-function))))))
 
 ;;;###autoload
 (defalias 'pcomplete/time 'pcomplete/xargs)
@@ -240,6 +244,22 @@ pcomplete/rsh
   (funcall (or (pcomplete-find-completion-function (pcomplete-arg 1))
                pcomplete-default-completion-function)))
 
+(defun pcomplete/sudo ()
+  (let ((pcomplete-cmd-name (pcomplete-command-name)))
+    (while (and (string= "sudo" pcomplete-cmd-name)
+                (pcomplete-match "^-" 'last))
+      (when (< pcomplete-index pcomplete-last)
+        (pcomplete-next-arg))
+      (pcomplete-opt "AbCDEegHhiKknPpSsUuVv-"))
+    (cond ((string= "sudo" pcomplete-cmd-name)
+           (while (pcomplete-here*
+                   (funcall pcomplete-command-completion-function)
+                   (pcomplete-arg 'last) t)))
+          (t
+           (funcall (or (pcomplete-find-completion-function
+                         pcomplete-cmd-name)
+                        pcomplete-default-completion-function))))))
+
 (provide 'pcmpl-unix)
 
 ;;; pcmpl-unix.el ends here
diff --git a/lisp/pcomplete.el b/lisp/pcomplete.el
index 014f9628b9..9ac4652126 100644
--- a/lisp/pcomplete.el
+++ b/lisp/pcomplete.el
@@ -119,6 +119,7 @@
 ;;; Code:
 
 (require 'comint)
+(eval-when-compile (require 'cl-lib))
 
 (defgroup pcomplete nil
   "Programmable completion."
@@ -674,9 +675,42 @@ pcomplete-next-arg
 	(message "No completions")
 	(throw 'pcompleted nil))))
 
+(defvar pcomplete-special-commands '("sudo" "xargs"))
 (defun pcomplete-command-name ()
   "Return the command name of the first argument."
-  (file-name-nondirectory (pcomplete-arg 'first)))
+  (let ((coms (cl-loop with lst = (reverse (pcomplete-parse-arguments))
+                       for str in (or (member "|" lst)
+                                      (member "||" lst)
+                                      (member "&" lst)
+                                      (member ";" lst)
+                                      lst)
+                       for exec = (or (executable-find str)
+                                      ;; `executable-find' or 'which'
+                                      ;; doesn't return these paths.
+                                      (car (member str '("cd" "pushd" "popd"))))
+                       when exec collect exec)))
+    (file-name-nondirectory
+     ;; we may have commands embeded in executables that looks
+     ;; like executables (e.g apt-get install).
+     ;; Assume that all executables are using only one command
+     ;; like this.
+     ;; e.g - if we have (install apt-get sudo)
+     ;;       what we want is apt-get.
+     ;;     - if we have (apt-get sudo)
+     ;;       what we want is sudo,
+     ;;       then pcomplete/sudo will check if
+     ;;       a pcomplete handler exists for apt-get.
+     (cond (;; e.g (install apt-get sudo)
+            (> (length coms) 2) (cadr coms))
+           (;; e.g (apt-get sudo)
+            (and (= (length coms) 2)
+                 (member (file-name-nondirectory (cadr coms))
+                         pcomplete-special-commands))
+            (car coms))
+           (;; e.g (sudo)
+            (= (length coms) 1) (car coms))
+           (t ;; e.g (install apt-get)
+            (cadr coms))))))
 
 (defun pcomplete-match (regexp &optional index offset start)
   "Like `string-match', but on the current completion argument."
diff --git a/lisp/shell.el b/lisp/shell.el
index 9667dab2af..48eb69f0b6 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -460,9 +460,8 @@ shell-command-completion-function
 This is the value of `pcomplete-command-completion-function' for
 Shell buffers.  It implements `shell-completion-execonly' for
 `pcomplete' completion."
-  (pcomplete-here (pcomplete-entries nil
-				     (if shell-completion-execonly
-					 'file-executable-p))))
+  (let ((data (shell--command-completion-data)))
+    (and data (pcomplete-here (all-completions "" (nth 2 data))))))
 
 (defun shell-completion-vars ()
   "Setup completion vars for `shell-mode' and `read-shell-command'."


-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




This bug report was last modified 4 years and 238 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.