-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for Emacs #110
Comments
I started using lsp-mode.el with LanguageServer.jl a few days ago and had the same problems. The first error might be caused by an empty The second error can temporarily be fixed by changing the shutdown request to a shutdown notification |
Thanks for the tips-- both worked great. |
This is very cool! On the empty initialized request, that looks like a bug in lsp-mode.el? Or is that something we should address on our end? I guess the correct way to handle the exist story would be to send an exit notification? I don't really understand the shutdown request, I guess the idea is that the server stops processing messages after that one, but the process doesn't shut down? Would be great if one of you would add a wiki page on how to get emacs working and then open a PR that adds a link to that wiki page to the README, similar to what we have for Neovim. |
The empty
According to the language server 3.0 protocol, the
Looks like it might not be a bug in lsp-mode.el. I could make a PR to change the method signature if its ok with you. I guess the idea of sending a shutdown request before sending the exit notification is that the server could do some cleanup, but I am not sure what the LanguageServer should do when a shutdown request is issued. Maybe the LanguageServer could just send an empty response? I can start writing a wiki page over the weekend and hopefully send a PR at the beginning of next week. |
I've also been trying to get the language server working with emacs and I haven't had much success. If either of you (@MartinWolke @rsrock) could be so kind to post your setup I would be very grateful and I'd be happy to help in any way I could. |
That looks right to me, but lets see what @ZacLN says, he has done more on this part of the code lately.
Yes, just doing nothing on that one also sounds good to me. Does that mean that we can easily integrate once we have those two changes merged here in LanguageServer.jl? That would be very cool! |
That fix to the method signature looks fine to me, though could it just be changed to I was confused by the descriptions for shutdown/exit though I suppose then can both just call |
I think we might just try and see what happens if we handle a shutdown request by essentially doing nothing? I assume the emacs client is then still sending an exit request, right? |
Ah ok I get you now, PR |
Thank you for making a PR for the shutdown request, @ZacLN. The PR fixes the problem, Emacs is now able to shutdown properly. The emacs-lsp.el language server client always sends an exit notification after sending a shutdown request. |
On the Emacs side of things, I was doing this. Hopefully it can be a useful start. ;;; Code:
(require 'lsp-mode)
(require 'julia-mode)
;; patch, until PR #117 lands
(defun lsp--shutdown-cur-workspace ()
"Shut down the language server process for lsp--cur-workspace"
(lsp--send-notification (lsp--make-notification "shutdown" (make-hash-table)))
(lsp--send-notification (lsp--make-notification "exit" nil))
(lsp--uninitialize-workspace))
;;;###autoload
(lsp-define-stdio-client
'julia-mode "julia" 'stdio
#'(lambda () default-directory)
"Julia Language Server"
'("julia"
"--startup-file=no"
"--history-file=no"
"-e"
"using LanguageServer; server = LanguageServer.LanguageServerInstance(STDIN, STDOUT, false); server.runlinter = true; run(server);")
:ignore-regexps '("^langserver-go: reading on stdin, writing on stdout$"))
(provide 'lsp-julia)
;;; lsp-julia.el ends here I haven't explored options for the default-directory line yet. |
Is this solid enough now that we could add a wiki page like for Neovim that describes how to set this up? Or are there still things that we need to fix here to make this a smooth ride? I'm not an Emacs user, so we need some help here with testing, figuring things out etc. |
Sorry for the delay. I made a PR to fix the initialized issue. There seems to be a new error caused by an empty message send by the emacs package. After opening a .jl file, the lsp-mode.el package sends a While investigating the error, I found it quite usefull to display stackstraces as info messages using the following code in the run method: while true
message = read_transport_layer(server.pipe_in, server.debug_mode)
request = parse(JSONRPC.Request, message)
server.isrunning && serverbusy(server)
process(request, server)
server.isrunning && serverready(server)
try
message = read_transport_layer(server.pipe_in, server.debug_mode)
request = parse(JSONRPC.Request, message)
server.isrunning && serverbusy(server)
process(request, server)
server.isrunning && serverready(server)
catch
info("Stackframe: ")
foreach(s -> info("$s"), catch_stacktrace())
end
end Something like this might be a quite useful feature. |
The error mentioned in the last post is now fixed. I added a wiki entry on how to setup Emacs to work with the LanguageServer. I hope that everything works, but it would be great if someone could test it and provide feedback. |
Perfect, thanks so much! I've asked for some more testers on the julia slack channel. |
Got it working. Current glitches:
in Emacs. They seem to block cursor movement occasionally, maybe something was compiled or parsed. Otherwise it is amazing. Thanks! I will be using it from now on. If I find specific issues, should they be reported in this one, or a new one? |
Thank you for testing! It should be possible to disable the |
Fantastic! As a temporary fix you can comment out lines 34 and 36 of |
Could we somehow use the server capabilities stuff at initialization to decide whether we want to send these non-standard messages? |
One quick option might be to activate non-standard messages using the
According to the 3.0 protocol, another option is to add a new field to the `ClientCapabilities' struct. "Servers receiving a ClientCapabilities object literal with unknown properties should ignore these properties. A missing property should be interpreted as an absence of the capability. " |
I found that I cannot exit Emacs if the language server is not responding: in
How can I force it to stop? |
@tpapp Sometimes the communication to the language server seems to crash. I am not yet sure why. Does terminating the process ( Btw., the |
I experimented with Emacs & LanguageServer.jl earlier, but went back to julia-repl for daily work in September. I would like to try it again, and have two questions:
|
I've toyed with it too, but turned it off recently. From what I've seen, it works well. One annoyance is that eldoc shoves the documentation in the minibuffer. So just moving the point around makes the minibuffer resize like crazy because we have multiline docs. I was starting to look into sending the docs to a dedicated buffer instead (perhaps triggered by a keybinding), but it wasn't a top priority for me right now. |
As a workaround I just display the first line of a multiline comment: (defun julia--hover-format (message)
(if eldoc-echo-area-use-multiline-p
message
(car (split-string message "\n"))))
(advice-add #'lsp--text-document-hover-string :filter-return #'julia--hover-format) My (require 'ess-site)
(require 'julia-mode)
(require 'lsp-mode)
(defun lsp-julia--get-root ()
"Try to find the package directory by searching for a .gitignore file.
If no .gitignore file can be found use the default directory "
(let ((dir (locate-dominating-file default-directory ".gitignore")))
(if dir
(expand-file-name dir)
default-directory)))
(defun lsp-julia--rls-command ()
`("julia" "--startup-file=no" "--history-file=no" "-e"
"using LanguageServer; server = LanguageServer.LanguageServerInstance(STDIN, STDOUT, false); server.runlinter = true; run(server);"))
(defconst lsp-julia--handlers
'(("window/setStatusBusy" .
(lambda (w _p)))
("window/setStatusReady" .
(lambda(w _p)))))
(defun lsp-julia--initialize-client(client)
(mapcar #'(lambda (p) (lsp-client-on-notification client (car p) (cdr p))) lsp-julia--handlers))
(lsp-define-stdio-client lsp-julia "julia" #'lsp-julia--get-root nil
:command-fn #'lsp-julia--rls-command
:initialize #'lsp-julia--initialize-client)
(provide 'lsp-julia)
(defun julia--line-at-location (file line)
(with-temp-buffer
(find-file file)
(goto-char (point-min))
(forward-line line)
(substring (thing-at-point 'line t) 0 -2)))
(defun julia--location-to-xref (location)
"Convert Location object LOCATION to an xref-item.
interface Location {
uri: string;
range: Range;
}"
(lsp--send-changes lsp--cur-workspace)
(let ((uri (string-remove-prefix "file://" (gethash "uri" location)))
(ref-pos (gethash "start" (gethash "range" location))))
(xref-make (julia--line-at-location uri (gethash "line" ref-pos))
(xref-make-file-location uri
(1+ (gethash "line" ref-pos))
(gethash "character" ref-pos)))))
;; use helm-xref
(require 'helm-xref)
(setq xref-show-xrefs-function 'helm-xref-show-xrefs)
;; replace xref message
(defun lsp--location-to-xref (location)
(julia--location-to-xref location)) Overall the setup is useable for me, initializing a large project takes a few seconds though. |
I tried it and the language server keeps crashing with different error messages, e.g.: WARNING: Module URIParser with uuid 26552956908380 is missing from the cache. |
Update: emacs support works pretty well, there are currently issues, because |
LanguageServer.jl works pretty well on emacs (both lsp-mode and eglot), so I think this issue should be closed. |
I've started to play with this in Emacs (using lsp-mode.el), and was finally able to get both sides to talk to each other. Shocked and delighted that jump to symbol works! Here are a couple of questions/issues that I've run into.
I ran into a problem with an empty or malformed message taking down the server right at the start. I solved this by wrapping the
process(request, server)
line inlanguageserverinstance.jl
with a try-catch block, ignoring any errors. I'm guessing there's a better approach, but I'm obviously not too familiar with the inner workings of this package.Emacs refuses to quit, because it cannot shut down the language server. It looks like the required message is not implemented here? https://github.com/JuliaEditorSupport/LanguageServer.jl/blob/eff7b98c8a3a3834dc3111ed96abaef0b9e414bd/src/provider_misc.jl#L68
Can that be added? It does make hacking on this somewhat difficult.
Thanks
The text was updated successfully, but these errors were encountered: