João Távora [Thu, 17 May 2018 13:03:20 +0000 (14:03 +0100)]
Make it work on windows
Apparently passing :coding 'no-conversion to make-process on windows
is essential to receive any text at all in the process filter.
Also needed to tweak uri-to-path and path-to-uri.
Thanks to lsp-mode.el for these hints
* eglot.el (eglot--make-process): Pass :coding 'no-conversion to
make-process.
(eglot--path-to-uri): Add a forward slash if windows-nt.
(eglot--uri-to-path): Remove a forward slash if windows-nt.
(eglot--server-textDocument/publishDiagnostics): Simplify and use
eglot--uri-to-path.
João Távora [Wed, 16 May 2018 23:30:53 +0000 (00:30 +0100)]
Simplify some function calling infrastructure
eglot--mapply is a confusing abstraction. Hide some of that confusion
behind eglot--lambda. More stably dispatch server notifications and
requests without introspecting their contents.
* eglot.el (eglot--process-receive): Simplify.
(eglot--async-request): Improve doc.
(eglot--request): Simplify.
(eglot--mapply): Remove.
(xref-backend-identifier-completion-table)
(xref-backend-definitions, xref-backend-references)
(xref-backend-apropos, eglot-completion-at-point)
(eglot-eldoc-function, eglot-imenu, eglot--apply-text-edits):
Don't use eglot--mapply, use normal mapcar/mapc.
João Távora [Wed, 16 May 2018 22:45:35 +0000 (23:45 +0100)]
Replace eglot--with-lsp-range with a function and pcase-let
* eglot.el (eglot--with-lsp-range): Remove.
(eglot--range-region): New function.
(eglot--server-textDocument/publishDiagnostics)
(eglot--hover-info, eglot-eldoc-function)
(eglot--apply-text-edits): Use it.
João Távora [Wed, 16 May 2018 22:39:12 +0000 (23:39 +0100)]
Simpler callback protocol for jsonrpc parameters and results
Instead of introspecting the :params or :result object to discover if
an object is present, and changing the Elisp function call type
(funcall vs apply) accordingly, alway funcall. It's up to the
application to destructure if it wishes. jrpc-lambda can help with
that and keep the application code simple.
* jrpc.el (jrpc--process-receive): Allow only keys defined in
JSONRPC2.0
(jrpc--process-receive): Don't overload function call type based
on remote response.
(jrpc-lambda): Return a unary lambda.
(jrpc-request): Simplify.
(jrpc-mapply): Remove.
João Távora [Tue, 15 May 2018 12:24:08 +0000 (13:24 +0100)]
Add php's php-language-server to built-in guessed servers
Closes https://github.com/joaotavora/eglot/issues/1. The problem in that issue is that php-language-server has a
bug when it's not passed it the deprecated ":rootPath" field. The bug
doesn't happen if the ":processId" field is also absent. Eglot was
triggering the bug, because it didn't pass ":rootPath", but there's
nothing wrong in doing so.
* README.md: Add php-language-server to the built-in list.
* eglot.el (eglot-server-programs): Add php-language-server.
(eglot--connect): Also pass (deprecated) rootPath.
João Távora [Mon, 14 May 2018 20:49:58 +0000 (21:49 +0100)]
Jrpc-connect is now passed a generic dispatching function
* eglot.el (eglot--dispatch): New helper.
(eglot--connect): Use it.
* jrpc.el (jrpc--dispatcher, jrpc--request-continuations)
(jrpc--server-request-ids): New process-local var.
(jrpc--pending-continuations, jrpc--method-prefix): Remove.
(jrpc-connect): Take DISPATCHER instead of PREFIX.
(jrpc--process-receive): Use proc's dispatcher.
(jrpc--process-send): Make private.
(jrpc-forget-pending-continuations, jrpc-async-request)
(jrpc-reply, jrpc-notify): Use new function names.
João Távora [Mon, 14 May 2018 18:19:12 +0000 (19:19 +0100)]
Proper server shutdown when jrpc.el is used
The shutdown hook can't be a buffer-local thing, it has
to be a server property. Also, on shutdown in eglot.el,
remember to first unmanage buffers and only then affect
eglot--processes-by-project.
* eglot.el (eglot--on-shutdown): reverse order of first
two sexps.
(eglot--connect): Pass a shutdown function to jrpc-connect
(eglot--managed-mode): Don't use jrpc-server-moribund-hook
(eglot--buffer-managed-p): Simplify. Use eglot--find-current-process.
João Távora [Mon, 14 May 2018 13:18:18 +0000 (14:18 +0100)]
Support didchangewatchedfiles with dynamic registration
RLS uses this, presumaly for knowing about Cargo.toml changes and stuff.
* README.md: Update protocol compliance.
* eglot.el (filenotify): Require it.
(eglot--file-watches): New process-local var.
(eglot--process-sentinel): Kill all watches
(eglot--register-unregister): New helper.
(eglot--server-client/registerCapability): Simplify.
(eglot--server-client/unregisterCapability): New method.
(eglot--register-workspace/didChangeWatchedFiles)
(eglot--unregister-workspace/didChangeWatchedFiles): New
capability.
(eglot--client-capabilities): Update.
João Távora [Sun, 13 May 2018 22:25:15 +0000 (23:25 +0100)]
Use rls in travis ci and add actual tests
Also run a hook when connected
* eglot-tests.el (eglot--with-dirs-and-files)
(eglot--make-file-or-dirs, eglot--call-with-dirs-and-files)
(eglot--find-file-noselect): New helpers.
(auto-detect-running-server, auto-reconnect): New actual tests.
* eglot.el (eglot-connect): Run hook when connected
(eglot-connect-hook): New variable
Unfortunately, this may cause problems when calling the error
callbacks directly as in the process sentinel. In that particular
scenario the accept-process-output won't have return, because no
output has is being handled. Consequently, if we're unlucky, we have
another 30 seconds to way before the flag is tested and the loop
exits.
* eglot.el (eglot-request): Use catch/loop/throw again
João Távora [Sat, 12 May 2018 14:59:53 +0000 (15:59 +0100)]
New command eglot-help-at-point and a readme update
* README.md (Commands and keybindings): New section.
* eglot.el (eglot-eldoc-function): Use eglot--hover-info.
Don't care about kind in highlightSymbol
(eglot--hover-info): New helper.
(eglot-help-at-point): New command.
João Távora [Thu, 10 May 2018 18:23:56 +0000 (19:23 +0100)]
Improve eglot-eldoc-function
Use the :range key if the server provided it. Also simplify code with
a new eglot--with-lsp-range macro.
* eglot.el (eglot--format-markup): Tweak comment.
(eglot--with-lsp-range): New helper macro.
(eglot--server-textDocument/publishDiagnostics)
(eglot--apply-text-edits): Use it.
(eglot-eldoc-function): Use range if server provides it.
João Távora [Thu, 10 May 2018 17:44:47 +0000 (18:44 +0100)]
Reduce log chatter
* eglot.el (eglot--process-sentinel, eglot--request): Use
eglot--log-event.
(eglot--log-event): Print "message" if type unknown.
(eglot--debug, eglot--log): Remove.
(eglot--server-window/logMessage, eglot--server-telemetry/event):
Make noops.
(eglot--call-deferred): Also reduce chatter here.
João Távora [Thu, 10 May 2018 12:14:19 +0000 (13:14 +0100)]
Resist server failure during synchronous requests
Calling the error handler unprotected could lead to the rest of the
sentinel not running at all. This defeated the auto-reconnection in
Rust, for example.
João Távora [Thu, 10 May 2018 11:51:21 +0000 (12:51 +0100)]
More rls-specifics: update flymake diags when indexing done
RLS could/should report diagnostics for every opened file, even if
there aren't any problems. Because it doesn't, loop for every buffer
managed by the process and call eglot--current-flymake-report-fn
João Távora [Thu, 10 May 2018 11:21:29 +0000 (12:21 +0100)]
Adjust flymake integration
When opening a new file (signalling textDocument/didOpen) it makes
sense to call the flymake callback (if it exists) with no diagnostics,
just to get rid of that "Wait", since we don't know if later in this
callback cycle the server will ever report new diagnostics.
* eglot.el (eglot--managed-mode): Don't call flymake-mode or eldoc-mode
(eglot--managed-mode-hook): Add them here.
(eglot--maybe-activate-editing-mode): Call flymake callback.
(eglot--server-textDocument/publishDiagnostics): Set unreported
diagnostics to nil if invoking callback.
João Távora [Thu, 10 May 2018 11:07:11 +0000 (12:07 +0100)]
More correctly setup rust-mode-related autoloads
By autoloading the add-hook form and the eglot--setup-rls-idiosyncrasies
definition, a user can start rust-mode without loading eglot.el along
with it.
* eglot.el (rust-mode-hook)
(eglot--setup-rls-idiosyncrasies): Wrap in autoloaded progn.
João Távora [Wed, 9 May 2018 21:41:37 +0000 (22:41 +0100)]
New "deferred requests" that wait until server is ready
Calling textDocument/hover or textDocument/documentHighlight before
the server has had a chance to process a textDocument/didChange is
normally useless. The matter is worse for servers like RLS which only
become ready much later and send a special notif for it (see
https://github.com/rust-lang-nursery/rls/issues/725).
So, keeping the same coding style add a DEFERRED arg to eglot--request
that makes it maybe not run the function immediately. Add a bunch of
logic for probing readiness of servers.
* README.md: Update
* eglot.el (eglot--deferred-actions): New process-local var.
(eglot--process-filter): Call deferred actions.
(eglot--request): Rewrite.
(eglot--sync-request): Rewrite.
(eglot--call-deferred, eglot--ready-predicates)
(eglot--server-ready-p): New helpers.
(eglot--signal-textDocument/didChange): Set spinner and call
deferred actions.
(eglot-completion-at-point): Pass DEFERRED to eglot-sync-request.
(eglot-eldoc-function): Pass DEFERRED to eglot-request
(eglot--rls-probably-ready-for-p): New helper.
(rust-mode-hook): Add eglot--setup-rls-idiosyncrasies
(eglot--setup-rls-idiosyncrasies): New helper.
João Távora [Wed, 9 May 2018 11:24:10 +0000 (12:24 +0100)]
Get rid of eglot-mode
* eglot.el (eglot--managed-mode): Don't call eglot-mode. When
shutting down, offer to kill server.
(mode-line-misc-info): Update to use eglot--managed-mode
João Távora [Tue, 8 May 2018 15:07:07 +0000 (16:07 +0100)]
Support workspace/applyedit
* eglot.el (eglot--reply): Don't send result or error if not
provided.
(eglot--server-workspace/applyEdit): New server method.
(eglot--apply-text-edits): Rework.
(eglot--apply-workspace-edit): New helper.
(eglot-rename): Simplify.
João Távora [Tue, 8 May 2018 12:37:35 +0000 (13:37 +0100)]
Support textdocument/rename
* README.md: Mention rename support.
* eglot.el (eglot--uri-to-path): Handle uri hidden in keywords.
(eglot--apply-text-edits): New helper.
(eglot-rename): New interactive command.
(eglot--client-capabilities): Add rename capability.
João Távora [Tue, 8 May 2018 10:38:02 +0000 (11:38 +0100)]
Reasonable textdocument/documenthighlight support
* README.md: Update.
* eglot.el (eglot--current-buffer-TextDocumentPositionParams): New
helper.
(xref-backend-identifier-completion-table): Refactor a bit.
(xref-backend-identifier-at-point): Use when-let and
eglot--current-buffer-TextDocumentPositionParams
(xref-backend-definitions, xref-backend-references): Refactor a
bit.
(eglot-completion-at-point): Use
eglot--current-buffer-TextDocumentPositionParams
(eglot-eldoc-function): Rewrite to handle
textDocument/documentHighlight.
(eglot--highlights): New variable.
(eglot--client-capabilities): Update with support for documentHighlight.
João Távora [Tue, 8 May 2018 01:05:03 +0000 (02:05 +0100)]
Fix odd bugs
* eglot.el (eglot--process-receive, eglot--request): Set status to
actual error message.
(eglot--managed-mode): Manage imenu-create-index-function
correctly.
(eglot--mode-line-format): Print error status.
João Távora [Mon, 7 May 2018 22:43:03 +0000 (23:43 +0100)]
Half-decent imenu support via textdocument/documentsymbol
* README.md: Update capability
* eglot.el (eglot--lsp-position-to-point): New function.
(eglot--managed-mode): Handle imenu-create-index-function.
(eglot--server-textDocument/publishDiagnostics): Use
eglot--lsp-position-to-point.
(eglot-imenu): New function.
(eglot--client-capabilities): Capable of documentSymbol.
João Távora [Mon, 7 May 2018 21:56:20 +0000 (22:56 +0100)]
Only request stuff that server says it's capable of
* eglot.el (eglot--server-capable): New helper.
(eglot-xref-backend)
(xref-backend-identifier-completion-table)
(xref-backend-references, xref-backend-apropos)
(eglot-completion-at-point, eglot-eldoc-function): Use it.
João Távora [Mon, 7 May 2018 15:32:23 +0000 (16:32 +0100)]
Solve another textdocument/didchange bug
* eglot.el (eglot--signal-textDocument/didChange): Rework a bit.
(eglot--after-change): Store the actual after-text in the
eglot--recent-after-changes.
João Távora [Mon, 7 May 2018 14:04:02 +0000 (15:04 +0100)]
Support javascript's javascript-typescript-langserver
* README.md: Improve a bit
* eglot.el (eglot--make-process): Take MANAGED-MAJOR-MODE arg
(eglot-executables): Add basic javascript support.
(eglot--connect): Pass mode to eglot--make-process
(eglot--interactive): Check that guessed command is a listp.
(eglot): Minor improvement to message.
(eglot--current-buffer-TextDocumentItem): Guess language from mode
symbol.
João Távora [Mon, 7 May 2018 12:42:56 +0000 (13:42 +0100)]
Workaround two suspected emacs bugs
* eglot.el (eglot--process-filter): Use a proper unique tag. Use
unwind-protect.
(eglot--sync-request): Rework.
(eglot--server-client/registerCapability): Use a proper done tag.
João Távora [Sat, 5 May 2018 10:26:12 +0000 (11:26 +0100)]
Half-decent xref support
* eglot.el
(eglot--xref-known-symbols): New hacky var.
(eglot--xref-reset-known-symbols): New helper.
(xref-find-definitions, xref-find-references): Advise after to
call the new helper.
(xref-backend-identifier-completion-table): Rework.
(eglot--xref-make): New helper.
(xref-backend-definitions): Use it.
(xref-backend-references, xref-backend-apropos): Implement.
(eglot--obj): Add a debug spec.
(eglot--lambda): Add debug spec.
João Távora [Sat, 5 May 2018 01:29:06 +0000 (02:29 +0100)]
Very basic xref support
* eglot.el (eglot--pos-to-lisp-position): Move up.
(eglot--mapply, eglot--lambda): New helpers.
(eglot--uri-to-path): New helper.
(eglot--managed-mode): Manage xref-backend-functions.
(eglot-xref-backend): New function.
(xref-backend-identifier-completion-table)
(xref-backend-identifier-at-point)
(xref-backend-definitions): New methods.
(xref-backend-references)
(xref-backend-apropos): New methods, still unimplemented.
João Távora [Sat, 5 May 2018 01:16:10 +0000 (02:16 +0100)]
New helper eglot--sync-request
This should help with xref definitions
* eglot.el (eglot--request): Rework a bit. Continuation is always
cleared on timeout, regardless of user-supplied fn.
(eglot--sync-request): New function.
(eglot--process-receive): watch out for vector results.
João Távora [Sat, 5 May 2018 01:24:37 +0000 (02:24 +0100)]
Cleanup mistake with textdocumentitem and textdocumentidentifier
Also introduce eglot--path-to-uri
* eglot.el (eglot--path-to-uri): Rename from eglot--uri and rework.
(eglot--connect): Use it.
(eglot--current-buffer-TextDocumentIdentifier): New function.
(eglot--current-buffer-VersionedTextDocumentIdentifier)
(eglot--signal-textDocument/didChange)
(eglot--signal-textDocument/didClose)
(eglot--signal-textDocument/willSave)
(eglot--signal-textDocument/didSave): Use it.
João Távora [Fri, 4 May 2018 11:17:26 +0000 (12:17 +0100)]
Handle requests from server correctly
* eglot.el (eglot--process-receive): Redesign.
(eglot--process-send): Take REPLY arg. Discover if message is error.
(eglot--reply): new function
(eglot--log-event): Tweak docstring.
(eglot--process-receive): Reply with -32601 if unimplemented.
(eglot--server-window/showMessageRequest)
(eglot--server-client/registerCapability): Use eglot--reply
João Távora [Fri, 4 May 2018 09:49:34 +0000 (10:49 +0100)]
Eglot-editing-mode becomes eglot--managed-mode
* eglot.el (eglot--sentinel): Use eglot--managed-mode.
(eglot--managed-mode-map): Renamed from eglot-editing-mode-map.
(eglot--managed-mode): Renamed from eglot-editing-mode.
(eglot-mode): Simplify.
(eglot--buffer-managed-p): New function.
(eglot--maybe-activate-editing-mode): Simplify.