Writing your own Google Apps Plugins

So I am currently between jobs and I like to use that time to learn new programming languages as I believe that you should try to think outside your day to day experiences. Especially in this world of microservices, it makes sense to broaden your horizon to see if you’re not always applying your favorite lawnmower to a problem that requires a hammer.

Given that I have about 4 weeks, I figure I can do more than one so I started with Erlang and I used Google docs to keep track of the notes. I quickly ran into a huge issue: there is no ‘format as code’ block functionality in standard Google Docs! Being used to Atlassian’s Confluence and even WordPress I was a bit undone. What next? Obviously I looked for plugins but they always want all the rights (like, run while you’re not around, access to your bookmarks and browser history, credit card details, you name it)

I also didn’t feel much for applying the same styles over and over again. So, what is a good procrastinator to do? Right! take a small break from his endeavours into Erlang and write a plugin for Google Docs! The API is pretty well documented and there are some samples online. But basically, if you go to Tools/Script Editor you’re already halfway there.

In the editor that popped up I wrote the following script (probably still buggy enough but it does the trick):

function onOpen() {
  DocumentApp.getUi()
  .createMenu('Custom')
  .addItem('Format As Code', 'formatAsCode')
  .addToUi();
}
 
// Define code styling
var style = {};
style[DocumentApp.Attribute.FONT_FAMILY] = "Courier New";
style[DocumentApp.Attribute.FONT_SIZE] = 10;
style[DocumentApp.Attribute.BACKGROUND_COLOR] = "#000000";
style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#FFFFFF";
style[DocumentApp.Attribute.BOLD] = false;
 
// Apply code formatting
function formatAsCode() {
  var selection = DocumentApp.getActiveDocument().getSelection();
 
  if (selection) {
    var body = DocumentApp.getActiveDocument().getBody();
 
    var insert = null;
    var table = null;
    var cell = null;
 
    var elements = selection.getRangeElements();
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      if (element.getElement().editAsText) {
        if (insert == null) {
          insert = element.getElement().getParent().getChildIndex(element.getElement());
          var detached = element.getElement().removeFromParent();
          var table = body.insertTable(insert);
          var cell = table.appendTableRow().appendTableCell();
          cell.setAttributes(style);
          cell.appendParagraph(detached.asText().getText()).setAttributes(style);
          // for some reason there is an empty text element now
          cell.getChild(0).removeFromParent();
        }
        else {
          cell.appendParagraph(element.getElement().removeFromParent().asText().getText()).setAttributes(style);
        }
 
      }
    }
  }
}

And it allows you to save and immediately try the effects.

So, now I can finally get back to what I was doing, learning Erlang 🙂