Eglot and Tramp

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Eglot and Tramp

João Távora
[ Felipe, I don't subscribe to tramp-devel, so please next time CC me in
these emails so that we try to fill in the blanks when there's something
not quite clear ]

Hi Michael,

> > I don't know if it's worth since it's not an `emacs -Q` test case
> >
> > but
> >
> > we can reproduce the error in my branch of eglot [1].
> >
> > The unit tests fail [2] because the the initialization json is sent,
> > but does not reach the remote server [3].
> >
> > To reproduce it locally, you need to setup a passwordless ssh access to
> > localhost, Emacs >= 27, pyls and eglot dependencies
> >
> > [1] = https://github.com/FelipeLema/eglot/tree/tramp-support
> > [2] = https://travis-ci.org/github/joaotavora/eglot/builds/686649196#L559
> > [3] = https://github.com/joaotavora/eglot/pull/463#issuecomment-629363409
>  
> I had a look on this, but I cannot extract a simple to run test for
> me. For further investigation, I would need some steps to apply (they
> must not need to start with "emacs -Q", cloning something at the
> beginning would be OK).

Thanks for looking into this.  I fully understand avoiding the complex
setup, so I've put together a small Elisp program that you can run from
Emacs -Q.

The test program, which you're meant to use inside the Elisp
eglot-tramp.el file directly, should work regardless of whether you open
that file as a Tramp path or not.

However, it exhibits strange behaviour when using Tramp.  It only works
sometimes, and often it will fail with:

  File is missing: File `/ssh:localhost:/tmp/tramp.thP95o' not found on remote host

or

  tramp-signal-hook-function: Cannot do file visiting in a non-empty buffer

I think it's related to Tramp's support of the :stderr option to
make-process, which assigns a buffer-file-name to that otherwise
fileless buffer.

There are two tests you can do within eglot-tramp.el: one using the
usual "cat" program, the other one is more interesting and requires that
you download "clangd", an LSP server ('sudo apt install clangd' will
probably do).

But if you don't want to do that (download "clangd"), any program that
spits out stdout and stderr should have the same effect.

> Furthermore, reading [3], it seems to me that you have already found a
> limitation in sending chunks to the remote. Teaching jsonrpc to send
> several chunks up to 4096 bytes could solve the problem, right?

I don't think so.  I believe that has been proven unnecessary: one just
has to use ensure tramp-process-connection-type is set to 'pipe and the
underlying tramp process will accept longer messages.  Actually even
without that it seems to work.  I tested this with my program and long
"cat" input.

João


;;; eglot-tramp.el -*- lexical-binding: t; -*-
(require 'tramp)

(defvar eglot-tramp-process nil)  (defvar eglot-tramp-program "cat")

(defun eglot-tramp (beg end &optional keep-alive)
  "Silly program that sends BEG..END to a process via TRAMP"
  (interactive
   (if (region-active-p)
       (list (region-beginning) (region-end) current-prefix-arg)
     (error "region must be active")))
  (when (and (not keep-alive) (process-live-p eglot-tramp-process))
    (kill-process eglot-tramp-process))
  (let* ((buffer (get-buffer-create "*eglot-tramp*"))
         (stderr-buffer (get-buffer-create "*eglot-tramp-error*"))
         (str (buffer-substring-no-properties beg end)))
    (unless (and eglot-tramp-process
                 (process-live-p eglot-tramp-process)
                 keep-alive)
      (if (process-live-p eglot-tramp-process)
          (kill-process eglot-tramp-process))
      (setq eglot-tramp-process
            (make-process :command eglot-tramp-program
                          :name "eglot-tramp"
                          :buffer buffer
                          :stderr stderr-buffer
                          :coding 'utf-8-emacs-unix
                          :file-handler (file-remote-p default-directory)
                          :connection-type 'pipe)))
    (with-current-buffer buffer
      (goto-char (point-max))
      (insert-before-markers
       (format "\n----About to insert %s characters----\n"
               (length str))))
    (process-send-string eglot-tramp-process (concat str "\n"))
    (accept-process-output eglot-tramp-process 30)
    (display-buffer buffer)))

;; Instructions for testing with "cat":

(setq eglot-tramp-program '("cat"))

;; Select and use this region for testing with 'cat'.  Just select
;; the region and type M-x eglot-tramp.  Doing this repeatedly should be
;; no problem.

;; Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer
;; ac enim massa. In hac habitasse platea dictumst. Maecenas dolor
;; nulla, euismod in augue sit amet, suscipit semper dui. In
;; pulvinar libero ut tortor dignissim, ut aliquet augue
;; pulvinar. Integer tempor scelerisque libero, in fermentum enim
;; tempus et. Donec et finibus velit. Nulla eu augue eu ex commodo
;; porta. Nulla at ullamcorper magna.

;; Now, with clagnd

(setq eglot-tramp-program '("clangd" "--log=verbose"))

;; Uncomment, then select the next paragraph (from the "C" to the
;; closing "}", inclusive ) for testing with `clangd --log=verbose'
;; Ideally, an LSP response should come in from stdout to the
;; *eglot-tramp* buffer and some debug information should appear
;; via stderr in the *eglot-tramp-error* buffer.

;; Content-Length: 67
;;
;; {"jsonrpc": "2.0",  "id": 1,  "method": "initialize", "params": {}}



Reply | Threaded
Open this post in threaded view
|

Re: Eglot and Tramp

Michael Albinus
João Távora <[hidden email]> writes:

> Hi Michael,

Hi João,

> [ Felipe, I don't subscribe to tramp-devel, so please next time CC me in
> these emails so that we try to fill in the blanks when there's something
> not quite clear ]

Or write an Emacs bug report, if several packages are involved.

> Thanks for looking into this.  I fully understand avoiding the complex
> setup, so I've put together a small Elisp program that you can run from
> Emacs -Q.

Thanks! It was very helpful. I've pushed a fix to master, which ought to
cure this.

> There are two tests you can do within eglot-tramp.el: one using the
> usual "cat" program, the other one is more interesting and requires that
> you download "clangd", an LSP server ('sudo apt install clangd' will
> probably do).
>
> But if you don't want to do that (download "clangd"), any program that
> spits out stdout and stderr should have the same effect.

I've tried both test cases. The clangd variant was a little bit tricky,
because I had to use Fedora's snap installer, and to adapt my remote
$PATH. And the installed clangd didn't return proper messages to my
eyes, but it returned stdout and stderr - all what I need for testing :-)

Could you pls check?

> João

Best regards, Michael.