Skip to content
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

Making lsp work over tramp #361

Open
fakedrake opened this issue Jan 10, 2022 · 7 comments
Open

Making lsp work over tramp #361

fakedrake opened this issue Jan 10, 2022 · 7 comments

Comments

@fakedrake
Copy link

fakedrake commented Jan 10, 2022

I am not quite sure how obscure my case is but I had some trouble setting up lsp. I thought I would open this issue for posterity. The fundamental problem was two-fold: the rustic readme suggested using lsp-stdio-connection rather than lsp-tramp-connection when defining the remote server and that lsp itself is (probably) inconsistent w.r.t. when it uses executable-find and when it doesnt. The solution was to advise executable-find to return the same string it receives when the argument is a remote executable path:

(defun rustic-lsp-conn-command ()
  (cons
   (executable-find "rust-analyzer" t)
   (cl-rest lsp-rust-analyzer-server-args)))

(with-eval-after-load "lsp-rust"
  (defun start-file-process-shell-command@around (start-file-process-shell-command name buffer &rest args)
    "Start a program in a subprocess.  Return the process object
for it. Similar to `start-process-shell-command', but calls
`start-file-process'."
    ;; On remote hosts, the local `shell-file-name' might be useless.
    (let ((command (mapconcat 'identity args " ")))
      (funcall start-file-process-shell-command name buffer command)))

  (advice-add 'start-file-process-shell-command
              :around #'start-file-process-shell-command@around)

 (lsp-register-client
  (make-lsp-client
   :new-connection (lsp-tramp-connection #'rustic-lsp-conn-command)
   :remote? t
   :major-modes '(rust-mode rustic-mode)
   :initialization-options 'lsp-rust-analyzer--make-init-options
   :notification-handlers (ht<-alist lsp-rust-notification-handlers)
   :action-handlers (ht ("rust-analyzer.runSingle" #'lsp-rust--analyzer-run-single))
   :library-folders-fn (lambda (_workspace) lsp-rust-library-directories)
   :after-open-fn (lambda ()
                    (when lsp-rust-analyzer-server-display-inlay-hints
                      (lsp-rust-analyzer-inlay-hints-mode)))
   :ignore-messages nil
   :server-id 'rust-analyzer-remote)))


(defun expand-file-name-remote (file)
  "A tramp-friendly version of expand-file-name.  Expand file
relative to the remote part of default-directory."
  (let ((file (expand-file-name file))
        (dir-remote (file-remote-p default-directory)))
    (if (file-remote-p file)
        ;; if file is already remote, return it
        file
      ;; otherwise prepend the remote part (if any) of default-directory
      (concat dir-remote file))))

(defun around-ad-executable-find (orig-fn cmd &optional is-remote)
  (let ((remote-cmd (if is-remote (expand-file-name-remote cmd) cmd)))
    (if (file-executable-p remote-cmd)
        cmd
      (funcall orig-fn cmd is-remote))))
(advice-add 'executable-find :around 'around-ad-executable-find)

Please advise on whether there is something more official that we can do with this information (and if more of it is required)

@fakedrake fakedrake changed the title Making rustic work over tramp Making lsp work over tramp Jan 10, 2022
@brotzeit
Copy link
Owner

brotzeit commented Jan 10, 2022

I also didn't get this to work #337. But it seems it was working when the docs were added...

@brotzeit
Copy link
Owner

@yyoncho sorry for the ping, I know you're quite busy. Do you see anything obvious that we don't notice ?

@fakedrake
Copy link
Author

Just to make sure that I am clear: with the above config lsp works (mostly) fine but it diverges a bit from the docs. Sometimes when the remote server dies the client is unable to restart it but I haven't been able to consistently reproduce it.

@buzmeg
Copy link

buzmeg commented Apr 26, 2022

One thing I would like to flag is that you likely need to have something like this stashed somewhere:

(require 'tramp)
(add-to-list 'tramp-remote-path 'tramp-own-remote-path)

Otherwise, tramp completely blows away your path on the remote machine and finding rust-analyzer is unlikely to work.

Figuring this out caused me quite a lot of grief.

@brotzeit
Copy link
Owner

brotzeit commented Dec 2, 2022

Unfortunately, lsp-mode doesn't seem to work with tramp. Hopefully somebody can fix this issue at some point. If you need to work with tramp the only option is eglot.

@cpoile
Copy link

cpoile commented Oct 19, 2023

Just wondering if there was any progress on this? I can confirm that the above code doesn't work for Emacs 29.1, and hoping maybe there was a new solution?

@bleggett
Copy link

bleggett commented Dec 6, 2023

(note: using DOOM emacs FWIW)

I have this:

(add-to-list 'tramp-remote-path 'tramp-own-remote-path)

and when I open a vterm shell in a tramp project, I can confirm that rust-analyzer is found in $PATH on the remote box - but rustic tries to find it from a location that doesn't exist on the remote box and doesn't seem to respect the remote $PATH when looking.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants