Programmer’s Notepad


10
Mar 09

First Poll Results

A little while back I asked people a couple of questions to help guide future PN development.

The results ended up looking like this:

Is the fact that you can float PN document windows useful?

This question is concerned with whether the MDI window management system is helpful to people. I suspected that most users had windows maximised all the time and used the tabs to switch – i.e. MDI wasn’t buying them much. Here are the results:

Results of MDI Poll

18% of people were using the abilities of MDI windows and were very happy about them. Pretty much everyone else doesn’t care or would rather be able to split the view.

Don’t worry, this isn’t going to drive any instant knee-jerk changes, but I’m keeping it in mind for future design work. I am definitely going to address the lack of split views, I’m just trying to decide how.

Do you use the individual output windows?

Here I wondered whether the hidden away option to use individual output windows instead of the global one for each window was actually being used – I suspected not. I was wrong!

Individual Output Poll Results

Lots of people use the individual output windows, and it appears lots of people have no idea what output windows are! I’m not sure whether this is because they have no need in their editing for tools and output, or are just unaware of the features.

I’ll be posting some more questions soon, and wanted to thank everyone who took the time to answer these polls or comment – it’s appreciated!


19
Feb 09

Programmer’s Notepad 2 0.9.926 Released

This is a minor bugfix testing release for Programmer’s Notepad, fixing a few niggles with the last release.

Downloads

There is also a new PyPN release fixing a couple of issues with the included scripts from the last build:

Thanks to all the users who have put time and effort into reporting and following up on bugs, testing, and contributing patches.


17
Feb 09

Adding a Menu Item from Your Extension

This is the second post in the Writing your First Extension series. You can see the full article here: Writing Your First Extension.

Menu items are added via the IPN object provided at extension load time. You add menu items by providing an implementation of IMenuItems. Here is a very simple implementation supporting a single item:

class Menu : public extensions::IMenuItems
{
public:
    Menu()
    {
        memset(&item1, 0, sizeof(item1));
        item1.Handler = &MyExtensionFunc;
        item1.Title = L"Hello World";
        // item1.Type = extensions::miItem;
        // item1.UserData = 0;
    }

    /**
     * Get the number of MenuItem instances that can be retrieved.
     */
    virtual int GetItemCount() const
    {
        return 1;
    }

    /**
     * Get an individual MenuItem instance by index.
     */
    virtual extensions::MenuItem& GetItem(int index) const
    {
        if (index == 0)
            return const_cast<extensions ::menuitem&>(item1);
    }

private:
    extensions::MenuItem item1;
};

This very simple implementation adds a single menu item called "Hello World". When the item is selected, the MyExtensionFunc method will be executed by PN.

It might seem like a fair bit of code to add a menu item, but in the next SDK version I’ll provide a general-purpose helper to make this easy. The reason for the interface is to make it easy for you to provide sub-menus. MenuItem instances can contain child items by changing Type to miSubItem and filling in the SubItems member with another instance implementing IMenuItems.

The handler method looks like this:

void MyExtensionFunc(extensions::cookie_t /*cookie*/)
{
    g_PN->GetGlobalOutputWindow()->AddToolOutput("Hello World!");
    g_PN->ShowOutput();
}

Once you have your handler and IMenuItems implementation, you just need to tell PN about your items. In your init function you need something like this:

bool __stdcall pn_init_extension(int iface_version, extensions::IPN* pn)
{
    if(iface_version != PN_EXT_IFACE_VERSION)
        return false;

    g_PN = pn;

    Menu menu;
    pn->AddPluginMenuItems(&menu);

    return true;
}

Now you have Programmer’s Notepad presenting your commands in the menu and can handle their selection. Next time we’ll look at the other events PN lets you attach to.


16
Feb 09

Creating your first Programmer’s Notepad extension

PyPN provides a great way to add functionality to Programmer’s Notepad by writing simple Python code, but you might want to do something more advanced. For this there’s the Programmer’s Notepad Extension SDK.

The SDK lets you extend PN using C++, allowing you to react to editor events and provide new commands in the menu. PyPN is itself implemented as an extension using this same SDK, and you can use the SDK to provide support for other scripting languages too.

What You’ll Need

You need a Windows C++ compiler and the Boost C++ library. Note that you don’t need to compile any of boost, we use the header-only bits.

I suggest using the free Microsoft Visual C++ Express if you don’t already have Visual Studio, this should guarantee compatibility.

Getting Started

Download the SDK and copy the template project, this is a good base for your extension. Note that the SDK also contains a demo extension showing use of various parts of the SDK. Change the name and version of your extension and you’re ready to add it to Programmer’s Notepad for the first time:

void __declspec(dllexport) __stdcall pn_get_extension_info(PN::BaseString& name, PN::BaseString& version)
{
    name = "My First Plugin";
    version = "1.0";
}

Compile the extension and place the .dll file in your PN directory. Now run “pn –findexts” and your plugin will be discovered and loaded the next time you start PN. Go to Tools->Options->Extensions and see your extension listed.

Everything else you want to do flows from the instance of IPN that’s passed to your init function. This interface gives you access to the open documents, lets you sign up to handle document events and gives you access to app-level services like script registration, find in files and options management.

Working with Documents

