Microsoft Language Server Protocol (LSP): A possible revolution for Notepad++?



  • Microsoft Language Server Protocol (LSP) defines the protocol used between an editor or IDE and a language server that provides language features like autocomplete, go to definition, find all references etc.:

    https://microsoft.github.io/language-server-protocol/

    Some cool editors are already making use of it, completely transforming the original editor being used for the communication with LSP:

    https://microsoft.github.io/language-server-protocol/implementors/tools/

    I think that compatibility with LSP would give Notepad++ a huge boost towards acting as an IDE. Given any programming language, it could be possible for example to check for syntax errors in real-time, look for definitions, get some info through mouse hovering on a variable, etc. All of this into Notepad++. Here are some of the LSP-based existent projects, with the supported programming languages:

    https://microsoft.github.io/language-server-protocol/implementors/servers/

    It seems that someone is already trying to implement LSP into Notepad++ by writing a specific plugin for it:

    https://github.com/dail8859/NppLSP

    Someone else instead suggested to write a script in some language, for example, Python, by making use of the already existent “Python Script” plugin:

    https://notepad-plus-plus.org/community/topic/14736/does-npp-have-any-plans-to-support-microsoft-s-language-service-protocol/6

    I think think this would lend to results similar to the ones achieved by this great plugin for Python programming in Notepad++:

    https://github.com/bitagoras/PyPadPlusPlus

    So, I decided to open this thread to discuss the possible integration of Notepad++ with LSP. What do you think about it?



  • @pidgeon777

    An LSP client for Npp would be AWESOME!!!
    I’m kinda new to PythonScript plugin but from what I understand it should be possible
    to create one but a dedicated plugin would be better, from my point of view, as it
    could introduce the needed windows more easily. At least, I haven’t figured out how
    to make this work using PythonScript plugin yet.



  • Yes, it would be awesome and, especially, a possible thing to do in Notepad++. The proper way to implement the LSP client into Notepad++ should, however, be discussed. Currently, some ways would be:

    • By making use of Python Script
      • Advantage: Ease of modification? Portability?
      • Disadvantages: Slowness? Optimization?
    • By writing a dedicated plugin

    I think Notepad++ is already the best choice when coding with some programming languages. Consider for example OpenEdge ABL, and see how this developer completely transformed Notepad++ into an IDE perfectly fitted for that language:

    https://jcaillon.github.io/3P/

    Many features were added with that plugin: a powerful auto-complete, linting, syntax checking, code browsing, go to definition, and so on… I just wished something similar to this existed for C/C++ (and many other languages), for Notepad++!

    I’m curious to know how many people would be interested in an integration of Notepad++ with LSP because this, in my opinion, it would hugely expand the current capabilities of this almost excellent editor.



  • I’ve made some thoughts about implementing a LSP server.
    All the cool stuff like auto-completion, signature help etc… aren’t part of this yet.
    This is more about the general workflow and potential risks.
    If someone has already read the specification or is aware how this is going to work,
    or has general ideas, then I would appreciate any input.

    Just in case it isn’t obvious - this would be the workflow for python code.
    def On… are the callbacks which are triggered by npp, the init function
    is the one which is going to be called as the very first function at all.

    def __init__():
        # read config file
        # create a dict of configured lspservers and their startup parameters
        #     sanity check - check if known lspservers do still exist as file on disk
        #     if not, log error and ignore config entry
        # create a dict of known languages npp/lsp
        #     dict key notepad.getCurrentLang().name should return the lsp equivalent
        # 
        
    def OnBufferActivated(args):
        #   if notepad.getCurrentLang().name not in lspclient.dictOfLSPServers
        #       return - nothing to do
        #   else 
        #       if lspserver is not running
        #           start lspserver
        #           if process is running
        #               send initialize request
        #               wait for response (how long??)
        #               if initialize response received
        #                   send initialized
        #               else
        #                   what to do?? send a second time?? document says NO
        #                   ignore the lspserver for the rest of npp runtime??
        #           else
        #               log error and (ignore the lspserver for the rest of npp runtime??)
        #
        #       if didOpen was not already sent
        #           send didOpen
        #       else
        #           send didChange ?? there seem to be no equivalent of buffer activated
        #                             should we send a didClose each time the active buffer changes??
        #       From the docs:
        #           The document open notification is sent from the client to the server to signal newly opened text documents. 
        #           The document’s truth is now managed by the client and the server must not try to read the document’s truth 
        #           using the document’s Uri. Open in this sense means it is managed by the client. 
        #           It doesn’t necessarily mean that its content is presented in an editor. 
        #           An open notification must not be sent more than once without a corresponding close notification send before. 
        #           This means open and close notification must be balanced and the max open count for a particular textDocument is one. 
        #           Note that a server’s ability to fulfill requests is independent of whether a text document is open or closed.
        #
        #
        #   The overall potential risk here is that it takes some time before a lspserver is completely started
        #   which means the user might start typing and expects interaction which isn't possible at this time yet.
        #   Maybe a startup parameter flag startLSPServer on npp startup could be helpful but this means lspserver
        #   gets started even if it is not needed. 
        #   In addition, I assume that publishDiagnostics notification is send upon didOpen/Change notification
        #   which would be another hint to have this run in its own thread but what if one constantly switches buffers?
        #   I assume queuing and checking if the notification is still valid is needed.
        
    
    def OnFileBeforeSave(args):
        # send willSave notification
        # don't understand the meaning of the willSaveWaitUntil request. 
        # Why should one allow to modify source code before closing the file - does not make sense to me.
        # From the docs
        #   The document will save request is sent from the client to the server before the document is actually saved. 
        #   The request can return an array of TextEdits which will be applied to the text document before it is saved. 
        #   Please note that clients might drop results if computing the text edits took too long or if a server 
        #   constantly fails on this request. This is done to keep the save fast and reliable.
    
    def OnFileClosed(args):
        # send didClose notification
    
    def OnFileOpened(args):
        # normally we would send didOpen notification from here but because this callback is not reliable,
        # you won't see this callback on npp startup, we use OnBufferActivated callback to send the didOpen notification
    
    def OnFileSaved(args):
        # send didSave notification
    
    def OnLangChanged(args):
        # trigger an OnBufferActivated callback should be all we need to do, to be on the save side
    
    def OnReady(args):
        # maybe do some init here instead of atstartup.py - is it reliable??
        
    def OnShutdown(args):
        # send shutdown request and exit notification


  • Ok - I found some time and created a python script based LSP client and it works in its early alpha stage quiet well.
    Now I need some help - as npp is a general purpose editor it supports a wide range of languages and this means
    my nppLspClient would, possibly, have to handle those different LSP servers.
    As I don’t know all of the possible languages :-) I would like to ask for help in identifying, creating and running those servers and
    most important providing some test scripts/programs in order for me to be able to test it.
    Just in case someone wants to point me to https://microsoft.github.io/language-server-protocol/implementors/servers/
    I already know it :-) but, for example, I don’t know how I can create and run a typescript based LSP server.
    Of course I could start investigating this but I would prefer to spend the time to work on the current client
    and someone who knows typescript would possibly have the answer already, so if you can help - please do so :-D

    Thank you.



  • I’m interested in supporting your development by making some experiments with the followings:

    VHDL-Tool

    rust_hdl

    Do you think those could be of help?



  • @pidgeon777

    sorry, totally missed this one - mostly related to the fact that
    I cannot login with my google account anymore but … that’s another story …

    I don’t know how vhdtool can be used as this is, currently,
    a linux only version but the rust_hdl seems interesting.

    Currently there are a couple of manual steps which are needed to be done and in debug mode it is very slow. Would you mind
    to provide a simple sample vhdl script with a short description
    what you expect to see/work and I’ll give it a try because if it
    doesn’t work like the python lsp server than it is easier to debug
    locally instead of communicating over the community.
    Once I can make it work I would provide you with the info how
    to setup PythonScript plugin and the lsp client in order to do more detailed tests on your side.


Log in to reply