Extending Marave

Marave is a text editor. If there's one thing that's true of most text editors, it's this: they lack the exact features you need.

So, the solution, in the ancient tradition of Emacs and Vim is... make it extensible.

I am a big fan of programs that can be extended by users.

So... here's the anatomy of a Marave plugin as it stands right now on SVN trunk, which of course can change any minute.

Creating a plugin

You just need to create a .py file in the plugins folder.

Here's the most basic plugin, which does nothing:

# -*- coding: utf-8 -*-

from plugins import Plugin
class Smarty(Plugin):
    name='smarty'
    shortcut='Ctrl+.'
    description='Smart quote and dash replacement'
    mode="qBde"

Default values for anything configurable (in this case, "mode") is just added to the class.

The mandatory fields:

  • shortcut: a keyboard shortcut that triggers this plugin
  • name: a short name
  • description: a one-line description of what it does

What does it do? It adds the plugin to the plugin list in the prefs dialog, and you can open its configuration dialog, where you can change the shortcut:

maraveplugin1

If you enable this plugin, whenever the shortcut is used the "run" method of the plugin is called.

Making the Plugin Configurable

This plugin supports different modes of operation. To make this reachable to the user, you need to implement a few extra methods.

The addConfigWidgets method takes a dialog argument and adds whatever you want there:

@classmethod
def addConfigWidgets(self, dialog):
    print 'Adding widgets to smarty config'
    l=dialog.ui.layout
    self.q=QtGui.QCheckBox(dialog.tr('Replace normal quotes'))
    if 'q' in self.mode:
        self.q.setChecked(True)
    self.b=QtGui.QCheckBox(dialog.tr('Replace backtick-style quotes (` and ``)'))
    if 'B' in self.mode:
        self.b.setChecked(True)
    self.d=QtGui.QCheckBox(dialog.tr('Replace -- by en-dash, --- by em-dash'))
    if 'd' in self.mode:
        self.d.setChecked(True)
    self.e=QtGui.QCheckBox(dialog.tr('Replace ellipses'))
    if 'e' in self.mode:
        self.e.setChecked(True)
    l.addWidget(self.q)
    l.addWidget(self.b)
    l.addWidget(self.d)
    l.addWidget(self.e)

And then the config dialog will look like this:

maraveplugin2

But then you need to save those options somewhere, which you do reimplementing saveConfig:

@classmethod
def saveConfig(self, dialog):

    self.shortcut=unicode(dialog.ui.shortcut.text())
    self.settings.setValue('plugin-'+self.name+'-shortcut', self.shortcut)

    newmode=""
    if self.q.isChecked():
        newmode+='q'
    if self.b.isChecked():
        newmode+='B'
    if self.d.isChecked():
        newmode+='d'
    if self.e.isChecked():
        newmode+='e'
    self.mode=newmode

    self.settings.setValue('plugin-smarty-mode',self.mode)
    self.settings.sync()

And you need to load those settings and put them in your class, too:

@classmethod
def loadConfig(self):
    print 'SMARTY loadconfig', self.settings
    if self.settings:
        sc=self.settings.value('plugin-'+self.name+'-shortcut')
        if sc.isValid():
            self.shortcut=unicode(sc.toString())
        mode=self.settings.value('plugin-smarty-mode')
        if mode.isValid():
            self.mode=unicode(mode.toString())

Making it Work

And yes, you need to make it do something useful. The plugin has access to a "client" which is Marave's main window. Everything is available there, somewhere ;-)

def run(self):
    print 'running smarty plugin'
    text=unicode(self.client.editor.toPlainText()).splitlines()
    prog=QtGui.QProgressDialog(self.client.tr("Applying smarty"),
                               self.client.tr("Cancel"),
                               0,len(text),
                               self.client)
    prog.show()
    output=[]
    for i,l in enumerate(text):
        output.append(unescape(smartyPants(l,self.mode)))
        prog.setValue(i)
        QtGui.QApplication.instance().processEvents()
    prog.hide()
    self.client.editor.setPlainText('\n'.join(output))

And there it is, if you enable the smarty plugin, you can "fix" your quotes, dashes and ellipsis with a key combination :-)

Full source code here: http://code.google.com/p/marave/source/browse/trunk/marave/plugins/smarty.py

Still to be done: other ways to integrate plugins into the UI, buttons, panels, etc.

Comments

Comments powered by Disqus