eglot icon indicating copy to clipboard operation
eglot copied to clipboard

Quirks with flex company candidates

Open haoyuan80s opened this issue 3 years ago • 14 comments

I test in python (pyls) and go (gopls). For both, the company misses flex candidates.

Python example: input sm -> M-x [company complete] -> "No completion found"

There the the company candidates in python (pyls) given by lsp-mode:

image

My eglot conifg

(use-package eglot
  :ensure t
  :commands (eglot eglot-ensure)
  :custom
  (eglot-ignored-server-capabilites '(:documentHighlightProvider))

  :hook ((rust-mode . eglot-ensure)
         (go-mode . eglot-ensure)
         (python-mode . eglot-ensure))
  :bind (:map eglot-mode-map
              ("C-c e r" . eglot-rename)
              ("C-c e h" . eglot-help-at-point)
              ("C-c e a" . eglot-code-actions))
  :init
  (setq eglot-autoshutdown t))

haoyuan80s avatar Sep 11 '20 19:09 haoyuan80s

Thanks for the report. Indeed I only get substring completion now in the servers I have handy. I will investigate better how to make this happen in Eglot.

joaotavora avatar Sep 11 '20 19:09 joaotavora

@haoyuan80s Maybe enabling pyls.plugins.jedi_completion.fuzzy option in pyls will help?

muffinmad avatar Sep 11 '20 19:09 muffinmad

@muffinmad Thanks for your suggestion. But, I cannot make it work.

In ".dir-locals.el", I added

((python-mode
  . ((eglot-workspace-configuration
      . ((:pyls . (:plugins (:jedi_completion (:fuzzy t)))))))))

The eglot-workspace-configuration has value

((:pyls :plugins (:jedi_completion (:fuzzy t))))

Still no flex candidates.

haoyuan80s avatar Sep 11 '20 20:09 haoyuan80s

@haoyuan80s You are right. Enabling fuzzy for pyls doesn't help.

test.py with point on |:

from datetime import datetime


def dotandmime():
    pass


dtm|

pyls response:

[client-request] (id:18) Mon Sep 14 15:33:56 2020:
(:jsonrpc "2.0" :id 18 :method "textDocument/completion" :params
	  (:textDocument
	   (:uri "file:///Users/mad/workspace/test1/test.py")
	   :position
	   (:line 7 :character 3)
	   :context
	   (:triggerKind 1)))
[server-reply] (id:18) Mon Sep 14 15:33:56 2020:
(:jsonrpc "2.0" :id 18 :result
	  (:isIncomplete :json-false :items
			 [(:label "datetime" :kind 7 :detail "test" :documentation "datetime(year: int, month: int, day: int, hour: int=..., minute: int=..., second: int=..., microsecond: int=..., tzinfo: Optional[_tzinfo]=..., *, fold: int=...)\n\ndatetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])\n\nThe year, month and day arguments are required. tzinfo may be None, or an\ninstance of a tzinfo subclass. The remaining arguments may be ints." :sortText "adatetime" :insertText "datetime")
			  (:label "dotandmime()" :kind 3 :detail "test" :documentation "dotandmime()" :sortText "adotandmime" :insertText "dotandmime")]))

But completion-at-point says "No match". And company-complete says "No completion found".

muffinmad avatar Sep 14 '20 12:09 muffinmad

Thanks for the investigation, @muffinmad . To reproduce this, is it as easy as doing the eglot-workspace-configuration trick to tell pyls to enable fuzzy?

But completion-at-point says "No match". And company-complete says "No completion found".

Seems like a bug, indeed I find it odd that clangd does give me fuzzy matches, wonder what's going on...

joaotavora avatar Sep 14 '20 13:09 joaotavora

@joaotavora Yes, sorry, forgot to mention configuration:

(setq-default eglot-workspace-configuration
	      '((:pyls :plugins (:jedi_completion (:fuzzy t)))))

muffinmad avatar Sep 14 '20 13:09 muffinmad

Curious. Can't reproduce. Works just fine in my system: image

joaotavora avatar Sep 14 '20 13:09 joaotavora

Works just fine in my system:

"Just fine" is an exaggeration. That "test" hint seems wrong, and the server actually replied with three completions:

(:isIncomplete :json-false :items
                         [(:label "datetime" :kind 7 :detail "test" :documentation "datetime(year: int, month: int, day: int, hour: int=..., minute: int=..., second: int=..., microsecond: int=..., tzinfo: Optional[_tzinfo]=..., *, fold: int=...)\n\ndatetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])\n\nThe year, month and day arguments are required. tzinfo may be None, or an\ninstance of a tzinfo subclass. The remaining arguments may be ints." :sortText "adatetime" :insertText "datetime")
                          (:label "dotandmime()" :kind 3 :detail "test" :documentation "dotandmime()" :sortText "adotandmime" :insertText "dotandmime")
                          (:label "datetime object" :kind 25 :detail "test" :documentation "datetime(year: int, month: int, day: int, hour: int=..., minute: int=..., second: int=..., microsecond: int=..., tzinfo: Optional[_tzinfo]=..., *, fold: int=...)\n\ndatetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])\n\nThe year, month and day arguments are required. tzinfo may be None, or an\ninstance of a tzinfo subclass. The remaining arguments may be ints." :sortText "adatetime" :insertText "datetime")])

joaotavora avatar Sep 14 '20 13:09 joaotavora

Well, here is the full receipt to check this:

Emacs 28.0.50 Python 3.7.8 python-language-server 0.35.0

  1. emacs -Q

  2. Insert into *scratch* buffer:

(progn
  (setq package-user-dir "/tmp/tmp-elpa")
  (require 'package)
  (package-initialize)
  (add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") t)
  (package-refresh-contents))

(package-install 'eglot)
(package-install 'company)

(setq-default eglot-workspace-configuration
	      '((:pyls :plugins (:jedi_completion (:fuzzy t)))))
(global-company-mode)
(find-file "test-eglot-flx.py")
(erase-buffer)
(insert "from datetime import datetime\n\n\ndef dotandmime():\n    pass\n\n\ndtm")
  1. M-x eval-buffer
  2. M-x eglot
  3. M-x company-complete "No completion found"

Not surprising considering that the only company backend in the current buffer is company-capf and the completion-at-point doesn't return completions.

muffinmad avatar Sep 14 '20 15:09 muffinmad

How can I forget! Thanks to one great man we now have flex completion style in Emacs 27!

Знімок екрана 2020-09-14 о 21 51 27

@haoyuan80s If you use Emacs 27, just (add-to-list 'completion-styles 'flex).

muffinmad avatar Sep 14 '20 18:09 muffinmad

I am using Emacs 28. After adding (add-to-list 'completion-styles 'flex), it works perfectly.

image

Thanks so much!

haoyuan80s avatar Sep 14 '20 21:09 haoyuan80s

I am using Emacs 28. After adding (add-to-list 'completion-styles 'flex), it works perfectly.

I'm glad we could help. But I wouldn't say it works "perfectly":

  • The annotation is odd, it should inform about the Python name (function)
  • Perhaps completion-styles should be set to flex by default in Eglot-managed buffers, so that you wouldn't have to to put that line in your .emacs.

So I'm keeping the issue open.

joaotavora avatar Sep 14 '20 21:09 joaotavora

  • The annotation is odd, it should inform about the Python name (function)

Not the Eglot issue. pyls for some reason provide the module name as detail for every completion candidate. Eglot is doing the right job by displaying it. If language server doesn't provide any detail for completion candidate, candidate type is shown:

Знімок екрана 2020-09-15 о 09 30 44
  • Perhaps completion-styles should be set to flex by default in Eglot-managed buffers, so that you wouldn't have to to put that line in your .emacs.

This will work only for those servers who support "fuzzy" completion. E.g. for pyls it must be explicitly turned on in config.

muffinmad avatar Sep 15 '20 06:09 muffinmad

@haoyuan80s Check out company-fuzzy

muffinmad avatar Sep 24 '20 10:09 muffinmad