Friday, March 9, 2012

Logic chains in javascript and python

Let's talk about javascript.  What happens when you have a function like this:

function(x) {
    x = x || 'default'

This is useful when you want to have a function where x is optional.  When you don't pass a value to your function x is treated as undefined and the statement is read as x = undefined || 'default'.  Whenever you have:

somevariable = statement || statement || statement ... || statement

the variable will get assigned the first true value from left to right or the last false value.

But what happens when you do this?
x = [] || 'kittens'
you would think that [] evaluates as a false value, but in javascript an empty list is true so x becomes []

lets try this in python
x = [] or 'kittens'
This evaluates the way you think, x becomes 'kittens'.

Now, I'm not saying anyone would have statements like this, but I just wanted you to think about the little differences that languages have and how they can cause unforeseen bugs.

The same thing applies to empty objects:
in javascript:
x = {} || 'yarg' /* yields {} */
in python
x = {} or 'yarg' /* yields yarg */
Complimentary to the 'or' examples, 'and's behave the opposite.  If you have:
somevariable = statement && statement && ... && statement
your variable will get the first false statement or the last true statement.

This works pretty well in javascript/python

x = 'lol' and 'heh' and 'doh'
x = 'lol' && 'heh' && 'doh'
/* x has doh */
but again, try this:
// javascript
x = 'lol' && [] && 'doh' /* yields 'doh' */

# python
x = 'lol' and [] and 'doh' /* yields [] */
Now you know; and knowing is half the battle.

Thursday, March 1, 2012

Fun Emacs Prank

I noticed while using emacs you can use this handy program called emacsclient to perhaps open a file or run a command on emacs. I took this as an opportunity to have fun with my co-workers.

They like to run emacs with X-Forwarding on remote hosts that are the development hosts. Its easy to log into their remote host and do something like this:
emacsclient --no-wait ~/prank-file

This would open the file on their currently running emacs. Sounds great right? You could make some ascii picture of something nsfw and then just run good old emacsclient to turn their day around!

Anywho, this wasn't enough for me. I wanted to make it so the file would change and maybe scroll across the screen saying something like "LOL Kittens!". Or even you could try and make it invert the ascii art and then invert it back. Somewhat like you are flashing the text.

I first tried to get it so you could scroll the art across the screen (from left to right)
first iteration

second iteration

final iteration

I started out trying this:
columns=`head -n 1 /tmp/ascii-art-file | wc -c`; # get the number of columns in the text file

for x in seq 1 $columns; do
    cut -c $x-$columns /tmp/ascii-art-file > /tmp/scroll;
    emacsclient --no-wait /tmp/scroll; 
    sleep 5;

This didn't work as expected. Emacs kept asking if I wanted to refresh the modified buffers.
I did some digging and it didn't seem like an easy solution. I wanted this to be something that would just appear on my co-worker's screen and cause mayhem.

After some more digging I found the handy emacs command: zone.
It does all fun stuff like scrolling your current buffer, or even dripping the text like the movie The Matrix.

I couldn't wait to find out that emacsclient came with --eval as an option. This allows you to run lisp on your emacs server. Checkmate.
I created this script:

emacsclient --no-wait $1
emacsclient -e '(with-current-buffer "'`basename $1`'" (zone))'
sleep 5

This script ran fine. But sometimes emacsclient blocked when you ran zone. This wasn't ideal. So I added this to the beginning to kill the emacsclient every time you run zone:
ps -ef | grep emacsclient | grep -v grep | awk '{print $2}' | xargs --no-run-if-empty kill -9
Finally, to get this to run over and over, just put zone in a while loop:

while true; do /tmp/zone /tmp/ascii-art-file; done;
Happy pranking!