bug#16197: 24.3.50; no completion on commands following "sudo" in shell and eshell

classic Classic list List threaded Threaded
17 messages Options
Reply | Threaded
Open this post in threaded view
|

bug#16197: 24.3.50; no completion on commands following "sudo" in shell and eshell

Thierry Volpiatto-2

Hi all,
shell and eshell are not completing commands after "sudo".

For eshell what is needed is a `pcomplete/sudo' function:

--8<---------------cut here---------------start------------->8---
(defun pcomplete/sudo ()
  (let ((prec (pcomplete-arg 'last -1)))
    (cond ((string= "sudo" prec)
           (while (pcomplete-here*
                   (funcall pcomplete-command-completion-function)
                   (pcomplete-arg 'last) t))))))
--8<---------------cut here---------------end--------------->8---

For shell modify `shell-command-completion' something like this:

--8<---------------cut here---------------start------------->8---
(defun shell-command-completion ()
  "Return the completion data for the command at point, if any."
  (let ((filename (comint-match-partial-filename))
        start)
    (if (and filename
             (save-match-data (not (string-match "[~/]" filename)))
             (eq (setq start (match-beginning 0))
                 (save-excursion (shell-backward-command 1)
                                 (if (looking-at "sudo")
                                     start (point)))))
        (shell--command-completion-data))))
--8<---------------cut here---------------end--------------->8---


       


In GNU Emacs 24.3.50.2 (x86_64-unknown-linux-gnu, X toolkit)
 of 2013-12-19 on dell-14z
Windowing system distributor `The X.Org Foundation', version 11.0.11103000
System Description: Ubuntu 12.04.3 LTS

Configured using:
 `configure --with-x-toolkit=lucid --without-toolkit-scroll-bars
 --without-gconf --without-gsettings'

Important settings:
  value of $LC_MONETARY: fr_FR.UTF-8
  value of $LC_NUMERIC: fr_FR.UTF-8
  value of $LC_TIME: fr_FR.UTF-8
  value of $LANG: fr_FR.UTF-8
  locale-coding-system: utf-8-unix

Major mode: Lisp Interaction

Minor modes in effect:
  diff-auto-refine-mode: t
  TeX-PDF-mode: t
  psession-mode: t
  global-semanticdb-minor-mode: t
  global-semantic-idle-scheduler-mode: t
  semantic-mode: t
  golden-ratio-mode: t
  winner-mode: t
  global-undo-tree-mode: t
  undo-tree-mode: t
  auto-image-file-mode: t
  eldoc-in-minibuffer-mode: t
  show-paren-mode: t
  display-time-mode: t
  recentf-mode: t
  savehist-mode: t
  eldoc-mode: t
  minibuffer-depth-indicate-mode: t
  helm-mode: t
  helm-descbinds-mode: t
  shell-dirtrack-mode: t
  helm-adaptative-mode: t
  helm-match-plugin-mode: t
  helm-occur-match-plugin-mode: t
  tooltip-mode: t
  electric-indent-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  column-number-mode: t
  line-number-mode: t
  transient-mark-mode: t

Recent input:
<right> <right> <backspace> <backspace> <backspace>
<backspace> <backspace> <backspace> <backspace> <backspace>
<backspace> <backspace> <backspace> <backspace> <backspace>
<backspace> <backspace> <backspace> <backspace> <backspace>
s t a r t C-M-x <f11> s h s u d o SPC f d <tab> <down>
<return> C-x C-b <return> <up> <up> <up> <up> <up>
<up> <up> <up> <up> <up> <up> <up> <down> <down> <down>
<down> <down> <down> <down> <up> <up> <up> <up> <left>
<left> <left> <left> <left> <left> <left> <left> <left>
<left> <left> <left> <left> <left> <left> <left> <left>
<left> <left> <left> <left> <left> <left> <left> <left>
<left> <left> <left> <left> <left> <left> <left> <left>
<left> C-M-SPC M-w <f11> s h <backspace> <backspace>
<backspace> <backspace> <backspace> <backspace> <backspace>
<backspace> <backspace> <backspace> c a t SPC . e m
a c s <tab> <return> SPC | SPC s u d o SPC g r <tab>
e p <down> <return> <backspace> <backspace> <backspace>
<backspace> <backspace> <backspace> <backspace> <backspace>
<backspace> <backspace> <backspace> <backspace> <backspace>
<backspace> <backspace> <backspace> <backspace> <backspace>
<backspace> <backspace> <backspace> <backspace> <backspace>
<backspace> <backspace> <backspace> <backspace> <backspace>
<backspace> <backspace> <backspace> <backspace> C-x
C-b <return> <down> <down> <down> <down> <down> <down>
<down> <down> <down> <right> <right> <right> <right>
<right> <right> <right> <right> <right> <right> <right>
<right> <right> <right> <right> <right> <right> <right>
<right> <right> <right> <right> <right> <right> <right>
<right> <right> <right> <right> <right> <right> <right>
<right> <right> <right> <right> <right> <right> <right>
<right> <right> <right> <f11> s h s u d o SPC a p t
- g <tab> SPC | SPC g r <tab> <down> <down> <down>
<down> e <down> <down> <down> <down> <down> <down>
<down> <down> <down> <down> <down> <down> <down> <down>
<down> <down> <return> <backspace> <backspace> <backspace>
<backspace> <backspace> <backspace> <backspace> <backspace>
<backspace> <backspace> <backspace> <backspace> <backspace>
<backspace> <backspace> <backspace> <backspace> <backspace>
<backspace> C-x C-b <return> <up> M-x r e p o r t
<return>

