I use Python everyday, it has become my first tool to use when I need to do anything. In Arabic (in Shami Arabic specifically) I’d say that Python has become my hand and leg :P

Yesterday I was writing a small Python script to read the YACC file and generate a list of all the specified rules inside it, so I don’t have to scroll through the long file to find out what rules are inside it ;)

I use Notepad++ as my default text editor on Windows, and I was writing the script using it – Notepad++. I wanted to test if the script is working, so I ran an instance of Command Line Prompt, and as I was going to change the directory to the directory of the script I thought; “Why doesn’t Notepad++ have a Run In Python command in it?”. So as usual I got pissed off and decided to create my own plugin to have that command in Notepad++ 8)

The Reference

I searched on the net, I found this Notepad++ Plugin Template, I edited it a little bit and I managed to do it :)

The Process

To run a Python script; the plugin must do the following:

  • Get the path of the selected file in Notepad++.
  • Get the path of Python executable file, since not everyone has Python in the PATH environment variable.
  • Building the run command.
  • Execute the run command.

Get The Path of The Selected File In Notepad++

I also searched the net and found the following code:

std::wstring getCurrentFile()
{
	TCHAR path[MAX_PATH];
	::SendMessage(nppData._nppHandle, NPPM_GETFULLCURRENTPATH, MAX_PATH, (LPARAM)path);

	return std::wstring(path);
}

The function sends a message to Notepad++ asking it to put the full path of the currently selected file into a specific variable, and then returns the variable’s value.

Get The Path Of Python Executable File

UPDATE (18/4/2010): I edited this section so the plugin will search for Python in its default path (“C:\Python[VER]“). If this method fails the plugin will search in registry for the key.

bool pythonExists(std::wstring foldername) {
	std::wstring path = L"C:\\";
	path += foldername;
	path += L"\\python.exe";
	WIN32_FIND_DATA data;
	HANDLE h = FindFirstFile(const_cast<LPCWSTR>(path.c_str()), &data);
	return (h != INVALID_HANDLE_VALUE);
}

	//This code will be run before the plugin calls the function 'getPythonLocation'
	std::wstring pythonLoc = L"";
	bool pythonInstalled = false;

	WIN32_FIND_DATA data;
	HANDLE h = FindFirstFile(L"c:\\python*", &data);
	if( h != INVALID_HANDLE_VALUE )
	{
		do
		{
			if (!(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
				continue;

			char*   nPtr = new char [lstrlen( data.cFileName ) + 1];
			for( int i = 0; i &lt; lstrlen( data.cFileName ); i++ )
				nPtr[i] = char( data.cFileName[i] );

			nPtr[lstrlen( data.cFileName )] = '\0';
			if (pythonExists(const_cast<LPWSTR>(data.cFileName)))
			{
				pythonLoc = L"C:\\";
				pythonLoc += const_cast<LPWSTR>(data.cFileName);
				pythonLoc += L"\\";
				pythonInstalled = true;
				break;
			}
		} while (FindNextFile(h, &data));
	}

END OF UPDATE
The Python installation path exists in the Windows Registry, so I wrote a small function to search the registry for the path and return it:

bool getPythonLocation(std::wstring &amp;amp;loc)
{
	HKEY hKey;
	if(RegOpenKeyEx(HKEY_CURRENT_USER, TEXT(&quot;Software\\Python\\PythonCore&quot;), 0,
		KEY_READ, &amp;hKey) != ERROR_SUCCESS)
	{
		return false;
	}
	DWORD dwIdx=0;
	TCHAR szKeyName[1024];
	DWORD dwSize=1024;
	FILETIME fTime;
	TCHAR pyPath[MAX_PATH];
	DWORD length = MAX_PATH;

	if (RegEnumKeyEx(hKey, dwIdx, szKeyName, &amp;dwSize, NULL, NULL, NULL, &amp;fTime) == ERROR_SUCCESS)
	{
		HKEY hSubKey;
		if (RegOpenKeyEx(hKey, szKeyName, 0, KEY_READ, &amp;hSubKey) == ERROR_SUCCESS)
		{
			LONG x = RegOpenKeyEx(hSubKey, TEXT(&quot;InstallPath&quot;), 0, KEY_READ, &amp;hSubKey);
			if (x == ERROR_SUCCESS)
			{
				if(RegQueryValueEx(
					hSubKey,
					TEXT(&quot;&quot;),
					NULL,
					NULL,
					(LPBYTE)pyPath,
					&amp;length) != ERROR_SUCCESS)
				{
					return false;
				}

				loc = loc.append(pyPath);
				return true;
			}
			else
				return false;
		}
		else
			return false;
	}
	else
		return false;
}

The code opens “HKEY_CURRENT_USER\Software\Python\PythonCore”, if the key exists it will get the path from the first child key of this key.

Building The Run Command

This one would be very simple, just concatenate: Python installation path, “python.exe” and the full path of the current file.

std::wstring buildRunCommand(std::wstring &amp;filePath, std::wstring &amp;pypath)
{
	std::wstring command = pypath;
	command += TEXT(&quot;python.exe \&quot;&quot;);
	command += filePath;
	command += TEXT(&quot;\&quot;&quot;);
	return command;
}

Execute The Run Command

This one is also simple, just create a new process with the run command.

bool launchPython(std::wstring &amp;command)
{
	STARTUPINFOW si;
	PROCESS_INFORMATION pi;
	memset(&amp;si, 0, sizeof(si));
	memset(&amp;pi, 0, sizeof(pi));
	si.cb = sizeof(si);

	return CreateProcess(
		NULL,
		const_cast&lt;LPWSTR&gt;(command.c_str()),
		NULL,
		NULL,
		FALSE,
		CREATE_DEFAULT_ERROR_MODE,
		NULL,
		NULL,
		&amp;si,
		&amp;pi) != 0;
}

Screenshot

PyNPP

License

This work is licensed under GNU General Public License v3.

Download

Plugin DLL:

Plugin DLL

Source Code:

Source Code