I’ve just had some success with a new technique for writing plugins, and I thought I’d share it.
I needed to write a plugin that provided a dynamic number of new commands. I wanted to use python’s built-in ‘type()’ function to create a new class for each command. Python lets you create new classes by writing code like this;
X = type('X', (object,), dict(a=1))
which is equivalent to
class X(object):
a = 1
In my case, I’m creating a system which converts plain text files to a number of different document formats. I have a number of templates (".tex" files) and I need to create a command for every “.tex” file in my plugin folder.
Which means I needed to write code like the following. It has been cleaned up a bit for clarity;
#
# Here's the base class for
# all dynamic classes:
#
class DynamicPdfCommand(sublimeplugin.TextCommand):
def run(self, view, args):
self.compile(view, self.template)
#
# Here's the loop creating adding
# a class per template;
#
requiredEnd = ".tex"
for file in os.listdir(packageDir):
if file.lower().endswith(requiredEnd):
className = createClassName(file)
newClass = type(className, (DynamicPdfCommand,), dict(template=file))
globals() className ] = newClass
So the things to note are;
-
First, create a base class for all your dynamic types. Note how the DynamicPdfCommand.run() method uses refers to ‘self.template’; we’ll set this later
-
Inside a loop, you create new class names as strings, then use type() to create the new classes. The last parameter here is a dictionary of initial values – that’s where we set the self.template variable.
-
Once you’ve created the type, you need to add it to the module so that ST will pick it up. That’s what the line
globals() className ] = newClass
is all about.
Anyway, that’s the technique. Hope someone else finds it useful.