Recent messages:
Result: 34 (#o42, #x22, ?\")

Result: 34 (#o42, #x22, ?\")

Result: nil
Back to top level.
Auto-saving...
shell-command-completion [2 times]
Mark set
Auto-saving...done

Load-path shadows:
/usr/local/share/emacs/24.3.50/lisp/gnus/.dir-locals hides ~/elisp/magit/.dir-locals
~/elisp/auctex/lpath hides ~/elisp/emacs-wget/lpath
/usr/local/share/emacs/24.3.50/lisp/emacs-lisp/tq hides ~/elisp/emms/lisp/tq

Features:
(shadow epa-mail emacsbug helm-command edebug debug helm-dabbrev
cl-indent help-mode helm-eshell helm-ring helm-sys magit-cherry
magit-bisect magit-log-edit log-edit add-log magit-key-mode magit view
iswitchb ido ediff-merg ediff-wind ediff-diff ediff-mult ediff-help
ediff-init ediff-util ediff diff-mode magit-compat smiley gnus-cite
flow-fill mm-archive mail-extr gnus-async gnus-bcklg gnus-ml nndraft
nnmh utf-7 nnimap utf7 nnml nnfolder parse-time netrc network-stream
starttls tls gnus-agent gnus-srvr gnus-score score-mode nnvirtual
gnus-msg gnus-art mm-uu mml2015 mm-view mml-smime smime dig nntp
gnus-cache gnus-dired nnir gnus-sum gnus-group gnus-undo nnmail
mail-source nnoo gnus-start gnus-spec gnus-int gnus-range gnus-win
semantic/bovine/c hideif semantic/bovine/c-by semantic/lex-spp
semantic/bovine/gcc semantic/bovine semantic/analyze/refs
semantic/analyze semantic/sort semantic/scope semantic/analyze/fcn
cc-langs cc-mode cc-fonts cc-guess cc-menus cc-cmds cc-styles cc-align
cc-engine cc-vars cc-defs preview prv-emacs tex-buf reftex-dcr
reftex-auc reftex imenu reftex-vars font-latex latex tex-style tex dbus
crm latexenc vc-rcs sh-script smie executable vc-hg semantic/tag-file
semantic/db-file data-debug cedet-files semantic/wisent/python
semantic/decorate/include semantic/db-find semantic/db-ref
semantic/decorate/mode semantic/decorate pulse semantic/dep
semantic/wisent/python-wy semantic/wisent semantic/wisent/wisent
markdown-mode vc-git naquadah-theme em-unix em-script em-prompt em-ls
em-hist em-pred em-glob em-dirs em-cmpl em-basic em-banner em-alias
align-let git-gutter server persistent-sessions semantic/db-mode
semantic/db eieio-base semantic/idle semantic/format ezimage
semantic/tag-ls semantic/find semantic/ctxt semantic/util-modes
semantic/util semantic semantic/tag semantic/lex semantic/fw mode-local
cedet package golden-ratio winner undo-tree diff image-file newsticker
newst-treeview newst-plainview newst-reader newst-ticker newst-backend
shr xdvi-search preview-latex tex-site auto-loads pcomplete-extension
em-term term disp-table ehelp helm-ipython helm-elisp helm-eval python
rx eldoc-eval warnings whitespace paren time avoid recentf tree-widget
savehist smtpmail-async smtpmail sendmail helm-async iterator
simple-call-tree iedit-rect rect iedit iedit-lib smallurl mm-url gnus
gnus-ems nnheader wid-edit rectangle-utils ledger-config ledger esh-var
esh-io esh-cmd esh-opt esh-ext esh-proc eldoc esh-groups eshell
esh-module esh-mode esh-arg esh-util tv-utils async pcvs vc-cvs
pcvs-parse pcvs-info pcvs-defs pcvs-util ewoc mb-depth cl-info
slime-autoloads esh-toggle flymake no-word htmlize dired-extension
emms-mpd-config emms-playlist-limit emms-volume emms-volume-amixer
emms-i18n emms-history emms-score emms-stream-info
emms-metaplaylist-mode emms-bookmarks emms-cue emms-mode-line-icon
emms-browser sort emms-playlist-sort emms-last-played emms-player-xine
emms-player-mpd tq emms-playing-time emms-lyrics emms-url hl-line
emms-tag-editor emms-mark emms-mode-line emms-cache emms-info-ogginfo
emms-info-mp3info emms-playlist-mode emms-player-vlc emms-player-mplayer
emms-info emms-streams later-do emms-source-playlist emms-source-file
emms-player-simple emms-setup emms emms-compat org-config-thierry ob-sh
cal-china lunar solar cal-dst cal-bahai cal-islam cal-hebrew holidays
hol-loaddefs appt diary-lib diary-loaddefs org-element org-rmail org-mhe
org-irc org-info org-gnus org-docview doc-view jka-compr image-mode
org-bibtex bibtex org-bbdb org-w3m org-agenda org-annotation-helper
addressbook-bookmark message rfc822 mml mml-sec mm-decode mm-bodies
mm-encode mail-parse rfc2231 rfc2047 rfc2045 ietf-drums mailabbrev
mail-utils gmm-utils mailheader firefox-protocol
bookmark-firefox-handler bookmark-extensions init-helm-thierry helm-mode
helm-dictionary helm-ls-git helm-descbinds helm-ls-hg helm-files
image-dired tramp tramp-compat tramp-loaddefs trampver shell dired-x
dired-aux ffap thingatpt helm-buffers helm-elscreen helm-tags
helm-bookmark helm-adaptative helm-info helm-net browse-url xml url
url-proxy url-privacy url-expand url-methods url-history url-cookie
url-domsuf url-util url-parse url-vars mailcap helm-plugin bookmark pp
helm-help helm-match-plugin helm-grep wgrep-helm wgrep helm-regexp grep
helm-external helm-utils dired compile helm-locate helm vc vc-dispatcher
helm-config helm-aliases epa-file epa derived epg epg-config auth-source
eieio eieio-core gnus-util mm-util mail-prsvr password-cache info
cl-macs gv edmacro kmacro org-crypt org byte-opt bytecomp byte-compile
cconv advice help-fns org-macro org-footnote org-pcomplete pcomplete
org-list org-faces org-entities time-date noutline outline easy-mmode
org-version ob-emacs-lisp ob ob-tangle org-src ob-ref ob-lob ob-table
ob-keys ob-exp ob-comint comint ansi-color ring ob-core ob-eval
org-compat org-macs org-loaddefs format-spec find-func cal-menu easymenu
calendar cal-loaddefs net-utils cl cl-loaddefs cl-lib tooltip electric
uniquify ediff-hook vc-hooks lisp-float-type mwheel x-win x-dnd tool-bar
dnd fontset image regexp-opt fringe tabulated-list newcomment lisp-mode
prog-mode register page menu-bar rfn-eshadow timer select scroll-bar
mouse jit-lock font-lock syntax facemenu font-core frame cham georgian
utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao korean
japanese hebrew greek romanian slovak czech european ethiopic indian
cyrillic chinese case-table epa-hook jka-cmpr-hook help simple abbrev
minibuffer nadvice loaddefs button faces cus-face macroexp files
text-properties overlay sha1 md5 base64 format env code-pages mule
custom widget hashtable-print-readable backquote make-network-process
dbusbind gfilenotify dynamic-setting font-render-setting x-toolkit x
multi-tty emacs)

--
Thierry
Get my Gnupg key:
gpg --keyserver pgp.mit.edu --recv-keys 59F29997



Reply | Threaded
Open this post in threaded view
|

bug#16197: 24.3.50; no completion on commands following "sudo" in shell and eshell

Thierry Volpiatto-2
Thierry Volpiatto <[hidden email]> writes:

> Hi all,
> shell and eshell are not completing commands after "sudo".
>
> For eshell what is needed is a `pcomplete/sudo' function:
>
> (defun pcomplete/sudo ()
>   (let ((prec (pcomplete-arg 'last -1)))
>     (cond ((string= "sudo" prec)
>            (while (pcomplete-here*
>                    (funcall pcomplete-command-completion-function)
>                    (pcomplete-arg 'last) t))))))
>
> For shell modify `shell-command-completion' something like this:
>
> (defun shell-command-completion ()
>   "Return the completion data for the command at point, if any."
>   (let ((filename (comint-match-partial-filename))
>         start)
>     (if (and filename
>     (save-match-data (not (string-match "[~/]" filename)))
>     (eq (setq start (match-beginning 0))
> (save-excursion (shell-backward-command 1)
>                                  (if (looking-at "sudo")
>                                      start (point)))))
> (shell--command-completion-data))))
>

However this is not enough if one wants completion on arguments entered
after the command that is after "sudo".
For this the pcomplete/sudo function should looks like this:

--8<---------------cut here---------------start------------->8---
(defun pcomplete/sudo ()
  (let ((prec (pcomplete-arg 'last -1)))
    (cond ((string= "sudo" prec)
           (while (pcomplete-here*
                   (funcall pcomplete-command-completion-function)
                   (pcomplete-arg 'last) t)))
          (t
           (funcall (or (pcomplete-find-completion-function
                         (pcomplete-command-name))
                        pcomplete-default-completion-function))))))
--8<---------------cut here---------------end--------------->8---

However it still not working with this definition because
`pcomplete-command-name' is bad defined, thus it is crashing emacs
maybe because it sometimes try to do (file-name-nondirectory nil).
(Haven't debugged this yet).

So the function should be redefined something like this:

--8<---------------cut here---------------start------------->8---
(defun pcomplete-command-name ()
  "Return the command name of the first argument."
  (let ((com (pcomplete-arg 'first))
        (com1 (pcomplete-arg 'first 1))
        (com2 (pcomplete-arg 'last -1))
        (com3 (pcomplete-arg 'last)))
    (cond ((and (stringp com) (stringp com1)
                (not (string= com1 ""))
                (string= com "sudo"))
           (file-name-nondirectory com1))
          ((and (stringp com2) (string= com2 "sudo")
                (not (string= com3 "")))
           (file-name-nondirectory com3))
          (t
           (file-name-nondirectory com)))))
--8<---------------cut here---------------end--------------->8---

With this I have completion on arguments of commands entered after
"sudo" (only in eshell though, not shell for the moment) and emacs is
not crashing when hitting TAB.

--
Thierry
Get my Gnupg key:
gpg --keyserver pgp.mit.edu --recv-keys 59F29997




Reply | Threaded
Open this post in threaded view
|

bug#16197: 24.3.50; no completion on commands following "sudo" in shell and eshell

Thierry Volpiatto-2
In reply to this post by Thierry Volpiatto-2
Thierry Volpiatto <[hidden email]> writes:

> With this I have completion on arguments of commands entered after
> "sudo" (only in eshell though, not shell for the moment) and emacs is
> not crashing when hitting TAB.

Now I have the completion in shell also, for this
`shell-command-completion' have to be redefined.

--8<---------------cut here---------------start------------->8---
(defun shell-command-completion ()
  "Return the completion data for the command at point, if any."
  (let ((filename (comint-match-partial-filename))
        (args (split-string
               (buffer-substring-no-properties
                (point) (save-excursion (shell-backward-command 1) (point))))))
    (if (and filename
             (save-match-data (not (string-match "[~/]" filename)))
             (and (string= (car args) "sudo")
                  (string= filename (cadr args))))
        (shell--command-completion-data))))
--8<---------------cut here---------------end--------------->8---

HTH, though the crash happening above should not happen.

--
Thierry
Get my Gnupg key:
gpg --keyserver pgp.mit.edu --recv-keys 59F29997




Reply | Threaded
Open this post in threaded view
|

bug#16197: 24.3.50; no completion on commands following "sudo" in shell and eshell

Thierry Volpiatto-2
In reply to this post by Thierry Volpiatto-2
Thierry Volpiatto <[hidden email]> writes:

> Thierry Volpiatto <[hidden email]> writes:
>
>> With this I have completion on arguments of commands entered after
>> "sudo" (only in eshell though, not shell for the moment) and emacs is
>> not crashing when hitting TAB.
>
> Now I have the completion in shell also, for this
> `shell-command-completion' have to be redefined.
>
> (defun shell-command-completion ()
>   "Return the completion data for the command at point, if any."
>   (let ((filename (comint-match-partial-filename))
>         (args (split-string
>                (buffer-substring-no-properties
>                 (point) (save-excursion (shell-backward-command 1) (point))))))
>     (if (and filename
>              (save-match-data (not (string-match "[~/]" filename)))
>              (and (string= (car args) "sudo")
>                   (string= filename (cadr args))))
>         (shell--command-completion-data))))
>
> HTH, though the crash happening above should not happen.

So now my completion commands are working both with sudo and without,
the needed modifications are here if somebody is interested to fix this bug:

https://github.com/thierryvolpiatto/emacs-tv-config/blob/master/pcomplete-extension.el

Note that all pcomplete/* commands provided in emacs are not working
with "sudo".

--
Thierry
Get my Gnupg key:
gpg --keyserver pgp.mit.edu --recv-keys 59F29997




Reply | Threaded
Open this post in threaded view
|

bug#16197: 24.3.50; no completion on commands following "sudo" in shell and eshell

Thierry Volpiatto-2
In reply to this post by Thierry Volpiatto-2
Thierry Volpiatto <[hidden email]> writes:

> So now my completion commands are working both with sudo and without,
> the needed modifications are here if somebody is interested to fix this bug:
>
> https://github.com/thierryvolpiatto/emacs-tv-config/blob/master/pcomplete-extension.el
>
> Note that all pcomplete/* commands provided in emacs are not working
> with "sudo".

They are now working (pcomplete/tar etc...) with the last version of
pcomplete-extension.el, but entering multiples args (with and without
sudo and from emacs- Q) is not working at all (on second arg it try to
complete filenames) e.g

(cursor is "!")
emacs -Q
M-x shell
tar -! TAB => ok I have completion on options.
tar -z -! TAB => I have completion on filenames.

Maybe because you are using pcomplete-match with an hard coded value of
0 for index.(Not tested)

Completions provided in pcomplete-extension.el are allowing doing this
when needed.

--
Thierry
Get my Gnupg key:
gpg --keyserver pgp.mit.edu --recv-keys 59F29997




Reply | Threaded
Open this post in threaded view
|

bug#16197: 24.3.50; no completion on commands following "sudo" in shell and eshell

Stefan Monnier
> Maybe because you are using pcomplete-match with an hard coded value of
> 0 for index.(Not tested)

Not sure who "you" is.  I'm afraid your description of the problem,
solutions, and problems of those solutions is a bit too cryptic for me.

Here's my starting point:
- I understand that currently pcomplete does not provide completion for
  "sudo" and it would be nice to add it.
- "sudo" is not particularly special, so whatever solution is used for
  it should also work for many other commands.
- There is already pcomplete/xargs and pcomplete/rsh.

Can pcomplete/sudo use the same approach as pcomplete/xargs and pcomplete/rsh?
If not, why not?

If yes but there are still problems, do those problems also affect
pcomplete/xargs and pcomplete/rsh?
If not, why not?

If yes, then let's first focus on fixing pcomplete/xargs.


        Stefan



Reply | Threaded
Open this post in threaded view
|

bug#16197: 24.3.50; no completion on commands following "sudo" in shell and eshell

Thierry Volpiatto-2
Stefan Monnier <[hidden email]> writes:

>> Maybe because you are using pcomplete-match with an hard coded value of
>> 0 for index.(Not tested)
>
> Not sure who "you" is.

Whoever wrote pcomplete/tar.

> I'm afraid your description of the problem, solutions, and problems of
> those solutions is a bit too cryptic for me.
>
> Here's my starting point:
> - I understand that currently pcomplete does not provide completion for
>   "sudo" and it would be nice to add it.
> - "sudo" is not particularly special, so whatever solution is used for
>   it should also work for many other commands.
> - There is already pcomplete/xargs and pcomplete/rsh.

Don't know what */rsh does, but */xargs is actually not working.
Same for tar as described in previous posts.

> Can pcomplete/sudo use the same approach as pcomplete/xargs and pcomplete/rsh?
> If not, why not?

Well I didn't read */xargs, but here are the problems:

- `pcomplete-command-name' actually is always returning the first arg of
  command line e.g for "sudo apt-get" it is returning "sudo".

- `shell-command-completion' is trying to complete after what
  `shell-backward-command' returns, which is actually the first command
  near prompt or "[&;|]+ ", so when you try to complete after sudo or
  xargs, you call the completion against "sudo" or "xargs" which returns
  nothing of course.

Actually the fix made to these two functions is affecting only sudo, but
I can easily fix it to handle also 'xargs'.

> If yes but there are still problems, do those problems also affect
> pcomplete/xargs and pcomplete/rsh?
> If not, why not?
>
> If yes, then let's first focus on fixing pcomplete/xargs.

Don't think so, I think the problem should be fixed at another level as
descripted above.

You can look at the code here:

https://github.com/thierryvolpiatto/emacs-tv-config/blob/master/pcomplete-extension.el

--
Thierry
Get my Gnupg key:
gpg --keyserver pgp.mit.edu --recv-keys 59F29997



Reply | Threaded
Open this post in threaded view
|

bug#16197: 24.3.50; no completion on commands following "sudo" in shell and eshell

Thierry Volpiatto-2
In reply to this post by Thierry Volpiatto-2
Thierry Volpiatto <[hidden email]> writes:

> You can look at the code here:
>
> https://github.com/thierryvolpiatto/emacs-tv-config/blob/master/pcomplete-extension.el

I have fixed code for xargs.
I also have a look at `pcomplete/xargs':
As explained previously it it just calling `shell-command-completion',
which is looking at the first arg returned by `shell-backward-command'.
At best it would work with a command line starting with 'xargs' which is
not really useful, but it doesn't anyway, try it in emacs -Q.

I also find pcomplete/ssh:
It complete args but only the first not the second. i.e ssh -f -! =>no
completions.

Probably others have this problem.

--
Thierry
Get my Gnupg key:
gpg --keyserver pgp.mit.edu --recv-keys 59F29997




Reply | Threaded
Open this post in threaded view
|

bug#16197: 24.3.50; no completion on commands following "sudo" in shell and eshell

Stefan Monnier
In reply to this post by Thierry Volpiatto-2
> Don't know what */rsh does, but */xargs is actually not working.

Aha!

> Well I didn't read */xargs, but here are the problems:

> - `pcomplete-command-name' actually is always returning the first arg of
>   command line e.g for "sudo apt-get" it is returning "sudo".

> - `shell-command-completion' is trying to complete after what
>   `shell-backward-command' returns, which is actually the first command
>   near prompt or "[&;|]+ ", so when you try to complete after sudo or
>   xargs, you call the completion against "sudo" or "xargs" which returns
>   nothing of course.

Can you describe those problems in terms of user-visible behavior
(i.e. a recipe) so I can better understand what the code does (and
should do instead)?

> Actually the fix made to these two functions is affecting only sudo, but
> I can easily fix it to handle also 'xargs'.

That would be nice.

> Don't think so, I think the problem should be fixed at another level as
> descripted above.

I missed the description, I'm afraid.

> https://github.com/thierryvolpiatto/emacs-tv-config/blob/master/pcomplete-extension.el

Not sure what I should look at there.

Can you send it as a patch against pcmpl-unix.el to fix pcomplete/xargs
(and add pcomplete/sudo at the same time)?


        Stefan



Reply | Threaded
Open this post in threaded view
|

bug#16197: 24.3.50; no completion on commands following "sudo" in shell and eshell

Thierry Volpiatto-2
Stefan Monnier <[hidden email]> writes:

>> Don't know what */rsh does, but */xargs is actually not working.
>
> Aha!
>
>> Well I didn't read */xargs, but here are the problems:
>
>> - `pcomplete-command-name' actually is always returning the first arg of
>>   command line e.g for "sudo apt-get" it is returning "sudo".
>
>> - `shell-command-completion' is trying to complete after what
>>   `shell-backward-command' returns, which is actually the first command
>>   near prompt or "[&;|]+ ", so when you try to complete after sudo or
>>   xargs, you call the completion against "sudo" or "xargs" which returns
>>   nothing of course.
>
> Can you describe those problems in terms of user-visible behavior
> (i.e. a recipe) so I can better understand what the code does (and
> should do instead)?
(! is the cursor)

emacs -Q
M-x shell
$ find . -name '*.el' | xargs et!
Press TAB, nothing, no completion against "et".
M-: (shell-backward-command)
I have now the cursor at xargs:
$ find . -name '*.el' | !xargs et
To provide completion against "et" I should have the cursor at:
$ find . -name '*.el' | xargs !et
after evaling (shell-backward-command).

Now download and load:
https://github.com/thierryvolpiatto/emacs-tv-config/blob/master/pcomplete-extension.el
And repeat the same recipe.

For `pcomplete-command-name' it is harder to give a recipe, the best is
to edebug it to have an idea (be careful the actual version is crashing
emacs sometimes).

>> Actually the fix made to these two functions is affecting only sudo, but
>> I can easily fix it to handle also 'xargs'.
>
> That would be nice.

Done in pcomplete-extension.el.

>> Don't think so, I think the problem should be fixed at another level as
>> descripted above.
>
> I missed the description, I'm afraid.
>
>> https://github.com/thierryvolpiatto/emacs-tv-config/blob/master/pcomplete-extension.el
>
> Not sure what I should look at there.

- pcomplete/sudo
- shell-backward-command
- pcomplete-command-name

> Can you send it as a patch against pcmpl-unix.el to fix pcomplete/xargs
> (and add pcomplete/sudo at the same time)?

Not only against pcmpl-unix.el I think:

* pcmpl-unix.el: Add `pcomplete/sudo'.
* pcomplete.el: Redefine `pcomplete-command-name'.
* shell.el: Redefine `shell-backward-command'.

Not urgent:

I would be happy to give also pcomplete/find,hg,ls,apt-get.
Not sure where they would go in this case, pcmpl-linux? unix? gnu?

Also more things to fix are `pcomplete/tar', `pcomplete/ssh' and maybe
others (allow completion on more than one arg), but I haven't worked on
this already.

--
Thierry
Get my Gnupg key:
gpg --keyserver pgp.mit.edu --recv-keys 59F29997



Reply | Threaded
Open this post in threaded view
|

bug#16197: 24.3.50; no completion on commands following "sudo" in shell and eshell

Thierry Volpiatto-2
In reply to this post by Stefan Monnier
Stefan Monnier <[hidden email]> writes:

>> https://github.com/thierryvolpiatto/emacs-tv-config/blob/master/pcomplete-extension.el
>
> Not sure what I should look at there.

For a quick test, you can load this file and do the following tests in
`shell' and/or `eshell':

;; Tests
;; find . -name '*.el' | xargs et      =>ok
;; sudo apt-g                          =>ok
;; sudo apt-get in                     =>ok
;; sudo apt-get --                     =>ok
;; sudo apt-get -                      =>ok
;; sudo apt-get -V -                   =>ok
;; sudo apt-get -V --                  =>ok
;; sudo apt-get --reinstall ins        =>ok
;; sudo apt-get --reinstall install em =>ok
;; sudo -                              =>ok
;; sudo -p "pass" -                    =>ok
;; sudo -p "pass" apt-g                =>ok
;; sudo -p "pass" apt-get ins          =>ok
;; apt-get in                          =>ok
;; apt-get install em                  =>ok

Tell me if something went wrong on these tests or if you have other
cases that are not working.
NOTE: [...] | xargs -0 foo
is not working yet because args are not handled in pcomplete/xargs.
I would do it later if you accept the patch below.

> 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).

--8<---------------cut here---------------start------------->8---
Changes from master to stash
3 files changed, 52 insertions(+), 4 deletions(-)
 lisp/pcmpl-unix.el | 16 ++++++++++++++++
 lisp/pcomplete.el  | 35 ++++++++++++++++++++++++++++++++++-
 lisp/shell.el      |  5 ++---

        Modified   lisp/pcmpl-unix.el
diff --git a/lisp/pcmpl-unix.el b/lisp/pcmpl-unix.el
index 6ac3e15..1c55f67 100644
--- a/lisp/pcmpl-unix.el
+++ b/lisp/pcmpl-unix.el
@@ -215,6 +215,22 @@ Includes files as well as host names followed by a colon."
                                        (pcmpl-ssh-hosts)))))))
                 (complete-with-action action table string pred))))))
 
