EmacsWiki: Eshell Completion (2025)

Eshell completion can be activated inline by usual with TAB, and M-TAB. Also, pcomplete is available with C-c TAB and it shows a separate side-buffer with all completions listed.

Other completion libraries can also be used. For instace, CompanyMode (and CompanyBox) provides an inline suggestion and completion; fish-completion adds completing strings from the Fish shell; and esh-autosuggest provides inline suggestions as gray text of the first completing string found.

The default Eshell library to provide completion is the em-cmpl.el. It defines the ‘eshell-cmp-mode’ minor mode with the following keymaps:

TABcompletion-at-point
backtabpcomplete-reverse
C-c TABpcomplete-expand-and-complete
C-c SPCpcomplete-expand
C-M-ieshell-complete-lisp-symbol
M-?completion-help-at-point
C-c M-heshell-completion-help

Customization

Eshell offers you completion of filenames. If several filenames are possible, the most recently modified file will be used first.

This is determined by ‘eshell-cmpl-compare-entry-function’ and defaults to ‘file-newer-than-file-p’. The idea is that once you start working with a certain file, you will want it to appear first in your completion list.

Here’s some untested code to reverse this order, and to take ‘completion-ignored-extensions’ into account.

 (setq eshell-cmpl-compare-entry-function (function(lambda (left right) (let ((exts completion-ignored-extensions) found) (while exts (if (string-match (concat "\\" (car exts) "$") right) (setq found t exts nil)) (setq exts (cdr exts))) (if foundnil (file-newer-than-file-p left right))))))

Contributors: KaiGrossjohann, JohnWiegley

Remote Files

If I want to change directory to /scratch, then pressing TAB after typing “cd /sc” leads to TrampMode trying to open a connection. This is because the tramp-completion-file-name-handler entry in file-name-handler-alist leads to:

 (file-name-all-completions "sc" "/") => ("scpx:" "scp2_old:" "scp1_old:" "scp2:" "scp1:" "scp:" "scratch/")

and pcomplete tries to run file-directory-p on all these entries.

