Colors not shown when open code files
-
Hi, I just installed Windows 11 and wanted to install Notepad++ as I use it primarily for code editing (Stata, R, and related). My new Notepad++ installation is not showing colors as were shown before (e.g. with “commenting” I use “*”, which used to turn to green in comparison with other code chunks. How can I restore this old setting? Thanks!
-
“Stata” isn’t in the Language menu (and never has been), but “R” is, so Notepad++ doesn’t handle Stata by default.
For R, if you open a file that has the extension
.r
or.s
or.splus
, it will apply syntax highlighting. And my quick search claims that R comments are#
: Notepad++ highlights# ...
as green with the default styler:
As I said, Notepad++ has never made Stata highlighting available. You may have previously used a User Defined Language for Stata.
While Notepad++ doesn’t make Stata available, the underlying Lexilla lexer which Notepad++ uses does have Stata, at least in Notepad++ versions 8.4 and newer. And we discussed in a recent topic that if you are willing to install and use the PythonScript plugin, you can activate one of the “hidden” lexers – that discussion showed how using SAS, but the procedure for Stata should be the same:
You would grab the script that I linked in this post in that discussion, follow the instructions in the How to run a script in PythonScript plugin FAQ for instructions on installing and running the script. Then you would have to edit that script to refer to the STATA constants and keywords rather than the SAS list.
Even better, @Ekopalypse might confirm whether with the addition of NPPM_CREATELEXER in v8.4.3, it might be easier to implement than the script I showed before.
-
This script “enable-stata-lexer.py” is an edited version of the script linked earlier, customized for Stata. It probably doesn’t have every keyword (I am not a Stata user, so just hacked together from a few web searches)
The Stata lexer has two keyword lists, so you can only have two individual colors that you specify in the script. It labels them as “words” and as “types”, so I assumed the “words” were meant as keywords, and the “types” as the data types.
-
Yes, with the newly introduced NPPM_CREATELEXER message we can get rid of the function determining definitions.
So something like this works now.# -*- coding: utf-8 -*- ''' Makes the builtin SAS lexer available for NPP. To toggle the escape characters on/off one can create another script with these two lines of code. sas_lexer.show_escape_chars = not sas_lexer.show_escape_chars editor.styleSetVisible(sas_lexer.SCE_ERR_ESCSEQ, sas_lexer.show_escape_chars) ''' """ Peter trying to adapt https://raw.githubusercontent.com/Ekopalypse/NppPythonScripts/master/npp/error_list_lexer_support2.py based on Eko's comments https://community.notepad-plus-plus.org/topic/23147/missing-lexers-from-lexilla/7 """ from Npp import notepad, editor, NOTIFICATION from ctypes import windll, WINFUNCTYPE, addressof, create_unicode_buffer from ctypes.wintypes import HWND, UINT, WPARAM, LPARAM, HMODULE, LPCWSTR, LPCSTR, LPVOID class SasLexer: def __init__(self): ''' Initialize the class, should be called only once. ''' # **************** configuration area **************** # files with these extensions and a null lexer, # aka normal text, assigned do get handled self.known_extensions = ['sas'] # # **************************************************** self.SCE_SAS_DEFAULT = 0 self.SCE_SAS_COMMENT = 1 self.SCE_SAS_COMMENTLINE = 2 self.SCE_SAS_COMMENTBLOCK = 3 self.SCE_SAS_NUMBER = 4 self.SCE_SAS_OPERATOR = 5 self.SCE_SAS_IDENTIFIER = 6 self.SCE_SAS_STRING = 7 self.SCE_SAS_TYPE = 8 self.SCE_SAS_WORD = 9 self.SCE_SAS_GLOBAL_MACRO = 10 self.SCE_SAS_MACRO = 11 self.SCE_SAS_MACRO_KEYWORD = 12 self.SCE_SAS_BLOCK_KEYWORD = 13 self.SCE_SAS_MACRO_FUNCTION = 14 self.SCE_SAS_STATEMENT = 15 self.NPPM_CREATELEXER = (1024 + 1000 + 110) self.SCI_SETILEXER = 4033 self.user32 = windll.user32 self.notepad_hwnd = self.user32.FindWindowW(u'Notepad++', None) self.editor1_hwnd = self.user32.FindWindowExW(self.notepad_hwnd, None, u"Scintilla", None) self.editor2_hwnd = self.user32.FindWindowExW(self.notepad_hwnd, self.editor1_hwnd, u"Scintilla", None) self.lexer_name = create_unicode_buffer('sas') self.user32.SendMessageW.argtypes = [HWND, UINT, WPARAM, LPARAM] self.user32.SendMessageW.restype = LPARAM notepad.callback(self.on_langchanged, [NOTIFICATION.LANGCHANGED]) notepad.callback(self.on_bufferactivated, [NOTIFICATION.BUFFERACTIVATED]) console.write("Initialized SAS lexer\n") def __del__(self): ''' Destructor (kind of) ''' console.write("Clear SAS lexer callbacks...\n") notepad.clearCallbacks(self.on_langchanged) notepad.clearCallbacks(self.on_bufferactivated) console.write("Destroyed SAS lexer\n") def init_lexer(self): ''' Initializes the lexer and its properties Args: None Returns: None ''' editor.styleSetFore(self.SCE_SAS_DEFAULT , notepad.getEditorDefaultForegroundColor()) editor.styleSetFore(self.SCE_SAS_COMMENT , (0,255,0)) editor.styleSetFore(self.SCE_SAS_COMMENTLINE , (0,255,0)) editor.styleSetFore(self.SCE_SAS_COMMENTBLOCK , (0,255,0)) editor.styleSetFore(self.SCE_SAS_NUMBER , (255,0,0)) editor.styleSetFore(self.SCE_SAS_OPERATOR , (128,64,0)) editor.styleSetFore(self.SCE_SAS_IDENTIFIER , (64,64,64)) editor.styleSetFore(self.SCE_SAS_STRING , (128,128,128)) editor.styleSetFore(self.SCE_SAS_TYPE , (128,0,255)) # not implemented editor.styleSetFore(self.SCE_SAS_WORD , (255,128,0)) # not implemented editor.styleSetFore(self.SCE_SAS_GLOBAL_MACRO , (255,255,0)) # not implemented editor.styleSetFore(self.SCE_SAS_MACRO , (0,0,255)) # start with % editor.styleSetFore(self.SCE_SAS_MACRO_KEYWORD , (0,255,255)) # keywords/keywords1 editor.styleSetFore(self.SCE_SAS_BLOCK_KEYWORD , (0,0,127)) # keywords2 editor.styleSetFore(self.SCE_SAS_MACRO_FUNCTION , (0,127,127)) # keywords3 editor.styleSetFore(self.SCE_SAS_STATEMENT , (0xAA,0,0)) # keywords4 # ordering is important ilexer_ptr = self.user32.SendMessageW(self.notepad_hwnd, self.NPPM_CREATELEXER, 0, addressof(self.lexer_name)) editor_hwnd = self.editor1_hwnd if notepad.getCurrentView() == 0 else self.editor2_hwnd self.user32.SendMessageW(editor_hwnd, self.SCI_SETILEXER, 0, ilexer_ptr) editor.setKeyWords(0, "%let %do") editor.setKeyWords(1, "also cards class data input model ods proc var where") editor.setKeyWords(2, "%printz") editor.setKeyWords(3, "run") console.write("SAS lexer: set styles\n") def check_lexers(self): ''' Checks if the current document is of interest. Args: None Returns: None ''' has_no_lexer_assigned = editor.getLexerLanguage() == 'null' _, _, file_extension = notepad.getCurrentFilename().rpartition('.') if has_no_lexer_assigned and file_extension in self.known_extensions: self.init_lexer() console.write("check_lexers: {} {}\n".format(editor.getLexerLanguage(), has_no_lexer_assigned)) def on_bufferactivated(self, args): ''' Callback which gets called every time one switches a document. Triggers the check if the document is of interest. Args: provided by notepad object but none are of interest Returns: None ''' self.check_lexers() console.write("on_bufferactivated\n") def on_langchanged(self, args): ''' Callback gets called every time one uses the Language menu to set a lexer Triggers the check if the document is of interest Args: provided by notepad object but none are of interest Returns: None ''' self.check_lexers() console.write("on_langchanged\n") def main(self): ''' Main function entry point. Simulates the buffer_activated event to enforce detection of current document and potential styling. Args: None Returns: None ''' self.on_bufferactivated(None) console.show() sas_lexer = SasLexer() sas_lexer.main() """ example junk SAS (just lists some of the keywords): %let %do also cards class data input model ods proc var where %printz run * ... comment style 1; run // ... comment style 2; run /* comment style 3 */ 5 + 7 = 9 one blech """