+(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
        Modified   lisp/pcomplete.el
diff --git a/lisp/pcomplete.el b/lisp/pcomplete.el
index dbeefda..68351e2 100644
--- a/lisp/pcomplete.el
+++ b/lisp/pcomplete.el
@@ -633,9 +633,42 @@ user actually typed in."
  (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."
        Modified   lisp/shell.el
diff --git a/lisp/shell.el b/lisp/shell.el
index 1d67f0b..5bb6a91 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -447,9 +447,8 @@ Thus, this does not include the shell's current directory.")
 This is the value of `pcomplete-command-completion-function' for
--8<---------------cut here---------------end--------------->8---
 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'."


--
Thierry
Get my Gnupg key:
gpg --keyserver pgp.mit.edu --recv-keys 59F29997



Reply | Threaded
Open this post in threaded view
|

bug#16197: 24.3.50; no completion on commands following "sudo" in shell and eshell

Thierry Volpiatto-2
In reply to this post by Stefan Monnier

After applying the patch on previous mail, that among other things fix:

[...] | xargs <completion>
but not
[...] | xargs -<arg> <completion>

This definition of pcomplete/xargs fix it:

--8<---------------cut here---------------start------------->8---
(defun pcomplete/xargs ()
  "Completion for `xargs'."
  (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))))))
