UDL: Suffix Mode



  • @Michael-Miller31

    Eko has offered to create something for you (I think). It would be nice if you could give him some actual text – not just a screenshot – to start working with.



  • My apologies. I thought you were looking for something visual. Thanks again!

    for index=1 to udim(ButtonNumbers)
    	if Fkey==ButtonNumbers(index) then 
    		let FnHasBeenPressed=1
    		let OrderNumber$=OrderNumbers$(FirstOrderOfPage-61+index)
    		if udim(Keys$) then
    			let UniqueKey$=Keys$(FirstOrderOfPage-61+index)
    		end if 
    	end if
    next index


  • Is it always a word which ends with $ or might it be that
    non-word characters like minus underscore etc… are part of
    the variable as well.
    Basically I’m asking if a regex like \w+?\$ would do the job
    or if it is needed to have something like \b.+?\$\b



  • @Eko-palypse said:

    or maybe a better approach - what allows the language how a variable
    can be defined



  • Always with $. The only time $ would ever be used in this language is to end a string variable.



  • No, there is a misunderstanding, if I use \w+?\$
    then a variable like UniqueKey$ will be colored but a variable like
    Unique-Key$ won’t be.
    If I know what the language allows, which chars can be used for a
    variable name, then we can find the right regex to make this work.



  • String functions can also end with a $ but those I have listed as a keyword in my UDL with prefix mode enabled. Since every function begins with “fn”.



  • Good to know - do you have a reference to the language you are using?





  • I can also give you the section from my userDefineLang.xml if it’s helpful



  • So this is what we are looking for, right?



  • exactly



  • First the script

    # -*- coding: utf-8 -*-
    
    from Npp import editor, editor1, editor2, notepad, NOTIFICATION, SCINTILLANOTIFICATION, INDICATORSTYLE
    import ctypes
    import ctypes.wintypes as wintypes
    
    from collections import OrderedDict
    
    try:
        EnhanceUDLLexer().main()
    except NameError:
    
        user32 = wintypes.WinDLL('user32')
    
        WM_USER = 1024
        NPPMSG = WM_USER+1000
        NPPM_GETLANGUAGEDESC = NPPMSG+84
    
    
        class SingletonEnhanceUDLLexer(type):
            _instance = None
            def __call__(cls, *args, **kwargs):
                if cls._instance is None:
                    cls._instance = super(SingletonEnhanceUDLLexer, cls).__call__(*args, **kwargs)
                return cls._instance
    
    
        class EnhanceUDLLexer(object):
    
            __metaclass__ = SingletonEnhanceUDLLexer
    
            @staticmethod
            def rgb(r,g,b):
                return (b << 16) + (g << 8) + r
    
    
            @staticmethod
            def paint_it(color, pos, length):
                if pos >= 0:
                    editor.setIndicatorCurrent(0)
                    editor.setIndicatorValue(color)
                    editor.indicatorFillRange(pos, length)
    
    
            def style(self):
                start_line = editor.getFirstVisibleLine()
                end_line = start_line + editor.linesOnScreen()
                start_position = editor.positionFromLine(start_line)
                end_position = editor.getLineEndPosition(end_line)
                editor.setIndicatorCurrent(0)
                editor.indicatorClearRange(0, editor.getTextLength())
                for color, regex in self.regexes.items():
                    editor.research(regex[0],
                                    lambda m: self.paint_it(color[1],
                                                            m.span(regex[1])[0],
                                                            m.span(regex[1])[1] - m.span(regex[1])[0]),
                                    0,
                                    start_position,
                                    end_position)
    
    
            def configure(self):
                SC_INDICVALUEBIT = 0x1000000
                SC_INDICFLAG_VALUEFORE = 1
                # editor.indicSetFore(0, (181, 188, 201))
                editor1.indicSetStyle(0, INDICATORSTYLE.TEXTFORE)
                editor1.indicSetFlags(0, SC_INDICFLAG_VALUEFORE)
                editor2.indicSetStyle(0, INDICATORSTYLE.TEXTFORE)
                editor2.indicSetFlags(0, SC_INDICFLAG_VALUEFORE)
                self.regexes = OrderedDict()
    
                # configuration area
                # self.regexes is a dictionary, basically a key=value list
                # the key is tuple starting with an increasing number and
                # the color which should be used, ored with SC_INDICVALUEBIT
                # the value is a raw bytestring which is the regex whose
                # matches get styled with the previously defined color
                #
                # using OrderedDict ensures that the regex will be
                # always executed in the same order.
                # This might matter if more than one regex is used.
                self.regexes[(0, self.rgb(79, 175, 239)  | SC_INDICVALUEBIT)] = (r'fn[A-Za-z0-9_]+?\$|([A-Za-z0-9_]+?\$)', 1)
    
                # defining the lexer_name ensures that
                # only this type of document get styled
                # should be the same name as displayed in first field of statusbar
                self.lexer_name = 'User Defined language file - BR! Source'
    
    
    
            def get_lexer_name(self):
                '''
                    returns the text which is shown in the
                    first field of the statusbar
                '''
                language = notepad.getLangType()
                length = user32.SendMessageW(self.npp_hwnd, NPPM_GETLANGUAGEDESC, language, None)
                buffer = ctypes.create_unicode_buffer(u' '*length)
                user32.SendMessageW(self.npp_hwnd, NPPM_GETLANGUAGEDESC, language, ctypes.byref(buffer))
                # print buffer.value  # uncomment if unsure how the lexername in configure should look like - npp restart needed
                return buffer.value
    
    
            def __init__(self):
                editor.callbackSync(self.on_updateui, [SCINTILLANOTIFICATION.UPDATEUI])
                notepad.callback(self.on_langchanged, [NOTIFICATION.LANGCHANGED])
                notepad.callback(self.on_bufferactivated, [NOTIFICATION.BUFFERACTIVATED])
                self.__is_lexer_doc = False
                self.lexer_name = None
                self.npp_hwnd = user32.FindWindowW(u'Notepad++', None)
                self.configure()
    
    
            def set_lexer_doc(self, bool_value):
                editor.setProperty(self.__class__.__name__, 1 if bool_value is True else -1)
                self.__is_lexer_doc = bool_value
    
    
            def on_bufferactivated(self, args):
                if (self.get_lexer_name() == self.lexer_name) and (editor.getPropertyInt(self.__class__.__name__) != -1):
                    self.__is_lexer_doc = True
                else:
                    self.__is_lexer_doc = False
    
    
            def on_updateui(self, args):
                if self.__is_lexer_doc:
                    self.style()
    
    
            def on_langchanged(self, args):
                self.set_lexer_doc(True if self.get_lexer_name() == self.lexer_name else False)
    
    
            def main(self):
                self.set_lexer_doc(True)
                self.style()
    
    
        EnhanceUDLLexer().main()
    
    


  • Do the following

    • copy the script

    • goto Plugins->Python Script->New Script

    • give it a meaningful name and press save button

    • paste the script into the newly ceated document

    • save it

    • open one of your BR! Source files

    • click on Plugins->Python Script->Scripts->NAME_OF_THE_NEWLY_CREATED_PYTHONSCRIPT

    If you want to know the details, let me know.



  • btw, when it works like you want and want it to be available automatically
    on every npp startup we need to create a USER startup.py but
    I guess this can be discussed it the script is useful to you at all



  • Thanks for putting the time into this!

    First, will this work on 64 bit N++?

    I had some trouble finding a version of Python Script that was compatible but I managed to find a beta version.

    also, I’m getting this error.

    Traceback (most recent call last):
    File “C:\Users\mmiller\AppData\Roaming\Notepad++\plugins\Config\PythonScript\scripts\create_strings.py”, line 4, in <module>
    import ctypes
    File “C:\Program Files\Notepad++\plugins\PythonScript\lib\ctypes_init_.py”, line 7, in <module>
    from _ctypes import Union, Structure, Array
    ImportError: No module named _ctypes



  • Yes, as I’m using x64 version as well.
    Where did you download pythonscript plugin from?
    Why didn’t you use Plugin Manager?
    The official release channel for python script plugin is here.



  • I don’t have plugin manager so I went through http://docs.notepad-plus-plus.org/index.php?title=Plugin_Central .

    Thanks for dealing with my idiocy. Going through plugin manager worked perfectly. Is there any way I can donate for your time?



  • @Michael-Miller31

    Is there any way I can donate for your time?

    yes, we urgently need 5 macbook pro’s. 👍
    thanks in advance. 😂



  • Thank you very much for asking and yes there is one thing
    you could do if you like :-)
    It might sound strange but if you have or know a cooking recipe
    which is worth testing - I would appreciate.
    I know tastes are different so … :-)


Log in to reply