I'm very fond of
ivy for completion and love that a simple
(ivy-mode 1) is enough to get
ivy almost everywhere that Emacs uses some sort of completion (that is acomplished by overriding
completeing-read, I believe). But this doesn't setup
eshell to use
ivy for tab completion. I do like
eshell's list of completion candidates, but would prefer the
ivy UI to pick among them. Is there some way to reuse whatever
eshell does to produce completion candidates and hand that off to `ivy'?
I'm very fond of
I found something that seems to work OK upon initial testing: essentially rebind
pcomplete-std-complete, but since that function isn't interactive for some reason, you need to wrap it:
(define-key eshell-mode-map (kbd "<tab>") (lambda () (interactive) (pcomplete-std-complete)))
pcompete-std-complete tries to use the completions written for
pcomplete with the standard completion UI, which
ivy by default will override (with the very recent update, they appear in a nice overlay right in the eshell buffer near point!).
The comments in the source code of
pcomplete-std-complete depends on) mention a couple of potential problems:
;; FIXME: it only completes the text before point, whereas the ;; standard UI may also consider text after point. ;; FIXME: the `pcomplete' UI may be used internally during ;; pcomplete-completions and then throw to `pcompleted', thus ;; imposing the pcomplete UI over the standard UI.
I think the first one won't affect me, since I don't think I ever press
<tab> except at the end of the input line. I haven't seen the second problem surface either, so far.
EDIT: For those unfamiliar with eshell's quirks (this is a euphemism), maybe I should add that to rebind eshell's key as suggested above you should put this in your init file:
(add-hook 'eshell-mode-hook (lambda () (define-key eshell-mode-map (kbd "<tab>") (lambda () (interactive) (pcomplete-std-complete)))))
Before you yell at me for the wasteful keybindings-in-a-hook antipattern, let me explain that eshell declares its keymap with
(defvar eshell-mode-map nil) and then does
(setq-local eshell-mode-map (sparse-keymap)) inside
eshell-mode! (The code has a helpful
;; FIXME: What the hell!?.) That means that you can't rebind keys until after
eshell-mode runs! Hence the hook.