[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Eglot and Tramp

From: João Távora
Subject: Eglot and Tramp
Date: Mon, 15 Jun 2020 17:53:21 +0100

[ 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] =
> > [2] =
> > [3] =
> 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 


  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.


;;; 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"
   (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)
      (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))
       (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 via email to

[Prev in Thread] Current Thread [Next in Thread]