--8<---------------cut here---------------end--------------->8---

Note that there is no completion on the args, but that could be done
later (no urge for this).

--
Thierry
Get my Gnupg key:
gpg --keyserver pgp.mit.edu --recv-keys 59F29997



Reply | Threaded
Open this post in threaded view
|

bug#16197: 24.3.50; no completion on commands following "sudo" in shell and eshell

Lars Ingebrigtsen
In reply to this post by Thierry Volpiatto-2
Thierry Volpiatto <[hidden email]> 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



Reply | Threaded
Open this post in threaded view
|

bug#16197: 24.3.50; no completion on commands following "sudo" in shell and eshell

Lars Ingebrigtsen
In reply to this post by Thierry Volpiatto-2
Stefan Monnier <[hidden email]> writes:

> Same here, I'd think that the "command name" is "xargs", but rather than
> argue about this philosophical point, it's probably better to focus on
> more concrete cases where this return value is a problem.

I think I read somewhere that Thierry is no longer working on Emacs
stuff...  Let's see...  Oh, here:

https://news.ycombinator.com/item?id=24449883

Hm, that's only about Helm...

Anyway, this doesn't help with the sudo case, I guess?

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



Reply | Threaded
Open this post in threaded view
|

bug#16197: 24.3.50; no completion on commands following "sudo" in shell and eshell

