Closed terlar closed 6 years ago
I do use this with pcomplete
, but not with company-capf
. I should clarify this in the README, but my aim was for this to not interfere with completion at all because it's not really a completion package, since it only suggests a single candidiate - the most recent matching history item. This is to try and follow fish shell's behavior. To much more closely follow fish shell autosuggestion behavior, you can use some tricky bindings:
If you use general.el:
(general-def :keymaps 'company-active-map
[tab] (general-predicate-dispatch nil
(not (eq major-mode 'eshell-mode)) 'company-complete-common)
[return] (general-predicate-dispatch nil
(not (eq major-mode 'eshell-mode)) 'company-complete-selection)
"RET" (general-predicate-dispatch nil
(not (eq major-mode 'eshell-mode)) 'company-complete-selection)
"<right>" (general-predicate-dispatch nil
(eq major-mode 'eshell-mode) 'company-complete-selection))
without general.el:
(define-key company-active-map
[tab] '(menu-item "" nil :filter
(lambda
(&optional _)
(cond
((not
(eq major-mode 'eshell-mode))
'company-complete-common)
(t nil)))))
(define-key company-active-map
[return] '(menu-item "" nil :filter
(lambda
(&optional _)
(cond
((not
(eq major-mode 'eshell-mode))
'company-complete-selection)
(t nil)))))
(define-key company-active-map
(kbd "RET") '(menu-item "" nil :filter
(lambda
(&optional _)
(cond
((not
(eq major-mode 'eshell-mode))
'company-complete-selection)
(t nil)))))
(define-key company-active-map
(kbd "<right>") '(menu-item "" nil :filter
(lambda
(&optional _)
(cond
((eq major-mode 'eshell-mode)
'company-complete-selection)
(t nil)))))
What this does is essentially escape some company-active-map
bindings in eshell, allowing eshell-company-autosuggest
to simply be a "passive" history suggestion mechanism, while relying on pcomplete for completion on pressing tab.
Notes:
eshell-mode-map
, which I think defaults to eshell-pcomplete
return
will always run your explicit input (which is cool in case you want to run ls
but it's being completed to ls [some-other-thing]
by company-eshell-autosuggest
<right>
.I have not looked into relying on company-capf first, I can investigate that option and get back to you.
I could be possible to look automate some of this behavior in a minor mode, though it might be a bit tricky to take into account user/externally customized bindings in company-active-map
.
@terlar I think I have some ideas, but could you describe in more detail the behavior you want? You want to use company-mode normally in eshell, with the capf backend, and if that doesn't find anything you'd like to get history suggestions (presumably multiple) ?
Or would it be fine to get just the single most recent history suggestion if company-capf has no completions? I think either case should be doable, give me some time :)
@dieggsy Thank you for your help, that behavior achieved from that one is pretty much exactly what I want, only that instead of using the default eshell-pcomplete
with the buffer popping up which I find annoying, I would have company showing those completions instead. I might have misunderstood from some company-mode issue that it was using company-capf
to get those completions, but that doesn't seem to be the case.
But somehow company receives the completions when the company-eshell-autosuggest
is disabled, but I am not sure from which backend. When I enable company-eshell-autosuggest
I lose those other completions. I figured it should just work if the company-eshell-autosuggest was just added to that list and I would complete the common parts first. But perhaps when actually experiencing that behavior it wouldn't be as nice as I expect.
I would want:
eshell-pcomplete
but with a company-popup.Okay, seems I have pretty much what I want and I was correct about the company-capf
. I will try it out for a bit. I am currently using it with '(company-capf company-eshell-autosuggest)
so it gets both completions in the list. I am not sure why it didn't work out earlier, I guess it we somewhere between the tab key being bound to eshell-pcomplete
and me not being sure which backend provided those pcomplete
completions for company.
@terlar I'm not sure you can have the autosuggested line always visible if you're using company-capf
on top of company-eshell-autosuggest
- is that working for you?
Regarding the annoying buffer - I agree. As an alternative, I'd recommend not using company-capf
and trying the following:
If you use ivy, I'd recommend trying out binding tab
to completion-at-point
in eshell-mode-map
like so:
(defun setup-eshell ()
(define-key eshell-mode-map (kbd "<tab>") 'completion-at-point))
(add-hook 'eshell-mode-hook 'setup-eshell)
You need to make sure ivy-do-completion-in-region
is t
, and if you find the in-buffer completion annoying and would like to use the minibuffer you can set ivy-display-functions-alist
to nil
.
If you use helm, you could bind tab
to helm-esh-pcomplete
:
(defun setup-eshell ()
(define-key eshell-mode-map (kbd "<tab>") 'helm-esh-pcomplete))
(add-hook 'eshell-mode-hook 'setup-eshell)
This is the most truly "fish"-like behavior I could get - you get history autosuggestions automatically, but tab will use the minibuffer for pcomplete completion (without the annoying popup window/buffer).
In any case, I think I'm gonna try to roll out some minor modes to make all of this painless, just (add-hook 'eshell-mode #'company-eshell-autosuggest-mode)
or (add-hook 'eshell-mode #'company-eshell-autosuggest-with-capf-mode)
.
Yes this is the conclusion I came to too, I tried out the ivy completion and it worked well, just I found it annoying having to accept the completion and not being able to continue with space, but that is fixable. Actually you can use this quite well with company mode if you enable the front-end: company-preview-frontend
, in that sense it works very good with the setup I mentioned earlier.
I am using:
(setq company-frontends
'(company-tng-frontend
company-pseudo-tooltip-unless-just-one-frontend
company-echo-metadata-frontend
company-preview-frontend
company-quickhelp-frontend))
I guess we can close this one since I figured it out.
@terlar If you don't mind, I'll reopen so I can remind myself that i'd like to enable these in a minor mode for convenience.
A question - shouldn't it work with the default company-frontends
? (In which case you wouldn't have to actually set that variable).
Of course I don't mind.
I think the caveat with having the line visible when using these two together is using the package company-statistics
and if the autosuggested one is the top alternative, then it will show as preview with company-preview-frontend
.
That would be neat, but I am not sure what is possible with company, I guess it should be technically possible if this mode combines these two in some way always showing the autosuggestion at top. I have seen other modes that wrap several modes at the package level.
@terlar oh, sorry - I meant that for your current use case (not your ideal one) you might be able to leave company-frontends
to its default value.
@terlar can you describe the setup you say is working now?
I'm testing setting company-backends
to '(company-capf company-eshell-autosuggest)
, but it seems i never actually get the history autosuggestions.
In fact, https://github.com/company-mode/company-mode/issues/663 and https://github.com/company-mode/company-mode/issues/142 seem to suggest this isn't possible...
Closing in light of https://github.com/company-mode/company-mode/issues/744, which confirms my previous comment. Note that there's now a minor mode for company-eshell-autosuggest if you don't want to use company as your main completion system, which gets around some of the funky bindings decribed here. Minor mode is described in the updated Readme.
Sorry for not getting back to you, but there were some issues with the loading of use-package during that time that made it hard for me to reproduce my setup, seems things are stable now and I can reproduce now.
Since I use company-statistics
my top choices will be presented first, so for example if I recently used docker ps -a
it will show up when I write docker
and I have bound C-e
to complete the current selection so that is what I use to accept the completion, however if I continue write docker p
and tab, it will use the completions from company-capf
.
Here is a short gif with demonstration:
As noted there in your comments it only works as long as the prefix is the same, so it only works for the first word, but after space when you try to complete next word it doesn't work.
The relevant setup for this would be:
(use-package company
:demand t
:hook
(after-init . global-company-mode)
:general
(:keymaps 'company-active-map
;; No interference with return key
[return] 'nil
"RET" 'nil
;; Abort company instead of insert mode
[escape] 'company-abort
;; Complete the common part before cycling
[tab] 'company-complete-common-or-cycle
"TAB" 'company-complete-common-or-cycle
[backtab] 'company-select-previous
"S-TAB" 'company-select-previous
;; Complete the current selection
"C-e" 'company-complete-selection
"C-f" 'company-complete-selection)
:preface
(defun company-preview-if-not-tng-frontend (command)
"`company-preview-frontend', but not when tng is active."
(unless (and (eq command 'post-command)
company-selection-changed
(memq 'company-tng-frontend company-frontends))
(company-preview-frontend command)))
:init
(autoload 'company-tng-frontend "company-tng" nil t)
(setq company-require-match nil
company-frontends
'(company-tng-frontend
company-pseudo-tooltip-unless-just-one-frontend
company-preview-if-not-tng-frontend
company-echo-metadata-frontend)
company-backends
company-transformers '(company-sort-by-occurrence)))
(use-package company-statistics
:hook (company-mode . company-statistics-mode))
(use-package esh-autosuggest
:commands esh-autosuggest
:init
(add-hook 'eshell-mode-hook
(lambda () (setq-local 'company-backends (push '(company-capf esh-autosuggest) company-backends)))))
Ah, cool. Thanks for the detailed description - since I don't actually use this method, do you think the readme could be clearer regarding this alternative, or is it sufficient? You could also feel free to add your setup to the wiki if it's not covered by the readme, or open a PR for the readme.
My setup is a bit bigger than minimally needed, even I stripped out most irrelevant stuff. I think it is fine with the mention you already have about being able to combine company-capf
and esh-autosuggest
. I just wanted to update you since I never got back to you and realized things was working as I wanted now.
Great. Thanks, I appreciated it.
I am trying to use this together with the pcomplete suggestions from emacs-fish-completion. However specifying the backend:
company-eshell-autosuggest
seems to only suggest the autosuggest completions. I assume you have this working looking at your setup and your blog post. If I don't have thecompany-eshell-autosuggest
the other suggestions work very well.I would like to have the pcomplete first and if nothing else matches fallback to this one.