kristoff-it / superhtml

HTML Language Server & Templating Language Library
MIT License
725 stars 25 forks source link

No instructions for Emacs installation on the README #49

Closed OrionRandD closed 2 weeks ago

OrionRandD commented 3 weeks ago

Any instruction to integrating superhtml on Emacs? If so, could you add it on the README? If not, could you add a note saying not for Emacs or the like? Thx.

kristoff-it commented 3 weeks ago

I don't use Emacs, but integration is definitely doable, it just needs somebody who uses the editor and is interested in SuperHTML to figure that out.

You can either integrate it as a CLI tool, or via some language server extension (which I assume might be available for Emacs).

If you decide to figure this out, feel free to PR your findings.

ndegruchy commented 3 weeks ago

I can get Emacs eglot package to pick up SuperHTML, but it seems to be balking at me for passing the wrong content type when I use web-mode. I haven't tried the built-in sgml-mode.

I get the following:

[eglot] Server reports (type=1): Unrecognized languageId, expected are: html, superhtml, xml

My configuration for eglot looks like this so far:

;;;; Eglot
(use-package eglot
  :defer t
  :hook ((web-mode . eglot-ensure)
     (markdown-mode . eglot-ensure)
     (tex-mode . eglot-ensure))
  :config
  (add-to-list 'eglot-server-programs '(tex-mode . ("texlab")))
  (add-to-list 'eglot-server-programs '(markdown-mode . ("marksman")))
  (add-to-list 'eglot-server-programs '(web-mode . ("superhtml" "lsp"))))

I feel like I'm close, though.

kristoff-it commented 3 weeks ago

languageId is a core concept of how a LSP client talks to a server, eglot must definitely have some info on it or knob that you can turn.

In other editors it usually works like this:

file extension maps to a languageId in the editor, editor communicates to the language server the languageId of a given file, language server decides what to do with the information.

so you might want to check what files you're trying to have the language server look at (must be .html and .shtml files only) and which languageId is being set for them

ndegruchy commented 3 weeks ago

I just tried sgml-mode (the default mode for HTML) and it still doesn't like it. I'm wondering what Emacs is reporting to SuperHTML as the content type. Seems like the mode.

Yep, seems so:

[err] (super_lsp): unrecognized language id: 'sgml'
[err] (default): unrecognized language id, exiting

null
/Users/kristoff/superhtml/src/cli/lsp.zig:154:13: 0x10465c7 in loop (superhtml)
/Users/kristoff/superhtml/src/cli/lsp.zig:35:20: 0x1047b4d in main (superhtml)
/Users/kristoff/zig/0.13.0/files/lib/std/start.zig:524:37: 0x102ad56 in posixCallMainAndEx
it (superhtml)
/Users/kristoff/zig/0.13.0/files/lib/std/start.zig:266:5: 0x102ac91 in _start (superhtml)
???:?:?: 0x1 in ??? (???)
Unwind information for `???:0x1` was not available, trace may be incomplete

I wonder if eglot can be configured to send something else. Right now it seems to just chop off -mode from the mode and hope for the best.

ndegruchy commented 3 weeks ago

Okay, I'm getting somewhere. eglot helpfully provides a buffer for monitoring events. It looks like it's not setting the languageId to HTML properly.

[jsonrpc] e[12:40:29.600] --> textDocument/didOpen {"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///home/nathan/Projects/old-deg/index.html","version":0,"languageId":"web","text":"

I see in the documentation that there are ways of passing elisp properties as JSON. Going to try fiddling with that...

ndegruchy commented 3 weeks ago

I'm hoping someone else can look at this (I'm at work :face_exhaling: ). It doesn't seem like what I do is being passed out to SuperHTML:

  (add-to-list 'eglot-server-programs `(web-mode . ("superhtml" "lsp"
                                :initializationOptions
                                (:params
                                 (:languageId "html"))))))
[jsonrpc] e[12:57:06.004] --> initialize[1] {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"processId":19775,"clientInfo":{"name":"Eglot","version":"1.17.30"},"rootPath":"/home/nathan/Projects/old-deg/","rootUri":"file:///home/nathan/Projects/old-deg","initializationOptions":{"params":{"languageId":"html"}}...

but then...

[jsonrpc] e[12:57:06.115] --> textDocument/didOpen {"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///home/nathan/Projects/old-deg/index.html","version":0,"languageId":"web","text":"...
kristoff-it commented 3 weeks ago

I guess that option allows you to set extra flags for the init event (the connection handshake), and not for subsequent requests, which makes sense, since you might want to open different files with different languageIds with the same language server.

SuperHTML itself supports vanilla HTML files (.html, langaugeId = html) and SuperHTML templates (.shtml, languageId = superhtml), for example.

In other words eglot needs to have some piece of information defined on a per-buffer basis, in order to report the correct languageId.

In any case, this is all very core stuff to LSP so if you interact with the maintainer of eglot, I would expect them to be interested in improving this stuff in eglot.

kristoff-it commented 3 weeks ago

Looking at the comments here, it seems to have been solved already:

https://github.com/joaotavora/eglot/pull/678

ndegruchy commented 3 weeks ago

That did it!

For using eglot with web-mode (or any other mode that doesn't send the correct format) you can use it like this:

(use-package eglot
  :defer t
  :hook ((web-mode . eglot-ensure)
     ...)
  :config
  ...
  (add-to-list 'eglot-server-programs '((web-mode :language-id "html") . ("superhtml" "lsp"))))

This, of course, also assumes that superhtml is in your $PATH.

Thanks!