Stefan Monnier
>> Same here, I'd think that the "command name" is "xargs", but rather than
>> argue about this philosophical point, it's probably better to focus on
>> more concrete cases where this return value is a problem.
>
> I think I read somewhere that Thierry is no longer working on Emacs
> stuff...  Let's see...  Oh, here:
>
> https://news.ycombinator.com/item?id=24449883
>
> Hm, that's only about Helm...
>
> Anyway, this doesn't help with the sudo case, I guess?

The sudo case is the same as xargs, so it's a simple matter of
duplicating the pcomplete/xargs (or making an alias) as in the patch below.


        Stefan


diff --git a/lisp/pcmpl-unix.el b/lisp/pcmpl-unix.el
index dc0d729849..8d4e7ea33d 100644
--- a/lisp/pcmpl-unix.el
+++ b/lisp/pcmpl-unix.el
@@ -83,10 +83,14 @@ pcomplete/rm
 ;;;###autoload
 (defun pcomplete/xargs ()
   "Completion for `xargs'."
-  (pcomplete-here (funcall pcomplete-command-completion-function))
+  ;; FIXME: Add completion of xargs-specific arguments.
+  (funcall pcomplete-command-completion-function)
   (funcall (or (pcomplete-find-completion-function (pcomplete-arg 1))
        pcomplete-default-completion-function)))
 
