Creating the Fakework macro

If you're a decent programmer, you'll hopefully find this funny. If you're a completely incompetent programmer, you may find this macro useful or even essential.

My friend Gozer told me about someone who had hacked up a tool to make his conference presentations run smoothly. Instead of typing in all the commands and code in the demo and exposing his poor typing skills, he "pre-recorded" the presentation. His script would play back the keystrokes, one character at a time, with the pressing of any key. Random characters in; blazingly fast, perfect code out.

Obviously others have had this idea too. I found Fake Notepad which does the same kind of keystroke playback in a Windows Notepad clone. "File > Open" allows you to choose a text file, but the buffer stays blank until you start mashing keys.

But that application only works for text files, and even the pointiest haired boss knows that developers don't use Notepad. That text needs syntax highlighting! Enter the Fakework macro for Komodo.

In the Toolbox menu, click "Add > New Macro...". Give the macro a cryptic name ("Fakework" is terribly incriminating), make sure "Language:" is set to "JavaScript" and click "OK". We'll put some code in there in a second, but we'll do it in an editor tab where we can get some auto-completion for the Komodo JavaScript API. Right click on your new macro in the Toolbox and select "Edit Macro".

Adding and removing event listeners

First we'll need an event listener, just like the one I mentioned in a previous silly macro:

ko.views.manager.topView.addEventListener("keypress", fakework, true);

Now, for that previous macro, I created a separate macro for turning the event listener off. The equivalent here would be:

ko.views.manager.topView.removeEventListener("keypress", fakework, true);

That's clunky. I've since learned how to do this a little more sensibly. We'll make a function to turn off the listener, and run it when the escape key is pressed:

normalMode = function () {
  ko.views.manager.topView.removeEventListener("keypress", fakework, true);
}

Here's a stub for the fakework function:

fakework = function (event) {
  if (event.keyCode == event.DOM_VK_ESCAPE) {
    normalMode();
  } else {
  alert("No escape!");
  }
}

Komodo can use DOM Level 3 events. If you want to use a different key, choose one from the KeyEvent interface.

Putting together what we have so far, here's the macro:

fakework = function (event) {
  if (event.keyCode == event.DOM_VK_ESCAPE) {
    normalMode();
  } else {
  alert("No escape!");
  }
}

normalMode = function () {
  ko.views.manager.topView.removeEventListener("keypress", fakework, true);
}

ko.views.manager.topView.addEventListener("keypress", fakework, true);

Inserting text, one character at a time

Let's put some dummy data in there for our fake work:

data = "Look! I'm working really, really hard!"

pos = 0    // current position in the string

... and add the magic in our function to insert it:

fakework = function (event) {
  if (event.keyCode == event.DOM_VK_ESCAPE) {
    normalMode();
  } else {
    event.stopPropagation();  // prevent propagation
    event.preventDefault();  // stops us from inserting real text
    var scimoz = ko.views.manager.currentView.scimoz;
    scimoz.insertText(scimoz.currentPos, data[pos]); // insert fake text starting at position 0
    scimoz.currentPos++ // increment the position in the buffer
    pos++ // ... and the position in the fake text
  }
}

Now, open an empty buffer, double-click on your macro, and start hitting keys. The text in data should be inserted instead of the actual keystrokes.

Getting data from a file

Now entering a corpus of fake work directly into the macro kind of defeats the purpose of pretending to work. It would be much better to take this information from a file, preferably some really gnarly, impenetrable code written by a much better programmer.

I couldn't find anything in the Komodo JavaScript API for reading files, and that often means it's something handled directly by Mozilla (which Komodo is based on). A little Googling led me to some informationĀ on MDC. Sure enough, the "Creating an snIFile object" and "Reading from a file" examples worked as expected:

var file = Components.classes["@mozilla.org/file/local;1"].
                     createInstance(Components.interfaces.nsILocalFile);
file.initWithPath("C:\\dev\gnarlycode.js");
  
var data = "";
var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"].
                        createInstance(Components.interfaces.nsIFileInputStream);
var cstream = Components.classes["@mozilla.org/intl/converter-input-stream;1"].
                        createInstance(Components.interfaces.nsIConverterInputStream);
fstream.init(file, -1, 0, 0);
cstream.init(fstream, "UTF-8", 0, 0); // you can use another encoding here if you wish

let (str = {}) {
  cstream.readString(-1, str); // read the whole file and put it in str.value
  data = str.value;
}
cstream.close(); // this closes fstream

Replace the file.initWithPath() with your favorite l33t bit of code and remove the placeholder data variable we put in earlier. When we glue all the bits together we get something like this:

var file = Components.classes["@mozilla.org/file/local;1"].
                     createInstance(Components.interfaces.nsILocalFile);
file.initWithPath("C:\\dev\gnarlycode.js");
  
var data = "";
var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"].
                        createInstance(Components.interfaces.nsIFileInputStream);
var cstream = Components.classes["@mozilla.org/intl/converter-input-stream;1"].
                        createInstance(Components.interfaces.nsIConverterInputStream);
fstream.init(file, -1, 0, 0);
cstream.init(fstream, "UTF-8", 0, 0); 

let (str = {}) {
  cstream.readString(-1, str); 
  data = str.value;
}
cstream.close();

pos = 0;

fakework = function (event) {
  if (event.keyCode == event.DOM_VK_ESCAPE) {
    normalMode();
  } else {
    event.stopPropagation();
    event.preventDefault();
    var scimoz = ko.views.manager.currentView.scimoz;
    scimoz.insertText(scimoz.currentPos, data[pos]);
    scimoz.currentPos++
    pos++
  }
}

normalMode = function () {
  ko.views.manager.topView.removeEventListener("keypress", fakework, true);
}

ko.views.manager.topView.addEventListener("keypress", fakework, true);

So the next time you spot your boss approaching in your rearview monitor mirror, Alt-Tab into Komodo, hit your Fakework macro keybinding, and blaze out some irrelevant, plagiarized, incredibly impressive code.