Notepad++ Language Selector
I keep code samples that I find useful as small text files. I store them as vanilla txt files as opposed to the language in which they are written so that they will open in Notepad++ (NPP) instead of the editor. In other words, I don't want my c++ examples to open in an IDE, just notepad.
Notepad++ has syntax highlighting for various languages, but it is based on the file type. Therefore, all my SQL examples show up as normal text. I thought it would be nice if I could have NPP select the language format based on a simple keyword in the text file.
I asked this question 4 years ago on stackoverflow (the answer was that it couldn’t be done), and then I realized I could achieve this goal using the python plugin! I’m going to assume you already know how to use the python plugin for NPP and how to setup your environment. If not, refer to my post about custom timestamps in NPP.
Walkthrough
The first line of the file will start with "##", followed by the menucommand code for that language
- The menucommand codes are listed on the npppythonscript project website:
http://npppythonscript.sourceforge.net/docs/latest/enums.html#MENUCOMMAND - They are formatted like: MENUCOMMAND.LANG_?????
- examples: LANG_C, LANG_CPP, LANG_SQL, LANG_PYTHON etc
The 3 step process:
- Define a function that will switch the language after the file is opened
- Write a command that links your function to the “File Opened” notification in NPP
- Put it all together
Step 1 and 2: Define your function and link to notification
#if found determine the menu command and switch language in NPP
def switch_language_view(args):
notepad.activateBufferID(args["bufferID"])
lineone = editor.getLine(0)
if '##' in lineone:
lineone = lineone[lineone.rfind('##'):].replace('##', '')
lineone = "MENUCOMMAND." + lineone.upper()
try:
notepad.menuCommand( eval(lineone) )
except:
pass
#command to link notification
notepad.callback(switch_language_view, [NOTIFICATION.FILEOPENED])
- This script grabs the first line of the file and looks for the command. After it finds the ## tag, it tries to send the menu command to notepad
- Quick note about args: you need the args so that the script gets access to the current file being opened. Otherwise (as I discovered) it will read the first line of your code instead!
- The last line is a separate call that links your function with the NPP event NOTIFICATION.FILEOPENED
Step 3: Put it all together
You have to place the code (both parts) in a special python script that will run when NPP starts. It’s called startup.py, and I pasted the above code at the end of that file, one after the other.
Some things to note about startup.py:
By default, this script is only run before you run your first python script. You want to change this behavior, so you need to change a configuration setting in the plugin.
- Menu: Plugins > Python Script > Configuration
- Switch Initialisation from “LAZY” to “ATSTARTUP” (there’s an explanation in the dialog)
On my PC, the startup.py script is located in the Program Files folder:
C:\Program Files (x86)\Notepad++\plugins\PythonScript\scripts\startup.py
This unfortunately means it might have some protective permissions. There are two things you could do to make your life somewhat easier:
- Open Notepad.exe (yes notepad) as an Administrator, which will allow you to save any changes
- Change the permissions on startup.py to allow Full Control for all users on your computer
Test Script
Setup the test script:
- Menu: Plugins > Python Script > New Python Script
- It will ask you for a new file name, I choose: switch_language.py
- A new tab will appear in NP++ for you to enter the script
- After saving, you should be able to run this code from the menu: Plugins > Python Script > Scripts > switch_language.py
- Make sure you have a test file active when you test the script!
- This script writes the result to the python console in NPP (make sure you have it displayed)
#This is the script I used (for testing):
#script to test switching language syntax of active file
lineone = editor.getLine(0)
if '##' in lineone:
lineone = lineone[lineone.rfind('##'):].replace('##', '')
lineone = "MENUCOMMAND." + lineone.upper()
try:
notepad.menuCommand( eval(lineone) )
except:
pass
console.write(lineone)
Example using the test script