On Wednesday 05 September 2007 18:54:17 Rob McMullen wrote:
> Yes, Dusty, welcome to the Text Editor Writers support group!  I'm
> hopeful that we can all continue to share ideas and code.  In writing
> peppy, I started off as a pet project where I was writing most of my
> own stuff, but as it got bigger, there was more to debug.  I started
> thinking that it would be a good idea to let the time spent by others
> not go to waste.  So, I started shamelessly borrowing code.
>
> What I'd love to see with pyxides is a lot of code that we could mix
> and match among applications.  Stani's Fold Explorer comes to mind, if
> I'd ever get back to working on the text editing part of peppy rather
> than the framework.
>
> I know we all have different goals with our editors, but were we to
> have a big set of code with few external dependencies (i.e. low
> coupling), we could all borrow stuff at will.  For example, the
> overarching goal of peppy is to have multiple top level windows with
> multiple ways to view the same file.  That may be too much overhead
> for some people to consider using peppy for a framework, and that's
> cool.  But, if I can make some of my stuff independent enough, maybe
> it will be useful for others.  I've been trying to pull stuff out of
> classes where I can and putting them into mixins or standalone files
> in the peppy.lib module.
>
> To kick off some discussion, I was wondering if you'd talk about (or
> point to a good description of) the jedit plugin system that you were
> emulating.  Do you have to define all the messages that get passed
> around in advance, i.e. do all plugins have to implement the same
> interface?
>
> For peppy, I rolled my own plugins for a while until I ran across the
> Trac component architecture
> (http://trac.edgewall.org/wiki/TracDev/ComponentArchitecture).
> Basically a Trac component (aka plugin) is a singleton that registers
> entry points that other Trac plugins can add themselves to.  You
> define interfaces, and one plugin can implement one or many of the
> interfaces.  I have found that useful.
>
> The implication of this architecture is that you can't have multiple
> instances of the same Trac plugin -- you've got to treat the Trac
> plugin as a factory to generate other objects.  That's its drawback, I
> suppose, and though I've found that limiting at times there were
> always ways to work around it.  As a bonus, they integrate well with
> the setuptools plugins.
>
> The thing that intrigues me about what I think I understand about the
> jedit plugins is the message passing.  I wonder if a Trac component
> could be a factory for jedit plugins?  I'm still struggling with
> message passing (wx.lib.pubsub), because with my multiple views I
> might want a message to be sent to only one of the views, but there's
> no way to do that with vanilla pubsub.  I was trying to get away from
> the message *passer* having to know the target view: it just sends its
> message and the message passing facility would knows where to direct
> it.  Don't have a good solution -- I could have each message receiver
> check if it is the intended target, but it seemed like there should be
> a better solution.
>
> Rob

Hi,

Well, firstly, I should say that we are not all text-editor developers here. I 
personally feel that writing a new text editor is fairly much a waste of 
time, and hence PIDA's philosophy of using external mature and well-featured 
editors. Secondly, I should say that we are not all wxPython developers.

With those two asides, I would guess that we all have come across the problem 
of writing a fully-featured plugin architecture.

Trac plugin architecture is a nice starting point, as you describe. I have no 
idea about JEdit plugins, but I did have a good look at Eclipse plugins 
before writing the current (3rd) version of the PIDA plugin architecture.

PIDA has two levels of "plugin". The first is a very low-level thing, akin to 
the Trac architecture but more featured. The second level is the level at 
which this architecture is used to create actual plugins that do real things.

The low level plugin is essentially a registry where other components can 
register things. The three kind of things that a component can register with 
the registry are "Singletons", "Features", and "Extension Points". I won't 
bore you with the details, you can check the docstring at 
http://pida.co.uk/trac/browser/trunk/pida/core/plugins.py.

An "Extension Point" is somewhat like a Trac extension point, but in practise 
we have found these things quite useless. A "Feature" is a similar thing, 
except that the keys, or interfaces that are expected to be provided are not 
predetermined, and can be registered at runtime, which allows for a real 
modification in behaviour without changing the core code.

So, using this low-level architecture, we have built real plugins. These 
plugins define the following:

Configuration - options
Commands - the external interface for the plugin
Events - events that the plugin will fire to any interested observers
Features - As features described above
Actions - UI Actions which loosely map 1:1 with menu items or toolbar buttons
Views - UI components which display as views

Using this, a plugin can modify the behaviour of PIDA in any way via a 
controlled interface. As an example, recently we added a code completion 
framework. The problem was that code completion should be able to use the 
same backend for any editor, and any plugin should be able to provide a 
completion function that can be used. The results sent back to the editor 
should be a combination of all the individual results from the plugins that 
implement this feature. So, without changing any core code: Write a plugin 
which has a feature for completing. Call it ICompletionResults. Allow any 
plugin to register with this feature. Done.

I find myself going on and on and on about this, so excuse me.

Ali

Reply via email to