Increasing 30 Style limit for plugin lexers



  • I am working on a plugin lexer for some
    Ruby on Rails template languages (ERB, Haml, Slim, etc.) and want to include the embedded languages (like the default HTML ones).

    Notepad has a styles per language limit (fixed size array to load the XML) while Scintilla allows 256 styles. The builtin lexers use the embedded languages for this, but does not look to be exposed.

    Is there any existing way for a plugin while still using the style configurator (sending a bunch of Scintilla messages to apply them is ok)?

    Or would a small API enhancement be required, and what would be the process for getting it accepted?



  • Is there any existing way for a plugin while still using the style configurator

    The style configurator is not exposed by the API at all.

    (sending a bunch of Scintilla messages to apply them is ok)

    You can completely circumvent the style configurator by sending your own Scintilla messages if you really want to, but then everything would be hard coded, which may be sufficient for what you are doing.

    Or would a small API enhancement be required, and what would be the process for getting it accepted?

    In theory if it is just changing a #define in the code then it shouldn’t be a problem to submit a pull request on github.



  • I spent some time looking through what is there and would be more than just a define. Based on how the builtin lexers do it and having played with a few things I think the options are.

    1. Create an interface (like IDocument) with a couple methods like addLang (npp already has suitable functions to implement it) and pass it to the lexer via the Scintilla API when setting an external lexer. npp does this when opening files, switching tabs, style config changes, etc. and is how built in lexers do this, just without the interface.

    2. As 1. but use NPP messages and notifications rather than an interface/Scintilla API.

    3. As 2., but just the single set message. Plugins need to listen to several events to avoid bugs, due to the different places npp resets the lexer and styles. I think I found all the relevant indirect events, but hard to be sure.



  • Yeah its possible it is alot more complicated than what I stated since I never looked into it in detail. Keep in mind if any modifications need done within the “scintilla” directory then these would need submitted to the Scintilla project. Notepad++ just uses Scintilla as is.



  • I’m pretty certain there is no issue with Scintilla here for what I want, since its the same as the existing lexers. The issue is just that Notepad++ hardcodes its lexers (a subset of the current Scintilla lexers, plus a custom one for the search results window) in using other Notepad++ API’s that are not part of the plugin interface when it comes to configuring them. The “external lexer” Notepad++ configuration code is separate in many places (presumably because the builtin ones were done first, and never refactored to use common code).



  • Took a quick shot a 1, would look something like:

    //PluginInterface.h
    static const int NPPLEX_SET = 1;
    // Configure a Scintilla lexer when it is being set as the active lexer
    // This is passed to the ILexer via PrivateCall(NPP_LEX_SET, ISetLexerConfig)
    class ISetLexerConfig
    {
    public:
    	// The Scintilla window this lexer is for
    	virtual HWND getScintilla() = 0;
    	// Adds the styles defined by a language (overwrites any existing style with the same ID)
    	// By default Notepad++ will have added the styles for the lexers own language already
    	virtual void addStyles(const TCHAR *languageName) = 0;
    };
    
    //ScintillaEditView.cpp end of void ScintillaEditView::setExternalLexer(LangType typeDoc)
    class SetLexerConfig : public ISetLexerConfig
    {
    public:
    	explicit SetLexerConfig(ScintillaEditView *self) : _self(self) {}
    	virtual HWND getScintilla()override
    	{
    		return _self->getHSelf();
    	}
    	virtual void addStyles(const TCHAR *languageName)override
    	{
    		LexerStyler *pStyler = (_self->_pParameter->getLStylerArray()).getLexerStylerByName(languageName);
    		if (pStyler)
    		{
    			for (int i = 0; i < pStyler->getNbStyler(); ++i)
    			{
    				_self->setStyle(pStyler->getStyler(i));
    			}
    		}
    	}
    private:
    	ScintillaEditView *_self;
    };
    SetLexerConfig setLexerConfig(this);
    execute(SCI_PRIVATELEXERCALL, NPPLEX_SET, reinterpret_cast<LPARAM>(&setLexerConfig));
    

    Then the lexer can just do something like:

    config->addStyles(L"Scss");
    config->addStyles(L"Javascipt");
    config->addStyles(L"Markdown");
    config->addStyles(L"Ruby");
    

    As well as having a convenient handle to the Scintilla control for more advanced things outside the Notepad++ style GUI.

    Not really looked at the “word lists” yet, but should be same idea (maybe included in addStyles).

    It also occurred to me that maybe some of this could be put in the XML file, which I guess would be approach 4.


Log in to reply