UDL: Suffix Mode



  • I was wondering if it was possible to have a “suffix mode” as opposed to the prefix mode in the keywords list.
    The language I use differentiates between string and numeric variables by ending them with a “$”. It would be nice if I could have a different color based on what variable type I’m using.



  • @Michael-Miller31

    afaik, no, not with the builtin features but we could, if you are willing
    to install the python script plugin, create a script which should be able
    to do what you are looking for.



  • That would be great, actually!



  • @Michael-Miller31

    would you mind posting a sample program and describing what needs to be done, together with the name of your UDL as is shown in the first
    field of the statusbar? Which npp version are you using? (Can be seen via ? menu -> DebugInfo)





  • Variables are currently in dark green. It would be nice if I could have a different color if a variable ends with a “$”.



  • Ok, you are using npp 7.5.9 which means you should be able to use
    Plugin Manger to install PythonScript plugin.
    (Just keep in mind that if you upgrade to a newer (but still betas) version
    there are a lot of changes in the plugin area!!)

    Could you just copy and paste the example - makes it easier for me to use it for testing :-D



  • @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()
    
    

Log in to reply