Subject: bug#65356: 30.0.50; [wishlist] Support Tramp method, user name and host name completion in eshell

From: Michael Albinus <[email-masked]>
Date: Sat, 19 Aug 2023 19:48:17 +0200

Jim Porter <[email-masked]> writes:

Hi Jim & Stefan,

>>> Yes. However, there is already another problem in shell-mode. My patch
>>> completes only incomplete Tramp file names, like "/ss". Complete Tramp
>>> file names are handled by pcomplete-dirs already. So we see in a *shell*
>>> buffer, w/o my patch:
>> Good point.
>> Still, we have the problem that `pcomplete/<CMD>` should be used
>> only
>> for external commands (because they are independent from the language
>> used to write the command, a.k.a the shell), but for things like `cd` we
>> should be more precise to distinguish the completion rules for Eshell's
>> `cd` from those of bash's `cd`.
>
> That should be possible by defining 'pcomplete/eshell-mode/CMD', but
> that runs into two issues: 1) it's annoying to manually write all of
> these, and 2) there may be other contexts in Eshell we want to
> tab-complete remote directories that aren't covered by the
> command-specific Pcomplete functions like that.
>
> (#1 should be fixable with a new version of
> 'eshell-eval-using-options', but I haven't looked at that in much
> detail yet.)

I gave it another try. There is a new user option pcomplete-remote-ignore.
When nil (the default), pcomplete expands remote file names, including
method, user name and host name. The corresponding let-bindings in
pcomplete--entries are short.

In shell-completion-vars, I set it buffer-local to t. This prevents
remote file name completion in *shell* buffers, fixing also the bug
mentioned above.

In eshell I haven't set anything, so by default remote file names are
expanded. It should be easy to set pcomplete-remote-ignore, depending
on whether the command is a built-in (keep it nil), or an external
command (set it to t).

The patch is appended. Please note, that this has effect only when Tramp
is loaded, so you might need to test with "emacs -Q -l tramp". People,
who never use Tramp, won't see a difference.

For testing you need a recent checkout of Emacs master, because I have
added another function to tramp.el. This is already pushed to master.

Comments?

Best regards, Michael.

diff --git a/lisp/pcomplete.el b/lisp/pcomplete.el
index c7ec228c1db..e8bede9d605 100644
--- a/lisp/pcomplete.el
+++ b/lisp/pcomplete.el
@@ -138,6 +138,11 @@ pcomplete-dir-ignore
   "A regexp of names to be disregarded during directory completion."
   :type '(choice regexp (const :tag "None" nil)))

+(defcustom pcomplete-remote-ignore nil
+  "Whether to ignore remote file names."
+  :version "30.1"
+  :type 'boolean)
+
 (define-obsolete-variable-alias 'pcomplete-ignore-case 'completion-ignore-case
   "28.1")

@@ -924,7 +929,10 @@ pcomplete--entries
                            (sort comps pcomplete-compare-entry-function)))
                      ,@(cdr (completion-file-name-table s p a)))
         (let ((completion-ignored-extensions nil)
-	      (completion-ignore-case completion-ignore-case))
+	      (completion-ignore-case completion-ignore-case)
+              (tramp-mode (and tramp-mode (not pcomplete-remote-ignore)))
+              (non-essential (not (file-remote-p s)))
+              (minibuffer-completing-file-name  (not (file-remote-p s))))
           (completion-table-with-predicate
            #'comint-completion-file-name-table pred 'strict s p a))))))

diff --git a/lisp/shell.el b/lisp/shell.el
index 7ea9d1c2ead..17ab12dda6d 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -595,6 +595,8 @@ shell-completion-vars
   ;; Don't use pcomplete's defaulting mechanism, rely on
   ;; shell-dynamic-complete-functions instead.
   (setq-local pcomplete-default-completion-function #'ignore)
+  ;; Do not expand remote file names.
+  (setq-local pcomplete-remote-ignore t)
   (setq-local comint-input-autoexpand shell-input-autoexpand)
   ;; Not needed in shell-mode because it's inherited from comint-mode, but
   ;; placed here for read-shell-command.