One way to avoid this is to use the following:

 (defadvice pcomplete (around avoid-remote-connections activate) (let ((file-name-handler-alist (copy-alist file-name-handler-alist))) (setq file-name-handler-alist (delete (rassoc 'tramp-completion-file-name-handler file-name-handler-alist) file-name-handler-alist)) ad-do-it))

Note that completion of “cd su::” still works because this is handled by tramp-file-name-handler.

Perhaps there are better ways of doing this? – Matt Hodges

Subcommand completions

In default subcommands are not completed, so I make the completion functions for the commands (systemctl, sudo, man) which have subcommands. Completion functions have the corresponding commands’ names.

;;;; sudo completion(defun pcomplete/sudo () "Completion rules for the `sudo' command." (let ((pcomplete-ignore-case t)) (pcomplete-here (funcall pcomplete-command-completion-function)) (while (pcomplete-here (pcomplete-entries)))));;;; systemctl completion(defcustom pcomplete-systemctl-commands '("disable" "enable" "status" "start" "restart" "stop" "reenable" "list-units" "list-unit-files") "p-completion candidates for `systemctl' main commands" :type '(repeat (string :tag "systemctl command")) :group 'pcomplete)(defvar pcomplete-systemd-units (split-string (shell-command-to-string "(systemctl list-units --all --full --no-legend;systemctl list-unit-files --full --no-legend)|while read -r a b; do echo \" $a\";done;")) "p-completion candidates for all `systemd' units")(defvar pcomplete-systemd-user-units (split-string (shell-command-to-string "(systemctl list-units --user --all --full --no-legend;systemctl list-unit-files --user --full --no-legend)|while read -r a b;do echo \" $a\";done;")) "p-completion candidates for all `systemd' user units")(defun pcomplete/systemctl () "Completion rules for the `systemctl' command." (pcomplete-here (append pcomplete-systemctl-commands '("--user"))) (cond ((pcomplete-test "--user") (pcomplete-here pcomplete-systemctl-commands) (pcomplete-here pcomplete-systemd-user-units)) (t (pcomplete-here pcomplete-systemd-units))));;;; man completion(defvar pcomplete-man-user-commands (split-string (shell-command-to-string "apropos -s 1 .|while read -r a b; do echo \" $a\";done;")) "p-completion candidates for `man' command")(defun pcomplete/man () "Completion rules for the `man' command." (pcomplete-here pcomplete-man-user-commands))

Completed subcommands on systemctl are set disable, enable, status, start, restart, stop, but if needed, you can add other subcommands.

KatsuyukiKiso

Miscellaneous

If I set my own prompt, like this:

 (setq eshell-prompt-function (lambda () (concat "[" (user-login-name) "@" (system-name) " " (eshell/pwd) "]" (if (= (user-uid) 0) "# " "$ "))))

completion stops working. When I press tab, I get the message “Text is read-only”. Can anyone explain this? – bkhl

This happens because you haven’t modified eshell-prompt-regexp accordingly (see the documentation for eshell-prompt-function). This should work:
 (setq eshell-prompt-regexp "^[^#$\n]*[#$] ")
See EshellFunctions for more examples. – MattHodges

Ok, thanks. I like pcomplete-list better than the completion cycling. I tried this:

 (add-hook 'eshell-mode-hook '(lambda () (define-key eshell-mode-map "\t" 'pcomplete-list)))

but it doesn’t work. How should this be done properly? – bkhl

I use:
 (setq eshell-cmpl-cycle-completions nil)
to avoid completion cycling. – MattHodges

AutoComplete

I use the amazing AutoComplete package for completion. Eshell provides completion through the ProgrammableCompletion package. I did not found a suitable auto-complete source for pcomplete, so I use the following code:

(defun ac-pcomplete () ;; eshell uses `insert-and-inherit' to insert a \t if no completion ;; can be found, but this must not happen as auto-complete source (flet ((insert-and-inherit (&rest args))) ;; this code is stolen from `pcomplete' in pcomplete.el (let* (tramp-mode ;; do not automatically complete remote stuff (pcomplete-stub) (pcomplete-show-list t) ;; inhibit patterns like * being deleted pcomplete-seen pcomplete-norm-func pcomplete-args pcomplete-last pcomplete-index (pcomplete-autolist pcomplete-autolist) (pcomplete-suffix-list pcomplete-suffix-list) (candidates (pcomplete-completions)) (beg (pcomplete-begin)) ;; note, buffer text and completion argument may be ;; different because the buffer text may bet transformed ;; before being completed (e.g. variables like $HOME may be ;; expanded) (buftext (buffer-substring beg (point))) (arg (nth pcomplete-index pcomplete-args))) ;; we auto-complete only if the stub is non-empty and matches ;; the end of the buffer text (when (and (not (zerop (length pcomplete-stub))) (or (string= pcomplete-stub ; Emacs 23 (substring buftext (max 0 (- (length buftext) (length pcomplete-stub))))) (string= pcomplete-stub ; Emacs 24 (substring arg (max 0 (- (length arg) (length pcomplete-stub))))))) ;; Collect all possible completions for the stub. Note that ;; `candidates` may be a function, that's why we use ;; `all-completions`. (let* ((cnds (all-completions pcomplete-stub candidates)) (bnds (completion-boundaries pcomplete-stub candidates nil "")) (skip (- (length pcomplete-stub) (car bnds)))) ;; We replace the stub at the beginning of each candidate by ;; the real buffer content. (mapcar #'(lambda (cand) (concat buftext (substring cand skip))) cnds))))))(defvar ac-source-pcomplete '((candidates . ac-pcomplete)))(add-hook 'eshell-mode-hook #'(lambda () (setq ac-sources '(ac-source-pcomplete))))(add-to-list 'ac-modes 'eshell-mode)

CategoryEshell


Add Translation

Talk Edit this page View other revisions Administration

Last edited 2024-12-15 20:05 UTC by ChristianGiménez (diff)

EmacsWiki: Eshell Completion (1)

This work is licensed to you under version 2 of theGNU General Public License.Alternatively, you may choose to receive this work under any otherlicense that grants the right to use, copy, modify, and/or distributethe work, as long as that license imposes the restriction thatderivative works have to grant the same rights and impose the samerestriction. For example, you may choose to receive this work undertheGNUFree Documentation License, theCreativeCommonsShareAlikeLicense, the XEmacs manual license, orsimilar licenses.

Please note our Privacy Statement.

EmacsWiki: Eshell Completion (2025)
Top Articles
Latest Posts
Recommended Articles
Article information

Author: Nicola Considine CPA

Last Updated:

Views: 6360

Rating: 4.9 / 5 (69 voted)

Reviews: 92% of readers found this page helpful

Author information

Name: Nicola Considine CPA

Birthday: 1993-02-26

Address: 3809 Clinton Inlet, East Aleisha, UT 46318-2392

Phone: +2681424145499

Job: Government Technician

Hobby: Calligraphy, Lego building, Worldbuilding, Shooting, Bird watching, Shopping, Cooking

Introduction: My name is Nicola Considine CPA, I am a determined, witty, powerful, brainy, open, smiling, proud person who loves writing and wants to share my knowledge and understanding with you.