Snippets code from my daily experience

August 17, 2009

Experimenting with Bespin plugins

Filed under: bespin — dafi @ 11:38 am

code_square I’ve started to use Bespin intensively, long editing sessions to test how much it fits my needs.

Bespin is very good and I’m really satisfied to use it as general purpose collaboration editor but I’m a very lazy developer and I need many little features, not yet present on Bespin, making my coding life easier.

Bespin supports plugins allowing users to write Javascript code that is easily “plugged” into editor so I started to study its programming model.

There are hundred of APIs but I focused my attention to the specific sections shown below, discovering an excellent support.

  • General text handling (unicode support, cursor position and so on)
  • Text selection
  • Undo/Redo groups of text operations
  • Clipboard

More details about installing and using plugins are available at Bespin wiki

A brief survey of Bespin architecture

When plugins interact with the editor soon or later they must use some core components.

  • editor itself; It holds reference to all editor structures
  • edit session; The current file buffer user are editing
  • model; The most important component, it allows to access to text abstracting internal character representation (eg unicode), you see anything as rows and columns
  • actions; move cursor, handle history (undo/redo) and many other text actions

It is possible to access to components using the Bespin singletons

bespin.get('editor') // access to the editor component

or navigating the data structure (ok you must use always a starting singleton😛 )

bespin.get('editSession').editor // access to the editor component starting from editSession

The “Comment Selection” plugin

To understand how Bespin APIs work I’ve written a stupid but useful (at least for me) plugin used to comment out a text selection based on file language, so CSS selected lines are commented using /* … */, HTML using <!– … –> and so on.

The “comment selection” is treated as a single text operation, if ten lines are commented and user makes undo all lines are undone, user doesn’t need to make ten times undo!
Grouping operations for undo/redo it is possible thanks to beginEdit()/endEdit() methods

    editor.ui.actions.beginEdit("commentSelection");
    ...
    editor.ui.actions.endEdit();

Stop blah blah blah, I want to read code!

The plugin code is very easy.

We get the selection info (not the text) and then use the model to insert characters, this allows to take benefits of history manager (undo/redo) and character internal representation.

exports.commentSelection = function(instruction) {
    var currPath = bespin.get('editSession').path;
    var extFile = bespin.util.path.fileType(currPath);
    var commentDelimiters = exports.getCommentDelimitersByLang(extFile);

    if (typeof (commentDelimiters) == "undefined") {
      return;
    }

    var selection = bespin.get('editor').getSelection();
    var model = bespin.get('editSession').editor.model;
    var editor = bespin.get('editSession').editor;

    var startRow;
    var endRow;
    if (selection) {
      startRow = selection.startModelPos.row;
      endRow = selection.endModelPos.row;
    } else {
      startRow = endRow = editor.getCursorPos().row;
    }
    instruction.addOutput(startRow + "," + endRow + " model" + model);
    editor.ui.actions.beginEdit("commentSelection");
    for (var r = startRow; r <= endRow; r++) {
      var modelPos = {row : r, col : 0};
      model.insertCharacters(modelPos, commentDelimiters.begin);
      modelPos.col = model.rows[r].length;
      model.insertCharacters(modelPos, commentDelimiters.end);
      }
    editor.ui.actions.endEdit();
}

You can view the full plugin code following me at bespin.mozilla.com, do login and from command line type

follow dafi

SVN aficionados can browse the code here

4 Comments

  1. > var commentDelimitiers = exports.getCommentDelimitiersByLang(extFile);

    “Delimiters” is spelled thusly, not delimitiers. Like begin -> beginner, delimit -> delimiter. In general words ending in a vowel or ‘y’ get the “ier” suffix.

    Cheers

    Comment by skierpage — August 17, 2009 @ 10:28 pm

    • Typo fixed, thanks😛

      Comment by dafi — August 18, 2009 @ 7:23 am

  2. Dumb question. How do you call your plugin from within the document. Not install it, but actually use it?

    Comment by Josh — August 18, 2009 @ 11:50 pm

  3. Nevermind, got it.

    Comment by Josh — August 18, 2009 @ 11:54 pm


RSS feed for comments on this post.

Create a free website or blog at WordPress.com.

%d bloggers like this: