astoff / digestif

A language server for TeX and friends
Other
264 stars 6 forks source link

Corfu completion error, jsonrpc-error, trying to access unopened document #67

Open ChlorophyII opened 9 months ago

ChlorophyII commented 9 months ago

I am not sure whether it is a corfu problem or a digestif problem, but corfu works fine with other languages, together with Eglot. Here is a minimal config and tex file to reproduce the error. The error appears when corfu tries completion, after typing a few characters.

(use-package emacs
  :init
  (add-to-list 'package-archives
               '("melpa" . "https://melpa.org/packages/") t))

(use-package tex :ensure auctex)

(use-package corfu
  :ensure t
  :custom (corfu-auto t)
  :init (global-corfu-mode))

(use-package eglot :hook (LaTeX-mode . eglot-ensure))

(provide 'init)
\documentclass{article}
\begin{document}
tes
\end{document}

Error message:

Corfu completion error: jsonrpc-error: "request id=34 failed:", (jsonrpc-error-code . 1), (jsonrpc-error-message . "/opt/homebrew/share/lua/5.4/digestif/langserver.lua:34: Trying to access unopened document /Users/ChlorophyII/Documents/test.tex"), (jsonrpc-error-data)

With debug-on-error:

Debugger entered--Lisp error: (jsonrpc-error "request id=52 failed:" (jsonrpc-error-code . 1) (jsonrpc-error-message . "/opt/homebrew/share/lua/5.4/digestif/langserver.lu...") (jsonrpc-error-data))
  signal(jsonrpc-error ("request id=52 failed:" (jsonrpc-error-code . 1) (jsonrpc-error-message . "/opt/homebrew/share/lua/5.4/digestif/langserver.lu...") (jsonrpc-error-data)))
  #f(compiled-function (arg1 arg2 arg3 &rest rest) "Make a request to CONNECTION, wait for a reply.\nLike `jsonrpc-async-request' for CONNECTION, METHOD and PARAMS,\nbut synchronous.\n\nExcept in the case of a non-nil CANCEL-ON-INPUT (explained\nbelow), this function doesn't exit until anything interesting\nhappens (success reply, error reply, or timeout).  Furthermore,\nit only exits locally (returning the JSONRPC result object) if\nthe request is successful, otherwise it exits non-locally with an\nerror of type `jsonrpc-error'.\n\nDEFERRED and TIMEOUT as in `jsonrpc-async-request', which see.\n\nIf CANCEL-ON-INPUT is non-nil and the user inputs something while\nthe function is waiting, then it exits immediately, returning\nCANCEL-ON-INPUT-RETVAL.  Any future replies (normal or error) are\nignored." #<bytecode -0x115d77e935cb8352>)(#<eglot-lsp-server eglot-lsp-server-486bc858> :textDocument/completion (:textDocument (:uri "file:///Users/ChlorophyII/Documents/test.tex") :position (:line 3 :character 3) :context (:triggerKind 1)) :deferred :textDocument/completion :cancel-on-input t)
  apply(#f(compiled-function (arg1 arg2 arg3 &rest rest) "Make a request to CONNECTION, wait for a reply.\nLike `jsonrpc-async-request' for CONNECTION, METHOD and PARAMS,\nbut synchronous.\n\nExcept in the case of a non-nil CANCEL-ON-INPUT (explained\nbelow), this function doesn't exit until anything interesting\nhappens (success reply, error reply, or timeout).  Furthermore,\nit only exits locally (returning the JSONRPC result object) if\nthe request is successful, otherwise it exits non-locally with an\nerror of type `jsonrpc-error'.\n\nDEFERRED and TIMEOUT as in `jsonrpc-async-request', which see.\n\nIf CANCEL-ON-INPUT is non-nil and the user inputs something while\nthe function is waiting, then it exits immediately, returning\nCANCEL-ON-INPUT-RETVAL.  Any future replies (normal or error) are\nignored." #<bytecode -0x115d77e935cb8352>) (#<eglot-lsp-server eglot-lsp-server-486bc858> :textDocument/completion (:textDocument (:uri "file:///Users/ChlorophyII/Documents/test.tex") :position (:line 3 :character 3) :context (:triggerKind 1)) :deferred :textDocument/completion :cancel-on-input t))
  jsonrpc-request(#<eglot-lsp-server eglot-lsp-server-486bc858> :textDocument/completion (:textDocument (:uri "file:///Users/ChlorophyII/Documents/test.tex") :position (:line 3 :character 3) :context (:triggerKind 1)) :deferred :textDocument/completion :cancel-on-input t)
  #f(compiled-function () #<bytecode 0xe761b54c9398bdb>)()
  #f(compiled-function (probe pred action) #<bytecode 0xb17b3f04b64391a>)("" nil t)
  all-completions("" #f(compiled-function (probe pred action) #<bytecode 0xb17b3f04b64391a>) nil)
  completion-pcm--all-completions("" (prefix "t" any "e" any "s") #f(compiled-function (probe pred action) #<bytecode 0xb17b3f04b64391a>) nil)
  completion-substring--all-completions("tes" #f(compiled-function (probe pred action) #<bytecode 0xb17b3f04b64391a>) nil 3 completion-flex--make-flex-pattern)
  #f(compiled-function (string table pred point) "Get flex-completions of STRING in TABLE, given PRED and POINT." #<bytecode 0x14e9e00a60879cc5>)("tes" #f(compiled-function (probe pred action) #<bytecode 0xb17b3f04b64391a>) nil 3)
  apply(#f(compiled-function (string table pred point) "Get flex-completions of STRING in TABLE, given PRED and POINT." #<bytecode 0x14e9e00a60879cc5>) ("tes" #f(compiled-function (probe pred action) #<bytecode 0xb17b3f04b64391a>) nil 3))
  completion-flex-all-completions("tes" #f(compiled-function (probe pred action) #<bytecode 0xb17b3f04b64391a>) nil 3)
  #f(compiled-function (style) #<bytecode -0x18c966dab7576dbf>)(flex)
  completion--some(#f(compiled-function (style) #<bytecode -0x18c966dab7576dbf>) (flex basic partial-completion emacs22))
  completion--nth-completion(2 "tes" #f(compiled-function (probe pred action) #<bytecode 0xb17b3f04b64391a>) nil 3 (metadata (category . eglot) (display-sort-function . #f(compiled-function (completions) #<bytecode 0x3905570360e206d>))))
  completion-all-completions("tes" #f(compiled-function (probe pred action) #<bytecode 0xb17b3f04b64391a>) nil 3 (metadata (category . eglot) (display-sort-function . #f(compiled-function (completions) #<bytecode 0x3905570360e206d>))))
  apply(completion-all-completions ("tes" #f(compiled-function (probe pred action) #<bytecode 0xb17b3f04b64391a>) nil 3 (metadata (category . eglot) (display-sort-function . #f(compiled-function (completions) #<bytecode 0x3905570360e206d>)))))
  corfu--filter-completions("tes" #f(compiled-function (probe pred action) #<bytecode 0xb17b3f04b64391a>) nil 3 (metadata (category . eglot) (display-sort-function . #f(compiled-function (completions) #<bytecode 0x3905570360e206d>))))
  corfu--recompute("tes" 3 #f(compiled-function (probe pred action) #<bytecode 0xb17b3f04b64391a>) nil)
  corfu--update(interruptible)
  corfu--exhibit(auto)
  corfu--auto-complete-deferred((#<window 6 on test.tex> #<buffer test.tex> 231 46))
  apply(corfu--auto-complete-deferred (#<window 6 on test.tex> #<buffer test.tex> 231 46))
  timer-event-handler([t 26079 30907 817136 nil corfu--auto-complete-deferred ((#<window 6 on test.tex> #<buffer test.tex> 231 46)) nil 0 nil])

Versions: OS: macOS Sonoma 14.3.1 (23D60) Emacs: 29.2 Corfu: 1.2 Eglot: 1.12.29 digestif: 0.5.1-1

Any insight in how this may be resolved?

astoff commented 9 months ago

Thanks for the report. To be sure, $HOME/Documents/test.tex is the file you're currently editing, right?

ChlorophyII commented 9 months ago

Thanks for the report. To be sure, $HOME/Documents/test.tex is the file you're currently editing, right?

Yes.

skyler544 commented 7 months ago

I'm still in the process of debugging a similar problem, but digestif works out-of-the-box with the Emacs builtin tex-mode but not with auctex. I switched to using a Makefile instead of trying to use the auctex build commands; I'll post the Makefile here when I finish it.

skyler544 commented 7 months ago

Here's the Makefile:

LATEX   := latexmk -interaction=nonstopmode

all: clean-all build

build:
    $(LATEX)  -shell-escape -f -pdf

clean:
    $(LATEX) -c

clean-all:
    $(LATEX) -C

I'm no LaTeX whiz; there are probably many situations where this isn't sufficient. However, it works perfectly for the few documents I maintain, including automatic BibTeX and includes of files from subdirectories. The builtin tex-mode plus digestif plus this Makefile seems like a better experience than AUCTeX so far.

coffeemug commented 5 months ago

Confirming experiencing the same problem. Eglot+digestif gives me OP's error in auctex, but not in emacs built-in tex mode.

evgeniysharapov commented 4 months ago

The problem here is most likely you use AucTeX, that means that by default major-mode is something like ConTeXt-mode rather than context-mode. Below I am using ConTeXt-mode as an example, but adjust it to your case be it TeX-mode or LaTeX-mode.

If you use eglot it uses major-mode to figure out and to send language id to the LSP server. In fact you can run something like M-x eglot-events-buffer and see what it sends to the LSP server. If you use AucTeX it will send ConTeXt as a language id and thus LSP server throws an error Invalid LSP language id 'ConTeXt.

If we look inside langserver.lua we will see the list of languages it supports

local languageId_translation_table = {
  bibtex = "bibtex",
  context = "context",
  doctex = "doctex",
  latex = "latex",
  plain = "plain",
  plaintex = "plain",
  ["plain-tex"] = "plain",
  tex = "latex", -- this is for vim; maybe "tex" should mean "tex file, undecided format"
  texinfo = "texinfo"
}

The problem could be resolved by sending a correct language id to the LSP server. If you are using eglot you are in luck. You can specify a property for the symbol of the major mode you are in like so

(put 'ConTeXt-mode 'eglot-language-id "context")

Now you can reconnect eglot and it should work

astoff commented 4 months ago

@evgeniysharapov In fact, if I go to eglot-events-buffer I see all my Digestif buffers get the language ID "tex", which seems to be by design, when I look up the definition of eglot--lookup-mode. So this is a bug in the definiton of eglot-server-programs.

That said, why do you think this is related to the bug described here?

@ChlorophyII, @skyler544: I can't reproduce this problem, but if you could call M-x eglot-events-buffer and post the contents here (or send my by email privately) I might be able to understand the issue.

evgeniysharapov commented 4 months ago

@astoff It could be specific to the eglot configuration. I have it with default settings and had this issue when used digestif with AucTeX. Plain tex-mode that comes with Emacs works fine. It is not the bug of digestif and I don't think it's the bug in eglot either. Perhaps an oddity of AucTeX. The steps I have described fixed the issue, so I thought I would share it as a workaround

  (add-hook 'ConTeXt-mode-hook
            (lambda ()
              (setq lsp-tex-server 'digestiff)
              (put 'ConTeXt-mode 'eglot-language-id "context")
              (eglot-ensure))))
mguzmann commented 1 month ago

I confirm I have the same issue with eglot + digestif. @evgeniysharapov solution doe snot work for me.

astoff commented 1 month ago

@mguzmann Can you post a backtrace? You should get one with M-x toggle-debug-on-error.

mguzmann commented 1 month ago

`Debugger entered--Lisp error: (jsonrpc-error "request id=71 failed:" (jsonrpc-error-code . 1) (jsonrpc-error-message . "/home/matias/.digestif/digestif/langserver.lua:34:...") (jsonrpc-error-data)) signal(jsonrpc-error ("request id=71 failed:" (jsonrpc-error-code . 1) (jsonrpc-error-message . "/home/matias/.digestif/digestif/langserver.lua:34:...") (jsonrpc-error-data)))

(# :textDocument/completion (:textDocument (:uri "file:///home/matias/Documentos/Uni/classes/cl-typo...") :position (:line 147 :character 6) :context (:triggerKind 1)) :deferred :textDocument/completion :cancel-on-input t)

apply(# (# :textDocument/completion (:textDocument (:uri "file:///home/matias/Documentos/Uni/classes/cl-typo...") :position (:line 147 :character 6) :context (:triggerKind 1)) :deferred :textDocument/completion :cancel-on-input t)) jsonrpc-request(# :textDocument/completion (:textDocument (:uri "file:///home/matias/Documentos/Uni/classes/cl-typo...") :position (:line 147 :character 6) :context (:triggerKind 1)) :deferred :textDocument/completion :cancel-on-input t)

f(compiled-function () #<bytecode -0x13f0dc4b1de23531>)()

f(compiled-function (probe pred action) #<bytecode 0x1d27e1025dd04780>)("" nil t)

completion-pcm--all-completions("" (prefix "i") #f(compiled-function (probe pred action) #<bytecode 0x1d27e1025dd04780>) nil) completion-substring--all-completions("i" #f(compiled-function (probe pred action) #<bytecode 0x1d27e1025dd04780>) nil 1 completion-flex--make-flex-pattern) completion-flex-all-completions("i" #f(compiled-function (probe pred action) #<bytecode 0x1d27e1025dd04780>) nil 1)

f(compiled-function (style) #<bytecode -0x1b64e8b274eba5bf>)(flex)

completion--some(#f(compiled-function (style) #<bytecode -0x1b64e8b274eba5bf>) (flex basic fuzzy)) completion--nth-completion(2 "i" #f(compiled-function (probe pred action) #<bytecode 0x1d27e1025dd04780>) nil 1 (metadata (category . eglot) (display-sort-function . #))) completion-all-completions("i" #f(compiled-function (probe pred action) #<bytecode 0x1d27e1025dd04780>) nil 1 (metadata (category . eglot) (display-sort-function . #))) company--capf-completions("i" "" #f(compiled-function (probe pred action) #<bytecode 0x1d27e1025dd04780>) nil (metadata (category . eglot) (display-sort-function . #))) company-capf--candidates-1("i" "" #f(compiled-function (probe pred action) #<bytecode 0x1d27e1025dd04780>) nil (metadata (category . eglot) (display-sort-function . #)) nil) company-capf--candidates("i" "")

(candidates "i" "")

company-flx-company-capf-advice(# candidates "i" "") apply(company-flx-company-capf-advice # (candidates "i" "")) company-capf(candidates "i" "") company--multi-backend-adapter-candidates((company-capf company-yasnippet) 2 nil) company--multi-backend-adapter((company-capf :with company-yasnippet) candidates "i" "") apply(company--multi-backend-adapter (company-capf :with company-yasnippet) (candidates "i" "")) company-call-backend-raw(candidates "i" "") company--fetch-candidates("i" "") company-calculate-candidates("i" nil "") company--begin-new() company--perform() company-auto-begin() company-idle-begin(#<buffer main.tex> #<window 3 on main.tex> 898 4041) apply(company-idle-begin (#<buffer main.tex> #<window 3 on main.tex> 898 4041)) timer-event-handler([t 26402 22981 558990 nil company-idle-begin (#<buffer main.tex> #<window 3 on main.tex> 898 4041) nil 65000 nil]) `