multilspy icon indicating copy to clipboard operation
multilspy copied to clipboard

Allow easy usage of external Language Servers in `multilspy`

Open Moosems opened this issue 1 year ago • 4 comments

If I want to use ruff server as a user and know the command to use and the specific initialization parameters/runtime dependencies it might require, it doesn't seem like it would be too difficult to allow the user to use their own Language Servers if they would be allowed to.

Moosems avatar Jul 08 '24 21:07 Moosems

Dear @Moosems,

Thanks a lot for the great suggestion. Do you have a specific interface in mind that would benefit your usecase? Once we have discussed that, it could be implemented and merged quickly.

LakshyAAAgrawal avatar Jul 15 '24 07:07 LakshyAAAgrawal

If multilspy could be extracted, that would be great. I am looking forward to it :)

adlternative avatar Jul 15 '24 12:07 adlternative

@LakshyAAAgrawal I would imagine it looking something looking something like this:

from monitors4codegen.multilspy import LanguageServer
from monitors4codegen.multilspy.multilspy_config import MultilspyConfig, DefaultInitParams, JavaLang # Python, Rust, and other languages come with language servers
from monitors4codegen.multilspy.multilspy_logger import MultilspyLogger

from time import sleep
...
java_config = MultilspyConfig(language="Java", language_server=JavaLang, init_params=DefaultInitParams)
java_logger = MultilspyLogger()
java_lsp = LanguageServer(java_config, "/abs/path/to/project/root/", logger) # Make the logger default to None and not require it but still allow it (and highly recommend it)
# The server start should probably be automatic as well
java_lsp.open_file("relative/path/to/code_file.java") # Tell the langserver a file has been opened and theoretically allow the flexibility of code snippets
result = java_lsp.request( # use a standard request method that takes a command and pattern matches instead of using a bunch of boilerplate functions
    "Definitions", # We can also add a set of string constants to give a form of spell checking
    "relative/path/to/code_file.java", # Filename of location where request is being made (now the Language Server will use the current state of the file as we describe it)
    # This also means I don't have to save the file on every change
    163, # line number of symbol for which request is being made
    4 # column number of symbol for which request is being made
)
result2 = lsp.request(
    "Completions",
    ...
)
java_lsp.try_kill()
sleep(0.5)
java_lsp.check_kill()
...
custom_py_config = MultilspyConfig(language="Python", language_server=["ruff", "server", "--preview"], init_params=DefaultInitParams) # We can allow a custom server
py_logger = MultilspyLogger()
ruff_langserver = LanguageServer(custom_py_config, "some/random/path", py_logger) # Again, make logging optional
ruff_langserver.try_kill()
sleep(0.5) # Sometimes it takes a moment for the langserver to die but forcing asyncio is also not a great option (I like how it's completely optional in it's current state)
ruff_langserver.check_kill()

I would also highly recommend putting the package on pypi as it simplifies imports for most projects and makes it more approachable for many. Some good docs on the necessary arguments for any given command in this new system would also be great. I would be more than willing to give a hand at trying to write docs if that makes this any more appealing :D

My hope is for there to be a LSP system as flexible and powerful as possible while still allowing it to be easy to use and provide easy defaults when the user doesn't need much customization all in Python.

Moosems avatar Jul 15 '24 20:07 Moosems

A force_kill option should also be provided if the server starts to freak out and stops responding but should be a last resort

Moosems avatar Jul 15 '24 20:07 Moosems