Everything you want to do with an open document is done through the IDocument interface. You get a pointer to one of these from your IPN instance by calling GetCurrentDocument, NewDocument or equivalent.

    // Make a new document
    IDocumentPtr doc = pn->NewDocument(NULL);

    // Send scintilla messages (see scintilla.org documentation)
    doc->SendEditorMessage(SCI_APPENDTEXT, 6, (LPARAM)"Hello!");

    // Save changes
    doc->Save("c:\\temp\\test.txt", true);

    // Done with the document
    doc->Close();

This is the first in a series of posts that will become the introductory documentation for extensions. Next time we’ll look at how to add menu commands for your plugin. The series will be added to the docs site as we go: Writing your First Extension


11
Feb 09

Programmer’s Notepad 2 0.9.921 Released

The latest testing release of Programmer’s Notepad 2 is finally out. There are plenty of fixes in this release, and a few minor new features too. Of particular note are the following:

  1. Updates to the extensions interface allowing extensions to create menu items
  2. International input fixed (I know this will please a whole bunch of users)
  3. Read only edit protection cleaned up
  4. More text transforms, also available from context menu
  5. Tab to space and vice versa conversions fixed
  6. Notepad’s .LOG feature natively supported
  7. Fix a problem using PN on the Windows 7 beta causing PN to hang on exit

Downloads

There is a new PyPN release supporting the updated plugin interface:

Thanks to all the users who have put time and effort into reporting and following up on bugs, testing, and contributing patches.


20
Jan 09

PN Usage Polls – Output Windows

I want to get a feeling for how some controversial features and configuration options in Programmer’s Notepad are used so that I can better work out where to spend my time. To do so, I’m going to run some polls and spread the word about them as widely as possible. You can really help both me and Programmer’s Notepad to improve by voting in these polls.

The first is to find out how you use the output window:

and the second is about the MDI window framework that PN uses:


7
Nov 08

PN 2 0.9.872 Released

The latest testing release of Programmer’s Notepad 2 is out, fixing a couple of annoying bugs in the previous release amongst other things. This release is also the first in-the-wild use of the “check for updates” feature. If you are running build 853 or newer and have enabled looking for testing updates, then in the next day or so PN will notify you that there is a new version available.

Changes in this build:

  1. Wombat preset included
  2. Ignore ctags warnings when parsing tags
  3. Fixed bug causing tools capture not to work properly
  4. Allow changing display name of root magic folder
  5. Add support for displaying the caret as a block
  6. Switch back to a DLL for Scintilla for those that use a custom build

Note that if you intend to use a custom build of Scintilla (SciLexer.dll) to support other schemes or prototype changes then you will need to build using the project in the PN source or you will lose the new Regular Expression support. To get the source and build the project you might like to look at How To Compile PN on the docs site.


5
Nov 08

Search within comments

There was a question on the programming reddit today about finding text within comments only. There’s no way to do this from the UI in Programmer’s Notepad, but it’s easy in PyPN:

d = pn.CurrentDoc()
s = scintilla.Scintilla(d)

searchopts = pn.GetUserSearchOptions()

while not pn.CurrentDoc().FindNext(searchopts) == -1:
    # s.GetStyleAt(s.TargetStart) will work in the next PyPN release
    style = d.SendMessage(2010, s.TargetStart, 0)
    # pn.AddOutput(str(style)) - find the current style
    if d.SendMessage(2010, s.TargetStart, 0) == 2:
    break

That small bit of code will find whatever is in the current user’s search options only where the style is 2 – that’s the C++ comment style number. Sadly these numbers are not uniform across schemes, so we’d need to do a bit more work to do this properly across anything. To turn that small snippet of code into a script that can be run from a keyboard shortcut is also easy:

import pn, scintilla

@script("Find In C++ Comments")
def FindInCComments():
    d = pn.CurrentDoc()
    s = scintilla.Scintilla(d)

    searchopts = pn.GetUserSearchOptions()

    while not pn.CurrentDoc().FindNext(searchopts) == -1:
        style = d.SendMessage(2010, s.TargetStart, 0)
        if d.SendMessage(2010, s.TargetStart, 0) == 2:
        break

Just save that into your scripts directory and you’re good to go!


31
Oct 08

Server E-mail Fixed

There were problems with the pnotepad.org host not sending on e-mail, so registrations for the forums and comment notifications were not being sent. This is all fixed now, so if you were trying to register please try again!


31
Oct 08

35 New Schemes

That’s right! 35 New Schemes for Programmer’s Notepad, all the schemes that Scintilla supports should now be available. These new schemes will not be bundled with PN but will be available as downloadable add-ons.

The schemes are:

  1. ASN.1
  2. AVE
  3. Ada
  4. Apache Conf
  5. AutoIt
  6. Baan
  7. BlitzBasic
  8. Bullant
  9. Csound
  10. E-Script
  11. Eiffel
  12. Erlang
  13. Flagship
  14. Forth files
  15. FreeBasic
  16. Inno Setup
  17. Kix-Script
  18. Lisp and Scheme
  19. Lot
  20. Lout
  21. Lua
  22. MMixal
  23. Objective Caml
  24. Octave
  25. Opal
  26. POV-Ray SDL
  27. PostScript
  28. Prolog
  29. PureBasic
  30. Rebol
  31. Scriptol
  32. Smalltalk
  33. Spice
  34. Yaml
  35. nnCron

Download from Google Code

The schemes will be linked from pnotepad.org as soon as I get around to it.