pyeditor -- A Scriptable Text Editor

Contents:

Back to top

Introduction

pyeditor.py is an extensible editor whose high-level code is written is Python. It is built on pyscintilla, the Python wrapping of the Scintilla editor component and on PyGtk, the Python wrapping of the Gtk GUI toolkit.

It's purpose is to provide a text editor that is usable as is and that can be easily extended for specialized editing tasks.

pyeditor is written in Python (using pyscintilla which is a wrapper around Scintilla, which is written in C++). Thus, pyeditor is extendible in Python. However, much power can be gained by extending pyeditor with C and C++. A particularly interesting example is XML processing.

This document describes how to extend and customize pyeditor for special tasks and for more complex tasks.

Back to top


How to add a new menu item

Follow these steps:

  1. In pyeditor.py search for method init_menu_new. Copy a line in the menu definition list in that method. Edit it, changing the following items:

    • Change the menu label. For example, change "/_File/_Save" to "/_File/_Test".

    • Change the quick key. Use None for no key. Add "", "", or "<alt>" in front of the key as modifiers. For example, change "<control>S" to "<alt>X".

    • Change the method to be invoked. For example, change self.file_save to self.file_test.

    • Change the item number. This item number is passed as an argument to the invoked method. For example, change 2 to 3.

  2. Add a new method (to class PyeditorApp). For example, add the method:

        def file_test(self, *args):
    
  3. Implement the new method. Here are some hints:

    • Get access the to the current buffer (the buffer that is currently visible) with the following:

          buffer = self.getCurBuf()
      
    • Access and manipulate the current buffer using the methods defined in pyscintilla.py. For example, get the contents of the current line with the following:

          start, end = buffer.get_selection()
          curLineNo = buffer.get_line_at_position(start)
          lineNo = curLineNo
          line = buffer.get_line(lineNo)
      
Back to top

How to change an existing menu item

Follow these steps:

  1. Find the menu item definition in method init_menu_new.

    • If you want a different label, change the label.

    • If you want a different quick key, change the quick key.

    • If you want a different method, change the method.

  2. Edit the (existing) method.
Back to top

How to add a new toolbar item

Follow these steps:

  1. Find the method create_toolbar in pyeditor.py.

  2. Add a new pix map using a line something like the following:

        testpix, testmask = gtk.create_pixmap_from_xpm(win, None, home + "pixmaps/test.xpm")
    
    If you need a new pix map for your button, you will have to create it yourself.

  3. Add the new button to the toolbar using something like the following:

        toolbar.append_item("Test", "Run a test",
            "Run a test",
            gtk.GtkPixmap(testpix, testmask),
            self.run_test)
    
  4. Implement the method (in this case run_test. Methods used to implement toolbar actions are similar to those used to implement menu item actions. Follow the suggestions for menu item methods above.

Back to top

How to create a new toolbar

Since space on the existing toolbar is limited, you may decide to create an additional toolbar. Here is how to do it:

  1. In class PyeditorApp, find the definition of method create_toolbar. Duplicate and rename this method definition.

  2. Find the call to create_toolbar in method create_window. Add a call to your new toolbar method right after (or before) that call. At this point you might want to run your editor to ensure that it creates two toolbars.

  3. Now modify your new toolbar method so that it has the buttons that you need and so that they call the methods you want called. See the section on how to add a new toolbar item for help with this. In particular, for each toolbar item, you will want to change:

    • The text for the item, i.e. the text that will show in addition to or in place of the icon.

    • The text for the tool-tip.

    • The pixmap for the icon.

    • The call-back method.

Back to top

How to customize behavior for a specific file type

Behavior specific to a given file type is implemented by creating a custom class, then installing an instance of that class in the buffer for a file when the file is loaded.

The default behaviors are in class Custom. To implement behavior for a new file type, create a new sub-class of class Custom. As an example, we'll add a new behavior for a property file type which has extension ".prop".

Follow these steps:

  1. Create a new class, for example, PropertyCustom as a sub-class of class Custom:

        class PropertyCustom(Custom):
            pass
    
  2. ScintillaX is an extension of class Scintilla, the Python wrapping of the Scintilla editor component. Instances of the buffer are instances of class ScintillaX. In the constructor for class ScintillaX, add another case to the if statement that checks the file extension and then creates an instance of the custom class. Use something like the following:

        elif ext == '.prop':
            self.fileCustom = PropertyCustom()
    
  3. Implement your special behavior in the custom class, in this case in class PropertyCustom. Here are some hints:

    • In the constructor of your custom class, call the constructor in class Custom to initialize defaults:

          class PropertyCustom(Custom):
              def __init__(self):
                  Custom.__init__(self)
      
    • Override defaults from class Custom as necessary. For example:

          class PropertyCustom(Custom):
              def __init__(self):
                  Custom.__init__(self)
                  self.defaultTabWidth = 8
                  self.useTabs = 1
      
    • See classes PythonCustom, CppCustom, XmlCustom, etc in pyeditor.py for examples.

    • In order to add a new category of behavior, you may need to do the following:

      • Add a new member variable and initialize it to a default value in the constructor of class Custom and initialize it to a special value in your specializing class.

      • Add a new behavior by adding a default method in class Custom and the same method in your specialization class.

Back to top

Extending pyeditor in C and C++

This section, as might be expected, will be short. Python can call extension modules written in C and C++. pyeditor is extendible in Python. So all that needs to be done to extend pyeditor with C or C++ is to (1) import a Python extension module, then (2) call the functions in that extension module or create instances of the classes in that module and so on.

pyeditor comes with several examples of using Python modules written in C to extend pyeditor. See the file utils_xml.py, where it uses libxml_saxlib (available at http://www.rexx.com/~dkuhlman/libxml_saxlib.html) and libxsltmod (available at http://www.rexx.com/~dkuhlman/libxsltmod.html).

The important thing to remember here is that any Python module can be used in extending pyeditor. From the point of view of using the module, it makes no difference whether the module was written in C/C++ or in plain Python.

Python is particularly well suited for being extended in C and C++. "Python is glue." In fact SWIG (Simplified Wrapper Interface Generator available at http://www.swig.org) will, for some purposes generate these wrappers for you.

Back to top


How to change the buffer menu and pop-up menu etc

The default pop-up menu can be enabled and disabled by changing the call to enable_defaultpopup in the method create_toplevel. Pass in 1 to enable and 0 to disable.

The method buffers_buildmenu is called to create the Buffers menu. The method popup_buildmenu is called to create the popup menu (which appears when you right-click in the text edit pane). You can add or remove items in these menus by modifying these two methods.

The method buffers_buildmenu replaces a menu that is created in create_menus. Look at the calls to buffers_buildmenu and the definition of that method itself to learn how to specialize other menus that change dynamically while the editor is running.

Back to top


Last update: 10/23/01