Wednesday, December 3, 2014

Notepad++ Language Selector


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 3 step process:

  1. Define a function that will switch the language after the file is opened
  2. Write a command that links your function to the “File Opened” notification in NPP
  3. 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.

  1. Menu: Plugins > Python Script > Configuration
  2. 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:

  1. Open Notepad.exe (yes notepad) as an Administrator, which will allow you to save any changes
  2. Change the permissions on startup.py to allow Full Control for all users on your computer
I started out with option 1, but after some initial issues I switched to option 2 which made things much easier to debug using the Python Console in NPP.


Test Script

Setup the test script:

  1. Menu: Plugins > Python Script > New Python Script
  2. It will ask you for a new file name, I choose: switch_language.py
  3. A new tab will appear in NP++ for you to enter the script
  4. After saving, you should be able to run this code from the menu: Plugins > Python Script > Scripts > switch_language.py
  5. Make sure you have a test file active when you test the script!
  6. 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