So what I was thinking about is to use the UDL as the main lexer while
using this script to do additional colorings.
To use this script you need to install PythonScript plugin, create a new script,
paste content from below, safe it.
Then modify it to your needs - see configure section for more details.
Basically add/modify the regexes and more important modify the lexer name
self.lexer_name = 'User Defined language file'
Once done, save it and run it. It should, hopefully, go hand ind hand with your UDL
I have added two regular expressions just to show you how it can be extended.
From the problem given, I assume you only need the second one.
from Npp import editor, 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):
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,
lambda m: self.paint_it(color[1], m.span()[0], m.span()[1] - m.span()[0]),
0,
start_position,
end_position)
def configure(self):
SC_INDICVALUEBIT = 0x1000000
SC_INDICFLAG_VALUEFORE = 1
editor.indicSetFore(0, (181, 188, 201))
editor.indicSetStyle(0, INDICATORSTYLE.TEXTFORE)
editor.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'\b([A-F0-9]+[\s\?]*)+\b'
self.regexes[(1, self.rgb(189, 102, 216) | SC_INDICVALUEBIT)] = r'\b([a-f0-9]+[\s\?]*)+\b'
# defining the lexer_name ensures that
# only this type of document get stlyed
# should be the same name as displayed in first field of statusbar
self.lexer_name = 'User Defined language file'
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
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()