Sublime Forum

Creating dynamic commands with the type() function

#1

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.

0 Likes