+;; FIXME: Add completion of sudo-specific arguments.
+(defalias 'pcomplete/sudo #'pcomplete/xargs)
+
 ;;;###autoload
 (defalias 'pcomplete/time 'pcomplete/xargs)
 
diff --git a/lisp/shell.el b/lisp/shell.el
index e574aac99d..d2c41a9690 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -461,9 +461,12 @@ 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))))
+  (if (pcomplete-match "/")
+      (pcomplete-here (pcomplete-entries nil
+ (if shell-completion-execonly
+     'file-executable-p)))
+    (pcomplete-here
+     (nth 2 (shell--command-completion-data)))))
 
 (defun shell-completion-vars ()
   "Setup completion vars for `shell-mode' and `read-shell-command'."




Reply | Threaded
Open this post in threaded view
|

bug#16197: 24.3.50; no completion on commands following "sudo" in shell and eshell

Lars Ingebrigtsen
Stefan Monnier <[hidden email]> writes:

> The sudo case is the same as xargs, so it's a simple matter of
> duplicating the pcomplete/xargs (or making an alias) as in the patch below.

Great!  Are you applying this, then?

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



Reply | Threaded
Open this post in threaded view
|

bug#16197: 24.3.50; no completion on commands following "sudo" in shell and eshell

Lars Ingebrigtsen
Stefan Monnier <[hidden email]> writes:

>>> The sudo case is the same as xargs, so it's a simple matter of
>>> duplicating the pcomplete/xargs (or making an alias) as in the patch below.
>> Great!  Are you applying this, then?
>
> Done,
>
>         Stefan

Thanks; works fine, so I'm closing this bug report.

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