[plugin development] Implementing a self-contained lexer for scintilla

  • Hello community,

    The context :
    I’m currently creating a npp plugin (in C#) to help my co-workers programming in “4GL progress”.
    I currently have an UDL xml which color the code, what i would like to do now is to implement a lexer directly in my plugin so the user only has to install my .dll to have a fully functionnal progress development environnement.

    The problem :
    With the help of scintilla’s documentation and this page : http://sphere.sourceforge.net/flik/docs/scintilla-container_lexer.html, I was able to initiate my own lexer implementation. My problem is that i don’t know (in the code) where to send a message to scintilla and tell him to use the container lexer.

    At the moment, I’m sending this message when the user switches buffers (i.e. when responding to a NPPN_BUFFERACTIVATED notification), if the document has the correct extension (.p or .i) i sendmessage scintilla to use the lexer_container for this document. It kind of works… but i briefly see the coloration defined in my UDL before the one from my lexer_container is applied!?

    The question :
    Where is the right place for me to send a “use container_lexer” message to scintilla?

    Bonus question :
    I want to offer my user the option to set up my plugin’s command menu directly to the main menu of npp instead of main menu>plugin>my plugin. Kind of like TextFX is placed directly next to the “Run” menu. Is there a way to tell npp to place it there?


  • Ok,

    To clarify my problem :
    I can manage to set the lexer to “SCLEX_CONTAINER” without problems, but when i switch to another document, it seems that the previous Lexer used for that document is set back.

    i got document 1 with is a .cs file, and document 2 which is a .p file (i want to colorize this one).
    By default document 1 is set to lexer 3 (for C#) and document 2 is set to lexer 1 (SCLEX_NULL).
    I switch to document 2 from document 1, the current lexer for document 2 is set to 0 (SCLEX_CONTAINER) (this is my plugin behavior),
    i then switch to document 1, then go back to document 2, the lexer for document 2 is briefly set back to lexer 1 (SCLEX_NULL) before being corrected by my plugin to lexer 0 (SCLEX_CONTAINER)

    I don’t understand why npp switches back to the original lexer when i change the current document… This is really annoying cause when i need to colorize >5mb document i don’t want to compute the whole coloration each time i switches documents!

  • If you understand how Notepad++ works it will help to see what is going on.

    Notepad++ only has 2 scintilla windows, one for the primary main view and one for the secondary view (only used if you have more than one view open), so when you switch from one document to another the main view is updated with the contents of the current document each time you switch (the documents are buffered in memory not reloaded from file each time), therefore the lexer has to be reapplied each time.

    For your document 2 you have told the scintilla control to use SCLEX_CONTAINER via you plugin, however Notepad++ has no knowledge of this and will switch it back to SCLEX_NULL as that is what Notepad++ thinks it should be.

    If each document you opened had it own Scintilla instance this would not be an issue, however that is not how Notepad++ is working, it is just updated an single Scintilla instance each time you switch document.

  • Yes, it makes sense indeed.

    Isn’t there a way to notify npp to use a certain lexer on a document?


    Thank you for your explanation Nick Brown,
    After some more testing, i actually can’t see the “switch” between SCLEX_NULL and SCLEX_CONTAINER anymore so… Problem solved :)

    Do you have an idea for my bonus question?

  • @greenzest As for your bonus question…there is not a defined way to add commands to the main N++ menu. IIRC, I think that TextFx is a special case since it is so old and has been around a while. That’s not to say with enough knowledge of the Win32 API you couldn’t figure out a way to do it, but I’m not sure if that would ever run you into problems later. So is it possible? (Yeah, probably) Is it suggested? (No)

Log in to reply