ActiveBlog

Creating the Fakework macro
by Troy Topnik

Troy Topnik, August 11, 2009

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 a File
I/O article
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.

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 href="http://www.softpedia.com/get/Others/Fun/Fake-Notepad.shtml">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 href="http://docs.activestate.com/komodo/5.1/komodo-js-api.html">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 href="https://developer.mozilla.org/en/DOM/element.addEventListener">event
listener, just like the one I mentioned in a href="http://www.openkomodo.com/blogs/troyt/revenge-auto-wrap-type-type-type-ding">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 href="http://www.w3.org/TR/2000/WD-DOM-Level-3-Events-20000901/events.html#Events-KeyEvent">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 a href="https://developer.mozilla.org/en/Code_snippets/File_I%2F%2FO">File
I/O article 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 href="http://www.thinkgeek.com/computing/accessories/2940/">rearview
monitor mirror, Alt-Tab into Komodo, hit your Fakework macro
keybinding, and blaze out some irrelevant, plagiarized, incredibly
impressive code.

Subscribe to ActiveState Blogs by Email

Share this post:

About the Author: RSS

Troy Topnik is ActiveState's technical writer. After joining ActiveState in 2001 as a "Customer Relationship Representative" (AKA Tech Support), Troy went on to lead the PureMessage Enterprise Support team before moving on to a technical writing role in 2004. His talent for describing software for new users stems from his difficulty understanding things that developers find obvious. He has a Bachelor of Music from the University of Victoria.