How to integrate external lexer with NPP?



  • I’ve made an external lexer that performs as expected if I send an SCI_SETLEXER msg to the nppData._scintillaMainHandle to set SCLEX_CONTAINER.

    I’ve integrated it with the standard CPP plugintemplate and exported GetLexerFactory, GetLexerStatusText, GetLexerName & GetLexerCount.

    How do I now make it appear in NPP Languages menu and Settings -> Style Configurator menu?

    Thanks.



  • Afaik only if it would be added within npp source code.



  • Thanks, but I wonder then how the Gedcom plugin lexer manages it!?

    I’ve been looking through it’s source, but I can’t figure out how it does it yet…
    NPP Language menu showing GEDCOM



  • Putting it into the menu isn’t the problem.
    I assume it is calling InsertMenu(A/W) at some point and is hooking
    the message queue to receive the click event.

    The problem starts when you want to appear it in the settings dialog and want npp to interact with it.

    All in all, you can make it work if you start subclassing everything npp offers.



  • @moon6969

    looks like I’m wrong, there is a way, npp knows something about external lexers.

    Edit: and this.



  • @moon6969

    looks like this is added when your plugin is identified
    as an lexer plugin. See here.

    Edit: you need to provide an xml file which describes your lexer.



  • Thanks again - will be able to try some more based on highlighted NPP source.

    The issue is probably my imperfect understanding of C++ - especially exports etc!



  • @moon6969

    I don’t know if you are using PS, probably not but in case you do,
    here a little script which would check if your plugin has the exports
    and do act correctly.

    import ctypes
    from ctypes import wintypes
    
    external_lexer = ctypes.WinDLL(r'D:\temp\GedcomLexer\GedcomLexer.dll')
    
    GetLexerCount = external_lexer.GetLexerCount
    GetLexerName = external_lexer.GetLexerName
    GetLexerName.argtypes = [wintypes.UINT, 
                             wintypes.LPCSTR,
                             wintypes.INT]
    GetLexerStatusText = external_lexer.GetLexerStatusText
    GetLexerStatusText.argtypes = [wintypes.UINT,
                                   wintypes.LPCWSTR,
                                   wintypes.INT]
    
    GetLexerFactory = external_lexer.GetLexerFactory  # ??
    
    MAX_EXTERNAL_LEXER_NAME_LEN = 16 #+1
    MAX_EXTERNAL_LEXER_DESC_LEN = 32 #+1
    
    numLexers = GetLexerCount()
    print('Lexers:{}'.format(numLexers))
    lexName = ctypes.create_string_buffer(MAX_EXTERNAL_LEXER_NAME_LEN)
    lexDesc = ctypes.create_unicode_buffer(MAX_EXTERNAL_LEXER_DESC_LEN)
    
    for x in range(numLexers):
        GetLexerName(x, lexName, MAX_EXTERNAL_LEXER_NAME_LEN)
        print(lexName.value)
        GetLexerStatusText(x, lexDesc, MAX_EXTERNAL_LEXER_DESC_LEN)
        print(lexDesc.value)
    

    Testing with Gedcom lexer returns

    Lexers:1
    GEDCOM
    GEDCOM file
    

    and a Npp pop saying that the GedcomLexer.xml is missing.

    a3898e13-d916-4ebe-b276-3855455c5267-image.png

    Not a surprise as I just loaded the dll but did not install the plugin at all.

    Note, the GetLexerFactory is missing in the script.



  • @Ekopalypse Cool! It gave me expected count, but no name - I will investigate further tomorrow.


Log in to reply