Also use signature label offsets for parameter info
According to the LSP specification, a parameter of a callable-signature
has a label and a optional doc-commet. The label of a parameter
information is either a string or an inclusive start and exclusive end
offsets within its containing signature label.
Previously, this was only taken in account for highlighting the
parameter in the definition signature.
* eglot.el (eglot--sig-info): Handle signature label offsets
when printing the signature parameter information.
Some language servers may specify null for some capabilities in the list
of server capabilities. This does not conform to the specification, but
treating it as false is more reasonable than treating it as true.
A current example is the PHP language server. which specifies null for
every capability it does not handle, like documentHighlightProvider.
This would cause Eglot to send constant textDocument/documentHighlight
requests, which all timed out.
* eglot.el (eglot--server-capable): Change the handling of null values
for capabilities to treat them as false instead of true.
Change the default of eglot-move-to-column-function
Previous default (move-to-column) works on visual columns, the LSP
specification and the new default (eglot-move-to-column) use "real"
columns. Fixes https://github.com/joaotavora/eglot/issues/293 and https://github.com/joaotavora/eglot/issues/297.
* eglot.el (eglot-move-to-column): New function.
(eglot-move-to-column-function): Use it as default.
David Florness [Mon, 19 Aug 2019 00:09:13 +0000 (18:09 -0600)]
Require array package to use current-line ()
The jsonrpc package (one of eglot's dependencies) recently
updated and removed the line requiring the array package. Since
current-line is provided by array and is used by eglot, require
array explicitly.
Jürgen Hötzel [Mon, 12 Aug 2019 20:13:47 +0000 (22:13 +0200)]
Expand directory watcher globs containing ** ()
Previously, if the server requested a glob pattern like foo/**/*
to be watched, we would just error. Now we watch foo/bar/ and
foo/baz/ as if the server had requested those two watchers
instead of just the one with the **.
As a limitation, the implementation of file-expand-wildcards
doesn't fully handle ** globstars (** matches at most one path
segment).
* eglot.el (eglot-register-capability workspace/didChangeWatchedFiles):
Use file-expand-wildcards to make a ** glob into multiple **-less
globs.
Jürgen Hötzel [Thu, 18 Jul 2019 19:36:56 +0000 (21:36 +0200)]
Fix invalid guess for php language server ()
* eglot.el (eglot-server-programs): Change the position of the php
language server, otherwise it will always be hidden by the c-mode
server (php-mode is derived from c-mode).
João Távora [Thu, 9 May 2019 10:38:58 +0000 (11:38 +0100)]
Work around a bug in emacs's change detection
When using capitalize-word, or any case-fiddling function,
before-change-functions will record e.g. the whole word's start and
end, even though only the first character has changed. Not only is
this longer than needed but also conflicts with what we get in
after-change-functions, which records just the one-char-long change.
Also, if the word didn't need any fiddling at all then
before-change-function will run but after-change-functions won't: an
"orphan" before-change will erroneously be sent to the server.
* eglot.el (eglot--after-change): Detect problematic case and fix
change description.
(eglot--before-change): Store markers of changed region.
(eglot--signal-textDocument/didChange): Weed out orphan changes.
João Távora [Sun, 6 Jan 2019 22:14:27 +0000 (22:14 +0000)]
Rename new defcustoms with friendlier names
* eglot.el (eglot-doc-too-large-for-echo-area): Rename from
eglot-eldoc-extra-buffer-if-too-large.
(eglot-put-doc-in-help-buffer): Rename from
eglot-eldoc-extra-buffer.
(eglot-auto-display-help-buffer): Rename from
eglot-auto-display-eldoc-extra-buffer.
(eglot--eldoc-message): Use new variable names.
João Távora [Sun, 6 Jan 2019 12:55:21 +0000 (12:55 +0000)]
Fix test failure introduced by previous commit
Remove the hack of unsetting eldoc-last-message in
eglot--eldoc-message. This allows any subsequent eglot-eldoc-function
calls (prompted by simple cursor movement) to return it immediately,
thus refreshing the help buffer with the same contents. For this to
work, we also have to set eglot--eldoc-hint globally in
eglot-eldoc-function.
An alternative to making the test pass would be to keep the hack of
unsetting eldoc-last-message only in the case that we actually get to
display the help buffer. This would actually be more efficient, but
potentially more hacky.
The bottom line here is that eldoc doesn't have a good API to deal
with asynchronous docstring fetching. See this thread:
João Távora [Sat, 5 Jan 2019 22:47:43 +0000 (22:47 +0000)]
Show large docs in help buffer instead of echo are by default
* eglot.el (eglot--managed-mode): Add and remove from eglot--eldoc-message
(eglot--eldoc-hint, eglot--help-buffer): New helpers.
(eglot-eldoc-extra-buffer)
(eglot-auto-display-eldoc-extra-buffer): New defcustoms.
(eglot--eldoc-message): New helper.
(eglot-eldoc-function): Set eglot--eldoc-hint.
(eglot-help-at-point): Use new helpers.
(eglot-eldoc-extra-buffer-if-too-large): New predicate.
GitHub-reference: per https://github.com/joaotavora/eglot/issues/198
João Távora [Sat, 5 Jan 2019 13:32:13 +0000 (13:32 +0000)]
Handle (un)registercapability requests via generic functions
* eglot.el (Version): Bump to 1.4
(eglot-register-capability, eglot-unregister-capability): New
generic functions.
(eglot--register-unregister): Call eglot-register-capability,
eglot-unregister-capability.
(eglot-register-capability s (eql
workspace/didChangeWatchedFiles)): Rename from
eglot--register-workspace/didChangeWatchedFiles.
(eglot-unregister-capability s (eql
workspace/didChangeWatchedFiles)): Rename from
eglot--unregister-workspace/didChangeWatchedFiles.
João Távora [Wed, 2 Jan 2019 17:12:36 +0000 (17:12 +0000)]
Run connection hooks with proper dir-locals
eglot-connect-hook and eglot-server-initialized-hook must run in a
buffer with properly setup directory-local variables for the project.
This is crucial for things like eglot-signal-didChangeConfiguration,
which needs a properly setup value of eglot-workspace-configuration to
succeed.
I could have chosen any of the buffers where Eglot is activating
itself, but the approach using
hack-dir-local-variables-non-file-buffer seems more correct, despite
the name.
* eglot.el (eglot--connect): Run connection hooks with proper
dir-locals.
João Távora [Sun, 16 Dec 2018 19:03:06 +0000 (19:03 +0000)]
Take over flymake and eldoc completely while managing buffers
Take a pragmatic approach and override all other Flymake and Eglot
backends while Eglot is enabled. Restore previous values after
eglot-shutdown.
Certainly cases might arise where using more than one datasource
besides LSP while Eglot is managing the buffer is useful. But
currently contrary, it confuses users enabling Eglot in buffers that
already have flymake/eldoc backends configured.
The reasons are slightly different for Eldoc and Flymake:
- For Eldoc the :before-until strategy only makes sense for
synchronous backends, which Eglot isn't. This conflicts with
python.el default python-eldoc-function, which is also asynchronous.
- For Flymake, the default backends in Emacs (python-mode, c-mode, and
a few others) are mainly repetitions of what LSP does. The global
value is still run though (in case you want to put, say, a
spell-checking backend there).
* eglot.el (eglot--saved-bindings, eglot--setq-saving): New
helpers.
(eglot--managed-mode): Use them.
João Távora [Thu, 6 Dec 2018 18:26:17 +0000 (18:26 +0000)]
Warn about suspicious interface usage at compile-time
For fun, set eglot-strict-mode to '(disallow-non-standard-keys
enforce-required-keys enforce-optional-keys) when compiling, or just
use flymake-mode in eglot.el.
* eglot.el (eglot--lsp-interface-alist): Use in compile-time.
Order alphabetically. Fix a few bugs.
(eglot-strict-mode): Disallow non-standard-keys when compiling.
Update docstring.
(eglot--keywordize-vars, eglot--check-interface): New
compile-time-helpers.
(eglot--dbind, eglot--dcase): Use new helpers.
João Távora [Mon, 3 Dec 2018 12:24:26 +0000 (12:24 +0000)]
Robustify previous fix against non-standard insertion bindings
* eglot.el (eglot--managed-mode): Manage post-self-insert-hook.
(eglot--last-inserted-char): New variable.
(eglot--post-self-insert-hook): Set it.
(eglot--before-change): Reset it.
(eglot--CompletionParams): Use it.
GitHub-reference: per https://github.com/joaotavora/eglot/issues/173
João Távora [Sun, 2 Dec 2018 10:54:09 +0000 (10:54 +0000)]
Support completioncontext to help servers like ccls
* eglot.el (eglot-client-capabilities): Annouce
textDocument/completion/contextSupport.
(eglot--CompletionParams): New helper.
(eglot-completion-at-point): Use it.
GitHub-reference: close https://github.com/joaotavora/eglot/issues/173
João Távora [Sat, 1 Dec 2018 22:47:56 +0000 (22:47 +0000)]
Don't break in indirect buffers
Indirect buffers, such as the ones created by ediff-regions-wordwise,
have eglot enabled but not buffer-file-name. Resort to the finding
the file-name of the original buffer for these.
* eglot.el (eglot--TextDocumentIdentifier): Work in indirect
buffers.
* eglot.el (eglot--lsp-interface-alist): Add CodeAction,
FileSystemWatcher, Registration, TextDocumentEdit, WorkspaceEdit.
(eglot-handle-notification): Use eglot--dbind.
(eglot--apply-workspace-edit): Use eglot--dbind and eglot--lambda.
(eglot-code-actions): Use eglot--lambda.
(eglot--register-workspace/didChangeWatchedFiles): Use eglot--lambda.
João Távora [Wed, 28 Nov 2018 20:26:37 +0000 (20:26 +0000)]
Simplify interface of eglot--dbind macro
* eglot.el (eglot--dbind): Use new interface.
(eglot--lambda): Use new eglot--dbind interface.
(eglot--lsp-interface-alist): Fix docstring.
(eglot--call-with-interface): Simplify.
(eglot--plist-keys): New helper.
* eglot-tests.el (eglot-strict-interfaces):
Add a new test clause.
* eglot.el (eglot-current-column): Rename from eglot--current-column.
(eglot-current-column-function): Use it as value and mention in docstring.
(eglot--xref-make): Use eglot-current-column.
(eglot-current-column-function): Set to eglot--current-column.
(eglot--pos-to-lsp-position): Don't bind tab-width anymore.
(eglot--xref-make): Use eglot--current-column.
João Távora [Tue, 27 Nov 2018 13:49:30 +0000 (13:49 +0000)]
Improve performance of xref summary line collection
* eglot.el (eglot--temp-location-buffers): New variable.
(eglot--handling-xrefs): New macro.
(eglot--xref-make): Use eglot--temp-location-buffers.
(xref-backend-definitions, xref-backend-references)
(xref-backend-apropos): Use eglot--handling-xrefs.
GitHub-reference: per https://github.com/joaotavora/eglot/issues/52
GitHub-reference: per https://github.com/joaotavora/eglot/issues/127
João Távora [Fri, 23 Nov 2018 12:31:15 +0000 (12:31 +0000)]
Control strictness towards incoming lsp messages
A new variable, eglot-strict-mode controls whether Eglot is strict or
lax with regard to incoming LSP messages.
1. Bug reports should be tested with eglot-strict-mode set to
'(disallow-non-standard-keys enforce-required-keys)
2. Users struggling to get non-standard servers working set this
variable to '(), nil. For now, by popular demand, this is the
default value.
Note that this commit in particular introduces a new infrastructure,
but does not yet alter any code in Eglot to use it. Neither is the
variable eglot--lsp-interface-alist populated.
* eglot-tests.el (eglot-strict-interfaces): New test.
* eglot.el (eglot--lsp-interface-alist): New variable.
(eglot-strict-mode): New variable.
(eglot--call-with-interface): New helper.
(eglot--dbind): New macro.
(eglot--lambda): New macro.
GitHub-reference: per https://github.com/joaotavora/eglot/issues/144
GitHub-reference: per https://github.com/joaotavora/eglot/issues/156
João Távora [Mon, 19 Nov 2018 23:16:33 +0000 (23:16 +0000)]
Fix potential security issue fontifying lsp doc
Previously, a server could mistankely or maliciously call *-mode
functions by in the response to a completion or hover request,
specifically in the :documentation field of the response.
Although there are plenty of similar avenues of attack in Emacs, it's
probably a good idea not to let LSP servers decide which functions to
call in an Emacs session running Eglot.
* eglot.el (eglot--format-markup): Call major-mode to fontify
buffer, not some dynamically constructed function name.
(eglot-completion-at-point): Ensure eglot--format-markup runs in
source buffer.
* eglot.el (eglot--pos-to-lsp-position): Call
eglot-current-column-function with tab-width bound to 1.
(eglot--lsp-position-to-point): Call eglot-move-to-column-function
with tab-width bound to 1.
João Távora [Tue, 13 Nov 2018 22:08:16 +0000 (22:08 +0000)]
Add ability to report lsp-compliant columns
* eglot.el (eglot-current-column-function): New variable.
(eglot-lsp-abiding-column): New helper.
(eglot--pos-to-lsp-position): Use eglot-current-column-function.
(eglot-move-to-column-function): Tweak docstring.
João Távora [Mon, 12 Nov 2018 22:29:38 +0000 (22:29 +0000)]
Add ability to move to lsp-precise columns
Also close https://github.com/joaotavora/eglot/issues/125.
Idea and much of design contributed by Michał Krzywkowski
<k.michal@zoho.com>
This introduces the variable eglot-move-to-column-function.
According to the standard, LSP column/character offsets are based
on a count of UTF-16 code units, not actual visual columns. So
when LSP says position 3 of a line containing just \"aXbc\",
where X is a multi-byte character, it actually means `b', not
`c'. This is what the function
`eglot-move-to-lsp-abiding-column' does.
However, many servers don't follow the spec this closely, and
thus this variable should be set to `move-to-column' in buffers
managed by those servers.
* eglot.el (eglot-move-to-column-function): New variable.
(eglot-move-to-lsp-abiding-column): New function.
(eglot--lsp-position-to-point): Use eglot-move-to-column-function.