9fans / acme-lsp

Language Server Protocol tools for the acme text editor
MIT License
195 stars 25 forks source link

Multiple language id, file extension pairs support (trying ocamllsp) #37

Closed gdiazlo closed 4 years ago

gdiazlo commented 4 years ago

Hello

I am trying the ocaml-lsp server (https://github.com/ocaml/ocaml-lsp) and it requires a combination of file-extension / languageId parameters which I am unable to set up using acme-lsp.

I guess DetectLanguage is only prepared for golang and python, and it might work if the file extension is the same as the language id in the language server you're using. I've tried scala metals in the past and it worked, probably because of this.

Seems that making the obvious change to the function DetectLanguage gets the ocaml-lsp server working.

Adding a language id parameter in acme-lsp would come handy to support more languages.

This server supports multiple languages a the same time like ReasonML and Ocaml. My guess is that each time one is opened in an editor, the apropriate extension/langId is generated.

Something like:

$ acme-lsp -lang ml:ocaml -lang rml:reasonml -lang ...

could work. What do you think?

gabi

fhs commented 4 years ago

The spec defines these languages: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentItem I'm surprised ocaml isn't even there. I think I originally envisioned of just having a big table mapping extension to language since there are not many languages, but if we're going to have languages not listed in spec, it might be worth making it configurable.

I think we can extend the -server and -dial flags to take the language ID instead of adding a new flag. Something like this:

$ acme-lsp -server '\.ml$:ocaml:ocaml-lsp' ...
fhs commented 4 years ago

Extending -server like that would mean you'll have separate instances of the lsp server running for each file extension. It's easier with the config file:

[Servers]
    [Servers.ocamllsp]
    Command = ["ocaml-lsp"]

[[FilenameHandlers]]
Pattern = '\.ml$'
LangID = "ocaml"
ServerKey = "ocamllsp"

[[FilenameHandlers]]
Pattern = '\.rml$'
LangID = "reasonml"
ServerKey = "ocamllsp"

I'm not sure how that would translate to the command line. Maybe like this:

$ acme-lsp \
-filehandler '\.ml$:ocaml:ocamllsp' \
-filehandler '\.rml$:reasonml:ocamllsp' \
-servercmd ocamllsp:ocaml-lsp
gdiazlo commented 4 years ago

I think the first approach is quite concise, each -server representing a single instance of a language server with all the ext:landID it supports. Shouldn't be easier to implement too?

$ acme-lsp -server '\.ml$@ocaml|\.mli$@ocaml|\.rml$@reasonml:ocaml-lsp options' -server '\.go$:gopls' ...

I haven't read that code for the current acme-lsp though :(

fhs commented 4 years ago

I opted for comma as the separator instead of | because we might want to use | in the regexp.

$ HOME=/ ./acme-lsp -showconfig -server '\.ml$@ocaml,\.mli$@ocaml,\.rml$@reasonml:ocaml-lsp options'
....
[Servers]
  [Servers._userCmdServer0]
    Command = ["ocaml-lsp", "options"]
    Address = ""
    StderrFile = ""
    LogFile = ""

[[FilenameHandlers]]
  Pattern = "\\.ml$"
  LanguageID = "ocaml"
  ServerKey = "_userCmdServer0"

[[FilenameHandlers]]
  Pattern = "\\.mli$"
  LanguageID = "ocaml"
  ServerKey = "_userCmdServer0"

[[FilenameHandlers]]
  Pattern = "\\.rml$"
  LanguageID = "reasonml"
  ServerKey = "_userCmdServer0"
gdiazlo commented 4 years ago

nice! works great :+1: