I’ve got elixir-mode and eglot configured in my emacs.d and it mostly works. One thing I can’t figure out though is how to work with the code completion (via company) in elixir code.
Say I type
defm at this point I get the completion options pop up. I select
defmodule and then it expands to
defmodule $1 do
But the cursor (point) moves to the end of
end. I get no opportunity to specify the module name and also complete the module body.
When I disable
eglot and use only
elixir-mode I get the expected behaviour were selecting
defmodule from the completion list places the cursor (point) between
do where I type the module name then another tab places the cursor inside the module body.
What is the way to work with what seems to be eglot’s way of code completion?
@thepreacher I couldn’t reproduce this bug. Running latest eglot in elpa, and elixir-lsp/elixir-ls (more updated fork at the moment). When I hit enter on defmodule completion, works as expected: cursor at module name, and tab goes to module body.
I wonder if you have a
company issue, or with another package.
@rodrigues can I take a look around your
emacs.d? My company config is really simple below and I spent hours going over it without success.
;; Company mode
(add-to-list 'completion-styles 'initials t)
:hook (after-init . global-company-mode)
(setq company-minimum-prefix-length 2)
;;(setq company-auto-complete nil)
(setq company-idle-delay 0)
(setq company-require-match 'never)
(setq-default company-dabbrev-other-buffers 'all
(setq tab-always-indent 'complete)
;;(defvar completion-at-point-functions-saved nil)
(define-key company-mode-map (kbd "M-/") 'company-complete)
(define-key company-active-map (kbd "C-n") 'company-select-next)
(define-key company-active-map (kbd "C-p") 'company-select-previous))
Eglot currently is setup like so
and Elixir’s looks like this:
:after (company flycheck)
;;(add-to-list 'exec-path "/Users/napo/Github/elixir-ls/release")
(add-to-list 'eglot-server-programs '(elixir-mode . ("/Users/napo/Github/elixir-ls/release/language_server.sh")))
;;(add-hook 'elixir-mode-hook #'lsp)
(add-hook 'elixir-mode-hook 'eglot-ensure)
(add-hook 'elixir-mode-hook 'flycheck-mode)
(add-hook 'elixir-mode-hook #'smartparens-mode)
(lambda () (add-hook 'before-save-hook 'eglot-format nil t))))
@thepreacher my emacs.d repo gets constantly rebased with https://github.com/purcell/emacs.d
Other than that, that’s my only company specific custom config:
(add-hook 'after-init-hook 'global-company-mode)
(setq company-dabbrev-downcase 0)
(setq company-idle-delay 0)
As for eglot/elixir, there it is, at the moment:
'(elixir-mode . ("sh" "/Users/rodrigues/code/elixir-ls/release/language_server.sh")))
(add-hook 'before-save-hook 'eglot-format nil t)))
I run into same issue with my Emacs setup, and I was able to solve it.
Based on the github issue I was able to deduce that Eglot upon start communicates to Language Server that he supports snippets, and I would guess, that based on this start-up info it will either try to pass it into snippet engine or not. You could look into your
*EGLOT (....) events* buffer; find first message ( with
M-<), and verify your settings.
client-request (id:1) Fri Jan 31 00:35:47 2020:
(:jsonrpc "2.0" :id 1 :method "initialize" :params
(:processId 14783 :rootPath ....
(:dynamicRegistration :json-false :completionItem
I was able to achieve such setup by installing Yasnippets, and turning them on in
:commands (eglot eglot-ensures)
(elixir-mode . eglot-ensure)
(before-save . eglot-format-buffer)
`eglot-server-programs `(elixir-mode ,(expand-file-name "~/elixir_ls/release/language_server.sh"))))
:hook (elixir-mode . yas-minor-mode))